diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2005-09-16 14:22:51 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2005-10-28 19:47:39 -0400 |
commit | a1d59ce842a35b552f22868404e4e7c923242257 (patch) | |
tree | ee92b9406d1d10e07dcc433ae403dc6574f3013c | |
parent | 8b4cd42134fbd3c9a9a5c3467d31717798219b1b (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.c | 4 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 42 | ||||
-rw-r--r-- | drivers/usb/host/uhci-hcd.h | 6 | ||||
-rw-r--r-- | drivers/usb/host/uhci-q.c | 20 |
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 | ||
688 | err_create_td_pool: | 696 | err_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 | |
699 | err_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 | ||
692 | err_alloc_fl: | 704 | err_alloc_frame: |
693 | debugfs_remove(uhci->dentry); | 705 | debugfs_remove(uhci->dentry); |
694 | 706 | ||
695 | err_create_debug_entry: | 707 | err_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; |