Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 36354
b: refs/heads/master
c: d413984
h: refs/heads/master
v: v3
  • Loading branch information
David Brownell authored and Greg Kroah-Hartman committed Sep 27, 2006
1 parent eeddb22 commit 4eb82b6
Show file tree
Hide file tree
Showing 14 changed files with 100 additions and 46 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 06afff00bcab0e384afbef70194fd3469532abdf
refs/heads/master: d413984ae936fad46678403b38d79c595e5aaafe
2 changes: 1 addition & 1 deletion trunk/drivers/usb/host/ohci-at91.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ static const struct hc_driver ohci_at91_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,

.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
5 changes: 1 addition & 4 deletions trunk/drivers/usb/host/ohci-au1xxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -268,10 +268,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
* basic lifecycle operations
*/
.start = ohci_au1xxx_start,
#ifdef CONFIG_PM
/* suspend: ohci_au1xxx_suspend, -- tbd */
/* resume: ohci_au1xxx_resume, -- tbd */
#endif /*CONFIG_PM*/
.stop = ohci_stop,

/*
Expand All @@ -291,6 +287,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/usb/host/ohci-dbg.c
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,11 @@ show_registers (struct class_device *class_dev, char *buf)
size -= temp;
next += temp;

temp = scnprintf (next, size, "hub poll timer %s\n",
ohci_to_hcd(ohci)->poll_rh ? "ON" : "off");
size -= temp;
next += temp;

/* roothub */
ohci_dump_roothub (ohci, 1, &next, &size);

Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/usb/host/ohci-ep93xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ static struct hc_driver ohci_ep93xx_hc_driver = {
.get_frame_number = ohci_get_frame,
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
41 changes: 32 additions & 9 deletions trunk/drivers/usb/host/ohci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@

#include "../core/hcd.h"

#define DRIVER_VERSION "2005 April 22"
#define DRIVER_VERSION "2006 August 04"
#define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell"
#define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver"

Expand All @@ -110,9 +110,10 @@
#undef OHCI_VERBOSE_DEBUG /* not always helpful */

/* For initializing controller (mask in an HCFS mode too) */
#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
#define OHCI_CONTROL_INIT OHCI_CTRL_CBSR
#define OHCI_INTR_INIT \
(OHCI_INTR_MIE | OHCI_INTR_UE | OHCI_INTR_RD | OHCI_INTR_WDH)
(OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE \
| OHCI_INTR_RD | OHCI_INTR_WDH)

#ifdef __hppa__
/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */
Expand All @@ -128,6 +129,8 @@

static const char hcd_name [] = "ohci_hcd";

#define STATECHANGE_DELAY msecs_to_jiffies(300)

#include "ohci.h"

static void ohci_dump (struct ohci_hcd *ohci, int verbose);
Expand Down Expand Up @@ -446,7 +449,6 @@ static int ohci_init (struct ohci_hcd *ohci)

disable (ohci);
ohci->regs = hcd->regs;
ohci->next_statechange = jiffies;

/* REVISIT this BIOS handshake is now moved into PCI "quirks", and
* was never needed for most non-PCI systems ... remove the code?
Expand Down Expand Up @@ -637,18 +639,22 @@ static int ohci_run (struct ohci_hcd *ohci)
return -EOVERFLOW;
}

/* start controller operations */
/* use rhsc irqs after khubd is fully initialized */
hcd->poll_rh = 1;
hcd->uses_new_polling = 1;

/* start controller operations */
ohci->hc_control &= OHCI_CTRL_RWC;
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
ohci->hc_control |= OHCI_CONTROL_INIT | OHCI_USB_OPER;
ohci_writel (ohci, ohci->hc_control, &ohci->regs->control);
hcd->state = HC_STATE_RUNNING;

/* wake on ConnectStatusChange, matching external hubs */
ohci_writel (ohci, RH_HS_DRWE, &ohci->regs->roothub.status);

/* Choose the interrupts we care about now, others later on demand */
mask = OHCI_INTR_INIT;
ohci_writel (ohci, mask, &ohci->regs->intrstatus);
ohci_writel (ohci, ~0, &ohci->regs->intrstatus);
ohci_writel (ohci, mask, &ohci->regs->intrenable);

/* handle root hub init quirks ... */
Expand All @@ -672,6 +678,7 @@ static int ohci_run (struct ohci_hcd *ohci)
// flush those writes
(void) ohci_readl (ohci, &ohci->regs->control);

ohci->next_statechange = jiffies + STATECHANGE_DELAY;
spin_unlock_irq (&ohci->lock);

// POTPGT delay is bits 24-31, in 2 ms units.
Expand Down Expand Up @@ -709,7 +716,23 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd, struct pt_regs *ptregs)
/* interrupt for some other device? */
} else if ((ints &= ohci_readl (ohci, &regs->intrenable)) == 0) {
return IRQ_NOTMINE;
}
}

