diff options
author | Alan Stern <stern@rowland.harvard.edu> | 2006-05-19 16:34:57 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-06-21 18:04:12 -0400 |
commit | c433472658b4df11bd3590a59be79194a1ff43ae (patch) | |
tree | 32d48a155360c8e877be3956c9964d2d4c19a236 /drivers/usb/host/uhci-hcd.c | |
parent | 3612242e527eb47ee4756b5350f8bdf791aa5ede (diff) |
[PATCH] UHCI: use integer-sized frame numbers
This patch (as687) changes uhci-hcd to keep track of frame numbers as
full-sized integers rather than 11-bit values. This makes them a lot
easier to handle and makes it possible to schedule beyond a 2-second
window, should anyone ever want to do so.
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/uhci-hcd.c')
-rw-r--r-- | drivers/usb/host/uhci-hcd.c | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 395402eec5ef..5e75ad6dc29f 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -13,7 +13,7 @@ | |||
13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface | 13 | * (C) Copyright 2000 Yggdrasil Computing, Inc. (port of new PCI interface |
14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). | 14 | * support from usb-ohci.c by Adam Richter, adam@yggdrasil.com). |
15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) | 15 | * (C) Copyright 1999 Gregory P. Smith (from usb-ohci.c) |
16 | * (C) Copyright 2004-2005 Alan Stern, stern@rowland.harvard.edu | 16 | * (C) Copyright 2004-2006 Alan Stern, stern@rowland.harvard.edu |
17 | * | 17 | * |
18 | * Intel documents this fairly well, and as far as I know there | 18 | * Intel documents this fairly well, and as far as I know there |
19 | * are no royalties or anything like that, but even so there are | 19 | * are no royalties or anything like that, but even so there are |
@@ -31,7 +31,6 @@ | |||
31 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
32 | #include <linux/sched.h> | 32 | #include <linux/sched.h> |
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <linux/smp_lock.h> | ||
35 | #include <linux/errno.h> | 34 | #include <linux/errno.h> |
36 | #include <linux/unistd.h> | 35 | #include <linux/unistd.h> |
37 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
@@ -146,7 +145,8 @@ static void configure_hc(struct uhci_hcd *uhci) | |||
146 | outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); | 145 | outl(uhci->frame_dma_handle, uhci->io_addr + USBFLBASEADD); |
147 | 146 | ||
148 | /* Set the current frame number */ | 147 | /* Set the current frame number */ |
149 | outw(uhci->frame_number, uhci->io_addr + USBFRNUM); | 148 | outw(uhci->frame_number & UHCI_MAX_SOF_NUMBER, |
149 | uhci->io_addr + USBFRNUM); | ||
150 | 150 | ||
151 | /* Mark controller as not halted before we enable interrupts */ | 151 | /* Mark controller as not halted before we enable interrupts */ |
152 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; | 152 | uhci_to_hcd(uhci)->state = HC_STATE_SUSPENDED; |
@@ -239,7 +239,6 @@ __acquires(uhci->lock) | |||
239 | dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); | 239 | dev_warn(uhci_dev(uhci), "Controller not stopped yet!\n"); |
240 | 240 | ||
241 | uhci_get_current_frame_number(uhci); | 241 | uhci_get_current_frame_number(uhci); |
242 | smp_wmb(); | ||
243 | 242 | ||
244 | uhci->rh_state = new_state; | 243 | uhci->rh_state = new_state; |
245 | uhci->is_stopped = UHCI_IS_STOPPED; | 244 | uhci->is_stopped = UHCI_IS_STOPPED; |
@@ -253,7 +252,6 @@ static void start_rh(struct uhci_hcd *uhci) | |||
253 | { | 252 | { |
254 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; | 253 | uhci_to_hcd(uhci)->state = HC_STATE_RUNNING; |
255 | uhci->is_stopped = 0; | 254 | uhci->is_stopped = 0; |
256 | smp_wmb(); | ||
257 | 255 | ||
258 | /* Mark it configured and running with a 64-byte max packet. | 256 | /* Mark it configured and running with a 64-byte max packet. |
259 | * All interrupts are enabled, even though RESUME won't do anything. | 257 | * All interrupts are enabled, even though RESUME won't do anything. |
@@ -360,12 +358,21 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd, struct pt_regs *regs) | |||
360 | 358 | ||
361 | /* | 359 | /* |
362 | * Store the current frame number in uhci->frame_number if the controller | 360 | * Store the current frame number in uhci->frame_number if the controller |
363 | * is runnning | 361 | * is runnning. Expand from 11 bits (of which we use only 10) to a |
362 | * full-sized integer. | ||
363 | * | ||
364 | * Like many other parts of the driver, this code relies on being polled | ||
365 | * more than once per second as long as the controller is running. | ||
364 | */ | 366 | */ |
365 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) | 367 | static void uhci_get_current_frame_number(struct uhci_hcd *uhci) |
366 | { | 368 | { |
367 | if (!uhci->is_stopped) | 369 | if (!uhci->is_stopped) { |
368 | uhci->frame_number = inw(uhci->io_addr + USBFRNUM); | 370 | unsigned delta; |
371 | |||
372 | delta = (inw(uhci->io_addr + USBFRNUM) - uhci->frame_number) & | ||
373 | (UHCI_NUMFRAMES - 1); | ||
374 | uhci->frame_number += delta; | ||
375 | } | ||
369 | } | 376 | } |
370 | 377 | ||
371 | /* | 378 | /* |
@@ -798,18 +805,15 @@ done: | |||
798 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) | 805 | static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) |
799 | { | 806 | { |
800 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); | 807 | struct uhci_hcd *uhci = hcd_to_uhci(hcd); |
801 | unsigned long flags; | 808 | unsigned frame_number; |
802 | int is_stopped; | 809 | unsigned delta; |
803 | int frame_number; | ||
804 | 810 | ||
805 | /* Minimize latency by avoiding the spinlock */ | 811 | /* Minimize latency by avoiding the spinlock */ |
806 | local_irq_save(flags); | 812 | frame_number = uhci->frame_number; |
807 | is_stopped = uhci->is_stopped; | 813 | barrier(); |
808 | smp_rmb(); | 814 | delta = (inw(uhci->io_addr + USBFRNUM) - frame_number) & |
809 | frame_number = (is_stopped ? uhci->frame_number : | 815 | (UHCI_NUMFRAMES - 1); |
810 | inw(uhci->io_addr + USBFRNUM)); | 816 | return frame_number + delta; |
811 | local_irq_restore(flags); | ||
812 | return frame_number; | ||
813 | } | 817 | } |
814 | 818 | ||
815 | static const char hcd_name[] = "uhci_hcd"; | 819 | static const char hcd_name[] = "uhci_hcd"; |