aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hcd.c
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2012-07-11 11:21:54 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-07-16 19:53:16 -0400
commitd58b4bcc6df8046cf9c3c59f9ff84d2cd86b93eb (patch)
treebef387c0c81654a38271f8528bb8b877ac5d3ed7 /drivers/usb/host/ehci-hcd.c
parentc0c53dbc32ea05a1e1dd9dba4772327da9a11750 (diff)
USB: EHCI: introduce high-res timer
This patch (as1572) begins the conversion of ehci-hcd over to using high-resolution timers rather than old-fashioned low-resolution kernel timers. This reduces overhead caused by timer roundoff on systems where HZ is smaller than 1000. Also, the new timer framework introduced here is much more logical and easily extended than the ad-hoc approach ehci-hcd currently uses for timers. An hrtimer structure is added to ehci_hcd, along with a bitflag array and an array of ktime_t values, to keep track of which timing events are pending and what their expiration times are. Only the infrastructure for the timing operations is added in this patch. Later patches will add routines for handling each of the various timing events the driver needs. In some cases the new hrtimer handlers will replace the existing handlers for ehci-hcd's kernel timers; as this happens the old timers will be removed. In other cases the new timing events will replace busy-wait loops. Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/host/ehci-hcd.c')
-rw-r--r--drivers/usb/host/ehci-hcd.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index bc94822f4c5d..f8fed163a23a 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -30,8 +30,7 @@
30#include <linux/vmalloc.h> 30#include <linux/vmalloc.h>
31#include <linux/errno.h> 31#include <linux/errno.h>
32#include <linux/init.h> 32#include <linux/init.h>
33#include <linux/timer.h> 33#include <linux/hrtimer.h>
34#include <linux/ktime.h>
35#include <linux/list.h> 34#include <linux/list.h>
36#include <linux/interrupt.h> 35#include <linux/interrupt.h>
37#include <linux/usb.h> 36#include <linux/usb.h>
@@ -380,6 +379,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci)
380static void end_unlink_async(struct ehci_hcd *ehci); 379static void end_unlink_async(struct ehci_hcd *ehci);
381static void ehci_work(struct ehci_hcd *ehci); 380static void ehci_work(struct ehci_hcd *ehci);
382 381
382#include "ehci-timer.c"
383#include "ehci-hub.c" 383#include "ehci-hub.c"
384#include "ehci-lpm.c" 384#include "ehci-lpm.c"
385#include "ehci-mem.c" 385#include "ehci-mem.c"
@@ -494,7 +494,10 @@ static void ehci_shutdown(struct usb_hcd *hcd)
494 spin_lock_irq(&ehci->lock); 494 spin_lock_irq(&ehci->lock);
495 ehci->rh_state = EHCI_RH_STOPPING; 495 ehci->rh_state = EHCI_RH_STOPPING;
496 ehci_silence_controller(ehci); 496 ehci_silence_controller(ehci);
497 ehci->enabled_hrtimer_events = 0;
497 spin_unlock_irq(&ehci->lock); 498 spin_unlock_irq(&ehci->lock);
499
500 hrtimer_cancel(&ehci->hrtimer);
498} 501}
499 502
500static void ehci_port_power (struct ehci_hcd *ehci, int is_on) 503static void ehci_port_power (struct ehci_hcd *ehci, int is_on)
@@ -561,12 +564,14 @@ static void ehci_stop (struct usb_hcd *hcd)
561 del_timer_sync(&ehci->iaa_watchdog); 564 del_timer_sync(&ehci->iaa_watchdog);
562 565
563 spin_lock_irq(&ehci->lock); 566 spin_lock_irq(&ehci->lock);
567 ehci->enabled_hrtimer_events = 0;
564 ehci_quiesce(ehci); 568 ehci_quiesce(ehci);
565 569
566 ehci_silence_controller(ehci); 570 ehci_silence_controller(ehci);
567 ehci_reset (ehci); 571 ehci_reset (ehci);
568 spin_unlock_irq(&ehci->lock); 572 spin_unlock_irq(&ehci->lock);
569 573
574 hrtimer_cancel(&ehci->hrtimer);
570 remove_sysfs_files(ehci); 575 remove_sysfs_files(ehci);
571 remove_debug_files (ehci); 576 remove_debug_files (ehci);
572 577
@@ -615,6 +620,10 @@ static int ehci_init(struct usb_hcd *hcd)
615 ehci->iaa_watchdog.function = ehci_iaa_watchdog; 620 ehci->iaa_watchdog.function = ehci_iaa_watchdog;
616 ehci->iaa_watchdog.data = (unsigned long) ehci; 621 ehci->iaa_watchdog.data = (unsigned long) ehci;
617 622
623 hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
624 ehci->hrtimer.function = ehci_hrtimer_func;
625 ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT;
626
618 hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); 627 hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params);
619 628
620 /* 629 /*
@@ -954,6 +963,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
954 dbg_status(ehci, "fatal", status); 963 dbg_status(ehci, "fatal", status);
955 ehci_halt(ehci); 964 ehci_halt(ehci);
956dead: 965dead:
966 ehci->enabled_hrtimer_events = 0;
967 hrtimer_try_to_cancel(&ehci->hrtimer);
957 ehci_reset(ehci); 968 ehci_reset(ehci);
958 ehci_writel(ehci, 0, &ehci->regs->configured_flag); 969 ehci_writel(ehci, 0, &ehci->regs->configured_flag);
959 usb_hc_died(hcd); 970 usb_hc_died(hcd);