aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/uhci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2006-05-19 16:34:57 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-06-21 18:04:12 -0400
commitc433472658b4df11bd3590a59be79194a1ff43ae (patch)
tree32d48a155360c8e877be3956c9964d2d4c19a236 /drivers/usb/host/uhci-hcd.c
parent3612242e527eb47ee4756b5350f8bdf791aa5ede (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.c40
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 */
365static void uhci_get_current_frame_number(struct uhci_hcd *uhci) 367static 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:
798static int uhci_hcd_get_frame_number(struct usb_hcd *hcd) 805static 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
815static const char hcd_name[] = "uhci_hcd"; 819static const char hcd_name[] = "uhci_hcd";