[RFC 1/3] EHCI: store the interrupt mask in memory

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

 



This patch adds a new field to the ehci-hcd private structure, for
holding the value of the EHCI Interrupt Enable register, together with
an inline routine for setting this value.

The ehci->intr-enable field will used in a following patch, when a
tasklet's bottom-half handler needs to restore the correct interrupt
mask.

Not-yet-signed-off-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>

---


 drivers/usb/host/ehci-hcd.c   |   21 ++++++++++++++-------
 drivers/usb/host/ehci-hub.c   |    6 +++---
 drivers/usb/host/ehci-timer.c |    2 +-
 drivers/usb/host/ehci.h       |    1 +
 4 files changed, 19 insertions(+), 11 deletions(-)

Index: usb-3.11/drivers/usb/host/ehci-hcd.c
===================================================================
--- usb-3.11.orig/drivers/usb/host/ehci-hcd.c
+++ usb-3.11/drivers/usb/host/ehci-hcd.c
@@ -134,6 +134,12 @@ static inline unsigned ehci_read_frame_i
 	return ehci_readl(ehci, &ehci->regs->frame_index);
 }
 
+static inline void ehci_set_intr_enable(struct ehci_hcd *ehci, u32 mask)
+{
+	ehci->intr_mask = mask;
+	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+}
+
 #include "ehci-dbg.c"
 
 /*-------------------------------------------------------------------------*/
@@ -194,7 +200,7 @@ static int ehci_halt (struct ehci_hcd *e
 	spin_lock_irq(&ehci->lock);
 
 	/* disable any irqs left enabled by previous code */
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci_set_intr_enable(ehci, 0);
 
 	if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) {
 		spin_unlock_irq(&ehci->lock);
@@ -639,8 +645,9 @@ static int ehci_run (struct usb_hcd *hcd
 		temp >> 8, temp & 0xff,
 		ignore_oc ? ", overcurrent ignored" : "");
 
-	ehci_writel(ehci, INTR_MASK,
-		    &ehci->regs->intr_enable); /* Turn On Interrupts */
+	spin_lock_irq(&ehci->lock);
+	ehci_set_intr_enable(ehci, INTR_MASK);	/* 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()
@@ -817,7 +824,7 @@ dead:
 		ehci->rh_state = EHCI_RH_STOPPING;
 		ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE);
 		ehci_writel(ehci, ehci->command, &ehci->regs->command);
-		ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+		ehci_set_intr_enable(ehci, 0);
 		ehci_handle_controller_death(ehci);
 
 		/* Handle completions when the controller stops */
@@ -1080,7 +1087,7 @@ int ehci_suspend(struct usb_hcd *hcd, bo
 	ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
 
 	spin_lock_irq(&ehci->lock);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci_set_intr_enable(ehci, 0);
 	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
 
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
@@ -1111,7 +1118,7 @@ int ehci_resume(struct usb_hcd *hcd, boo
 	 */
 	if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
 			!hibernated) {
-		int	mask = INTR_MASK;
+		u32	mask = INTR_MASK;
 
 		ehci_prepare_ports_for_controller_resume(ehci);
 
@@ -1121,7 +1128,7 @@ int ehci_resume(struct usb_hcd *hcd, boo
 
 		if (!hcd->self.root_hub->do_remote_wakeup)
 			mask &= ~STS_PCD;
-		ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+		ehci_set_intr_enable(ehci, mask);
 		ehci_readl(ehci, &ehci->regs->intr_enable);
  skip:
 		spin_unlock_irq(&ehci->lock);
Index: usb-3.11/drivers/usb/host/ehci-hub.c
===================================================================
--- usb-3.11.orig/drivers/usb/host/ehci-hub.c
+++ usb-3.11/drivers/usb/host/ehci-hub.c
@@ -352,7 +352,7 @@ static int ehci_bus_suspend (struct usb_
 	mask = INTR_MASK;
 	if (!hcd->self.root_hub->do_remote_wakeup)
 		mask &= ~STS_PCD;
-	ehci_writel(ehci, mask, &ehci->regs->intr_enable);
+	ehci_set_intr_enable(ehci, mask);
 	ehci_readl(ehci, &ehci->regs->intr_enable);
 
  done:
@@ -401,7 +401,7 @@ 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_set_intr_enable(ehci, 0);
 
 	/* re-init operational registers */
 	ehci_writel(ehci, 0, &ehci->regs->segment);
@@ -495,7 +495,7 @@ static int ehci_bus_resume (struct usb_h
 	spin_lock_irq(&ehci->lock);
 	if (ehci->shutdown)
 		goto shutdown;
-	ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable);
+	ehci_set_intr_enable(ehci, INTR_MASK);
 	(void) ehci_readl(ehci, &ehci->regs->intr_enable);
 	spin_unlock_irq(&ehci->lock);
 
Index: usb-3.11/drivers/usb/host/ehci.h
===================================================================
--- usb-3.11.orig/drivers/usb/host/ehci.h
+++ usb-3.11/drivers/usb/host/ehci.h
@@ -186,6 +186,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;
Index: usb-3.11/drivers/usb/host/ehci-timer.c
===================================================================
--- usb-3.11.orig/drivers/usb/host/ehci-timer.c
+++ usb-3.11/drivers/usb/host/ehci-timer.c
@@ -208,7 +208,7 @@ static void ehci_handle_controller_death
 	/* Clean up the mess */
 	ehci->rh_state = EHCI_RH_HALTED;
 	ehci_writel(ehci, 0, &ehci->regs->configured_flag);
-	ehci_writel(ehci, 0, &ehci->regs->intr_enable);
+	ehci_set_intr_enable(ehci, 0);
 	ehci_work(ehci);
 	end_unlink_async(ehci);
 

--
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