Date: Tue, 20 Nov 2007 22:50:15 GMT From: Hans Petter Selasky <hselasky@FreeBSD.org> To: Perforce Change Reviews <perforce@FreeBSD.org> Subject: PERFORCE change 129311 for review Message-ID: <200711202250.lAKMoFqt052302@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=129311 Change 129311 by hselasky@hselasky_laptop001 on 2007/11/20 22:49:44 This commit is needed to support loading of virtual buffers into DMA. Replaced "usbd_page_cache_offset" by "usbd_set_frame_offset" for sake of convenience. The initial function also contained a bug. The functions "usbd_set_frame_index" and "usbd_set_frame_offset" contradict eachother. The first one sets up an USB frame to use the system allocated DMA buffer at the give offset. The second one sets up an USB frame to use a virtual buffer for the given USB frame, that lateer will be loaded into DMA. Added new field "p_buffer" to "struct usbd_page_cache" which will hold the Virtual Address that should be loaded into DMA. Added new field "dma_page_ptr" to "struct usbd_xfer". How loading of virtual buffers into DMA now works under USB; When the system pre-allocates DMA memory it will fill out an array of "struct usbd_page" that contains information like physical address and virtual address. When we want to load some virtual memory into DMA we fill out a similar array of "struct usbd_page" with information about physical address and other needed stuff. Then we point the "page_start" field of the "usbd_page_cache" structure (see: xfer->frbuffers) to use a set of consequtive elements within the "xfer->dma_page_ptr" array. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#48 edit .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#55 edit .. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#42 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.c#48 (text+ko) ==== @@ -2052,31 +2052,6 @@ } /*------------------------------------------------------------------------------* - * usbd_page_cache_offset - *------------------------------------------------------------------------------*/ -void -usbd_page_cache_offset(struct usbd_page_cache *pc_src, - struct usbd_page_cache *pc_dst, - uint32_t offset) -{ - struct usbd_page *page = pc_src->page_start; - - offset += pc_src->page_offset_buf; - - if ((offset >= pc_src->page_offset_end) || - (offset < pc_src->page_offset_buf)) { - /* out of range */ - bzero(pc_dst, sizeof(*pc_dst)); - return; - } - page += (offset / USB_PAGE_SIZE); - pc_dst->page_start = page; - pc_dst->page_offset_buf = (offset % USB_PAGE_SIZE); - pc_dst->page_offset_end = (2 * pc_src->page_offset_end) - offset; - return; -} - -/*------------------------------------------------------------------------------* * usbd_page_fit_obj - fit object function *------------------------------------------------------------------------------*/ uint32_t ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#55 (text+ko) ==== @@ -203,6 +203,8 @@ struct usbd_page_cache { struct usbd_page *page_start; struct usbd_xfer *p_xfer; + void *p_buffer; /* virtual buffer to be loaded by + * BUS-DMA */ uint32_t page_offset_buf; uint32_t page_offset_end; }; @@ -210,6 +212,7 @@ struct usbd_setup_params { struct usbd_page_cache pc; + struct usbd_page *dma_page_ptr; struct usbd_page *page_ptr; struct usbd_device *udev; struct usbd_xfer *curr_xfer; @@ -217,7 +220,7 @@ const struct usbd_pipe_methods *methods; void *buf; - uint32_t size[3]; + uint32_t size[4]; uint32_t total_size[3]; uint32_t bufsize; uint32_t hc_max_frame_size; @@ -410,6 +413,7 @@ LIST_ENTRY(usbd_xfer) interrupt_list; /* used by HC driver */ LIST_ENTRY(usbd_xfer) pipe_list; /* used by HC driver */ + struct usbd_page *dma_page_ptr; struct usbd_pipe *pipe; struct usbd_device *udev; struct mtx *priv_mtx; @@ -661,7 +665,6 @@ uint8_t usbd_page_alloc(bus_dma_tag_t tag, struct usbd_page *page, uint32_t npages); void usbd_page_free(struct usbd_page *page, uint32_t npages); void usbd_page_cache_init(struct usbd_page_cache *pc, struct usbd_page *page_ptr, uint32_t offset, uint32_t size); -void usbd_page_cache_offset(struct usbd_page_cache *pc_src, struct usbd_page_cache *pc_dst, uint32_t offset); uint32_t usbd_page_fit_obj(uint32_t size, uint32_t obj_len); void *usbd_mem_alloc(bus_dma_tag_t parent, struct usbd_page *page, uint32_t size, uint8_t align_power); void usbd_mem_free(struct usbd_page *page); @@ -721,6 +724,7 @@ void usbd_transfer_start(struct usbd_xfer *xfer); void usbd_transfer_stop(struct usbd_xfer *xfer); void usbd_set_frame_data(struct usbd_xfer *xfer, void *ptr, uint32_t len, uint32_t frindex); +void usbd_set_frame_offset(struct usbd_xfer *xfer, uint32_t offset, uint32_t frindex); void usbd_callback_wrapper(struct usbd_xfer *xfer); void usbd_do_callback(struct usbd_xfer **pp_xfer, struct thread *td); void usbd_transfer_enqueue(struct usbd_xfer *xfer); ==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#42 (text+ko) ==== @@ -282,8 +282,9 @@ const struct usbd_config *setup = parm->curr_setup; usb_endpoint_descriptor_t *edesc; struct usbd_std_packet_size std_size; - uint16_t n_frlengths; - uint16_t n_frbuffers; + uint32_t n_frlengths; + uint32_t n_frbuffers; + uint32_t x; uint8_t type; uint8_t zmps; @@ -573,7 +574,8 @@ usbd_page_cache_init (xfer->frbuffers + 1, parm->page_ptr, - parm->size[1] + REQ_SIZE, parm->bufsize - REQ_SIZE); + parm->size[1] + REQ_SIZE, + parm->bufsize - REQ_SIZE); } /* * make a copy of the page cache that @@ -587,6 +589,18 @@ /* align data again */ parm->size[1] += ((-parm->size[1]) & (USB_HOST_ALIGN - 1)); } + /* + * check if we need to allocate + * temporary usbd_page structure(s) + * for loading memory into DMA + */ + + if (xfer->flags.bdma_enable) { + /* setup "dma_page_ptr" */ + xfer->dma_page_ptr = parm->dma_page_ptr; + parm->dma_page_ptr += n_frbuffers; + parm->dma_page_ptr += (parm->bufsize / USB_PAGE_SIZE); + } if (zmps) { /* correct maximum data length */ xfer->max_data_length = 0; @@ -601,6 +615,13 @@ parm->err = USBD_INVAL; goto done; } + /* initialize transfer backpointer */ + + if (parm->buf) { + for (x = 0; x < n_frbuffers; x++) { + xfer->frbuffers[x].p_xfer = xfer; + } + } done: if (parm->err) { xfer->max_usb_frame_size = 1; /* XXX avoid division by zero */ @@ -777,7 +798,14 @@ /* store offset temporarily */ parm.size[2] = parm.size[0]; - parm.size[0] += (sizeof(parm.page_ptr[0]) * parm.total_size[1]); + parm.size[0] += (sizeof(parm.page_ptr[0]) * + parm.total_size[1]); + + /* store offset temporarily */ + parm.size[3] = parm.size[0]; + + parm.size[0] += ((uint8_t *)parm.dma_page_ptr) - + ((uint8_t *)0); /* store total buffer size */ parm.total_size[0] = parm.size[0]; @@ -793,6 +821,7 @@ goto done; } parm.page_ptr = USBD_ADD_BYTES(buf, parm.size[2]); + parm.dma_page_ptr = USBD_ADD_BYTES(buf, parm.size[3]); if (usbd_page_alloc(udev->bus->dma_tag, parm.page_ptr, parm.total_size[1])) { @@ -1431,6 +1460,35 @@ usbd_set_frame_data(struct usbd_xfer *xfer, void *ptr, uint32_t len, uint32_t frindex) { + xfer->frbuffers[frindex].p_buffer = ptr; /* enable loading of + * memory into DMA */ + xfer->frlengths[frindex] = len; + return; +} + +/*------------------------------------------------------------------------* + * usbd_set_frame_offset + * + * This function sets the frame data buffer offset relative to the beginning + * of the USB DMA buffer allocated for this USB transfer. + *------------------------------------------------------------------------*/ +void +usbd_set_frame_offset(struct usbd_xfer *xfer, uint32_t offset, + uint32_t frindex) +{ + struct usbd_page *page = xfer->buf_data.page_start; + struct usbd_page_cache *pc = xfer->frbuffers + frindex; + + __KASSERT(!xfer->flags.ext_buffer, ("Cannot offset data frame " + " when the USB buffer is external!\n")); + + pc->page_offset_end = xfer->buf_data.page_offset_end - offset; + + offset += xfer->buf_data.page_offset_buf; + page += (offset / USB_PAGE_SIZE); + pc->page_start = page; + pc->page_offset_buf = (offset % USB_PAGE_SIZE); + pc->p_buffer = NULL; /* disable loading of memory into DMA */ return; }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200711202250.lAKMoFqt052302>