| From 5719df243e118fb343725e8b2afb1637e1af1373 Mon Sep 17 00:00:00 2001 |
| From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| Date: Thu, 24 Jun 2021 21:20:39 +0900 |
| Subject: usb: renesas_usbhs: Fix superfluous irqs happen after usb_pkt_pop() |
| |
| From: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| |
| commit 5719df243e118fb343725e8b2afb1637e1af1373 upstream. |
| |
| This driver has a potential issue which this driver is possible to |
| cause superfluous irqs after usb_pkt_pop() is called. So, after |
| the commit 3af32605289e ("usb: renesas_usbhs: fix error return |
| code of usbhsf_pkt_handler()") had been applied, we could observe |
| the following error happened when we used g_audio. |
| |
| renesas_usbhs e6590000.usb: irq_ready run_error 1 : -22 |
| |
| To fix the issue, disable the tx or rx interrupt in usb_pkt_pop(). |
| |
| Fixes: 2743e7f90dc0 ("usb: renesas_usbhs: fix the usb_pkt_pop()") |
| Cc: <stable@vger.kernel.org> # v4.4+ |
| Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com> |
| Link: https://lore.kernel.org/r/20210624122039.596528-1-yoshihiro.shimoda.uh@renesas.com |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/usb/renesas_usbhs/fifo.c | 7 +++++++ |
| 1 file changed, 7 insertions(+) |
| |
| --- a/drivers/usb/renesas_usbhs/fifo.c |
| +++ b/drivers/usb/renesas_usbhs/fifo.c |
| @@ -101,6 +101,8 @@ static struct dma_chan *usbhsf_dma_chan_ |
| #define usbhsf_dma_map(p) __usbhsf_dma_map_ctrl(p, 1) |
| #define usbhsf_dma_unmap(p) __usbhsf_dma_map_ctrl(p, 0) |
| static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map); |
| +static void usbhsf_tx_irq_ctrl(struct usbhs_pipe *pipe, int enable); |
| +static void usbhsf_rx_irq_ctrl(struct usbhs_pipe *pipe, int enable); |
| struct usbhs_pkt *usbhs_pkt_pop(struct usbhs_pipe *pipe, struct usbhs_pkt *pkt) |
| { |
| struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe); |
| @@ -123,6 +125,11 @@ struct usbhs_pkt *usbhs_pkt_pop(struct u |
| if (chan) { |
| dmaengine_terminate_all(chan); |
| usbhsf_dma_unmap(pkt); |
| + } else { |
| + if (usbhs_pipe_is_dir_in(pipe)) |
| + usbhsf_rx_irq_ctrl(pipe, 0); |
| + else |
| + usbhsf_tx_irq_ctrl(pipe, 0); |
| } |
| |
| usbhs_pipe_clear_without_sequence(pipe, 0, 0); |