From 905666432704a7279a52d28fc5d183c1c0b9c77f Mon Sep 17 00:00:00 2001 From: augustss Date: Tue, 22 Feb 2000 11:30:54 +0000 Subject: [PATCH] Prepare a little for having USB interrupt processing done outside the hard interrupt level (in a thread or a softintr). No real soft processing done yet. --- sys/dev/usb/ohci.c | 41 ++++++++++++++++++++++++++++++++--------- sys/dev/usb/ohcivar.h | 4 +++- sys/dev/usb/uhci.c | 27 ++++++++++++++++++++------- sys/dev/usb/usb.c | 8 +++++++- sys/dev/usb/usbdivar.h | 5 +++-- 5 files changed, 65 insertions(+), 20 deletions(-) diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index fff0c66cf517..7f7c10a13d8d 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -1,4 +1,4 @@ -/* $NetBSD: ohci.c,v 1.71 2000/02/01 05:42:52 augustss Exp $ */ +/* $NetBSD: ohci.c,v 1.72 2000/02/22 11:30:54 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */ /* @@ -130,11 +130,10 @@ static void ohci_shutdown __P((void *v)); static void ohci_power __P((int, void *)); static usbd_status ohci_open __P((usbd_pipe_handle)); static void ohci_poll __P((struct usbd_bus *)); +static void ohci_softintr __P((struct usbd_bus *)); static void ohci_waitintr __P((ohci_softc_t *, usbd_xfer_handle)); static void ohci_rhsc __P((ohci_softc_t *, usbd_xfer_handle)); -static void ohci_process_done __P((ohci_softc_t *, - ohci_physaddr_t)); static usbd_status ohci_device_request __P((usbd_xfer_handle xfer)); static void ohci_add_ed __P((ohci_soft_ed_t *, ohci_soft_ed_t *)); @@ -264,6 +263,7 @@ struct ohci_pipe { static struct usbd_bus_methods ohci_bus_methods = { ohci_open, ohci_poll, + ohci_softintr, ohci_allocm, ohci_freem, ohci_allocx, @@ -990,7 +990,6 @@ ohci_intr1(sc) intrs = 0; done = LE(sc->sc_hcca->hcca_done_head); if (done != 0) { - sc->sc_hcca->hcca_done_head = 0; if (done & ~OHCI_DONE_INTRS) intrs = OHCI_WDH; if (done & OHCI_DONE_INTRS) @@ -1019,7 +1018,21 @@ ohci_intr1(sc) intrs &= ~OHCI_SO; } if (eintrs & OHCI_WDH) { - ohci_process_done(sc, done &~ OHCI_DONE_INTRS); + done &= OHCI_DONE_INTRS; + if (sc->sc_done == 0) + sc->sc_done = done; + else { + /* Tack on at the end of sc_done. */ + ohci_physaddr_t ldone; + ohci_soft_td_t *std; + + for (ldone = sc->sc_done; ldone != 0; + ldone = LE(std->td.td_nexttd)) + std = ohci_hash_find_td(sc, done); + std->td.td_nexttd = LE(done); + } + sc->sc_hcca->hcca_done_head = 0; + usb_schedsoftintr(&sc->sc_bus); intrs &= ~OHCI_WDH; } if (eintrs & OHCI_RD) { @@ -1089,13 +1102,21 @@ char *ohci_cc_strs[] = { #endif void -ohci_process_done(sc, done) - ohci_softc_t *sc; - ohci_physaddr_t done; +ohci_softintr(bus) + struct usbd_bus *bus; { + ohci_softc_t *sc = (ohci_softc_t *)bus; + ohci_physaddr_t done; ohci_soft_td_t *std, *sdone, *stdnext; usbd_xfer_handle xfer; - int len, cc; + int len, cc, s; + + sc->sc_bus.intr_context++; + + s = splhardusb(); + done = sc->sc_done; + sc->sc_done = 0; + splx(s); DPRINTFN(10,("ohci_process_done: done=0x%08lx\n", (u_long)done)); @@ -1175,6 +1196,8 @@ ohci_process_done(sc, done) usb_transfer_complete(xfer); } } + + sc->sc_bus.intr_context--; } void diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index 7a6ecb2fcd8a..e26edf9ff5e9 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: ohcivar.h,v 1.19 2000/02/01 05:42:53 augustss Exp $ */ +/* $NetBSD: ohcivar.h,v 1.20 2000/02/22 11:30:55 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/ohcivar.h,v 1.13 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -102,6 +102,8 @@ typedef struct ohci_softc { usbd_xfer_handle sc_intrxfer; + ohci_physaddr_t sc_done; + char sc_vendor[16]; int sc_id_vendor; diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 6806ded14ef0..42e67eb9d3eb 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1,4 +1,4 @@ -/* $NetBSD: uhci.c,v 1.84 2000/01/28 00:44:27 augustss Exp $ */ +/* $NetBSD: uhci.c,v 1.85 2000/02/22 11:30:55 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */ /* @@ -236,6 +236,7 @@ static void uhci_root_intr_done __P((usbd_xfer_handle)); static usbd_status uhci_open __P((usbd_pipe_handle)); static void uhci_poll __P((struct usbd_bus *)); +static void uhci_softintr __P((struct usbd_bus *)); static usbd_status uhci_device_request __P((usbd_xfer_handle xfer)); @@ -274,6 +275,7 @@ static void uhci_dump_td __P((uhci_soft_td_t *)); struct usbd_bus_methods uhci_bus_methods = { uhci_open, + uhci_softintr, uhci_poll, uhci_allocm, uhci_freem, @@ -950,7 +952,6 @@ uhci_intr(arg) uhci_softc_t *sc = arg; int status; int ack; - uhci_intr_info_t *ii; #ifdef UHCI_DEBUG if (uhcidebug > 15) { @@ -998,8 +999,24 @@ uhci_intr(arg) else /* nothing to acknowledge */ return (0); - sc->sc_bus.intr_context++; sc->sc_bus.no_intrs++; + usb_schedsoftintr(&sc->sc_bus); + + DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev))); + + return (1); +} + +void +uhci_softintr(bus) + struct usbd_bus *bus; +{ + uhci_softc_t *sc = (uhci_softc_t *)bus; + uhci_intr_info_t *ii; + + DPRINTFN(10,("%s: uhci_softintr\n", USBDEVNAME(sc->sc_bus.bdev))); + + sc->sc_bus.intr_context++; /* * Interrupts on UHCI really suck. When the host controller @@ -1015,11 +1032,7 @@ uhci_intr(arg) for (ii = LIST_FIRST(&sc->sc_intrhead); ii; ii = LIST_NEXT(ii, list)) uhci_check_intr(sc, ii); - DPRINTFN(10, ("%s: uhci_intr: exit\n", USBDEVNAME(sc->sc_bus.bdev))); - sc->sc_bus.intr_context--; - - return (1); } /* Check for an interrupt. */ diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 96ba6eaa6552..2fcd398310fa 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -1,4 +1,4 @@ -/* $NetBSD: usb.c,v 1.38 2000/02/02 07:33:59 augustss Exp $ */ +/* $NetBSD: usb.c,v 1.39 2000/02/22 11:30:56 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usb.c,v 1.20 1999/11/17 22:33:46 n_hibma Exp $ */ /* @@ -695,6 +695,12 @@ usb_add_event(type, uep) psignal(usb_async_proc, SIGIO); splx(s); } +void +usb_schedsoftintr(bus) + struct usbd_bus *bus; +{ + bus->methods->soft_intr(bus); +} #if defined(__NetBSD__) || defined(__OpenBSD__) int diff --git a/sys/dev/usb/usbdivar.h b/sys/dev/usb/usbdivar.h index 10bd7177ef16..16d2a6170e74 100644 --- a/sys/dev/usb/usbdivar.h +++ b/sys/dev/usb/usbdivar.h @@ -1,4 +1,4 @@ -/* $NetBSD: usbdivar.h,v 1.46 2000/01/19 01:16:40 augustss Exp $ */ +/* $NetBSD: usbdivar.h,v 1.47 2000/02/22 11:30:56 augustss Exp $ */ /* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */ /* @@ -51,6 +51,7 @@ struct usbd_endpoint { struct usbd_bus_methods { usbd_status (*open_pipe)__P((struct usbd_pipe *pipe)); + void (*soft_intr)__P((struct usbd_bus *)); void (*do_poll)__P((struct usbd_bus *)); usbd_status (*allocm)__P((struct usbd_bus *, usb_dma_t *, u_int32_t bufsize)); @@ -233,8 +234,8 @@ void usb_transfer_complete __P((usbd_xfer_handle xfer)); void usb_disconnect_port __P((struct usbd_port *up, device_ptr_t)); /* Routines from usb.c */ -int usb_bus_count __P((void)); void usb_needs_explore __P((usbd_bus_handle)); +void usb_schedsoftintr __P((struct usbd_bus *)); #ifdef DIAGNOSTIC #define SPLUSBCHECK \