Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 67926
b: refs/heads/master
c: 32fe019
h: refs/heads/master
v: v3
  • Loading branch information
Alan Stern authored and Greg Kroah-Hartman committed Oct 12, 2007
1 parent aa812cd commit a0e98d1
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 3 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: 17f060224fb9f435c6f9306b7b61419d038def13
refs/heads/master: 32fe01985aa2cb2562f6fc171e526e279abe10db
8 changes: 7 additions & 1 deletion trunk/drivers/usb/core/hcd.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

#ifdef __KERNEL__

#include <linux/rwsem.h>

/* This file contains declarations of usbcore internals that are mostly
* used or exposed by Host Controller Drivers.
*/
Expand Down Expand Up @@ -470,5 +472,9 @@ static inline void usbmon_urb_complete(struct usb_bus *bus, struct urb *urb,
: (in_interrupt () ? "in_interrupt" : "can sleep"))


#endif /* __KERNEL__ */
/* This rwsem is for use only by the hub driver and ehci-hcd.
* Nobody else should touch it.
*/
extern struct rw_semaphore ehci_cf_port_reset_rwsem;

#endif /* __KERNEL__ */
15 changes: 14 additions & 1 deletion trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ MODULE_PARM_DESC(use_both_schemes,
"try the other device initialization scheme if the "
"first one fails");

/* Mutual exclusion for EHCI CF initialization. This interferes with
* port reset on some companion controllers.
*/
DECLARE_RWSEM(ehci_cf_port_reset_rwsem);
EXPORT_SYMBOL_GPL(ehci_cf_port_reset_rwsem);


static inline char *portspeed(int portstatus)
{
Expand Down Expand Up @@ -1581,6 +1587,11 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
{
int i, status;

/* Block EHCI CF initialization during the port reset.
* Some companion controllers don't like it when they mix.
*/
down_read(&ehci_cf_port_reset_rwsem);

/* Reset the port */
for (i = 0; i < PORT_RESET_TRIES; i++) {
status = set_port_feature(hub->hdev,
Expand Down Expand Up @@ -1612,7 +1623,7 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
usb_set_device_state(udev, status
? USB_STATE_NOTATTACHED
: USB_STATE_DEFAULT);
return status;
goto done;
}

dev_dbg (hub->intfdev,
Expand All @@ -1625,6 +1636,8 @@ static int hub_port_reset(struct usb_hub *hub, int port1,
"Cannot enable port %i. Maybe the USB cable is bad?\n",
port1);

done:
up_read(&ehci_cf_port_reset_rwsem);
return status;
}

Expand Down
8 changes: 8 additions & 0 deletions trunk/drivers/usb/host/ehci-hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -570,10 +570,18 @@ static int ehci_run (struct usb_hcd *hcd)
* are explicitly handed to companion controller(s), so no TT is
* involved with the root hub. (Except where one is integrated,
* and there's no companion controller unless maybe for USB OTG.)
*
* Turning on the CF flag will transfer ownership of all ports
* from the companions to the EHCI controller. If any of the
* companions are in the middle of a port reset at the time, it
* could cause trouble. Write-locking ehci_cf_port_reset_rwsem
* guarantees that no resets are in progress.
*/
down_write(&ehci_cf_port_reset_rwsem);
hcd->state = HC_STATE_RUNNING;
ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
up_write(&ehci_cf_port_reset_rwsem);

temp = HC_VERSION(ehci_readl(ehci, &ehci->caps->hc_capbase));
ehci_info (ehci,
Expand Down

0 comments on commit a0e98d1

Please sign in to comment.