usb with fast interrupts

Scott Long scottl at freebsd.org
Fri Nov 12 13:47:56 PST 2004


M. Warner Losh wrote:
> Our usb system supports soft interrupts, but we currently don't make
> productive use of them.  The following makes interrupts fast
> interrupts and uses taskqueues to queue data to a SWI.
> 
> Lemme know if it works for you.
> 
> Warner
> 

Taskqueues aren't good for timing-sensitive operations.  Even though USB
may not be terribly sensitive, I bet you'll actually see performance
drops with things like umass with this.  Could you instead just put the
real handler into a kthread and wake it up, or use a swi?

Scott

> 
> ------------------------------------------------------------------------
> 
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/ehci_pci.c /shadow/imp/p4/newcard/src/sys/dev/usb/ehci_pci.c
> --- /shadow/imp/p4/src/sys/dev/usb/ehci_pci.c	Sat Nov  6 12:30:30 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/ehci_pci.c	Sat Nov  6 12:18:29 2004
> @@ -282,7 +282,7 @@
>  		sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
>  	}
>  
> -	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
> +	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
>  	    (driver_intr_t *) ehci_intr, sc, &sc->ih);
>  	if (err) {
>  		device_printf(self, "Could not setup irq, %d\n", err);
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/ehcivar.h /shadow/imp/p4/newcard/src/sys/dev/usb/ehcivar.h
> --- /shadow/imp/p4/src/sys/dev/usb/ehcivar.h	Sat Nov  6 12:30:30 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/ehcivar.h	Sat Nov  6 12:18:30 2004
> @@ -145,8 +145,9 @@
>  
>  	usb_callout_t sc_tmo_pcd;
>  
> +#if defined(__NetBSD__) || defined(__OpenBSD__)
>  	device_ptr_t sc_child;		/* /dev/usb# device */
> -
> +#endif
>  	char sc_dying;
>  } ehci_softc_t;
>  
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/ohci_pci.c /shadow/imp/p4/newcard/src/sys/dev/usb/ohci_pci.c
> --- /shadow/imp/p4/src/sys/dev/usb/ohci_pci.c	Sat Nov  6 12:30:30 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/ohci_pci.c	Sat Nov  6 12:18:30 2004
> @@ -281,7 +281,7 @@
>  		sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
>  	}
>  
> -	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
> +	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
>  	    (driver_intr_t *) ohci_intr, sc, &sc->ih);
>  	if (err) {
>  		device_printf(self, "Could not setup irq, %d\n", err);
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/ohcivar.h /shadow/imp/p4/newcard/src/sys/dev/usb/ohcivar.h
> --- /shadow/imp/p4/src/sys/dev/usb/ohcivar.h	Sat Nov  6 12:30:30 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/ohcivar.h	Sat Nov  6 12:18:30 2004
> @@ -147,7 +147,9 @@
>  
>  	usb_callout_t sc_tmo_rhsc;
>  
> +#if defined(__NetBSD__) || defined(__OpenBSD__)
>  	device_ptr_t sc_child;
> +#endif
>  	char sc_dying;
>  } ohci_softc_t;
>  
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/uhci_pci.c /shadow/imp/p4/newcard/src/sys/dev/usb/uhci_pci.c
> --- /shadow/imp/p4/src/sys/dev/usb/uhci_pci.c	Sat Nov  6 12:30:31 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/uhci_pci.c	Sat Nov  6 12:18:30 2004
> @@ -327,7 +327,7 @@
>  		break;
>  	}
>  
> -	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
> +	err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
>  	    (driver_intr_t *) uhci_intr, sc, &sc->ih);
>  	if (err) {
>  		device_printf(self, "Could not setup irq, %d\n", err);
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/uhcivar.h /shadow/imp/p4/newcard/src/sys/dev/usb/uhcivar.h
> --- /shadow/imp/p4/src/sys/dev/usb/uhcivar.h	Sat Nov  6 12:30:31 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/uhcivar.h	Sat Nov  6 12:18:30 2004
> @@ -193,7 +193,9 @@
>  	void *sc_shutdownhook;		/* cookie from shutdown hook */
>  #endif
>  
> +#if defined(__NetBSD__) || defined(__OpenBSD__)
>  	device_ptr_t sc_child;		/* /dev/usb# device */
> +#endif
>  } uhci_softc_t;
>  
>  usbd_status	uhci_init(uhci_softc_t *);
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/usb.c /shadow/imp/p4/newcard/src/sys/dev/usb/usb.c
> --- /shadow/imp/p4/src/sys/dev/usb/usb.c	Sat Nov  6 12:30:32 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/usb.c	Sat Nov  6 12:18:31 2004
> @@ -213,6 +213,17 @@
>  	return (UMATCH_GENERIC);
>  }
>  
> +#if defined(USB_USE_SOFTINTR) && defined(__HAVE_TASKQUEUE)
> +static void
> +usb_taskqueue_fn(void *argp, int pending)
> +{
> +	mtx_lock(&Giant);
> +	usbd_bus_handle bus = argp;
> +	bus->methods->soft_intr(bus);
> +	mtx_unlock(&Giant);
> +}
> +#endif
> +
>  USB_ATTACH(usb)
>  {
>  #if defined(__NetBSD__) || defined(__OpenBSD__)
> @@ -264,6 +275,9 @@
>  	usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
>  
>  #ifdef USB_USE_SOFTINTR
> +#ifdef __HAVE_TASKQUEUE
> +	TASK_INIT(&sc->sc_bus->task, 0, usb_taskqueue_fn, sc->sc_bus);
> +#else
>  #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
>  	/* XXX we should have our own level */
>  	sc->sc_bus->soft = softintr_establish(IPL_SOFTNET,
> @@ -277,6 +291,7 @@
>  	usb_callout_init(sc->sc_bus->softi);
>  #endif
>  #endif
> +#endif
>  
>  	err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, speed, 0,
>  		  &sc->sc_port);
> @@ -745,7 +760,7 @@
>  void
>  usb_needs_explore(usbd_device_handle dev)
>  {
> -	DPRINTFN(2,("usb_needs_explore\n"));
> +	printf("usb_needs_explore\n");
>  	dev->bus->needs_explore = 1;
>  	wakeup(&dev->bus->needs_explore);
>  }
> @@ -847,6 +862,9 @@
>  	if (bus->use_polling) {
>  		bus->methods->soft_intr(bus);
>  	} else {
> +#ifdef __HAVE_TASKQUEUE
> +		taskqueue_enqueue(taskqueue_thread, &bus->task);
> +#else
>  #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
>  		softintr_schedule(bus->soft);
>  #else
> @@ -854,6 +872,7 @@
>  			callout_reset(&bus->softi, 0, bus->methods->soft_intr,
>  			    bus);
>  #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
> +#endif
>  	}
>  #else
>         bus->methods->soft_intr(bus);
> @@ -920,6 +939,9 @@
>  	usbd_finish();
>  
>  #ifdef USB_USE_SOFTINTR
> +#ifdef __HAVE_TASKQUEUE
> +	/* XXX should disestablish this task item */
> +#else
>  #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
>  	if (sc->sc_bus->soft != NULL) {
>  		softintr_disestablish(sc->sc_bus->soft);
> @@ -927,6 +949,7 @@
>  	}
>  #else
>  	callout_stop(&sc->sc_bus->softi);
> +#endif
>  #endif
>  #endif
>  
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/usb_port.h /shadow/imp/p4/newcard/src/sys/dev/usb/usb_port.h
> --- /shadow/imp/p4/src/sys/dev/usb/usb_port.h	Tue Nov  9 17:09:39 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/usb_port.h	Tue Nov  9 17:09:31 2004
> @@ -346,10 +346,9 @@
>  
>  #define USBVERBOSE
>  
> -/* We don't use the soft interrupt code in FreeBSD. */
> -#if 0
>  #define USB_USE_SOFTINTR
> -#endif
> +#define __HAVE_TASKQUEUE
> +#include <sys/taskqueue.h>
>  
>  #define Static static
>  
> @@ -525,7 +524,6 @@
>  SYSCTL_DECL(_hw_usb);
>  #endif
>  
> -#endif /* __FreeBSD__ */
> +#endif /* FreeBSD */
>  
>  #endif /* _USB_PORT_H */
> -
> diff --exclude CVS -I\$Revision -I\$Id -I\$Header -I \$FreeBSD -ur /shadow/imp/p4/src/sys/dev/usb/usbdivar.h /shadow/imp/p4/newcard/src/sys/dev/usb/usbdivar.h
> --- /shadow/imp/p4/src/sys/dev/usb/usbdivar.h	Sat Nov  6 12:30:32 2004
> +++ /shadow/imp/p4/newcard/src/sys/dev/usb/usbdivar.h	Sat Nov  6 12:18:31 2004
> @@ -122,10 +122,14 @@
>  #define USBREV_STR { "unknown", "pre 1.0", "1.0", "1.1", "2.0" }
>  
>  #ifdef USB_USE_SOFTINTR
> +#ifdef __HAVE_TASKQUEUE
> +	struct task		task;
> +#else
>  #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
>  	void		       *soft; /* soft interrupt cookie */
>  #else
>  	struct callout		softi;
> +#endif
>  #endif
>  #endif
>  
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> freebsd-current at freebsd.org mailing list
> http://lists.freebsd.org/mailman/listinfo/freebsd-current
> To unsubscribe, send any mail to "freebsd-current-unsubscribe at freebsd.org"



More information about the freebsd-current mailing list