PERFORCE change 130957 for review

Hans Petter Selasky hselasky at FreeBSD.org
Sat Dec 15 09:08:13 PST 2007


http://perforce.freebsd.org/chv.cgi?CH=130957

Change 130957 by hselasky at hselasky_laptop001 on 2007/12/15 17:07:50

	
	This commit is required for USB device side support.
	
	o This commit adds automatic context detection to 
	  "usb_callback_wrapper()", so that you can call the 
	  "usb_callback_wrapper()" from almost everywhere.
	  This leads to a lot of cleanup related to calling
	  callbacks in the EHCI, OHCI and UHCI drivers.
	
	o Optimized "uhci_interrupt()" a little bit.
	
	o The interrupt list where USB transfers are queued
	  has been moved to "struct usbd_bus" so that we can
	  factor out some code.
	
	o Allow all "usbd_bus_mem_xxx" functions to be passed
	  a NULL callback pointer.

Affected files ...

.. //depot/projects/usb/src/sys/dev/usb/ehci.c#62 edit
.. //depot/projects/usb/src/sys/dev/usb/ehci.h#25 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.c#51 edit
.. //depot/projects/usb/src/sys/dev/usb/ohci.h#21 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.c#52 edit
.. //depot/projects/usb/src/sys/dev/usb/uhci.h#21 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.c#70 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_subr.h#75 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.c#70 edit

Differences ...

==== //depot/projects/usb/src/sys/dev/usb/ehci.c#62 (text+ko) ====

@@ -79,7 +79,7 @@
 			       printf x ; } } while (0)
 #define	DPRINTFN(n,x)	do { if (ehcidebug > (n)) { printf("%s: ", __FUNCTION__); \
 			       printf x ; } } while (0)
