aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2005-09-16 14:22:51 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2005-10-28 19:47:39 -0400
commita1d59ce842a35b552f22868404e4e7c923242257 (patch)
treeee92b9406d1d10e07dcc433ae403dc6574f3013c
parent8b4cd42134fbd3c9a9a5c3467d31717798219b1b (diff)
[PATCH] USB: UHCI: Split apart the physical and logical framelist arrays
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>
-rw-r--r--drivers/usb/host/uhci-debug.c4
-rw-r--r--drivers/usb/host/uhci-hcd.c42
-rw-r--r--drivers/usb/host/uhci-hcd.h6
-rw-r--r--drivers/usb/host/uhci-q.c20
4 files changed, 44 insertions, 28 deletions
diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c
index 04eddd7995c3..151154df37fa 100644
--- a/drivers/usb/host/uhci-debug.c
+++ b/drivers/usb/host/uhci-debug.c
@@ -445,11 +445,11 @@ static int uhci_sprint_schedule(struct uhci_hcd *uhci, char *buf, int len)
445 out += sprintf(out, "Frame List\n"); 445 out += sprintf(out, "Frame List\n");
446 for (i = 0; i < UHCI_NUMFRAMES; ++i) { 446 for (i = 0; i < UHCI_NUMFRAMES; ++i) {
447 int shown = 0; 447 int shown = 0;
448 td = uhci->fl->frame_cpu[i]; 448 td = uhci->frame_cpu[i];
449 if (!td) 449 if (!td)
450 continue; 450 continue;
451 451
452 if (td->dma_handle != (dma_addr_t)uhci->fl->frame[i]) { 452 if (td->dma_handle != (dma_addr_t)uhci->frame[i]) {
453 show_frame_num(); 453 show_frame_num();
454 out += sprintf(out, " frame list does not match td->dma_handle!\n"); 454 out += sprintf(out, " frame list does not match td->dma_handle!\n");
455 } 455 }
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 17de9ee910f6..b44094fcd779 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -212,7 +212,7 @@ static void configure_hc(struct uhci_hcd *uhci)
212 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF); 212 outb(USBSOF_DEFAULT, uhci->io_addr + USBSOF);
213 213
214 /* Store the frame list base address */ 214 /* Store the frame list base address */
215 outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD); 215 outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD);
216 216
217 /* Set the current frame number */ 217 /* Set the current frame number */
218 outw(uhci->frame_number, uhci->io_addr + USBFRNUM); 218 outw(uhci->frame_number, uhci->io_addr + USBFRNUM);
@@ -445,8 +445,11 @@ static void release_uhci(struct uhci_hcd *uhci)
445 445
446 dma_pool_destroy(uhci->td_pool); 446 dma_pool_destroy(uhci->td_pool);
447 447
448 dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 448 kfree(uhci->frame_cpu);
449 uhci->fl, uhci->fl->dma_handle); 449
450 dma_free_coherent(uhci_dev(uhci),
451 UHCI_NUMFRAMES * sizeof(*uhci->frame),
452 uhci->frame, uhci->frame_dma_handle);
450 453
451 debugfs_remove(uhci->dentry); 454 debugfs_remove(uhci->dentry);
452} 455}
@@ -527,7 +530,6 @@ static int uhci_start(struct usb_hcd *hcd)
527 struct uhci_hcd *uhci = hcd_to_uhci(hcd); 530 struct uhci_hcd *uhci = hcd_to_uhci(hcd);
528 int retval = -EBUSY; 531 int retval = -EBUSY;
529 int i; 532 int i;
530 dma_addr_t dma_handle;
531 struct dentry *dentry; 533 struct dentry *dentry;
532 534
533 hcd->uses_new_polling = 1; 535 hcd->uses_new_polling = 1;
@@ -561,17 +563,23 @@ static int uhci_start(struct usb_hcd *hcd)
561 563
562 init_waitqueue_head(&uhci->waitqh); 564 init_waitqueue_head(&uhci->waitqh);
563 565
564 uhci->fl = dma_alloc_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 566 uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
565 &dma_handle, 0); 567 UHCI_NUMFRAMES * sizeof(*uhci->frame),
566 if (!uhci->fl) { 568 &uhci->frame_dma_handle, 0);
569 if (!uhci->frame) {
567 dev_err(uhci_dev(uhci), "unable to allocate " 570 dev_err(uhci_dev(uhci), "unable to allocate "
568 "consistent memory for frame list\n"); 571 "consistent memory for frame list\n");
569 goto err_alloc_fl; 572 goto err_alloc_frame;
570 } 573 }
574 memset(uhci->frame, 0, UHCI_NUMFRAMES * sizeof(*uhci->frame));
571 575
572 memset((void *)uhci->fl, 0, sizeof(*uhci->fl)); 576 uhci->frame_cpu = kcalloc(UHCI_NUMFRAMES, sizeof(*uhci->frame_cpu),
573 577 GFP_KERNEL);
574 uhci->fl->dma_handle = dma_handle; 578 if (!uhci->frame_cpu) {
579 dev_err(uhci_dev(uhci), "unable to allocate "
580 "memory for frame pointers\n");
581 goto err_alloc_frame_cpu;
582 }
575 583
576 uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci), 584 uhci->td_pool = dma_pool_create("uhci_td", uhci_dev(uhci),
577 sizeof(struct uhci_td), 16, 0); 585 sizeof(struct uhci_td), 16, 0);
@@ -654,7 +662,7 @@ static int uhci_start(struct usb_hcd *hcd)
654 irq = 7; 662 irq = 7;
655 663
656 /* Only place we don't use the frame list routines */ 664 /* Only place we don't use the frame list routines */
657 uhci->fl->frame[i] = UHCI_PTR_QH | 665 uhci->frame[i] = UHCI_PTR_QH |
658 cpu_to_le32(uhci->skelqh[irq]->dma_handle); 666 cpu_to_le32(uhci->skelqh[irq]->dma_handle);
659 } 667 }
660 668
@@ -686,10 +694,14 @@ err_create_qh_pool:
686 dma_pool_destroy(uhci->td_pool); 694 dma_pool_destroy(uhci->td_pool);
687 695
688err_create_td_pool: 696err_create_td_pool:
689 dma_free_coherent(uhci_dev(uhci), sizeof(*uhci->fl), 697 kfree(uhci->frame_cpu);
690 uhci->fl, uhci->fl->dma_handle); 698
699err_alloc_frame_cpu:
700 dma_free_coherent(uhci_dev(uhci),
701 UHCI_NUMFRAMES * sizeof(*uhci->frame),
702 uhci->frame, uhci->frame_dma_handle);
691 703
692err_alloc_fl: 704err_alloc_frame:
693 debugfs_remove(uhci->dentry); 705 debugfs_remove(uhci->dentry);
694 706
695err_create_debug_entry: 707err_create_debug_entry:
diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h
index 1c161b4f5bcf..b04d99df0a0e 100644
--- a/drivers/usb/host/uhci-hcd.h
+++ b/drivers/usb/host/uhci-hcd.h
@@ -359,7 +359,11 @@ struct uhci_hcd {
359 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */ 359 struct uhci_qh *skelqh[UHCI_NUM_SKELQH]; /* Skeleton QH's */
360 360
361 spinlock_t lock; 361 spinlock_t lock;
362 struct uhci_frame_list *fl; /* P: uhci->lock */ 362
363 dma_addr_t frame_dma_handle; /* Hardware frame list */
364 __le32 *frame; /* P: uhci->lock */
365 void **frame_cpu; /* CPU's frame list */
366
363 int fsbr; /* Full-speed bandwidth reclamation */ 367 int fsbr; /* Full-speed bandwidth reclamation */
364 unsigned long fsbrtimeout; /* FSBR delay */ 368 unsigned long fsbrtimeout; /* FSBR delay */
365 369
diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c
index d54038211ca6..51de06bc438d 100644
--- a/drivers/usb/host/uhci-q.c
+++ b/drivers/usb/host/uhci-q.c
@@ -89,10 +89,10 @@ static void uhci_insert_td_frame_list(struct uhci_hcd *uhci, struct uhci_td *td,
89 td->frame = framenum; 89 td->frame = framenum;
90 90
91 /* Is there a TD already mapped there? */ 91 /* Is there a TD already mapped there? */
92 if (uhci->fl->frame_cpu[framenum]) { 92 if (uhci->frame_cpu[framenum]) {
93 struct uhci_td *ftd, *ltd; 93 struct uhci_td *ftd, *ltd;
94 94
95 ftd = uhci->fl->frame_cpu[framenum]; 95 ftd = uhci->frame_cpu[framenum];
96 ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list); 96 ltd = list_entry(ftd->fl_list.prev, struct uhci_td, fl_list);
97 97
98 list_add_tail(&td->fl_list, &ftd->fl_list); 98 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,
101 wmb(); 101 wmb();
102 ltd->link = cpu_to_le32(td->dma_handle); 102 ltd->link = cpu_to_le32(td->dma_handle);
103 } else { 103 } else {
104 td->link = uhci->fl->frame[framenum]; 104 td->link = uhci->frame[framenum];
105 wmb(); 105 wmb();
106 uhci->fl->frame[framenum] = cpu_to_le32(td->dma_handle); 106 uhci->frame[framenum] = cpu_to_le32(td->dma_handle);
107 uhci->fl->frame_cpu[framenum] = td; 107 uhci->frame_cpu[framenum] = td;
108 } 108 }
109} 109}
110 110
@@ -114,16 +114,16 @@ static void uhci_remove_td(struct uhci_hcd *uhci, struct uhci_td *td)
114 if (td->frame == -1 && list_empty(&td->fl_list)) 114 if (td->frame == -1 && list_empty(&td->fl_list))
115 return; 115 return;
116 116
117 if (td->frame != -1 && uhci->fl->frame_cpu[td->frame] == td) { 117 if (td->frame != -1 && uhci->frame_cpu[td->frame] == td) {
118 if (list_empty(&td->fl_list)) { 118 if (list_empty(&td->fl_list)) {
119 uhci->fl->frame[td->frame] = td->link; 119 uhci->frame[td->frame] = td->link;
120 uhci->fl->frame_cpu[td->frame] = NULL; 120 uhci->frame_cpu[td->frame] = NULL;
121 } else { 121 } else {
122 struct uhci_td *ntd; 122 struct uhci_td *ntd;
123 123
124 ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list); 124 ntd = list_entry(td->fl_list.next, struct uhci_td, fl_list);
125 uhci->fl->frame[td->frame] = cpu_to_le32(ntd->dma_handle); 125 uhci->frame[td->frame] = cpu_to_le32(ntd->dma_handle);
126 uhci->fl->frame_cpu[td->frame] = ntd; 126 uhci->frame_cpu[td->frame] = ntd;
127 } 127 }
128 } else { 128 } else {
129 struct uhci_td *ptd; 129 struct uhci_td *ptd;