Each controller freelist finding code is the same - move it to the common code. This also merges the alloc_control and alloc_bulk code paths.
Signed-off-by: Kevin O'Connor kevin@koconnor.net --- src/usb-ehci.c | 35 ++++------------------------------- src/usb-ehci.h | 3 +-- src/usb-ohci.c | 27 ++++++--------------------- src/usb-ohci.h | 3 +-- src/usb-uhci.c | 37 +++++-------------------------------- src/usb-uhci.h | 3 +-- src/usb.c | 41 +++++++++++++++++++++++++---------------- src/usb.h | 1 + 8 files changed, 44 insertions(+), 106 deletions(-)
diff --git a/src/usb-ehci.c b/src/usb-ehci.c index 0678560..6115610 100644 --- a/src/usb-ehci.c +++ b/src/usb-ehci.c @@ -31,7 +31,6 @@ struct ehci_pipe { struct ehci_qtd *next_td, *tds; void *data; struct usb_pipe pipe; - u8 iscontrol; };
@@ -422,31 +421,18 @@ ehci_wait_td(struct ehci_pipe *pipe, struct ehci_qtd *td, int timeout) return 0; }
-static struct usb_pipe * -ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) +struct usb_pipe * +ehci_alloc_async_pipe(struct usb_pipe *dummy) { if (! CONFIG_USB_EHCI) return NULL; struct usb_ehci_s *cntl = container_of( dummy->cntl, struct usb_ehci_s, usb); - dprintf(7, "ehci_alloc_pipe %p %d\n", &cntl->usb, iscontrol); - - struct usb_pipe *freepipe = cntl->usb.freelist; - while (freepipe) { - struct ehci_pipe *pipe = container_of(cntl->usb.freelist - , struct ehci_pipe, pipe); - if (pipe->iscontrol == iscontrol) { - // Use previously allocated queue head. - cntl->usb.freelist = pipe->pipe.freenext; - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); - return &pipe->pipe; - } - freepipe = freepipe->freenext; - } + dprintf(7, "ehci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
// Allocate a new queue head. struct ehci_pipe *pipe; - if (iscontrol) + if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL) pipe = memalign_tmphigh(EHCI_QH_ALIGN, sizeof(*pipe)); else pipe = memalign_low(EHCI_QH_ALIGN, sizeof(*pipe)); @@ -457,7 +443,6 @@ ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) memset(pipe, 0, sizeof(*pipe)); memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); pipe->qh.qtd_next = pipe->qh.alt_next = EHCI_PTR_TERM; - pipe->iscontrol = iscontrol;
// Add queue head to controller list. struct ehci_qh *async_qh = cntl->async_qh; @@ -467,18 +452,6 @@ ehci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) return &pipe->pipe; }
-struct usb_pipe * -ehci_alloc_control_pipe(struct usb_pipe *dummy) -{ - return ehci_alloc_pipe(dummy, 1); -} - -struct usb_pipe * -ehci_alloc_bulk_pipe(struct usb_pipe *dummy) -{ - return ehci_alloc_pipe(dummy, 0); -} - static int fillTDbuffer(struct ehci_qtd *td, u16 maxpacket, const void *buf, int bytes) { diff --git a/src/usb-ehci.h b/src/usb-ehci.h index fd38b73..a4fbb77 100644 --- a/src/usb-ehci.h +++ b/src/usb-ehci.h @@ -4,10 +4,9 @@ // usb-ehci.c int ehci_init(struct pci_device *pci, int busid, struct pci_device *comppci); struct usb_pipe; -struct usb_pipe *ehci_alloc_control_pipe(struct usb_pipe *dummy); +struct usb_pipe *ehci_alloc_async_pipe(struct usb_pipe *dummy); int ehci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); -struct usb_pipe *ehci_alloc_bulk_pipe(struct usb_pipe *dummy); int ehci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); struct usb_pipe *ehci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp); int ehci_poll_intr(struct usb_pipe *p, void *data); diff --git a/src/usb-ohci.c b/src/usb-ohci.c index d77727e..9522309 100644 --- a/src/usb-ohci.c +++ b/src/usb-ohci.c @@ -319,23 +319,17 @@ wait_ed(struct ohci_ed *ed) }
struct usb_pipe * -ohci_alloc_control_pipe(struct usb_pipe *dummy) +ohci_alloc_async_pipe(struct usb_pipe *dummy) { if (! CONFIG_USB_OHCI) return NULL; + if (dummy->eptype != USB_ENDPOINT_XFER_CONTROL) { + dprintf(1, "OHCI Bulk transfers not supported.\n"); + return NULL; + } struct usb_ohci_s *cntl = container_of( dummy->cntl, struct usb_ohci_s, usb); - dprintf(7, "ohci_alloc_control_pipe %p\n", &cntl->usb); - - if (cntl->usb.freelist) { - // Use previously allocated queue head. - struct ohci_pipe *pipe = container_of(cntl->usb.freelist - , struct ohci_pipe, pipe); - cntl->usb.freelist = pipe->pipe.freenext; - - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); - return &pipe->pipe; - } + dprintf(7, "ohci_alloc_async_pipe %p\n", &cntl->usb);
// Allocate a new queue head. struct ohci_pipe *pipe = malloc_tmphigh(sizeof(*pipe)); @@ -415,15 +409,6 @@ ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize return ret; }
-struct usb_pipe * -ohci_alloc_bulk_pipe(struct usb_pipe *dummy) -{ - if (! CONFIG_USB_OHCI) - return NULL; - dprintf(1, "OHCI Bulk transfers not supported.\n"); - return NULL; -} - int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize) { diff --git a/src/usb-ohci.h b/src/usb-ohci.h index 6162d32..6085355 100644 --- a/src/usb-ohci.h +++ b/src/usb-ohci.h @@ -4,10 +4,9 @@ // usb-ohci.c void ohci_init(struct pci_device *pci, int busid); struct usb_pipe; -struct usb_pipe *ohci_alloc_control_pipe(struct usb_pipe *dummy); +struct usb_pipe *ohci_alloc_async_pipe(struct usb_pipe *dummy); int ohci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); -struct usb_pipe *ohci_alloc_bulk_pipe(struct usb_pipe *dummy); int ohci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); struct usb_pipe *ohci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp); int ohci_poll_intr(struct usb_pipe *p, void *data); diff --git a/src/usb-uhci.c b/src/usb-uhci.c index 9d46762..1c911c6 100644 --- a/src/usb-uhci.c +++ b/src/usb-uhci.c @@ -26,7 +26,6 @@ struct uhci_pipe { struct usb_pipe pipe; u16 iobase; u8 toggle; - u8 iscontrol; };
@@ -293,31 +292,18 @@ wait_pipe(struct uhci_pipe *pipe, int timeout) } }
-static struct usb_pipe * -uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) +struct usb_pipe * +uhci_alloc_async_pipe(struct usb_pipe *dummy) { if (! CONFIG_USB_UHCI) return NULL; struct usb_uhci_s *cntl = container_of( dummy->cntl, struct usb_uhci_s, usb); - dprintf(7, "uhci_alloc_pipe %p %d\n", &cntl->usb, iscontrol); - - struct usb_pipe *freepipe = cntl->usb.freelist; - while (freepipe) { - struct uhci_pipe *pipe = container_of(cntl->usb.freelist - , struct uhci_pipe, pipe); - if (pipe->iscontrol == iscontrol) { - // Use previously allocated queue head. - cntl->usb.freelist = pipe->pipe.freenext; - memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); - return &pipe->pipe; - } - freepipe = freepipe->freenext; - } + dprintf(7, "uhci_alloc_async_pipe %p %d\n", &cntl->usb, dummy->eptype);
// Allocate a new queue head. struct uhci_pipe *pipe; - if (iscontrol) + if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL) pipe = malloc_tmphigh(sizeof(*pipe)); else pipe = malloc_low(sizeof(*pipe)); @@ -329,30 +315,17 @@ uhci_alloc_pipe(struct usb_pipe *dummy, int iscontrol) memcpy(&pipe->pipe, dummy, sizeof(pipe->pipe)); pipe->qh.element = UHCI_PTR_TERM; pipe->iobase = cntl->iobase; - pipe->iscontrol = iscontrol;
// Add queue head to controller list. struct uhci_qh *control_qh = cntl->control_qh; pipe->qh.link = control_qh->link; barrier(); control_qh->link = (u32)&pipe->qh | UHCI_PTR_QH; - if (iscontrol) + if (dummy->eptype == USB_ENDPOINT_XFER_CONTROL) cntl->control_qh = &pipe->qh; return &pipe->pipe; }
-struct usb_pipe * -uhci_alloc_control_pipe(struct usb_pipe *dummy) -{ - return uhci_alloc_pipe(dummy, 1); -} - -struct usb_pipe * -uhci_alloc_bulk_pipe(struct usb_pipe *dummy) -{ - return uhci_alloc_pipe(dummy, 0); -} - int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize) diff --git a/src/usb-uhci.h b/src/usb-uhci.h index 59b190d..0706e8f 100644 --- a/src/usb-uhci.h +++ b/src/usb-uhci.h @@ -4,10 +4,9 @@ // usb-uhci.c void uhci_init(struct pci_device *pci, int busid); struct usb_pipe; -struct usb_pipe *uhci_alloc_control_pipe(struct usb_pipe *dummy); +struct usb_pipe *uhci_alloc_async_pipe(struct usb_pipe *dummy); int uhci_control(struct usb_pipe *p, int dir, const void *cmd, int cmdsize , void *data, int datasize); -struct usb_pipe *uhci_alloc_bulk_pipe(struct usb_pipe *dummy); int uhci_send_bulk(struct usb_pipe *p, int dir, void *data, int datasize); struct usb_pipe *uhci_alloc_intr_pipe(struct usb_pipe *dummy, int frameexp); int uhci_poll_intr(struct usb_pipe *p, void *data); diff --git a/src/usb.c b/src/usb.c index e7ee6bc..7c49c6a 100644 --- a/src/usb.c +++ b/src/usb.c @@ -36,19 +36,34 @@ free_pipe(struct usb_pipe *pipe) cntl->freelist = pipe; }
-// Allocate a control pipe to a default endpoint (which can only be -// used by 32bit code) +// Allocate an async pipe (control or bulk). static struct usb_pipe * -alloc_default_control_pipe(struct usb_pipe *dummy) +alloc_async_pipe(struct usb_pipe *dummy) { + // Check for an available pipe on the freelist. + struct usb_pipe **pfree = &dummy->cntl->freelist; + for (;;) { + struct usb_pipe *pipe = *pfree; + if (!pipe) + break; + if (pipe->eptype == dummy->eptype) { + // Use previously allocated pipe. + *pfree = pipe->freenext; + memcpy(pipe, dummy, sizeof(*pipe)); + return pipe; + } + pfree = &pipe->freenext; + } + + // Allocate a new pipe. switch (dummy->type) { default: case USB_TYPE_UHCI: - return uhci_alloc_control_pipe(dummy); + return uhci_alloc_async_pipe(dummy); case USB_TYPE_OHCI: - return ohci_alloc_control_pipe(dummy); + return ohci_alloc_async_pipe(dummy); case USB_TYPE_EHCI: - return ehci_alloc_control_pipe(dummy); + return ehci_alloc_async_pipe(dummy); } }
@@ -84,15 +99,8 @@ alloc_bulk_pipe(struct usb_pipe *pipe, struct usb_endpoint_descriptor *epdesc) { struct usb_pipe dummy; desc2pipe(&dummy, pipe, epdesc); - switch (pipe->type) { - default: - case USB_TYPE_UHCI: - return uhci_alloc_bulk_pipe(&dummy); - case USB_TYPE_OHCI: - return ohci_alloc_bulk_pipe(&dummy); - case USB_TYPE_EHCI: - return ehci_alloc_bulk_pipe(&dummy); - } + dummy.eptype = USB_ENDPOINT_XFER_BULK; + return alloc_async_pipe(&dummy); }
int @@ -253,7 +261,8 @@ usb_set_address(struct usbhub_s *hub, int port, int speed) dummy.type = cntl->type; dummy.maxpacket = 8; dummy.path = (u64)-1; - struct usb_pipe *defpipe = alloc_default_control_pipe(&dummy); + dummy.eptype = USB_ENDPOINT_XFER_CONTROL; + struct usb_pipe *defpipe = alloc_async_pipe(&dummy); if (!defpipe) return NULL; defpipe->speed = speed; diff --git a/src/usb.h b/src/usb.h index 47b25b6..44f8a96 100644 --- a/src/usb.h +++ b/src/usb.h @@ -18,6 +18,7 @@ struct usb_pipe { u16 maxpacket; u8 tt_devaddr; u8 tt_port; + u8 eptype; };
// Common information for usb controllers.