Re: [PATCH] usb: hcd: allow wakeups while suspended for Moorestown

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 13 Apr 2011, Kristen Carlson Accardi wrote:

> So are you going to send an updated patch?

Here is the promised patch.  I haven't tested it, but it look looks 
okay and compiles without errors.

Alan Stern



 drivers/usb/host/ehci-au1xxx.c |   12 +++++++-----
 drivers/usb/host/ehci-hcd.c    |   12 ++++++++++--
 drivers/usb/host/ehci-hub.c    |   13 +++++++------
 drivers/usb/host/ehci-pci.c    |   12 +++++++-----
 drivers/usb/host/ehci.h        |    1 +
 5 files changed, 32 insertions(+), 18 deletions(-)

Index: usb-2.6/drivers/usb/host/ehci-au1xxx.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-au1xxx.c
+++ usb-2.6/drivers/usb/host/ehci-au1xxx.c
@@ -229,7 +229,8 @@ static int ehci_hcd_au1xxx_drv_suspend(s
 	 */
 	ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
 	spin_lock_irqsave(&ehci->lock, flags);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci->intr_mask = 0;
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -262,13 +263,14 @@ static int ehci_hcd_au1xxx_drv_resume(st
 	 * Just undo the effect of ehci_pci_suspend().
 	 */
 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
-		int	mask = INTR_MASK;
-
 		ehci_prepare_ports_for_controller_resume(ehci);
+		spin_lock_irq(&ehci->lock);
+		ehci->intr_mask = INTR_MASK;
 		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+			ehci->intr_mask &= ~STS_PCD;
+		ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 		ehci_readl(ehci, &ehci->regs->intr_enable);
+		spin_unlock_irq(&ehci->lock);
 		return 0;
 	}
 
Index: usb-2.6/drivers/usb/host/ehci-hcd.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-hcd.c
+++ usb-2.6/drivers/usb/host/ehci-hcd.c
@@ -212,7 +212,8 @@ static int ehci_halt (struct ehci_hcd *e
 	u32	temp = ehci_readl(ehci, &ehci->regs->status);
 
 	/* disable any irqs left enabled by previous code */
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci->intr_mask = 0;
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 
 	if (ehci_is_TDI(ehci) && tdi_in_host_mode(ehci) == 0) {
 		return 0;
@@ -746,8 +747,11 @@ static int ehci_run (struct usb_hcd *hcd
 		temp >> 8, temp & 0xff,
 		ignore_oc ? ", overcurrent ignored" : "");
 
-	ehci_writel(ehci, INTR_MASK,
+	spin_lock_irq(&ehci->lock);
+	ehci->intr_mask = INTR_MASK;
+	ehci_writel(ehci, ehci->intr_mask,
 		    &ehci->regs->intr_enable); /* Turn On Interrupts */
+	spin_unlock_irq(&ehci->lock);
 
 	/* GRR this is run-once init(), being done every time the HC starts.
 	 * So long as they're part of class devices, we can't do it init()
@@ -881,6 +885,10 @@ dead:
 
 	if (bh)
 		ehci_work (ehci);
+
+	/* Threaded interrupt handler must re-enable interrupts */
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
+
 	spin_unlock (&ehci->lock);
 	if (pcd_status)
 		usb_hcd_poll_rh_status(hcd);
Index: usb-2.6/drivers/usb/host/ehci-hub.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-hub.c
+++ usb-2.6/drivers/usb/host/ehci-hub.c
@@ -204,7 +204,6 @@ static int ehci_bus_suspend (struct usb_
 {
 	struct ehci_hcd		*ehci = hcd_to_ehci (hcd);
 	int			port;
-	int			mask;
 	int			changed;
 
 	ehci_dbg(ehci, "suspend root hub\n");
@@ -318,10 +317,10 @@ static int ehci_bus_suspend (struct usb_
 		end_unlink_async(ehci);
 
 	/* allow remote wakeup */
-	mask = INTR_MASK;
+	ehci->intr_mask = INTR_MASK;
 	if (!hcd->self.root_hub->do_remote_wakeup)
-		mask &= ~STS_PCD;
-	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+		ehci->intr_mask &= ~STS_PCD;
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 	ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	ehci->next_statechange = jiffies + msecs_to_jiffies(10);
@@ -372,7 +371,8 @@ static int ehci_bus_resume (struct usb_h
 	/* at least some APM implementations will try to deliver
 	 * IRQs right away, so delay them until we're ready.
 	 */
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci->intr_mask = 0;
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 
 	/* re-init operational registers */
 	ehci_writel(ehci, 0, &ehci->regs->segment);
@@ -454,7 +454,8 @@ static int ehci_bus_resume (struct usb_h
 	hcd->state = HC_STATE_RUNNING;
 
 	/* Now we can safely re-enable irqs */
-	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+	ehci->intr_mask = INTR_MASK;
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 
 	spin_unlock_irq (&ehci->lock);
 	ehci_handover_companion_ports(ehci);
Index: usb-2.6/drivers/usb/host/ehci-pci.c
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci-pci.c
+++ usb-2.6/drivers/usb/host/ehci-pci.c
@@ -336,7 +336,8 @@ static int ehci_pci_suspend(struct usb_h
 	 */
 	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
 	spin_lock_irqsave (&ehci->lock, flags);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci->intr_mask = 0;
+	ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 	(void)ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -367,13 +368,14 @@ static int ehci_pci_resume(struct usb_hc
 	 */
 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
 				!hibernated) {
-		int	mask = INTR_MASK;
-
 		ehci_prepare_ports_for_controller_resume(ehci);
+		spin_lock_irq(&ehci->lock);
+		ehci->intr_mask = INTR_MASK;
 		if (!hcd->self.root_hub->do_remote_wakeup)
-			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+			ehci->intr_mask &= ~STS_PCD;
+		ehci_writel(ehci, ehci->intr_mask, &ehci->regs->intr_enable);
 		ehci_readl(ehci, &ehci->regs->intr_enable);
+		spin_unlock_irq(&ehci->lock);
 		return 0;
 	}
 
Index: usb-2.6/drivers/usb/host/ehci.h
===================================================================
--- usb-2.6.orig/drivers/usb/host/ehci.h
+++ usb-2.6/drivers/usb/host/ehci.h
@@ -122,6 +122,7 @@ struct ehci_hcd {			/* one per controlle
 	unsigned long		next_statechange;
 	ktime_t			last_periodic_enable;
 	u32			command;
+	u32			intr_mask;
 
 	/* SILICON QUIRKS */
 	unsigned		no_selective_suspend:1;

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux