[PATCH 3/5] usb/musb: don't read from MUSB_INTRTXE

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

 



This is part of the workaround for AM35x advisory Advisory 1.1.20.
The advisory says that the IPSS bridge can't handle 8 & 16 bit read
access. An 16bit read access to MUSB_INTRTXE results in an 32bit read
access which also reads INTRRX and therefore may lose interrupts.
This patch uses a shadow register of MUSB_INTRTXE so we only perform
write access to it.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
---
 drivers/usb/musb/musb_core.c   |    8 +++++---
 drivers/usb/musb/musb_gadget.c |   17 +++++++----------
 drivers/usb/musb/musb_host.c   |    8 +++-----
 3 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index ee04eae..b1dffea 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -670,7 +670,8 @@ static irqreturn_t musb_stage0_irq(struct musb *musb, u8 int_usb,
 		if (is_peripheral_active(musb)) {
 			/* REVISIT HNP; just force disconnect */
 		}
-		musb_writew(musb->mregs, MUSB_INTRTXE, musb->epmask);
+		musb->context.intrtxe = musb->epmask;
+		musb_writew(musb->mregs, MUSB_INTRTXE, musb->context.intrtxe);
 		musb->context.intrrxe = musb->epmask & 0xfffe;
 		musb_writew(musb->mregs, MUSB_INTRRXE, musb->context.intrrxe);
 		musb_writeb(musb->mregs, MUSB_INTRUSBE, 0xf7);
@@ -893,7 +894,8 @@ void musb_start(struct musb *musb)
 	dev_dbg(musb->controller, "<== devctl %02x\n", devctl);
 
 	/*  Set INT enable registers, enable interrupts */
-	musb_writew(regs, MUSB_INTRTXE, musb->epmask);
+	musb->context.intrtxe = musb->epmask;
+	musb_writew(regs, MUSB_INTRTXE, musb->context.intrtxe);
 	musb->context.intrrxe = musb->epmask & 0xfffe;
 	musb_writew(musb->mregs, MUSB_INTRRXE, musb->context.intrrxe);
 	musb_writeb(regs, MUSB_INTRUSBE, 0xf7);
@@ -942,6 +944,7 @@ static void musb_generic_disable(struct musb *musb)
 
 	/* disable interrupts */
 	musb_writeb(mbase, MUSB_INTRUSBE, 0);
+	musb->context.intrtxe = 0;
 	musb_writew(mbase, MUSB_INTRTXE, 0);
 	musb->context.intrrxe = 0;
 	musb_writew(musb->mregs, MUSB_INTRRXE, musb->context.intrrxe);
@@ -2142,7 +2145,6 @@ static void musb_save_context(struct musb *musb)
 		musb->context.busctl = musb_read_ulpi_buscontrol(musb->mregs);
 	}
 	musb->context.power = musb_readb(musb_base, MUSB_POWER);
-	musb->context.intrtxe = musb_readw(musb_base, MUSB_INTRTXE);
 	musb->context.intrusbe = musb_readb(musb_base, MUSB_INTRUSBE);
 	musb->context.index = musb_readb(musb_base, MUSB_INDEX);
 	musb->context.devctl = musb_readb(musb_base, MUSB_DEVCTL);
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index 629c2ea..cc24445 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1079,7 +1079,6 @@ static int musb_gadget_enable(struct usb_ep *ep,
 	 */
 	musb_ep_select(mbase, epnum);
 	if (usb_endpoint_dir_in(desc)) {
-		u16 int_txe = musb_readw(mbase, MUSB_INTRTXE);
 
 		if (hw_ep->is_shared_fifo)
 			musb_ep->is_in = 1;
@@ -1091,8 +1090,8 @@ static int musb_gadget_enable(struct usb_ep *ep,
 			goto fail;
 		}
 
-		int_txe |= (1 << epnum);
-		musb_writew(mbase, MUSB_INTRTXE, int_txe);
+		musb->context.intrtxe |= (1 << epnum);
+		musb_writew(mbase, MUSB_INTRTXE, musb->context.intrtxe);
 
 		/* REVISIT if can_bulk_split(), use by updating "tmp";
 		 * likewise high bandwidth periodic tx
@@ -1218,9 +1217,8 @@ static int musb_gadget_disable(struct usb_ep *ep)
 
 	/* zero the endpoint sizes */
 	if (musb_ep->is_in) {
-		u16 int_txe = musb_readw(musb->mregs, MUSB_INTRTXE);
-		int_txe &= ~(1 << epnum);
-		musb_writew(musb->mregs, MUSB_INTRTXE, int_txe);
+		musb->context.intrtxe &= ~(1 << epnum);
+		musb_writew(musb->mregs, MUSB_INTRTXE, musb->context.intrtxe);
 		musb_writew(epio, MUSB_TXMAXP, 0);
 	} else {
 		musb->context.intrrxe &= ~(1 << epnum);
@@ -1539,7 +1537,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 	void __iomem	*epio = musb->endpoints[epnum].regs;
 	void __iomem	*mbase;
 	unsigned long	flags;
-	u16		csr, int_txe;
+	u16		csr;
 
 	mbase = musb->mregs;
 
@@ -1547,8 +1545,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 	musb_ep_select(mbase, (u8) epnum);
 
 	/* disable interrupts */
-	int_txe = musb_readw(mbase, MUSB_INTRTXE);
-	musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
+	musb_writew(mbase, MUSB_INTRTXE, musb->context.intrtxe & ~(1 << epnum));
 
 	if (musb_ep->is_in) {
 		csr = musb_readw(epio, MUSB_TXCSR);
@@ -1572,7 +1569,7 @@ static void musb_gadget_fifo_flush(struct usb_ep *ep)
 	}
 
 	/* re-enable interrupt */
-	musb_writew(mbase, MUSB_INTRTXE, int_txe);
+	musb_writew(mbase, MUSB_INTRTXE, musb->context.intrtxe);
 	spin_unlock_irqrestore(&musb->lock, flags);
 }
 
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index 79cb0af..34829fe 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -714,15 +714,13 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
 	/* OUT/transmit/EP0 or IN/receive? */
 	if (is_out) {
 		u16	csr;
-		u16	int_txe;
 		u16	load_count;
 
 		csr = musb_readw(epio, MUSB_TXCSR);
 
 		/* disable interrupt in case we flush */
-		int_txe = musb_readw(mbase, MUSB_INTRTXE);
-		musb_writew(mbase, MUSB_INTRTXE, int_txe & ~(1 << epnum));
-
+		musb_writew(mbase, MUSB_INTRTXE, musb->context.intrtxe &
+				~(1 << epnum));
 		/* general endpoint setup */
 		if (epnum) {
 			/* flush all old state, set default */
@@ -807,7 +805,7 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
 		}
 
 		/* re-enable interrupt */
-		musb_writew(mbase, MUSB_INTRTXE, int_txe);
+		musb_writew(mbase, MUSB_INTRTXE, musb->context.intrtxe);
 
 	/* IN/receive */
 	} else {
-- 
1.7.9.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