From owner-p4-projects@FreeBSD.ORG Tue Apr 1 20:36:15 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 95B621065670; Tue, 1 Apr 2008 20:36:15 +0000 (UTC) Delivered-To: perforce@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5451F1065674 for ; Tue, 1 Apr 2008 20:36:15 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 437188FC1D for ; Tue, 1 Apr 2008 20:36:15 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m31KaFk2000397 for ; Tue, 1 Apr 2008 20:36:15 GMT (envelope-from hselasky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id m31KaE9b000395 for perforce@freebsd.org; Tue, 1 Apr 2008 20:36:14 GMT (envelope-from hselasky@FreeBSD.org) Date: Tue, 1 Apr 2008 20:36:14 GMT Message-Id: <200804012036.m31KaE9b000395@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to hselasky@FreeBSD.org using -f From: Hans Petter Selasky To: Perforce Change Reviews Cc: Subject: PERFORCE change 139161 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 01 Apr 2008 20:36:15 -0000 http://perforce.freebsd.org/chv.cgi?CH=139161 Change 139161 by hselasky@hselasky_laptop001 on 2008/04/01 20:35:25 To solve the following three problems I have to make a set of BUS-DMA related changes. Commit 1/3 P1) I should pass a valid lock function to "bus_dma_tag_create". P2) Currently the error code EINPROGRESS is not handled at all, when returned by "bus_dmamap_load". I have created a new condition variable that will be used to wait for the done callback. P3) Ensure that all USB page caches on an USB transfer are loaded in serial, mostly in case of page bouncing. Changes in "usb_subr.h" from the top: 1) In the USB page cache structure we no have "tag_parent" instead of "xfer". This allows the page cache consept to easily be extended beyond USB. 2) New structure "struct usbd_dma_parent_tag" that is associated with an array of "struct usbd_dma_tag". One purpose of this structure is to store constant parameters that were previously passed on the stack. 3) Several protypes have been updated to take advantage of 2) 4) New function: "usbd_dma_tag_find" which replaces "usbd_dma_tag_setup". 5) "usbd_bdma_done_event" is now a static function. Affected files ... .. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#101 edit Differences ... ==== //depot/projects/usb/src/sys/dev/usb/usb_subr.h#101 (text+ko) ==== @@ -122,6 +122,8 @@ struct usbd_bus; struct usbd_clone; struct usbd_config; +struct usbd_dma_tag; +struct usbd_dma_parent_tag; struct usbd_device; struct usbd_hw_ep_profile; struct usbd_interface; @@ -317,7 +319,7 @@ bus_dma_segment_t *p_seg; #endif struct usbd_page *page_start; - struct usbd_xfer *xfer; /* if set, backpointer to USB transfer */ + struct usbd_dma_parent_tag *tag_parent; /* always set */ void *buffer; /* virtual buffer pointer */ #ifdef __NetBSD__ int n_seg; @@ -406,13 +408,39 @@ }; /* - * The following structure keeps an USB DMA tag. + * The following typedef defines the USB DMA load done callback. + */ + +typedef void (usbd_dma_callback_t)(struct usbd_dma_parent_tag *udpt); + +/* + * The following structure describes the parent USB DMA tag. + */ +struct usbd_dma_parent_tag { + struct cv cv[1]; /* internal condition variable */ + + bus_dma_tag_t tag; /* always set */ + + struct mtx *mtx; /* private mutex, always set */ + struct usbd_memory_info *info; /* used by the callback function */ + usbd_dma_callback_t *func; /* load complete callback function */ + struct usbd_dma_tag *utag_first;/* pointer to first USB DMA tag */ + + uint8_t dma_error; /* set if DMA load operation failed */ + uint8_t dma_bits; /* number of DMA address lines */ + uint8_t utag_max; /* number of USB DMA tags */ +}; + +/* + * The following structure describes an USB DMA tag. */ struct usbd_dma_tag { #ifdef __NetBSD__ bus_dma_segment_t *p_seg; #endif + struct usbd_dma_parent_tag *tag_parent; bus_dma_tag_t tag; + uint32_t align; uint32_t size; #ifdef __NetBSD__ @@ -457,8 +485,8 @@ device_t bdev; /* filled by HC driver */ + struct usbd_dma_parent_tag dma_parent_tag[1]; struct usbd_dma_tag dma_tags[USB_BUS_DMA_TAG_MAX]; - bus_dma_tag_t dma_tag_parent; eventhandler_tag usb_clone_tag; struct usbd_bus_methods *methods; /* filled by HC driver */ @@ -783,6 +811,7 @@ struct usbd_memory_info { LIST_HEAD(, usbd_xfer) dma_head; LIST_HEAD(, usbd_xfer) done_head; + struct usbd_dma_parent_tag dma_parent_tag; struct proc *done_thread; void *memory_base; @@ -793,18 +822,21 @@ struct usbd_page_cache *xfer_page_cache_start; struct usbd_page_cache *xfer_page_cache_end; struct usbd_xfer *dma_curr_xfer; - struct usbd_dma_tag *dma_tag_p; struct usbd_bus *bus; uint32_t memory_size; uint32_t memory_refcount; uint32_t setup_refcount; uint32_t page_size; - uint32_t dma_refcount; + uint32_t dma_nframes; /* number of page caches to load */ + uint32_t dma_currframe; /* currect page cache number */ + uint32_t dma_frlength_0; /* length of page cache zero */ uint8_t dma_error; /* set if virtual memory could not be * loaded */ - uint8_t dma_tag_max; + uint8_t dma_refcount; /* set if we are waiting for a + * callback */ + uint8_t done_sleep; /* set if done thread is sleeping */ }; @@ -1019,9 +1051,9 @@ int usbd_uiomove(struct usbd_page_cache *pc, struct uio *uio, uint32_t pc_offset, uint32_t len); void usbd_copy_out(struct usbd_page_cache *cache, uint32_t offset, void *ptr, uint32_t len); void usbd_bzero(struct usbd_page_cache *cache, uint32_t offset, uint32_t len); -void usbd_dma_tag_create(bus_dma_tag_t tag_parent, struct usbd_dma_tag *udt, uint32_t size, uint32_t align); +void usbd_dma_tag_create(struct usbd_dma_tag *udt, uint32_t size, uint32_t align); void usbd_dma_tag_destroy(struct usbd_dma_tag *udt); -uint8_t usbd_pc_alloc_mem(bus_dma_tag_t parent_tag, struct usbd_dma_tag *utag, struct usbd_page_cache *pc, struct usbd_page *pg, uint32_t size, uint32_t align, uint8_t utag_max); +uint8_t usbd_pc_alloc_mem(struct usbd_page_cache *pc, struct usbd_page *pg, uint32_t size, uint32_t align); void usbd_pc_free_mem(struct usbd_page_cache *pc); void usbd_pc_load_mem(struct usbd_page_cache *pc, uint32_t size); void usbd_pc_cpu_invalidate(struct usbd_page_cache *pc); @@ -1040,10 +1072,11 @@ struct mbuf *usbd_ether_get_mbuf(void); int32_t device_delete_all_children(device_t dev); uint16_t usbd_isoc_time_expand(struct usbd_bus *bus, uint16_t isoc_time_curr); -struct usbd_dma_tag *usbd_dma_tag_setup(bus_dma_tag_t tag_parent, struct usbd_dma_tag *udt, uint32_t size, uint32_t align, uint8_t nudt); -void usbd_dma_tag_unsetup(struct usbd_dma_tag *udt, uint8_t nudt); +void usbd_dma_tag_setup(struct usbd_dma_parent_tag *udpt, struct usbd_dma_tag *udt, bus_dma_tag_t dmat, struct mtx *mtx, usbd_dma_callback_t *func, struct usbd_memory_info *info, uint8_t ndmabits, uint8_t nudt); +struct usbd_dma_tag *usbd_dma_tag_find(struct usbd_dma_parent_tag *updt, uint32_t size, uint32_t align); +void usbd_dma_tag_unsetup(struct usbd_dma_parent_tag *udpt); void usbd_bus_mem_flush_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb); -uint8_t usbd_bus_mem_alloc_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb); +uint8_t usbd_bus_mem_alloc_all(struct usbd_bus *bus, bus_dma_tag_t dmat, usbd_bus_mem_cb_t *cb); void usbd_bus_mem_free_all(struct usbd_bus *bus, usbd_bus_mem_cb_t *cb); uint8_t usbd_transfer_setup_sub_malloc(struct usbd_setup_params *parm, struct usbd_page_search *info, struct usbd_page_cache **ppc, uint32_t size, uint32_t align); struct usbd_device *usbd_bus_port_get_device(struct usbd_bus *bus, struct usbd_port *up); @@ -1094,7 +1127,6 @@ void usbd_transfer_unsetup(struct usbd_xfer **pxfer, uint16_t n_setup); void usbd_std_root_transfer(struct usbd_std_root_transfer *std, usbd_std_root_transfer_func_t *func); void usbd_start_hardware(struct usbd_xfer *xfer); -void usbd_bdma_done_event(struct usbd_memory_info *info); void usbd_bdma_pre_sync(struct usbd_xfer *xfer); void usbd_bdma_post_sync(struct usbd_xfer *xfer); void usbd_transfer_start(struct usbd_xfer *xfer);