-int	ehcidebug = 0;
+static int ehcidebug = 0;
 
 SYSCTL_NODE(_hw_usb, OID_AUTO, ehci, CTLFLAG_RW, 0, "USB ehci");
 SYSCTL_INT(_hw_usb_ehci, OID_AUTO, debug, CTLFLAG_RW,
@@ -105,11 +105,11 @@
 extern struct usbd_pipe_methods ehci_root_intr_methods;
 
 static usbd_config_td_command_t ehci_root_ctrl_task;
-static void ehci_root_ctrl_task_td(struct ehci_softc *sc, struct thread *ctd);
 static void ehci_do_poll(struct usbd_bus *bus);
+static void ehci_root_ctrl_poll(struct ehci_softc *sc);
 
 static usbd_std_root_transfer_func_t ehci_root_intr_done;
-static usbd_std_root_transfer_func_t ehci_root_ctrl_task_td_sub;
+static usbd_std_root_transfer_func_t ehci_root_ctrl_done;
 
 struct ehci_std_temp {
 	struct usbd_page_cache *pc;
@@ -213,8 +213,6 @@
 
 	DPRINTF(("start\n"));
 
-	LIST_INIT(&sc->sc_interrupt_list_head);
-
 	usb_callout_init_mtx(&sc->sc_tmo_pcd, &sc->sc_bus.mtx,
 	    CALLOUT_RETURNUNLOCKED);
 
@@ -1280,18 +1278,12 @@
  * Else: USB transfer is finished
  *------------------------------------------------------------------------*/
 static uint8_t
-ehci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
+ehci_check_transfer(struct usbd_xfer *xfer)
 {
 	struct usbd_pipe_methods *methods = xfer->pipe->methods;
 
 	uint32_t status;
 
-	if (xfer->usb_thread != ctd) {
-		/*
-		 * cannot call this transfer back due to locking !
-		 */
-		goto done;
-	}
 	DPRINTFN(12, ("xfer=%p checking transfer\n", xfer));
 
 	if (methods == &ehci_device_isoc_fs_methods) {
@@ -1402,57 +1394,48 @@
 	/* acknowledge any PCD interrupt */
 	EOWRITE4(sc, EHCI_USBSTS, EHCI_STS_PCD);
 
-	if (usbd_std_root_transfer(&(sc->sc_root_intr), NULL,
-	    &ehci_root_intr_done)) {
-		mtx_unlock(&(sc->sc_bus.mtx));
-	}
+	usbd_std_root_transfer(&(sc->sc_root_intr),
+	    &ehci_root_intr_done);
+
+	mtx_unlock(&(sc->sc_bus.mtx));
 	return;
 }
 
 static void
-ehci_interrupt_td(ehci_softc_t *sc, struct thread *ctd)
+ehci_interrupt_poll(ehci_softc_t *sc)
 {
-	enum {
-	FINISH_LIST_MAX = 16};
-
-	struct usbd_xfer *xlist[FINISH_LIST_MAX + 1];
-	struct usbd_xfer **xptr = xlist;
 	struct usbd_xfer *xfer;
-	struct thread *td;
-	uint32_t status;
-	uint8_t need_repeat = 0;
 
-	td = ctd;			/* default value */
-
-	mtx_lock(&sc->sc_bus.mtx);
-
-	/*
-	 * It can happen that an interrupt will be delivered to
-	 * us before the device has been fully attached and the
-	 * softc struct has been configured. Usually this happens
-	 * when kldloading the USB support as a module after the
-	 * system has been booted. If we detect this condition,
-	 * we need to squelch the unwanted interrupts until we're
-	 * ready for them.
-	 */
-	if (sc->sc_bus.bdev == NULL) {
-		goto done;
-	}
-	if (ctd) {
+	LIST_FOREACH(xfer, &sc->sc_bus.intr_list_head, interrupt_list) {
 		/*
-		 * the poll thread should not read any status registers that
-		 * will clear interrupts!
+		 * check if transfer is transferred
 		 */
-		goto repeat;
+		if (ehci_check_transfer(xfer)) {
+			/* queue callback for execution */
+			usbd_callback_wrapper(xfer, NULL, USBD_CONTEXT_CALLBACK);
+		}
 	}
-	td = curthread;			/* NULL is not a valid thread */
+	return;
+}
+
+/*------------------------------------------------------------------------*
+ *	ehci_interrupt - EHCI interrupt handler
+ *
+ * NOTE: Do not access "sc->sc_bus.bdev" inside the interrupt handler,
+ * hence the interrupt handler will be setup before "sc->sc_bus.bdev"
+ * is present !
+ *------------------------------------------------------------------------*/
+void
+ehci_interrupt(ehci_softc_t *sc)
+{
+	uint32_t status;
+
+	mtx_lock(&sc->sc_bus.mtx);
 
-	DPRINTFN(15, ("%s: real interrupt\n",
-	    device_get_nameunit(sc->sc_bus.bdev)));
+	DPRINTFN(15, ("real interrupt\n"));
 
 #ifdef USB_DEBUG
 	if (ehcidebug > 15) {
-		DPRINTF(("%s\n", device_get_nameunit(sc->sc_bus.bdev)));
 		ehci_dump_regs(sc);
 	}
 #endif
@@ -1474,8 +1457,8 @@
 		wakeup(&sc->sc_async_p_last);
 	}
 	if (status & EHCI_STS_HSE) {
-		device_printf(sc->sc_bus.bdev, "unrecoverable error, "
-		    "controller halted\n");
+		printf("%s: unrecoverable error, "
+		    "controller halted\n", __FUNCTION__);
 #ifdef USB_DEBUG
 		ehci_dump_regs(sc);
 		ehci_dump_isoc(sc);
@@ -1489,13 +1472,12 @@
 		sc->sc_eintrs &= ~EHCI_STS_PCD;
 		EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
 
-		if (!usbd_std_root_transfer(&(sc->sc_root_intr), ctd,
-		    &ehci_root_intr_done)) {
-			mtx_lock(&(sc->sc_bus.mtx));
-		}
+		usbd_std_root_transfer(&(sc->sc_root_intr),
+		    &ehci_root_intr_done);
+
 		/* do not allow RHSC interrupts > 1 per second */
 		usb_callout_reset(&sc->sc_tmo_pcd, hz,
-		    (void *)(void *)ehci_pcd_enable, sc);
+		    (void *)&ehci_pcd_enable, sc);
 	}
 	status &= ~(EHCI_STS_INT | EHCI_STS_ERRINT | EHCI_STS_PCD | EHCI_STS_IAA);
 
@@ -1503,69 +1485,24 @@
 		/* block unprocessed interrupts */
 		sc->sc_eintrs &= ~status;
 		EOWRITE4(sc, EHCI_USBINTR, sc->sc_eintrs);
-		device_printf(sc->sc_bus.bdev, "blocking intrs 0x%x\n",
-		    status);
+		printf("%s: blocking interrupts 0x%x\n", __FUNCTION__, status);
 	}
-repeat:
-	LIST_FOREACH(xfer, &sc->sc_interrupt_list_head, interrupt_list) {
-		/*
-		 * check if transfer is transferred
-		 */
-		if (ehci_check_transfer(xfer, ctd)) {
-			/* queue callback */
-
-			*(xptr++) = xfer;
+	/* poll all the USB transfers */
+	ehci_interrupt_poll(sc);
 
-			xfer->usb_thread = td;
-			xfer->usb_root->memory_refcount++;
-
-			/* check queue length */
-			if (xptr >= &xlist[FINISH_LIST_MAX]) {
-				need_repeat = 1;
-				break;
-			}
-		}
-	}
-
 done:
 	mtx_unlock(&sc->sc_bus.mtx);
-
-	/* zero terminate the callback list */
-	*(xptr) = NULL;
-
-	usbd_do_callback(xlist, td);
-
-	if (need_repeat) {
-		xptr = xlist;
-
-		need_repeat = 0;
-
-		mtx_lock(&sc->sc_bus.mtx);
-
-		goto repeat;
-	}
 	return;
 }
 
-void
-ehci_interrupt(ehci_softc_t *sc)
-{
-	ehci_interrupt_td(sc, NULL);
-	return;
-}
-
 /*
  * called when a request does not complete
  */
 static void
 ehci_timeout(struct usbd_xfer *xfer)
 {
-	struct thread *td;
-	struct usbd_xfer *xlist[2];
 	ehci_softc_t *sc = xfer->usb_sc;
 
-	td = curthread;
-
 	DPRINTF(("xfer=%p\n", xfer));
 
 	mtx_assert(&sc->sc_bus.mtx, MA_OWNED);
@@ -1573,17 +1510,11 @@
 	/* transfer is transferred */
 	ehci_device_done(xfer, USBD_TIMEOUT);
 
-	/* queue callback */
-	xlist[0] = xfer;
-	xlist[1] = NULL;
-
-	xfer->usb_thread = td;
-	xfer->usb_root->memory_refcount++;
+	/* queue callback for execution */
+	usbd_callback_wrapper(xfer, NULL, USBD_CONTEXT_CALLBACK);
 
 	mtx_unlock(&sc->sc_bus.mtx);
 
-	usbd_do_callback(xlist, td);
-
 	return;
 }
 
@@ -1591,29 +1522,15 @@
 ehci_do_poll(struct usbd_bus *bus)
 {
 	struct ehci_softc *sc = EHCI_BUS2SC(bus);
-	struct thread *ctd = curthread;
 
-	ehci_interrupt_td(sc, ctd);
 	mtx_lock(&(sc->sc_bus.mtx));
-	ehci_root_ctrl_task_td(sc, ctd);
+	ehci_interrupt_poll(sc);
+	ehci_root_ctrl_poll(sc);
 	mtx_unlock(&(sc->sc_bus.mtx));
 	return;
 }
 
-#define	ehci_add_interrupt_info(sc, xfer) \
-	LIST_INSERT_HEAD(&(sc)->sc_interrupt_list_head, (xfer), interrupt_list)
-
 static void
-ehci_remove_interrupt_info(struct usbd_xfer *xfer)
-{
-	if ((xfer)->interrupt_list.le_prev) {
-		LIST_REMOVE((xfer), interrupt_list);
-		(xfer)->interrupt_list.le_prev = NULL;
-	}
-	return;
-}
-
-static void
 ehci_setup_standard_chain_sub(struct ehci_std_temp *temp)
 {
 	struct usbd_page_search buf_res;
@@ -2227,12 +2144,6 @@
 		xfer->td_transfer_first = NULL;
 		xfer->td_transfer_last = NULL;
 	}
-	/* stop timeout */
-	usb_callout_stop(&xfer->timeout_handle);
-
-	/* remove interrupt info (if any) */
-	ehci_remove_interrupt_info(xfer);
-
 	if ((methods != &ehci_root_ctrl_methods) &&
 	    (methods != &ehci_root_intr_methods)) {
 
@@ -2329,7 +2240,7 @@
 	ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
 
 	/**/
-	ehci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	if (xfer->timeout && (!xfer->flags.use_polling)) {
 		usb_callout_reset(&xfer->timeout_handle, USBD_MS_TO_TICKS(xfer->timeout),
@@ -2379,7 +2290,7 @@
 	ehci_setup_standard_chain(xfer, &sc->sc_async_p_last);
 
 	/**/
-	ehci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	if (xfer->timeout && (!xfer->flags.use_polling)) {
 		usb_callout_reset(&xfer->timeout_handle, USBD_MS_TO_TICKS(xfer->timeout),
@@ -2485,7 +2396,7 @@
 	ehci_setup_standard_chain(xfer, &sc->sc_intr_p_last[xfer->qh_pos]);
 
 	/**/
-	ehci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	if (xfer->timeout && (!xfer->flags.use_polling)) {
 		usb_callout_reset(&xfer->timeout_handle, USBD_MS_TO_TICKS(xfer->timeout),
@@ -2741,7 +2652,7 @@
 	    (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
 
 	/**/
-	ehci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	/*
 	 * enqueue transfer (so that it can be aborted through pipe abort)
@@ -3020,7 +2931,7 @@
 	    (EHCI_VIRTUAL_FRAMELIST_COUNT - 1);
 
 	/**/
-	ehci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	/*
 	 * enqueue transfer (so that it can be aborted through pipe abort)
@@ -3192,12 +3103,12 @@
 ehci_root_ctrl_task(struct ehci_softc *sc,
     struct ehci_config_copy *cc, uint16_t refcount)
 {
-	ehci_root_ctrl_task_td(sc, NULL);
+	ehci_root_ctrl_poll(sc);
 	return;
 }
 
 static void
-ehci_root_ctrl_task_td_sub(struct usbd_xfer *xfer,
+ehci_root_ctrl_done(struct usbd_xfer *xfer,
     struct usbd_std_root_transfer *std)
 {
 	struct ehci_softc *sc = xfer->usb_sc;
@@ -3592,12 +3503,10 @@
 }
 
 static void
-ehci_root_ctrl_task_td(struct ehci_softc *sc, struct thread *ctd)
+ehci_root_ctrl_poll(struct ehci_softc *sc)
 {
-	if (!usbd_std_root_transfer(&(sc->sc_root_ctrl), ctd,
-	    &ehci_root_ctrl_task_td_sub)) {
-		mtx_lock(&sc->sc_bus.mtx);
-	}
+	usbd_std_root_transfer(&(sc->sc_root_ctrl),
+	    &ehci_root_ctrl_done);
 	return;
 }
 

==== //depot/projects/usb/src/sys/dev/usb/ehci.h#25 (text+ko) ====

@@ -443,7 +443,6 @@
 	struct usbd_bus sc_bus;		/* base device */
 	struct usbd_config_td sc_config_td;
 	struct usb_callout sc_tmo_pcd;
-	LIST_HEAD(, usbd_xfer) sc_interrupt_list_head;
 	union ehci_hub_desc sc_hub_desc;
 	struct usbd_std_root_transfer sc_root_ctrl;
 	struct usbd_std_root_transfer sc_root_intr;

==== //depot/projects/usb/src/sys/dev/usb/ohci.c#51 (text+ko) ====

@@ -84,7 +84,7 @@
 #undef DPRINTFN
 #define	DPRINTF(x)	do { if (ohcidebug) { printf("%s: ", __FUNCTION__); printf x ; } } while (0)
 #define	DPRINTFN(n,x)	do { if (ohcidebug > (n)) { printf("%s: ", __FUNCTION__); printf x ; } } while (0)
-int	ohcidebug = 0;
+static int ohcidebug = 0;
 
 SYSCTL_NODE(_hw_usb, OID_AUTO, ohci, CTLFLAG_RW, 0, "USB ohci");
 SYSCTL_INT(_hw_usb_ohci, OID_AUTO, debug, CTLFLAG_RW,
@@ -121,12 +121,12 @@
 extern struct usbd_pipe_methods ohci_root_intr_methods;
 
 static usbd_config_td_command_t ohci_root_ctrl_task;
-static void ohci_root_ctrl_task_td(struct ohci_softc *sc, struct thread *ctd);
+static void ohci_root_ctrl_poll(struct ohci_softc *sc);
 static void ohci_do_poll(struct usbd_bus *bus);
 static void ohci_device_done(struct usbd_xfer *xfer, usbd_status_t error);
 
 static usbd_std_root_transfer_func_t ohci_root_intr_done;
-static usbd_std_root_transfer_func_t ohci_root_ctrl_task_td_sub;
+static usbd_std_root_transfer_func_t ohci_root_ctrl_done;
 
 struct ohci_std_temp {
 	struct usbd_page_cache *pc;
@@ -412,8 +412,6 @@
 
 	usbd_bus_mem_flush_all(&(sc->sc_bus), &ohci_iterate_hw_softc);
 
-	LIST_INIT(&sc->sc_interrupt_list_head);
-
 	/* set up the bus struct */
 	sc->sc_bus.methods = &ohci_bus_methods;
 
@@ -1055,19 +1053,13 @@
  * Else: USB transfer is finished
  *------------------------------------------------------------------------*/
 static uint8_t
-ohci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
+ohci_check_transfer(struct usbd_xfer *xfer)
 {
 	ohci_ed_t *ed = xfer->qh_start;
 	uint32_t ed_flags;
 	uint32_t ed_headp;
 	uint32_t ed_tailp;
 
-	if (xfer->usb_thread != ctd) {
-		/*
-		 * cannot call this transfer back due to locking !
-		 */
-		return (0);
-	}
 	DPRINTFN(12, ("xfer=%p checking transfer\n", xfer));
 
 	usbd_pc_cpu_invalidate(ed->page_cache);
@@ -1118,54 +1110,52 @@
 	/* acknowledge any RHSC interrupt */
 	OWRITE4(sc, OHCI_INTERRUPT_STATUS, OHCI_RHSC);
 
-	if (usbd_std_root_transfer(&(sc->sc_root_intr), NULL,
-	    &ohci_root_intr_done)) {
-		mtx_unlock(&(sc->sc_bus.mtx));
-	}
+	usbd_std_root_transfer(&(sc->sc_root_intr),
+	    &ohci_root_intr_done);
+
+	mtx_unlock(&(sc->sc_bus.mtx));
 	return;
 }
 
 static void
-ohci_interrupt_td(ohci_softc_t *sc, struct thread *ctd)
+ohci_interrupt_poll(ohci_softc_t *sc)
 {
-	enum {
-		FINISH_LIST_MAX = 16,
-	};
+	struct usbd_xfer *xfer;
+
+	LIST_FOREACH(xfer, &(sc->sc_bus.intr_list_head), interrupt_list) {
+		/*
+		 * check if transfer is transferred
+		 */
+		if (ohci_check_transfer(xfer)) {
+			/* queue callback for execution */
+			usbd_callback_wrapper(xfer, NULL, USBD_CONTEXT_CALLBACK);
+		}
+	}
+	return;
+}
 
-	struct usbd_xfer *xlist[FINISH_LIST_MAX + 1];
-	struct usbd_xfer **xptr = xlist;
+/*------------------------------------------------------------------------*
+ *	ohci_interrupt - OHCI interrupt handler
+ *
+ * NOTE: Do not access "sc->sc_bus.bdev" inside the interrupt handler,
+ * hence the interrupt handler will be setup before "sc->sc_bus.bdev"
+ * is present !
+ *------------------------------------------------------------------------*/
+void
+ohci_interrupt(ohci_softc_t *sc)
+{
 	struct ohci_hcca *hcca;
-	struct usbd_xfer *xfer;
-	struct thread *td;
 	uint32_t status;
 	uint32_t done;
-	uint8_t need_repeat = 0;
 
-	td = ctd;			/* default value */
-
 	mtx_lock(&sc->sc_bus.mtx);
 
-	if (sc->sc_bus.bdev == NULL) {
-		/* too early interrupt */
-		goto done;
-	}
-	if (ctd) {
-		/*
-		 * the poll thread should not read any status registers that
-		 * will clear interrupts!
-		 */
-		goto repeat;
-	}
-	td = curthread;			/* NULL is not a valid thread */
-
 	hcca = ohci_get_hcca(sc);
 
-	DPRINTFN(15, ("%s: real interrupt\n",
-	    device_get_nameunit(sc->sc_bus.bdev)));
+	DPRINTFN(15, ("real interrupt\n"));
 
 #ifdef USB_DEBUG
 	if (ohcidebug > 15) {
-		DPRINTF(("%s:\n", device_get_nameunit(sc->sc_bus.bdev)));
 		ohci_dumpregs(sc);
 	}
 #endif
@@ -1221,12 +1211,12 @@
 		}
 #endif
 		if (status & OHCI_RD) {
-			device_printf(sc->sc_bus.bdev, "resume detect\n");
+			printf("%s: resume detect\n", __FUNCTION__);
 			/* XXX process resume detect */
 		}
 		if (status & OHCI_UE) {
-			device_printf(sc->sc_bus.bdev, "unrecoverable error, "
-			    "controller halted\n");
+			printf("%s: unrecoverable error, "
+			    "controller halted\n", __FUNCTION__);
 			OWRITE4(sc, OHCI_CONTROL, OHCI_HCFS_RESET);
 			/* XXX what else */
 		}
@@ -1238,13 +1228,12 @@
 			sc->sc_eintrs &= ~OHCI_RHSC;
 			OWRITE4(sc, OHCI_INTERRUPT_DISABLE, OHCI_RHSC);
 
-			if (!usbd_std_root_transfer(&(sc->sc_root_intr), ctd,
-			    &ohci_root_intr_done)) {
-				mtx_lock(&(sc->sc_bus.mtx));
-			}
+			usbd_std_root_transfer(&(sc->sc_root_intr),
+			    &ohci_root_intr_done);
+
 			/* do not allow RHSC interrupts > 1 per second */
 			usb_callout_reset(&sc->sc_tmo_rhsc, hz,
-			    (void *)(void *)ohci_rhsc_enable, sc);
+			    (void *)&ohci_rhsc_enable, sc);
 		}
 	}
 	status &= ~(OHCI_RHSC | OHCI_WDH | OHCI_SO);
@@ -1252,73 +1241,25 @@
 		/* Block unprocessed interrupts. XXX */
 		OWRITE4(sc, OHCI_INTERRUPT_DISABLE, status);
 		sc->sc_eintrs &= ~status;
-		device_printf(sc->sc_bus.bdev,
-		    "blocking intrs 0x%x\n", status);
+		printf("%s: blocking intrs 0x%x\n",
+		    __FUNCTION__, status);
 	}
-	/*
-	 * when the host controller interrupts because a transfer
-	 * is completed, all active transfers are checked!
-	 */
+	/* poll all the USB transfers */
+	ohci_interrupt_poll(sc);
 
-repeat:
-	LIST_FOREACH(xfer, &sc->sc_interrupt_list_head, interrupt_list) {
-		/*
-		 * check if transfer is transferred
-		 */
-		if (ohci_check_transfer(xfer, ctd)) {
-			/* queue callback */
-
-			*(xptr++) = xfer;
-
-			xfer->usb_thread = td;
-			xfer->usb_root->memory_refcount++;
-
-			/* check queue length */
-			if (xptr >= &xlist[FINISH_LIST_MAX]) {
-				need_repeat = 1;
-				break;
-			}
-		}
-	}
-
 done:
 	mtx_unlock(&sc->sc_bus.mtx);
-
-	/* zero terminate the callback list */
-	*(xptr) = NULL;
-
-	usbd_do_callback(xlist, td);
-
-	if (need_repeat) {
-		xptr = xlist;
-
-		need_repeat = 0;
-		mtx_lock(&sc->sc_bus.mtx);
-
-		goto repeat;
-	}
 	return;
 }
 
-void
-ohci_interrupt(ohci_softc_t *sc)
-{
-	ohci_interrupt_td(sc, NULL);
-	return;
-}
-
 /*
  * called when a request does not complete
  */
 static void
 ohci_timeout(struct usbd_xfer *xfer)
 {
-	struct thread *td;
-	struct usbd_xfer *xlist[2];
 	ohci_softc_t *sc = xfer->usb_sc;
 
-	td = curthread;
-
 	DPRINTF(("xfer=%p\n", xfer));
 
 	mtx_assert(&sc->sc_bus.mtx, MA_OWNED);
@@ -1326,17 +1267,11 @@
 	/* transfer is transferred */
 	ohci_device_done(xfer, USBD_TIMEOUT);
 
-	/* queue callback */
-	xlist[0] = xfer;
-	xlist[1] = NULL;
-
-	xfer->usb_thread = td;
-	xfer->usb_root->memory_refcount++;
+	/* queue callback for execution */
+	usbd_callback_wrapper(xfer, NULL, USBD_CONTEXT_CALLBACK);
 
 	mtx_unlock(&sc->sc_bus.mtx);
 
-	usbd_do_callback(xlist, td);
-
 	return;
 }
 
@@ -1344,28 +1279,14 @@
 ohci_do_poll(struct usbd_bus *bus)
 {
 	struct ohci_softc *sc = OHCI_BUS2SC(bus);
-	struct thread *ctd = curthread;
 
-	ohci_interrupt_td(sc, ctd);
 	mtx_lock(&(sc->sc_bus.mtx));
-	ohci_root_ctrl_task_td(sc, ctd);
+	ohci_interrupt_poll(sc);
+	ohci_root_ctrl_poll(sc);
 	mtx_unlock(&(sc->sc_bus.mtx));
 	return;
 }
 
-#define	ohci_add_interrupt_info(sc, xfer) \
-	LIST_INSERT_HEAD(&(sc)->sc_interrupt_list_head, (xfer), interrupt_list)
-
-static void
-ohci_remove_interrupt_info(struct usbd_xfer *xfer)
-{
-	if ((xfer)->interrupt_list.le_prev) {
-		LIST_REMOVE((xfer), interrupt_list);
-		(xfer)->interrupt_list.le_prev = NULL;
-	}
-	return;
-}
-
 static void
 ohci_setup_standard_chain_sub(struct ohci_std_temp *temp)
 {
@@ -1765,12 +1686,6 @@
 	xfer->td_transfer_first = NULL;
 	xfer->td_transfer_last = NULL;
 
-	/* stop timeout */
-	usb_callout_stop(&xfer->timeout_handle);
-
-	/* remove interrupt info */
-	ohci_remove_interrupt_info(xfer);
-
 	if ((methods != &ohci_root_ctrl_methods) &&
 	    (methods != &ohci_root_intr_methods)) {
 
@@ -1820,7 +1735,7 @@
 	ohci_setup_standard_chain(xfer, &sc->sc_bulk_p_last);
 
 	/**/
-	ohci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	if (xfer->timeout && (!(xfer->flags.use_polling))) {
 		usb_callout_reset(&xfer->timeout_handle, USBD_MS_TO_TICKS(xfer->timeout),
@@ -1870,7 +1785,7 @@
 	ohci_setup_standard_chain(xfer, &sc->sc_ctrl_p_last);
 
 	/**/
-	ohci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	if (xfer->timeout && (!(xfer->flags.use_polling))) {
 		usb_callout_reset(&xfer->timeout_handle, USBD_MS_TO_TICKS(xfer->timeout),
@@ -1952,7 +1867,7 @@
 	ohci_setup_standard_chain(xfer, &sc->sc_intr_p_last[xfer->qh_pos]);
 
 	/**/
-	ohci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	if (xfer->timeout && (!(xfer->flags.use_polling))) {
 		usb_callout_reset(&xfer->timeout_handle, USBD_MS_TO_TICKS(xfer->timeout),
@@ -2151,7 +2066,7 @@
 	OHCI_APPEND_QH(ed, td->itd_self, sc->sc_isoc_p_last);
 
 	/**/
-	ohci_add_interrupt_info(sc, xfer);
+	usbd_transfer_intr_enqueue(xfer);
 
 	/*
 	 * enqueue transfer (so that it can be aborted through pipe abort)
@@ -2296,12 +2211,12 @@
 ohci_root_ctrl_task(struct ohci_softc *sc,
     struct ohci_config_copy *cc, uint16_t refcount)
 {
-	ohci_root_ctrl_task_td(sc, NULL);
+	ohci_root_ctrl_poll(sc);
 	return;
 }
 
 static void
-ohci_root_ctrl_task_td_sub(struct usbd_xfer *xfer,
+ohci_root_ctrl_done(struct usbd_xfer *xfer,
     struct usbd_std_root_transfer *std)
 {
 	ohci_softc_t *sc = xfer->usb_sc;
@@ -2604,12 +2519,10 @@
 }
 
 static void
-ohci_root_ctrl_task_td(struct ohci_softc *sc, struct thread *ctd)
+ohci_root_ctrl_poll(struct ohci_softc *sc)
 {
-	if (!usbd_std_root_transfer(&(sc->sc_root_ctrl), ctd,
-	    &ohci_root_ctrl_task_td_sub)) {
-		mtx_lock(&sc->sc_bus.mtx);
-	}
+	usbd_std_root_transfer(&(sc->sc_root_ctrl),
+	    &ohci_root_ctrl_done);
 	return;
 }
 

==== //depot/projects/usb/src/sys/dev/usb/ohci.h#21 (text+ko) ====

@@ -320,7 +320,6 @@
 	struct usbd_bus sc_bus;		/* base device */
 	struct usbd_config_td sc_config_td;
 	struct usb_callout sc_tmo_rhsc;
-	LIST_HEAD(, usbd_xfer) sc_interrupt_list_head;
 	union ohci_hub_desc sc_hub_desc;
 	struct usbd_std_root_transfer sc_root_ctrl;
 	struct usbd_std_root_transfer sc_root_intr;

==== //depot/projects/usb/src/sys/dev/usb/uhci.c#52 (text+ko) ====

@@ -87,8 +87,8 @@
 #undef DPRINTFN
 #define	DPRINTF(x)	do { if (uhcidebug) { printf("%s: ", __FUNCTION__); printf x ; } } while (0)
 #define	DPRINTFN(n,x)	do { if (uhcidebug > (n)) { printf("%s: ", __FUNCTION__); printf x ; } } while (0)
-int	uhcidebug = 0;
-int	uhcinoloop = 0;
+static int uhcidebug = 0;
+static int uhcinoloop = 0;
 
 SYSCTL_NODE(_hw_usb, OID_AUTO, uhci, CTLFLAG_RW, 0, "USB uhci");
 SYSCTL_INT(_hw_usb_uhci, OID_AUTO, debug, CTLFLAG_RW,
@@ -158,7 +158,7 @@
 extern struct usbd_pipe_methods uhci_root_intr_methods;
 
 static usbd_config_td_command_t uhci_root_ctrl_task;
-static void uhci_root_ctrl_task_td(struct uhci_softc *sc, struct thread *ctd);
+static void uhci_root_ctrl_poll(struct uhci_softc *sc);
 static void uhci_do_poll(struct usbd_bus *bus);
 static void uhci_device_done(struct usbd_xfer *xfer, usbd_status_t error);
 
@@ -618,8 +618,6 @@
 
 	usbd_bus_mem_flush_all(&(sc->sc_bus), &uhci_iterate_hw_softc);
 
-	LIST_INIT(&sc->sc_interrupt_list_head);
-
 	/* set up the bus struct */
 	sc->sc_bus.methods = &uhci_bus_methods;
 
@@ -852,20 +850,6 @@
 	return;
 }
 
-#if 0
-static void
-uhci_dump_iis(struct uhci_softc *sc)
-{
-	struct usbd_xfer *xfer;
-
-	printf("interrupt list:\n");
-	LIST_FOREACH(xfer, &sc->sc_interrupt_list_head, interrupt_list) {
-		usbd_dump_xfer(xfer);
-	}
-	return;
-}
-
-#endif
 #endif
 
 /*
@@ -1341,18 +1325,12 @@
  * Else: USB transfer is finished
  *------------------------------------------------------------------------*/
 static uint8_t
-uhci_check_transfer(struct usbd_xfer *xfer, struct thread *ctd)
+uhci_check_transfer(struct usbd_xfer *xfer)
 {
 	uint32_t status;
 	uint32_t token;
 	uhci_td_t *td;
 
-	if (xfer->usb_thread != ctd) {
-		/*
-		 * cannot call this transfer back due to locking !
-		 */
-		goto done;
-	}
 	DPRINTFN(15, ("xfer=%p checking transfer\n", xfer));
 
 	if (xfer->pipe->methods == &uhci_device_isoc_methods) {
@@ -1436,54 +1414,40 @@
 }
 
 static void
-uhci_interrupt_td(uhci_softc_t *sc, struct thread *ctd)
+uhci_interrupt_poll(uhci_softc_t *sc)
 {
-	enum {
-	FINISH_LIST_MAX = 16};
-
-	struct usbd_xfer *xlist[FINISH_LIST_MAX + 1];
-	struct usbd_xfer **xptr = xlist;
 	struct usbd_xfer *xfer;
-	struct thread *td;
-	uint32_t status;
-	uint8_t need_repeat = 0;
 
-	td = ctd;			/* default value */
-
-	mtx_lock(&sc->sc_bus.mtx);
-
-	/*
-	 * It can happen that an interrupt will be delivered to
-	 * us before the device has been fully attached and the
-	 * softc struct has been configured. Usually this happens
-	 * when kldloading the USB support as a module after the
-	 * system has been booted. If we detect this condition,
-	 * we need to squelch the unwanted interrupts until we're
-	 * ready for them.
-	 */
-	if (sc->sc_bus.bdev == NULL) {	/* XXX */
-#if 0
-		UWRITE2(sc, UHCI_STS, 0xFFFF);	/* ack pending interrupts */
-		uhci_reset(sc);		/* stop the controller */
-		UWRITE2(sc, UHCI_INTR, 0);	/* disable interrupts */
-#endif
-		goto done;
-	}
-	if (ctd) {
+	LIST_FOREACH(xfer, &(sc->sc_bus.intr_list_head), interrupt_list) {
 		/*
-		 * the poll thread should not read any status registers that
-		 * will clear interrupts!
+		 * check if transfer is transferred
 		 */
-		goto repeat;
+		if (uhci_check_transfer(xfer)) {
+			/* queue callback for execution */
+			usbd_callback_wrapper(xfer, NULL, USBD_CONTEXT_CALLBACK);
+		}
 	}
-	td = curthread;			/* NULL is not a valid thread */
+	return;
+}
+
+/*------------------------------------------------------------------------*
+ *	uhci_interrupt - UHCI interrupt handler
+ *
+ * NOTE: Do not access "sc->sc_bus.bdev" inside the interrupt handler,
+ * hence the interrupt handler will be setup before "sc->sc_bus.bdev"
+ * is present !
+ *------------------------------------------------------------------------*/
+void
+uhci_interrupt(uhci_softc_t *sc)
+{
+	uint32_t status;
+
+	mtx_lock(&sc->sc_bus.mtx);
 
-	DPRINTFN(15, ("%s: real interrupt\n",
-	    device_get_nameunit(sc->sc_bus.bdev)));
+	DPRINTFN(15, ("real interrupt\n"));
 
 #ifdef USB_DEBUG
 	if (uhcidebug > 15) {
-		DPRINTF(("%s\n", device_get_nameunit(sc->sc_bus.bdev)));
 		uhci_dumpregs(sc);
 	}
 #endif
@@ -1492,27 +1456,31 @@
 		/* the interrupt was not for us */
 		goto done;
 	}
-	if (status & UHCI_STS_RD) {
+	if (status & (UHCI_STS_RD | UHCI_STS_HSE |
+	    UHCI_STS_HCPE | UHCI_STS_HCH)) {
+
+		if (status & UHCI_STS_RD) {
 #ifdef USB_DEBUG
-		device_printf(sc->sc_bus.bdev,
-		    "resume detect\n");
+			printf("%s: resume detect\n",
+			    __FUNCTION__);
 #endif
-	}
-	if (status & UHCI_STS_HSE) {
-		device_printf(sc->sc_bus.bdev,
-		    "host system error\n");
-	}
-	if (status & UHCI_STS_HCPE) {
-		device_printf(sc->sc_bus.bdev,
-		    "host controller process error\n");
-	}
-	if (status & UHCI_STS_HCH) {

>>> TRUNCATED FOR MAIL (1000 lines) <<<


More information about the p4-projects mailing list