diff options
Diffstat (limited to 'drivers/usb')
| -rw-r--r-- | drivers/usb/core/hcd-pci.c | 27 | ||||
| -rw-r--r-- | drivers/usb/core/hcd.c | 4 | ||||
| -rw-r--r-- | drivers/usb/host/xhci-ring.c | 2 | 
3 files changed, 29 insertions, 4 deletions
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 88d9109b4b4..b992a886f05 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c @@ -367,6 +367,13 @@ static int check_root_hub_suspended(struct device *dev)  		dev_warn(dev, "Root hub is not suspended\n");  		return -EBUSY;  	} +	if (hcd->shared_hcd) { +		hcd = hcd->shared_hcd; +		if (HCD_RH_RUNNING(hcd)) { +			dev_warn(dev, "Secondary root hub is not suspended\n"); +			return -EBUSY; +		} +	}  	return 0;  } @@ -391,11 +398,16 @@ static int suspend_common(struct device *dev, bool do_wakeup)  		 */  		if (do_wakeup && HCD_WAKEUP_PENDING(hcd))  			return -EBUSY; +		if (do_wakeup && hcd->shared_hcd && +				HCD_WAKEUP_PENDING(hcd->shared_hcd)) +			return -EBUSY;  		retval = hcd->driver->pci_suspend(hcd, do_wakeup);  		suspend_report_result(hcd->driver->pci_suspend, retval);  		/* Check again in case wakeup raced with pci_suspend */ -		if (retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) { +		if ((retval == 0 && do_wakeup && HCD_WAKEUP_PENDING(hcd)) || +				(retval == 0 && do_wakeup && hcd->shared_hcd && +				 HCD_WAKEUP_PENDING(hcd->shared_hcd))) {  			if (hcd->driver->pci_resume)  				hcd->driver->pci_resume(hcd, false);  			retval = -EBUSY; @@ -426,7 +438,9 @@ static int resume_common(struct device *dev, int event)  	struct usb_hcd		*hcd = pci_get_drvdata(pci_dev);  	int			retval; -	if (HCD_RH_RUNNING(hcd)) { +	if (HCD_RH_RUNNING(hcd) || +			(hcd->shared_hcd && +			 HCD_RH_RUNNING(hcd->shared_hcd))) {  		dev_dbg(dev, "can't resume, not suspended!\n");  		return 0;  	} @@ -440,6 +454,8 @@ static int resume_common(struct device *dev, int event)  	pci_set_master(pci_dev);  	clear_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); +	if (hcd->shared_hcd) +		clear_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);  	if (hcd->driver->pci_resume && !HCD_DEAD(hcd)) {  		if (event != PM_EVENT_AUTO_RESUME) @@ -449,6 +465,8 @@ static int resume_common(struct device *dev, int event)  				event == PM_EVENT_RESTORE);  		if (retval) {  			dev_err(dev, "PCI post-resume error %d!\n", retval); +			if (hcd->shared_hcd) +				usb_hc_died(hcd->shared_hcd);  			usb_hc_died(hcd);  		}  	} @@ -474,8 +492,9 @@ static int hcd_pci_suspend_noirq(struct device *dev)  	pci_save_state(pci_dev); -	/* If the root hub is dead rather than suspended, -	 * disallow remote wakeup. +	/* If the root hub is dead rather than suspended, disallow remote +	 * wakeup.  usb_hc_died() should ensure that both hosts are marked as +	 * dying, so we only need to check the primary roothub.  	 */  	if (HCD_DEAD(hcd))  		device_set_wakeup_enable(dev, 0); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index ba15eeab824..02b4dbfa488 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -1153,6 +1153,8 @@ int usb_hcd_check_unlink_urb(struct usb_hcd *hcd, struct urb *urb,  		dev_warn(hcd->self.controller, "Unlink after no-IRQ?  "  			"Controller is probably using the wrong IRQ.\n");  		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); +		if (hcd->shared_hcd) +			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);  	}  	return 0; @@ -2124,6 +2126,8 @@ irqreturn_t usb_hcd_irq (int irq, void *__hcd)  		rc = IRQ_NONE;  	} else {  		set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); +		if (hcd->shared_hcd) +			set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);  		if (unlikely(hcd->state == HC_STATE_HALT))  			usb_hc_died(hcd); diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 9e2b26c3da4..47763bed378 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c @@ -2181,6 +2181,8 @@ irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd)  	irqreturn_t ret;  	set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); +	if (hcd->shared_hcd) +		set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags);  	ret = xhci_irq(hcd);  |