/* NOTE: vendors didn't always make the same implementation
* choices for RHSC. Sometimes it triggers on an edge (like
* setting and maybe clearing a port status change bit); and
* it's level-triggered on other silicon, active until khubd
* clears all active port status change bits. Poll by timer
* til it's fully debounced and the difference won't matter.
*/
if (ints & OHCI_INTR_RHSC) {
ohci_vdbg (ohci, "rhsc\n");
ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrdisable);
hcd->poll_rh = 1;
ohci->next_statechange = jiffies + STATECHANGE_DELAY;
ohci_writel (ohci, OHCI_INTR_RHSC, &regs->intrstatus);
usb_hcd_poll_rh_status(hcd);
}

if (ints & OHCI_INTR_UE) {
disable (ohci);
Expand Down
67 changes: 46 additions & 21 deletions trunk/drivers/usb/host/ohci-hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@

/*-------------------------------------------------------------------------*/

/* hcd->hub_irq_enable() */
static void ohci_rhsc_enable (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);

ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
}

#ifdef CONFIG_PM

#define OHCI_SCHED_ENABLES \
Expand Down Expand Up @@ -123,6 +131,9 @@ static int ohci_bus_suspend (struct usb_hcd *hcd)
/* no resumes until devices finish suspending */
ohci->next_statechange = jiffies + msecs_to_jiffies (5);

/* no timer polling */
hcd->poll_rh = 0;

done:
/* external suspend vs self autosuspend ... same effect */
if (status == 0)
Expand Down Expand Up @@ -256,8 +267,8 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
/* TRSMRCY */
msleep (10);

/* keep it alive for ~5x suspend + resume costs */
ohci->next_statechange = jiffies + msecs_to_jiffies (250);
/* keep it alive for more than ~5x suspend + resume costs */
ohci->next_statechange = jiffies + STATECHANGE_DELAY;

/* maybe turn schedules back on */
enables = 0;
Expand Down Expand Up @@ -302,9 +313,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1;
int can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
int can_suspend;
unsigned long flags;

can_suspend = device_may_wakeup(&hcd->self.root_hub->dev);
spin_lock_irqsave (&ohci->lock, flags);

/* handle autosuspended root: finish resuming before
Expand Down Expand Up @@ -339,6 +351,10 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
for (i = 0; i < ohci->num_ports; i++) {
u32 status = roothub_portstatus (ohci, i);

/* can't autosuspend with active ports */
if ((status & RH_PS_PES) && !(status & RH_PS_PSS))
can_suspend = 0;

if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC
| RH_PS_OCIC | RH_PS_PRSC)) {
changed = 1;
Expand All @@ -348,32 +364,41 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
buf [1] |= 1 << (i - 7);
continue;
}
}

/* can suspend if no ports are enabled; or if all all
* enabled ports are suspended AND remote wakeup is on.
*/
if (!(status & RH_PS_CCS))
continue;
if ((status & RH_PS_PSS) && can_suspend)
continue;
/* after root hub changes, stop polling after debouncing
* for a while and maybe kicking in autosuspend
*/
if (changed) {
ohci->next_statechange = jiffies + STATECHANGE_DELAY;
can_suspend = 0;
} else if (time_before (jiffies, ohci->next_statechange)) {
can_suspend = 0;
} else {
#ifdef CONFIG_PM
can_suspend = can_suspend
&& !ohci->ed_rm_list
&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
& ohci->hc_control)
== OHCI_USB_OPER;
#endif
if (hcd->uses_new_polling) {
hcd->poll_rh = 0;
/* use INTR_RHSC iff INTR_RD won't apply */
if (!can_suspend)
ohci_writel (ohci, OHCI_INTR_RHSC,
&ohci->regs->intrenable);
}
}

