diff options
author | Balaji Rao <balajirrao@gmail.com> | 2007-11-21 23:28:14 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-02-02 01:34:52 +0300 |
commit | 90da096ee46b682011b7d549e52b81cf9742e60b (patch) | |
tree | f70838f277b69e82cb30525d96cad3728cc8b30b /drivers/usb/host/ehci-hub.c | |
parent | eb0be47dbbdca133b1b94adc564297f25176b3ab (diff) | |
download | linux-90da096ee46b682011b7d549e52b81cf9742e60b.tar.xz |
USB: force handover port to companion when hub_port_connect_change fails
This patch hands over the port to the companion when the
hub_port_connect_change fails.
Signed-off-by: Balaji Rao <balajirrao@gmail.com>
Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 68 |
1 files changed, 44 insertions, 24 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 1ad7a6572826..a165e0a0961c 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -314,41 +314,21 @@ static ssize_t show_companion(struct device *dev, } /* - * Dedicate or undedicate a port to the companion controller. - * Syntax is "[-]portnum", where a leading '-' sign means - * return control of the port to the EHCI controller. + * Sets the owner of a port */ -static ssize_t store_companion(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) +static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner) { - struct ehci_hcd *ehci; - int portnum, new_owner, try; u32 __iomem *status_reg; u32 port_status; + int try; - ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); - new_owner = PORT_OWNER; /* Owned by companion */ - if (sscanf(buf, "%d", &portnum) != 1) - return -EINVAL; - if (portnum < 0) { - portnum = - portnum; - new_owner = 0; /* Owned by EHCI */ - } - if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) - return -ENOENT; - status_reg = &ehci->regs->port_status[--portnum]; - if (new_owner) - set_bit(portnum, &ehci->companion_ports); - else - clear_bit(portnum, &ehci->companion_ports); + status_reg = &ehci->regs->port_status[portnum]; /* * The controller won't set the OWNER bit if the port is * enabled, so this loop will sometimes require at least two * iterations: one to disable the port and one to set OWNER. */ - for (try = 4; try > 0; --try) { spin_lock_irq(&ehci->lock); port_status = ehci_readl(ehci, status_reg); @@ -365,6 +345,36 @@ static ssize_t store_companion(struct device *dev, if (try > 1) msleep(5); } +} + +/* + * Dedicate or undedicate a port to the companion controller. + * Syntax is "[-]portnum", where a leading '-' sign means + * return control of the port to the EHCI controller. + */ +static ssize_t store_companion(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct ehci_hcd *ehci; + int portnum, new_owner; + + ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); + new_owner = PORT_OWNER; /* Owned by companion */ + if (sscanf(buf, "%d", &portnum) != 1) + return -EINVAL; + if (portnum < 0) { + portnum = - portnum; + new_owner = 0; /* Owned by EHCI */ + } + if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) + return -ENOENT; + portnum--; + if (new_owner) + set_bit(portnum, &ehci->companion_ports); + else + clear_bit(portnum, &ehci->companion_ports); + set_owner(ehci, portnum, new_owner); return count; } static DEVICE_ATTR(companion, 0644, show_companion, store_companion); @@ -867,3 +877,13 @@ error: spin_unlock_irqrestore (&ehci->lock, flags); return retval; } + +static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) +{ + struct ehci_hcd *ehci = hcd_to_ehci(hcd); + + if (ehci_is_TDI(ehci)) + return; + set_owner(ehci, --portnum, PORT_OWNER); +} + |