aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
authorBalaji Rao <balajirrao@gmail.com>2007-11-21 15:28:14 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2008-02-01 17:34:52 -0500
commit90da096ee46b682011b7d549e52b81cf9742e60b (patch)
treef70838f277b69e82cb30525d96cad3728cc8b30b /drivers/usb/host
parenteb0be47dbbdca133b1b94adc564297f25176b3ab (diff)
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')
-rw-r--r--drivers/usb/host/ehci-au1xxx.c1
-rw-r--r--drivers/usb/host/ehci-fsl.c1
-rw-r--r--drivers/usb/host/ehci-hub.c68
-rw-r--r--drivers/usb/host/ehci-pci.c1
-rw-r--r--drivers/usb/host/ehci-ppc-soc.c1
-rw-r--r--drivers/usb/host/ehci-ps3.c1
6 files changed, 49 insertions, 24 deletions
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 766ef68a0b4..da7532d38bf 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -222,6 +222,7 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
222 .hub_control = ehci_hub_control, 222 .hub_control = ehci_hub_control,
223 .bus_suspend = ehci_bus_suspend, 223 .bus_suspend = ehci_bus_suspend,
224 .bus_resume = ehci_bus_resume, 224 .bus_resume = ehci_bus_resume,
225 .relinquish_port = ehci_relinquish_port,
225}; 226};
226 227
227/*-------------------------------------------------------------------------*/ 228/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 430821cb95c..f35795fbd89 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -323,6 +323,7 @@ static const struct hc_driver ehci_fsl_hc_driver = {
323 .hub_control = ehci_hub_control, 323 .hub_control = ehci_hub_control,
324 .bus_suspend = ehci_bus_suspend, 324 .bus_suspend = ehci_bus_suspend,
325 .bus_resume = ehci_bus_resume, 325 .bus_resume = ehci_bus_resume,
326 .relinquish_port = ehci_relinquish_port,
326}; 327};
327 328
328static int ehci_fsl_drv_probe(struct platform_device *pdev) 329static int ehci_fsl_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index 1ad7a657282..a165e0a0961 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,
314} 314}
315 315
316/* 316/*
317 * Dedicate or undedicate a port to the companion controller. 317 * Sets the owner of a port
318 * Syntax is "[-]portnum", where a leading '-' sign means
319 * return control of the port to the EHCI controller.
320 */ 318 */
321static ssize_t store_companion(struct device *dev, 319static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner)
322 struct device_attribute *attr,
323 const char *buf, size_t count)
324{ 320{
325 struct ehci_hcd *ehci;
326 int portnum, new_owner, try;
327 u32 __iomem *status_reg; 321 u32 __iomem *status_reg;
328 u32 port_status; 322 u32 port_status;
323 int try;
329 324
330 ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev))); 325 status_reg = &ehci->regs->port_status[portnum];
331 new_owner = PORT_OWNER; /* Owned by companion */
332 if (sscanf(buf, "%d", &portnum) != 1)
333 return -EINVAL;
334 if (portnum < 0) {
335 portnum = - portnum;
336 new_owner = 0; /* Owned by EHCI */
337 }
338 if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
339 return -ENOENT;
340 status_reg = &ehci->regs->port_status[--portnum];
341 if (new_owner)
342 set_bit(portnum, &ehci->companion_ports);
343 else
344 clear_bit(portnum, &ehci->companion_ports);
345 326
346 /* 327 /*
347 * The controller won't set the OWNER bit if the port is 328 * The controller won't set the OWNER bit if the port is
348 * enabled, so this loop will sometimes require at least two 329 * enabled, so this loop will sometimes require at least two
349 * iterations: one to disable the port and one to set OWNER. 330 * iterations: one to disable the port and one to set OWNER.
350 */ 331 */
351
352 for (try = 4; try > 0; --try) { 332 for (try = 4; try > 0; --try) {
353 spin_lock_irq(&ehci->lock); 333 spin_lock_irq(&ehci->lock);
354 port_status = ehci_readl(ehci, status_reg); 334 port_status = ehci_readl(ehci, status_reg);
@@ -365,6 +345,36 @@ static ssize_t store_companion(struct device *dev,
365 if (try > 1) 345 if (try > 1)
366 msleep(5); 346 msleep(5);
367 } 347 }
348}
349
350/*
351 * Dedicate or undedicate a port to the companion controller.
352 * Syntax is "[-]portnum", where a leading '-' sign means
353 * return control of the port to the EHCI controller.
354 */
355static ssize_t store_companion(struct device *dev,
356 struct device_attribute *attr,
357 const char *buf, size_t count)
358{
359 struct ehci_hcd *ehci;
360 int portnum, new_owner;
361
362 ehci = hcd_to_ehci(bus_to_hcd(dev_get_drvdata(dev)));
363 new_owner = PORT_OWNER; /* Owned by companion */
364 if (sscanf(buf, "%d", &portnum) != 1)
365 return -EINVAL;
366 if (portnum < 0) {
367 portnum = - portnum;
368 new_owner = 0; /* Owned by EHCI */
369 }
370 if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params))
371 return -ENOENT;
372 portnum--;
373 if (new_owner)
374 set_bit(portnum, &ehci->companion_ports);
375 else
376 clear_bit(portnum, &ehci->companion_ports);
377 set_owner(ehci, portnum, new_owner);
368 return count; 378 return count;
369} 379}
370static DEVICE_ATTR(companion, 0644, show_companion, store_companion); 380static DEVICE_ATTR(companion, 0644, show_companion, store_companion);
@@ -867,3 +877,13 @@ error:
867 spin_unlock_irqrestore (&ehci->lock, flags); 877 spin_unlock_irqrestore (&ehci->lock, flags);
868 return retval; 878 return retval;
869} 879}
880
881static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum)
882{
883 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
884
885 if (ehci_is_TDI(ehci))
886 return;
887 set_owner(ehci, --portnum, PORT_OWNER);
888}
889
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index ad0d4965f2f..45e04000028 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -364,6 +364,7 @@ static const struct hc_driver ehci_pci_hc_driver = {
364 .hub_control = ehci_hub_control, 364 .hub_control = ehci_hub_control,
365 .bus_suspend = ehci_bus_suspend, 365 .bus_suspend = ehci_bus_suspend,
366 .bus_resume = ehci_bus_resume, 366 .bus_resume = ehci_bus_resume,
367 .relinquish_port = ehci_relinquish_port,
367}; 368};
368 369
369/*-------------------------------------------------------------------------*/ 370/*-------------------------------------------------------------------------*/
diff --git a/drivers/usb/host/ehci-ppc-soc.c b/drivers/usb/host/ehci-ppc-soc.c
index 452d4b1bc85..a3249078c80 100644
--- a/drivers/usb/host/ehci-ppc-soc.c
+++ b/drivers/usb/host/ehci-ppc-soc.c
@@ -162,6 +162,7 @@ static const struct hc_driver ehci_ppc_soc_hc_driver = {
162 .hub_control = ehci_hub_control, 162 .hub_control = ehci_hub_control,
163 .bus_suspend = ehci_bus_suspend, 163 .bus_suspend = ehci_bus_suspend,
164 .bus_resume = ehci_bus_resume, 164 .bus_resume = ehci_bus_resume,
165 .relinquish_port = ehci_relinquish_port,
165}; 166};
166 167
167static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev) 168static int ehci_hcd_ppc_soc_drv_probe(struct platform_device *pdev)
diff --git a/drivers/usb/host/ehci-ps3.c b/drivers/usb/host/ehci-ps3.c
index 03a6b2f4e6e..bbda58eb881 100644
--- a/drivers/usb/host/ehci-ps3.c
+++ b/drivers/usb/host/ehci-ps3.c
@@ -72,6 +72,7 @@ static const struct hc_driver ps3_ehci_hc_driver = {
72 .bus_suspend = ehci_bus_suspend, 72 .bus_suspend = ehci_bus_suspend,
73 .bus_resume = ehci_bus_resume, 73 .bus_resume = ehci_bus_resume,
74#endif 74#endif
75 .relinquish_port = ehci_relinquish_port,
75}; 76};
76 77
77static int ps3_ehci_probe(struct ps3_system_bus_device *dev) 78static int ps3_ehci_probe(struct ps3_system_bus_device *dev)