]> git.neil.brown.name Git - history.git/commitdiff
[PATCH] HCDs support new DMA APIs (part 1 of 2)
authorDavid Brownell <david-b@pacbell.net>
Tue, 13 Aug 2002 06:09:05 +0000 (23:09 -0700)
committerGreg Kroah-Hartman <greg@kroah.com>
Tue, 13 Aug 2002 06:09:05 +0000 (23:09 -0700)
-  teaches the hardware-specific code to
   use urb->*_dma instead of creating mappings.
   (And tells ohci-sa1111 to init its buffer pools.)
   EHCI and UHCI also eliminated duplicated state;
   all the HCDs are now a smidgeon smaller.

Sanity checked by enumerating, including through
a hub, and using a USB Ethernet adapter, with each
of the three host controllers.

Worth noting:  this removes pci_dma_sync_single()
calls from UHCI.  On x86 (and some others) that's
a NOP, but for UHCI on other platforms (rare except
maybe on IA64, as I understand) this anticipates
the upcoming patch to remove interrupt automagic.
(I'll likely submit that after a Linus release that
catches up to your USB tree. :)

drivers/usb/host/ehci-q.c
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci.h
drivers/usb/host/ohci-q.c
drivers/usb/host/ohci-sa1111.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.h

index e0426d675d6014b04ec9ffaff1fce164073bceaf..7c401d7d2c60cff12308c522494580426ea230b4 100644 (file)
@@ -163,7 +163,6 @@ static inline void qtd_copy_status (struct urb *urb, size_t length, u32 token)
 
 static void ehci_urb_done (
        struct ehci_hcd         *ehci,
-       dma_addr_t              addr,
        struct urb              *urb
 ) {
 #ifdef INTR_AUTOMAGIC
@@ -171,13 +170,6 @@ static void ehci_urb_done (
        struct usb_device       *dev = 0;
 #endif
 
-       if (urb->transfer_buffer_length)
-               pci_unmap_single (ehci->hcd.pdev,
-                       addr,
-                       urb->transfer_buffer_length,
-                       usb_pipein (urb->pipe)
-                           ? PCI_DMA_FROMDEVICE
-                           : PCI_DMA_TODEVICE);
        if (likely (urb->hcpriv != 0)) {
                struct ehci_qh  *qh = (struct ehci_qh *) urb->hcpriv;
 
@@ -263,7 +255,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                        if (likely (last->urb != urb)) {
                                /* complete() can reenter this HCD */
                                spin_unlock_irqrestore (&ehci->lock, flags);
-                               ehci_urb_done (ehci, last->buf_dma, last->urb);
+                               ehci_urb_done (ehci, last->urb);
                                spin_lock_irqsave (&ehci->lock, flags);
                        }
 
@@ -347,12 +339,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
                                urb, urb->status, qtd, token,
                                urb->actual_length);
 #endif
-
-               /* SETUP for control urb? */
-               if (unlikely (QTD_PID (token) == 2))
-                       pci_unmap_single (ehci->hcd.pdev,
-                               qtd->buf_dma, sizeof (struct usb_ctrlrequest),
-                               PCI_DMA_TODEVICE);
        }
 
        /* patch up list head? */
@@ -364,7 +350,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
 
        /* last urb's completion might still need calling */
        if (likely (last != 0)) {
-               ehci_urb_done (ehci, last->buf_dma, last->urb);
+               ehci_urb_done (ehci, last->urb);
                ehci_qtd_free (ehci, last);
        }
 }
@@ -405,10 +391,6 @@ static void qtd_list_free (
                                size = qtd->urb->transfer_buffer_length;
                                unmapped++;
                        }
-                       if (qtd->buf_dma)
-                               pci_unmap_single (ehci->hcd.pdev,
-                                       qtd->buf_dma,
-                                       size, direction);
                }
                ehci_qtd_free (ehci, qtd);
        }