done:
spin_unlock_irqrestore (&ohci->lock, flags);

#ifdef CONFIG_PM
/* save power by suspending idle root hubs;
#ifdef CONFIG_PM
/* save power by autosuspending idle root hubs;
* INTR_RD wakes us when there's work
*/
if (can_suspend
&& !changed
&& !ohci->ed_rm_list
&& ((OHCI_CTRL_HCFS | OHCI_SCHED_ENABLES)
& ohci->hc_control)
== OHCI_USB_OPER
&& time_after (jiffies, ohci->next_statechange)
&& usb_trylock_device (hcd->self.root_hub) == 0
) {
if (can_suspend && usb_trylock_device (hcd->self.root_hub) == 0) {
ohci_vdbg (ohci, "autosuspend\n");
(void) ohci_bus_suspend (hcd);
usb_unlock_device (hcd->self.root_hub);
Expand Down
5 changes: 1 addition & 4 deletions trunk/drivers/usb/host/ohci-lh7a404.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
* basic lifecycle operations
*/
.start = ohci_lh7a404_start,
#ifdef CONFIG_PM
/* suspend: ohci_lh7a404_suspend, -- tbd */
/* resume: ohci_lh7a404_resume, -- tbd */
#endif /*CONFIG_PM*/
.stop = ohci_stop,

/*
Expand All @@ -196,6 +192,7 @@ static const struct hc_driver ohci_lh7a404_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/usb/host/ohci-omap.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,8 +382,10 @@ ohci_omap_start (struct usb_hcd *hcd)
int ret;

config = hcd->self.controller->platform_data;
if (config->otg || config->rwc)
if (config->otg || config->rwc) {
ohci->hc_control = OHCI_CTRL_RWC;
writel(OHCI_CTRL_RWC, &ohci->regs->control);
}

if ((ret = ohci_run (ohci)) < 0) {
dev_err(hcd->self.controller, "can't start\n");
Expand Down Expand Up @@ -429,6 +431,7 @@ static const struct hc_driver ohci_omap_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/usb/host/ohci-pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,13 @@ static const struct hc_driver ohci_pci_hc_driver = {
*/
.reset = ohci_pci_reset,
.start = ohci_pci_start,
.stop = ohci_stop,

#ifdef CONFIG_PM
/* these suspend/resume entries are for upstream PCI glue ONLY */
.suspend = ohci_pci_suspend,
.resume = ohci_pci_resume,
#endif
.stop = ohci_stop,

/*
* managing i/o requests and associated device resources
Expand All @@ -199,6 +201,7 @@ static const struct hc_driver ohci_pci_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/usb/host/ohci-ppc-soc.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/usb/host/ohci-pxa27x.c
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ static const struct hc_driver ohci_pxa27x_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/usb/host/ohci-s3c2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,7 @@ static const struct hc_driver ohci_s3c2410_hc_driver = {
*/
.hub_status_data = ohci_s3c2410_hub_status_data,
.hub_control = ohci_s3c2410_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down
5 changes: 1 addition & 4 deletions trunk/drivers/usb/host/ohci-sa1111.c
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
* basic lifecycle operations
*/
.start = ohci_sa1111_start,
#ifdef CONFIG_PM
/* suspend: ohci_sa1111_suspend, -- tbd */
/* resume: ohci_sa1111_resume, -- tbd */
#endif
.stop = ohci_stop,

/*
Expand All @@ -235,6 +231,7 @@ static const struct hc_driver ohci_sa1111_hc_driver = {
*/
.hub_status_data = ohci_hub_status_data,
.hub_control = ohci_hub_control,
.hub_irq_enable = ohci_rhsc_enable,
#ifdef CONFIG_PM
.bus_suspend = ohci_bus_suspend,
.bus_resume = ohci_bus_resume,
Expand Down

0 comments on commit 4eb82b6

Please sign in to comment.