Browse Source

Merge tag 'fixes-for-v3.7-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb into usb-linus

usb: fixes for v3.7-rc2

Here's the first set of fixes for v3.7-rc cycle.

DesignWare Core USB3 Driver (dwc3) got two fixes. The first one fixes a long
standing bug which would keep endpoint with BUSY flag set forever if we cancel
a transfer which has already been started by the controller. The second fix
will just switch PHYs back off when DWC3 driver is removed.

MUSB fixed a bug which would cause a Kernel Oops at least on AM3517 when
removing a device. For some reason that particular device can fall into a
situation where you have both Disconnect and Endpoint IRQs happen
simultaneously (have both bits set in IRQ_STATUS register) and, because
Disconnect Interrupt is handled before Endpoint Interrupts, we would try to
transfer data over a disconnected device, thus generating a kernel oops.

Renensas' USB DRD driver got two fixes which are a) fixing an off-by-one bug on
the pipe iterator implementation and b) fixing Interrupt Status Clear procedure
in order to properly clear a single Interrupt event without clearing (and
masking) other events we didn't handle yet.
Greg Kroah-Hartman 12 years ago
parent
commit
6b7ced68f3

+ 4 - 0
drivers/usb/dwc3/core.c

@@ -409,6 +409,10 @@ static void dwc3_core_exit(struct dwc3 *dwc)
 {
 	dwc3_event_buffers_cleanup(dwc);
 	dwc3_free_event_buffers(dwc);
+
+	usb_phy_shutdown(dwc->usb2_phy);
+	usb_phy_shutdown(dwc->usb3_phy);
+
 }
 
 #define DWC3_ALIGN_MASK		(16 - 1)

+ 1 - 1
drivers/usb/dwc3/gadget.c

@@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
 	ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, &params);
 	WARN_ON_ONCE(ret);
 	dep->resource_index = 0;
-
+	dep->flags &= ~DWC3_EP_BUSY;
 	udelay(100);
 }
 

+ 2 - 2
drivers/usb/gadget/lpc32xx_udc.c

@@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work)
 
 		/* Get the VBUS status from the transceiver */
 		value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client,
-						 ISP1301_I2C_OTG_CONTROL_2);
+						 ISP1301_I2C_INTERRUPT_SOURCE);
 
 		/* VBUS on or off? */
-		if (value & OTG_B_SESS_VLD)
+		if (value & INT_SESS_VLD)
 			udc->vbus = 1;
 		else
 			udc->vbus = 0;

+ 6 - 0
drivers/usb/musb/am35x.c

@@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci)
 		ret = IRQ_HANDLED;
 	}
 
+	/* Drop spurious RX and TX if device is disconnected */
+	if (musb->int_usb & MUSB_INTR_DISCONNECT) {
+		musb->int_tx = 0;
+		musb->int_rx = 0;
+	}
+
 	if (musb->int_tx || musb->int_rx || musb->int_usb)
 		ret |= musb_interrupt(musb);
 

+ 3 - 3
drivers/usb/renesas_usbhs/mod.c

@@ -273,9 +273,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data)
 	usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC);
 	usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC);
 
-	usbhs_write(priv, BRDYSTS, 0);
-	usbhs_write(priv, NRDYSTS, 0);
-	usbhs_write(priv, BEMPSTS, 0);
+	usbhs_write(priv, BRDYSTS, ~irq_state.brdysts);
+	usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts);
+	usbhs_write(priv, BEMPSTS, ~irq_state.bempsts);
 
 	/*
 	 * call irq callback functions

+ 1 - 1
drivers/usb/renesas_usbhs/pipe.h

@@ -54,7 +54,7 @@ struct usbhs_pipe_info {
  * pipe list
  */
 #define __usbhs_for_each_pipe(start, pos, info, i)	\
-	for (i = start, pos = (info)->pipe;		\
+	for (i = start, pos = (info)->pipe + i;		\
 	     i < (info)->size;				\
 	     i++, pos = (info)->pipe + i)