@@ -425,7 +407,7 @@ qh_urb_transaction (
        int                     flags
 ) {
        struct ehci_qtd         *qtd, *qtd_prev;
-       dma_addr_t              buf, map_buf;
+       dma_addr_t              buf;
        int                     len, maxpacket;
        int                     is_input;
        u32                     token;
@@ -445,17 +427,8 @@ qh_urb_transaction (
        /* for split transactions, SplitXState initialized to zero */
 
        if (usb_pipecontrol (urb->pipe)) {
-               /* control request data is passed in the "setup" pid */
-               qtd->buf_dma = pci_map_single (
-                                       ehci->hcd.pdev,
-                                       urb->setup_packet,
-                                       sizeof (struct usb_ctrlrequest),
-                                       PCI_DMA_TODEVICE);
-               if (unlikely (!qtd->buf_dma))
-                       goto cleanup;
-
                /* SETUP pid */
-               qtd_fill (qtd, qtd->buf_dma, sizeof (struct usb_ctrlrequest),
+               qtd_fill (qtd, urb->setup_dma, sizeof (struct usb_ctrlrequest),
                        token | (2 /* "setup" */ << 8));
 
                /* ... and always at least one more pid */
@@ -474,16 +447,10 @@ qh_urb_transaction (
         */
        len = urb->transfer_buffer_length;
        is_input = usb_pipein (urb->pipe);
-       if (likely (len > 0)) {
-               buf = map_buf = pci_map_single (ehci->hcd.pdev,
-                       urb->transfer_buffer, len,
-                       is_input
-                           ? PCI_DMA_FROMDEVICE
-                           : PCI_DMA_TODEVICE);
-               if (unlikely (!buf))
-                       goto cleanup;
-       } else
-               buf = map_buf = 0;
+       if (likely (len > 0))
+               buf = urb->transfer_dma;
+       else
+               buf = 0;
 
        if (!buf || is_input)
                token |= (1 /* "in" */ << 8);
@@ -500,7 +467,6 @@ qh_urb_transaction (
                int this_qtd_len;
 
                qtd->urb = urb;
-               qtd->buf_dma = map_buf;
                this_qtd_len = qtd_fill (qtd, buf, len, token);
                len -= this_qtd_len;
                buf += this_qtd_len;
index 1cb1b8a701bd33a162e3aaff061244c20127cdc1..e11edf8307fc1e12309203298b2068dbd69d5b0e 100644 (file)
@@ -530,11 +530,6 @@ itd_free_list (struct ehci_hcd *ehci, struct urb *urb)
 {
        struct ehci_itd *first_itd = urb->hcpriv;
 
-       pci_unmap_single (ehci->hcd.pdev,
-               first_itd->buf_dma, urb->transfer_buffer_length,
-               usb_pipein (urb->pipe)
-                   ? PCI_DMA_FROMDEVICE
-                   : PCI_DMA_TODEVICE);
        while (!list_empty (&first_itd->itd_list)) {
                struct ehci_itd *itd;
 
@@ -630,16 +625,7 @@ itd_urb_transaction (
        int                     frame_index;
        struct ehci_itd         *first_itd, *itd;
        int                     status;
-       dma_addr_t              buf_dma, itd_dma;
-
-       /* set up one dma mapping for this urb */
-       buf_dma = pci_map_single (ehci->hcd.pdev,
-               urb->transfer_buffer, urb->transfer_buffer_length,
-               usb_pipein (urb->pipe)
-                   ? PCI_DMA_FROMDEVICE
-                   : PCI_DMA_TODEVICE);
-       if (buf_dma == 0)
-               return -ENOMEM;
+       dma_addr_t              itd_dma;
 
        /* allocate/init ITDs */
        for (frame_index = 0, first_itd = 0;
@@ -653,7 +639,8 @@ itd_urb_transaction (
                memset (itd, 0, sizeof *itd);
                itd->itd_dma = itd_dma;
 
-               status = itd_fill (ehci, itd, urb, frame_index, buf_dma);
+               status = itd_fill (ehci, itd, urb, frame_index,
+                               urb->transfer_dma);
                if (status != 0)
                        goto fail;
 
index 7efa35064789fefe0f7c20878d158e60324e71e1..45af6f3c7726fdbfcdcee2a24c6e5fd492d3b96c 100644 (file)
@@ -219,7 +219,6 @@ struct ehci_qtd {
 
        /* dma same in urb's qtds, except 1st control qtd (setup buffer) */
        struct urb              *urb;                   /* qtd's urb */
-       dma_addr_t              buf_dma;                /* buffer address */
        size_t                  length;                 /* length of buffer */
 } __attribute__ ((aligned (32)));
 
index eeb11c335f0d2c1d9317f71f6829ad9d83993b5a..0006cf7c05f46de2bce06520d996915def9d909c 100644 (file)
@@ -14,27 +14,8 @@ static void urb_free_priv (struct ohci_hcd *hc, urb_priv_t *urb_priv)
 
        if (last >= 0) {
                int             i;
-               struct td       *td = urb_priv->td [0];
-               int             len = td->urb->transfer_buffer_length;
-               int             dir = usb_pipeout (td->urb->pipe)
-                                       ? PCI_DMA_TODEVICE
-                                       : PCI_DMA_FROMDEVICE;
-
-               /* unmap CTRL URB setup buffer (always td 0) */
-               if (usb_pipecontrol (td->urb->pipe)) {
-                       pci_unmap_single (hc->hcd.pdev, 
-                                       td->data_dma, 8, PCI_DMA_TODEVICE);
-                       
-                       /* CTRL data buffer starts at td 1 if len > 0 */
-                       if (len && last > 0)
-                               td = urb_priv->td [1];          
-               }
-               /* else:  ISOC, BULK, INTR data buffer starts at td 0 */
+               struct td       *td;
 
-               /* unmap data buffer */
-               if (len && td->data_dma)
-                       pci_unmap_single (hc->hcd.pdev,
-                                       td->data_dma, len, dir);
                for (i = 0; i <= last; i++) {
                        td = urb_priv->td [i];
                        if (td)
@@ -85,15 +66,8 @@ static inline void intr_resub (struct ohci_hcd *hc, struct urb *urb)
        struct urb_priv *urb_priv = urb->hcpriv;
        unsigned long   flags;
 
-// FIXME rewrite this resubmit path.  use pci_dma_sync_single()
-// and requeue more cheaply, and only if needed.
-// Better yet ... abolish the notion of automagic resubmission.
-       pci_unmap_single (hc->hcd.pdev,
-               urb_priv->td [0]->data_dma,
-               urb->transfer_buffer_length,
-               usb_pipeout (urb->pipe)
-                       ? PCI_DMA_TODEVICE
-                       : PCI_DMA_FROMDEVICE);
+// FIXME going away along with the rest of interrrupt automagic...
+
        /* FIXME: MP race.  If another CPU partially unlinks
         * this URB (urb->status was updated, hasn't yet told
         * us to dequeue) before we call complete() here, an
@@ -612,13 +586,9 @@ static void td_submit_urb (
 
        urb_priv->td_cnt = 0;
 
-       if (data_len) {
-               data = pci_map_single (ohci->hcd.pdev,
-                                      urb->transfer_buffer, data_len,
-                                      is_out
-                                              ? PCI_DMA_TODEVICE
-                                              : PCI_DMA_FROMDEVICE);
-       } else
+       if (data_len)
+               data = urb->transfer_dma;
+       else
                data = 0;
 
        /* NOTE:  TD_CC is set so we can tell which TDs the HC processed by
@@ -665,11 +635,7 @@ static void td_submit_urb (
         */
        case PIPE_CONTROL:
                info = TD_CC | TD_DP_SETUP | TD_T_DATA0;
-               td_fill (info,
-                       pci_map_single (ohci->hcd.pdev,
-                                       urb->setup_packet, 8,
-                                       PCI_DMA_TODEVICE),
-                        8, urb, cnt++);
+               td_fill (info, urb->setup_dma, 8, urb, cnt++);
                if (data_len > 0) {
                        info = TD_CC | TD_R | TD_T_DATA1;
                        info |= is_out ? TD_DP_OUT : TD_DP_IN;
index 2fbc16d0c064d130b3712e2f57fa58f7fff8204c..f7b44577a7a0e4c40cbe6f148bab10dae331093d 100644 (file)
@@ -161,6 +161,12 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
        hcd->regs = (void *) &USB_OHCI_OP_BASE;
        hcd->pdev = SA1111_FAKE_PCIDEV;
 
+       retval = hcd_buffer_create (hcd);
+       if (retval != 0) {
+               dbg ("pool alloc fail");
+               goto err1;
+       }
+
        set_irq_type(NIRQHCIM, IRQT_RISING);
        retval = request_irq (NIRQHCIM, usb_hcd_sa1111_hcim_irq, SA_INTERRUPT,
                              hcd->description, hcd);
@@ -193,6 +199,7 @@ int usb_hcd_sa1111_probe (const struct hc_driver *driver, struct usb_hcd **hcd_o
        return 0;
 
  err2:
+       hcd_buffer_destroy (hcd);
        if (hcd) driver->hcd_free(hcd);
  err1:
        sa1111_stop_hc();
@@ -233,6 +240,7 @@ void usb_hcd_sa1111_remove (struct usb_hcd *hcd)
        hcd->state = USB_STATE_HALT;
 
        free_irq (hcd->irq, hcd);
+       hcd_buffer_destroy (hcd);
 
        usb_deregister_bus (&hcd->self);
        if (atomic_read (&hcd->self.refcnt) != 1)
index 86c8396d53dc0a95ccbce2649ca4a04a528977f2..150ae60fe1e60f34aa2b475e6888e05604ac9366 100644 (file)
@@ -646,23 +646,6 @@ static struct urb_priv *uhci_alloc_urb_priv(struct uhci_hcd *uhci, struct urb *u
 
        urb->hcpriv = urbp;
 
-       if (urb->transfer_buffer_length) {
-               urbp->transfer_buffer_dma_handle = pci_map_single(uhci->dev,
-                       urb->transfer_buffer, urb->transfer_buffer_length,
-                       usb_pipein(urb->pipe) ? PCI_DMA_FROMDEVICE :
-                       PCI_DMA_TODEVICE);
-               if (!urbp->transfer_buffer_dma_handle)
-                       return NULL;
-       }
-
-       if (usb_pipetype(urb->pipe) == PIPE_CONTROL && urb->setup_packet) {
-               urbp->setup_packet_dma_handle = pci_map_single(uhci->dev,
-                       urb->setup_packet, sizeof(struct usb_ctrlrequest),
-                       PCI_DMA_TODEVICE);
-               if (!urbp->setup_packet_dma_handle)
-                       return NULL;
-       }
-
        return urbp;
 }
 
@@ -721,19 +704,6 @@ static void uhci_destroy_urb_priv(struct uhci_hcd *uhci, struct urb *urb)
                uhci_free_td(uhci, td);
        }
 
-       if (urbp->setup_packet_dma_handle) {
-               pci_unmap_single(uhci->dev, urbp->setup_packet_dma_handle,
-                       sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-               urbp->setup_packet_dma_handle = 0;
-       }
-
-       if (urbp->transfer_buffer_dma_handle) {
-               pci_unmap_single(uhci->dev, urbp->transfer_buffer_dma_handle,
-                       urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
-                       PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-               urbp->transfer_buffer_dma_handle = 0;
-       }
-
        urb->hcpriv = NULL;
        kmem_cache_free(uhci_up_cachep, urbp);
 }
@@ -813,7 +783,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
        unsigned long destination, status;
        int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
        int len = urb->transfer_buffer_length;
-       dma_addr_t data = urbp->transfer_buffer_dma_handle;
+       dma_addr_t data = urb->transfer_dma;
 
        /* The "pipe" thing contains the destination in bits 8--18 */
        destination = (urb->pipe & PIPE_DEVEP_MASK) | USB_PID_SETUP;
@@ -832,7 +802,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb)
 
        uhci_add_td_to_urb(urb, td);
        uhci_fill_td(td, status, destination | uhci_explen(7),
-               urbp->setup_packet_dma_handle);
+               urb->setup_dma);
 
        /*
         * If direction is "send", change the frame from SETUP (0x2D)
@@ -1072,7 +1042,6 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb)
 {
        struct uhci_td *td;
        unsigned long destination, status;
-       struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
        if (urb->transfer_buffer_length > usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)))
                return -EINVAL;
@@ -1094,7 +1063,7 @@ static int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb)
        usb_dotoggle(urb->dev, usb_pipeendpoint(urb->pipe), usb_pipeout(urb->pipe));
 
        uhci_add_td_to_urb(urb, td);
-       uhci_fill_td(td, status, destination, urbp->transfer_buffer_dma_handle);
+       uhci_fill_td(td, status, destination, urb->transfer_dma);
 
        uhci_insert_td(uhci, uhci->skeltd[__interval_to_skel(urb->interval)], td);
 
@@ -1196,7 +1165,7 @@ static int uhci_submit_bulk(struct uhci_hcd *uhci, struct urb *urb, struct urb *
        int maxsze = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe));
        int len = urb->transfer_buffer_length;
        struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
-       dma_addr_t data = urbp->transfer_buffer_dma_handle;
+       dma_addr_t data = urb->transfer_dma;
 
        if (len < 0)
                return -EINVAL;
@@ -1358,7 +1327,6 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
        struct uhci_td *td;
        int i, ret, frame;
        int status, destination;
-       struct urb_priv *urbp = (struct urb_priv *)urb->hcpriv;
 
        status = TD_CTRL_ACTIVE | TD_CTRL_IOS;
        destination = (urb->pipe & PIPE_DEVEP_MASK) | usb_packetid(urb->pipe);
@@ -1378,7 +1346,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb)
 
                uhci_add_td_to_urb(urb, td);
                uhci_fill_td(td, status, destination | uhci_explen(urb->iso_frame_desc[i].length - 1),
-                       urbp->transfer_buffer_dma_handle + urb->iso_frame_desc[i].offset);
+                       urb->transfer_dma + urb->iso_frame_desc[i].offset);
 
                if (i + 1 >= urb->number_of_packets)
                        td->status |= cpu_to_le32(TD_CTRL_IOC);
@@ -1832,15 +1800,6 @@ static void uhci_finish_urb(struct usb_hcd *hcd, struct urb *urb)
        resubmit_interrupt = (usb_pipetype(urb->pipe) == PIPE_INTERRUPT &&
                        urb->interval);
 
-       if (urbp->transfer_buffer_dma_handle)
-               pci_dma_sync_single(uhci->dev, urbp->transfer_buffer_dma_handle,
-                       urb->transfer_buffer_length, usb_pipein(urb->pipe) ?
-                       PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE);
-
-       if (urbp->setup_packet_dma_handle)
-               pci_dma_sync_single(uhci->dev, urbp->setup_packet_dma_handle,
-                       sizeof(struct usb_ctrlrequest), PCI_DMA_TODEVICE);
-
        status = urbp->status;
        if (!resubmit_interrupt || killed)
                /* We don't need urb_priv anymore */
index a14b8c9a7c91b1e62d463f8983781e432ceac64e..ca05ac043841af6f66947f31f14c230991192a07 100644 (file)
@@ -338,9 +338,6 @@ struct urb_priv {
        struct urb *urb;
        struct usb_device *dev;
 
-       dma_addr_t setup_packet_dma_handle;
-       dma_addr_t transfer_buffer_dma_handle;
-
        struct uhci_qh *qh;             /* QH for this URB */
        struct list_head td_list;       /* P: urb->lock */