diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-18 11:14:10 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-10-18 11:14:10 -0400 |
commit | 6b7ced68f3fbbab6e9625b957f1ea0add22a5ac7 (patch) | |
tree | 40e367c4a0c6fd920faa69b0f948fcb0877f7b40 /drivers/usb | |
parent | 470809741a28c3092279f4e1f3f432e534d46068 (diff) | |
parent | 69da85edbab5cd42909d3ba65b3dad1c1fb40206 (diff) |
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.
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/dwc3/core.c | 4 | ||||
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 2 | ||||
-rw-r--r-- | drivers/usb/gadget/lpc32xx_udc.c | 4 | ||||
-rw-r--r-- | drivers/usb/musb/am35x.c | 6 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/mod.c | 6 | ||||
-rw-r--r-- | drivers/usb/renesas_usbhs/pipe.h | 2 |
6 files changed, 17 insertions, 7 deletions
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index b415c0c859d3..c14ebc975ba4 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -409,6 +409,10 @@ static void dwc3_core_exit(struct dwc3 *dwc) | |||
409 | { | 409 | { |
410 | dwc3_event_buffers_cleanup(dwc); | 410 | dwc3_event_buffers_cleanup(dwc); |
411 | dwc3_free_event_buffers(dwc); | 411 | dwc3_free_event_buffers(dwc); |
412 | |||
413 | usb_phy_shutdown(dwc->usb2_phy); | ||
414 | usb_phy_shutdown(dwc->usb3_phy); | ||
415 | |||
412 | } | 416 | } |
413 | 417 | ||
414 | #define DWC3_ALIGN_MASK (16 - 1) | 418 | #define DWC3_ALIGN_MASK (16 - 1) |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c9e729a4bf65..7b7deddf6a52 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -1904,7 +1904,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum) | |||
1904 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | 1904 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); |
1905 | WARN_ON_ONCE(ret); | 1905 | WARN_ON_ONCE(ret); |
1906 | dep->resource_index = 0; | 1906 | dep->resource_index = 0; |
1907 | 1907 | dep->flags &= ~DWC3_EP_BUSY; | |
1908 | udelay(100); | 1908 | udelay(100); |
1909 | } | 1909 | } |
1910 | 1910 | ||
diff --git a/drivers/usb/gadget/lpc32xx_udc.c b/drivers/usb/gadget/lpc32xx_udc.c index f696fb9b136d..21a9861dabf0 100644 --- a/drivers/usb/gadget/lpc32xx_udc.c +++ b/drivers/usb/gadget/lpc32xx_udc.c | |||
@@ -2930,10 +2930,10 @@ static void vbus_work(struct work_struct *work) | |||
2930 | 2930 | ||
2931 | /* Get the VBUS status from the transceiver */ | 2931 | /* Get the VBUS status from the transceiver */ |
2932 | value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client, | 2932 | value = i2c_smbus_read_byte_data(udc->isp1301_i2c_client, |
2933 | ISP1301_I2C_OTG_CONTROL_2); | 2933 | ISP1301_I2C_INTERRUPT_SOURCE); |
2934 | 2934 | ||
2935 | /* VBUS on or off? */ | 2935 | /* VBUS on or off? */ |
2936 | if (value & OTG_B_SESS_VLD) | 2936 | if (value & INT_SESS_VLD) |
2937 | udc->vbus = 1; | 2937 | udc->vbus = 1; |
2938 | else | 2938 | else |
2939 | udc->vbus = 0; | 2939 | udc->vbus = 0; |
diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c index 457f25e62c51..c964d6af178b 100644 --- a/drivers/usb/musb/am35x.c +++ b/drivers/usb/musb/am35x.c | |||
@@ -305,6 +305,12 @@ static irqreturn_t am35x_musb_interrupt(int irq, void *hci) | |||
305 | ret = IRQ_HANDLED; | 305 | ret = IRQ_HANDLED; |
306 | } | 306 | } |
307 | 307 | ||
308 | /* Drop spurious RX and TX if device is disconnected */ | ||
309 | if (musb->int_usb & MUSB_INTR_DISCONNECT) { | ||
310 | musb->int_tx = 0; | ||
311 | musb->int_rx = 0; | ||
312 | } | ||
313 | |||
308 | if (musb->int_tx || musb->int_rx || musb->int_usb) | 314 | if (musb->int_tx || musb->int_rx || musb->int_usb) |
309 | ret |= musb_interrupt(musb); | 315 | ret |= musb_interrupt(musb); |
310 | 316 | ||
diff --git a/drivers/usb/renesas_usbhs/mod.c b/drivers/usb/renesas_usbhs/mod.c index 35c5208f3249..61933a90e5bf 100644 --- a/drivers/usb/renesas_usbhs/mod.c +++ b/drivers/usb/renesas_usbhs/mod.c | |||
@@ -273,9 +273,9 @@ static irqreturn_t usbhs_interrupt(int irq, void *data) | |||
273 | usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC); | 273 | usbhs_write(priv, INTSTS0, ~irq_state.intsts0 & INTSTS0_MAGIC); |
274 | usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC); | 274 | usbhs_write(priv, INTSTS1, ~irq_state.intsts1 & INTSTS1_MAGIC); |
275 | 275 | ||
276 | usbhs_write(priv, BRDYSTS, 0); | 276 | usbhs_write(priv, BRDYSTS, ~irq_state.brdysts); |
277 | usbhs_write(priv, NRDYSTS, 0); | 277 | usbhs_write(priv, NRDYSTS, ~irq_state.nrdysts); |
278 | usbhs_write(priv, BEMPSTS, 0); | 278 | usbhs_write(priv, BEMPSTS, ~irq_state.bempsts); |
279 | 279 | ||
280 | /* | 280 | /* |
281 | * call irq callback functions | 281 | * call irq callback functions |
diff --git a/drivers/usb/renesas_usbhs/pipe.h b/drivers/usb/renesas_usbhs/pipe.h index 08786c06dcf1..3d80c7b1fd1b 100644 --- a/drivers/usb/renesas_usbhs/pipe.h +++ b/drivers/usb/renesas_usbhs/pipe.h | |||
@@ -54,7 +54,7 @@ struct usbhs_pipe_info { | |||
54 | * pipe list | 54 | * pipe list |
55 | */ | 55 | */ |
56 | #define __usbhs_for_each_pipe(start, pos, info, i) \ | 56 | #define __usbhs_for_each_pipe(start, pos, info, i) \ |
57 | for (i = start, pos = (info)->pipe; \ | 57 | for (i = start, pos = (info)->pipe + i; \ |
58 | i < (info)->size; \ | 58 | i < (info)->size; \ |
59 | i++, pos = (info)->pipe + i) | 59 | i++, pos = (info)->pipe + i) |
60 | 60 | ||