[PATCH] USB: UHCI: Split apart the physical and logical framelist arrays
authorAlan Stern <stern@rowland.harvard.edu>
Fri, 16 Sep 2005 18:22:51 +0000 (14:22 -0400)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 28 Oct 2005 23:47:39 +0000 (16:47 -0700)
This patch (as563) splits the physical and logical framelist arrays in
uhci-hcd into two separate pieces.  This will allow slightly better memory
utilization, since each piece is no larger than a single page whereas
before the whole thing was a little bigger than two pages.  It also allows
the logical array to be allocated in non-DMA-coherent memory.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/uhci-debug.c
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-q.c

index 04eddd7995c30d4c3db62cd157dfb167d28a227f..151154df37fa105bf62038b9e4e9c8ee1f03d7bf 100644 (file)
@@ -445,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
        out += sprintf(out, "Frame List\n");
        for (i = 0; i < UHCI_NUMFRAMES; ++i) {
                int shown = 0;
-               td = uhci->fl->frame_cpu[i];
+               td = uhci->frame_cpu[i];
                if (!td)
                        continue;
 
-               if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) {
+               if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
                        show_frame_num();
                        out += sprintf(out, "    frame list does not match td->dma_handle!\n");
                }
index 17de9ee910f60545a90b81528f9edb5aa5aac3df..b44094fcd779f9b6eb71da89a7bb1b94792fff3c 100644 (file)
@@ -212,7 +212,7 @@ static void configure_hc(struct uhci_hcd *uhci)
        outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
 
        /* Store the frame list base address */
-       outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
+       outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
 
        /* Set the current frame number */
        outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
@@ -445,8 +445,11 @@ static void release_uhci(struct uhci_hcd *uhci)
 
        dma_pool_destroy(uhci->td_pool);
 
-       dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       uhci->fl, uhci->fl->dma_handle);
+       kfree(uhci->frame_cpu);
+
+       dma_free_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       uhci->frame, uhci->frame_dma_handle);
 
        debugfs_remove(uhci->dentry);
 }
@@ -527,7 +530,6 @@ static int uhci_start(struct usb_hcd *hcd)
        struct uhci_hcd *uhci = hcd_to_uhci(hcd);
        int retval = -EBUSY;
        int i;
-       dma_addr_t dma_handle;
        struct dentry *dentry;
 
        hcd->uses_new_polling = 1;
@@ -561,17 +563,23 @@ static int uhci_start(struct usb_hcd *hcd)
 
        init_waitqueue_head(&uhci->waitqh);
 
-       uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       &dma_handle, 0);
-       if (!uhci->fl) {
+       uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       &uhci->frame_dma_handle, 0);
+       if (!uhci->frame) {
                dev_err(uhci_dev(uhci), "unable to allocate "
                                "consistent memory for frame list\n");
-               goto err_alloc_fl;
+               goto err_alloc_frame;
        }
+       memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
 
-       memset((void *)uhci->fl, 0, sizeof(*uhci->fl));
-
-       uhci->fl->dma_handle = dma_handle;
+       uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
+                       GFP_KERNEL);
+       if (!uhci->frame_cpu) {
+               dev_err(uhci_dev(uhci), "unable to allocate "
+                               "memory for frame pointers\n");
+               goto err_alloc_frame_cpu;
+       }
 
        uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
                        sizeof(struct uhci_td), 16, 0);
@@ -654,7 +662,7 @@ static int uhci_start(struct usb_hcd *hcd)
                        irq = 7;
 
                /* Only place we don't use the frame list routines */
-               uhci->fl->frame[i] = UHCI_PTR_QH |
+               uhci->frame[i] = UHCI_PTR_QH |
                                cpu_to_le32(uhci->skelqh[irq]->dma_handle);
        }
 
@@ -686,10 +694,14 @@ err_create_qh_pool:
        dma_pool_destroy(uhci->td_pool);
 
 err_create_td_pool:
-       dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl),
-                       uhci->fl, uhci->fl->dma_handle);
+       kfree(uhci->frame_cpu);
+
+err_alloc_frame_cpu:
+       dma_free_coherent(uhci_dev(uhci),
+                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                       uhci->frame, uhci->frame_dma_handle);
 
-err_alloc_fl:
+err_alloc_frame:
        debugfs_remove(uhci->dentry);
 
 err_create_debug_entry:
index 1c161b4f5bcf526f6ed882ebe4be963de8f90751..b04d99df0a0ec790dce83f492e9506238b1d0abc 100644 (file)
@@ -359,7 +359,11 @@ struct uhci_hcd {
        struct uhci_qh *skelqh[UHCI_NUM_SKELQH];        /* Skeleton QH's */
 
        spinlock_t lock;
-       struct uhci_frame_list *fl;             /* P: uhci->lock */
+
+       dma_addr_t frame_dma_handle;            /* Hardware frame list */
+       __le32 *frame;                          /* P: uhci->lock */
+       void **frame_cpu;                       /* CPU's frame list */
+
        int fsbr;                               /* Full-speed bandwidth reclamation */
        unsigned long fsbrtimeout;              /* FSBR delay */
 
index d54038211ca6650b2585c7f910aad6eb8c20f1b7..51de06bc438ddc4b8868846373ce75b65a6e72c3 100644 (file)
@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
        td->frame = framenum;
 
        /* Is there a TD already mapped there? */
-       if (uhci->fl->frame_cpu[framenum]) {
+       if (uhci->frame_cpu[framenum]) {
                struct uhci_td *ftd, *ltd;
 
-               ftd = uhci->fl->frame_cpu[framenum];
+               ftd = uhci->frame_cpu[framenum];
                ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
 
                list_add_tail(&td->fl_list, &ftd->fl_list);
@@ -101,10 +101,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
                wmb();
                ltd->link = cpu_to_le32(td->dma_handle);
        } else {
-               td->link = uhci->fl->frame[framenum];
+               td->link = uhci->frame[framenum];
                wmb();
-               uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle);
-               uhci->fl->frame_cpu[framenum] = td;
+               uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
+               uhci->frame_cpu[framenum] = td;
        }
 }
 
@@ -114,16 +114,16 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
        if (td->frame == -1 && list_empty(&td->fl_list))
                return;
 
-       if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) {
+       if (td->frame != -1 && uhci->frame_cpu[td->frame] == td) {
                if (list_empty(&td->fl_list)) {
-                       uhci->fl->frame[td->frame] = td->link;
-                       uhci->fl->frame_cpu[td->frame] = NULL;
+                       uhci->frame[td->frame] = td->link;
+                       uhci->frame_cpu[td->frame] = NULL;
                } else {
                        struct uhci_td *ntd;
 
                        ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
-                       uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
-                       uhci->fl->frame_cpu[td->frame] = ntd;
+                       uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
+                       uhci->frame_cpu[td->frame] = ntd;
                }
        } else {
                struct uhci_td *ptd;