Skip to content

Commit

Permalink
[PATCH] USB: UHCI: Split apart the physical and logical framelist arrays
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Oct 28, 2005
1 parent 8b4cd42 commit a1d59ce
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 28 deletions.
4 changes: 2 additions & 2 deletions drivers/usb/host/uhci-debug.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
42 changes: 27 additions & 15 deletions drivers/usb/host/uhci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -686,10 +694,14 @@ static int uhci_start(struct usb_hcd *hcd)
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:
Expand Down
6 changes: 5 additions & 1 deletion drivers/usb/host/uhci-hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */

Expand Down
20 changes: 10 additions & 10 deletions drivers/usb/host/uhci-q.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
}
}

Expand All @@ -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;
Expand Down

0 comments on commit a1d59ce

Please sign in to comment.