Commit 8355b2b3082d302091506703d2e4e239f7deed7f

Authored by Yoshihiro Shimoda
Committed by Felipe Balbi
1 parent f0798d6a04

usb: renesas_usbhs: fix the behavior of some usbhs_pkt_handle

Some gadget drivers will call usb_ep_queue() more than once before
the first queue doesn't finish. However, this driver didn't handle
it correctly. So, this patch fixes the behavior of some
usbhs_pkt_handle using the "running" flag. Otherwise, the oops below
happens if we use g_ncm driver and when the "iperf -u -c host -b 200M"
is running.

Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c0004000
[00000000] *pgd=00000000
Internal error: Oops: 80000007 [#1] SMP ARM
Modules linked in: usb_f_ncm g_ncm libcomposite u_ether
CPU: 0 PID: 0 Comm: swapper/0 Tainted: G        W      3.17.0-rc1-00008-g8b2be8a-dirty #20
task: c051c7e0 ti: c0512000 task.ti: c0512000
PC is at 0x0
LR is at usbhsf_pkt_handler+0xa8/0x114
pc : [<00000000>]    lr : [<c0278fb4>]    psr: 60000193
sp : c0513ce8  ip : c0513c58  fp : c0513d24
r10: 00000001  r9 : 00000193  r8 : eebec4a0
r7 : eebec410  r6 : eebe0c6c  r5 : 00000000  r4 : ee4a2774
r3 : 00000000  r2 : ee251e00  r1 : c0513cf4  r0 : ee4a2774

Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>

Showing 3 changed files with 41 additions and 1 deletions Side-by-side Diff

drivers/usb/renesas_usbhs/fifo.c
... ... @@ -544,6 +544,7 @@
544 544 usbhsf_send_terminator(pipe, fifo);
545 545  
546 546 usbhsf_tx_irq_ctrl(pipe, !*is_done);
  547 + usbhs_pipe_running(pipe, !*is_done);
547 548 usbhs_pipe_enable(pipe);
548 549  
549 550 dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
550 551  
551 552  
... ... @@ -570,12 +571,21 @@
570 571 * retry in interrupt
571 572 */
572 573 usbhsf_tx_irq_ctrl(pipe, 1);
  574 + usbhs_pipe_running(pipe, 1);
573 575  
574 576 return ret;
575 577 }
576 578  
  579 +static int usbhsf_pio_prepare_push(struct usbhs_pkt *pkt, int *is_done)
  580 +{
  581 + if (usbhs_pipe_is_running(pkt->pipe))
  582 + return 0;
  583 +
  584 + return usbhsf_pio_try_push(pkt, is_done);
  585 +}
  586 +
577 587 struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = {
578   - .prepare = usbhsf_pio_try_push,
  588 + .prepare = usbhsf_pio_prepare_push,
579 589 .try_run = usbhsf_pio_try_push,
580 590 };
581 591  
... ... @@ -589,6 +599,9 @@
589 599 if (usbhs_pipe_is_busy(pipe))
590 600 return 0;
591 601  
  602 + if (usbhs_pipe_is_running(pipe))
  603 + return 0;
  604 +
592 605 /*
593 606 * pipe enable to prepare packet receive
594 607 */
... ... @@ -597,6 +610,7 @@
597 610  
598 611 usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
599 612 usbhs_pipe_enable(pipe);
  613 + usbhs_pipe_running(pipe, 1);
600 614 usbhsf_rx_irq_ctrl(pipe, 1);
601 615  
602 616 return 0;
... ... @@ -642,6 +656,7 @@
642 656 (total_len < maxp)) { /* short packet */
643 657 *is_done = 1;
644 658 usbhsf_rx_irq_ctrl(pipe, 0);
  659 + usbhs_pipe_running(pipe, 0);
645 660 usbhs_pipe_disable(pipe); /* disable pipe first */
646 661 }
647 662  
... ... @@ -805,6 +820,7 @@
805 820 dev_dbg(dev, " %s %d (%d/ %d)\n",
806 821 fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
807 822  
  823 + usbhs_pipe_running(pipe, 1);
808 824 usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
809 825 usbhs_pipe_enable(pipe);
810 826 usbhsf_dma_start(pipe, fifo);
... ... @@ -836,6 +852,10 @@
836 852 if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
837 853 goto usbhsf_pio_prepare_push;
838 854  
  855 + /* return at this time if the pipe is running */
  856 + if (usbhs_pipe_is_running(pipe))
  857 + return 0;
  858 +
839 859 /* get enable DMA fifo */
840 860 fifo = usbhsf_get_dma_fifo(priv, pkt);
841 861 if (!fifo)
... ... @@ -873,6 +893,7 @@
873 893 pkt->actual = pkt->trans;
874 894  
875 895 *is_done = !pkt->zero; /* send zero packet ? */
  896 + usbhs_pipe_running(pipe, !*is_done);
876 897  
877 898 usbhsf_dma_stop(pipe, pipe->fifo);
878 899 usbhsf_dma_unmap(pkt);
879 900  
... ... @@ -972,8 +993,10 @@
972 993 if ((pkt->actual == pkt->length) || /* receive all data */
973 994 (pkt->trans < maxp)) { /* short packet */
974 995 *is_done = 1;
  996 + usbhs_pipe_running(pipe, 0);
975 997 } else {
976 998 /* re-enable */
  999 + usbhs_pipe_running(pipe, 0);
977 1000 usbhsf_prepare_pop(pkt, is_done);
978 1001 }
979 1002  
drivers/usb/renesas_usbhs/pipe.c
... ... @@ -578,6 +578,19 @@
578 578 return usbhsp_flags_has(pipe, IS_DIR_HOST);
579 579 }
580 580  
  581 +int usbhs_pipe_is_running(struct usbhs_pipe *pipe)
  582 +{
  583 + return usbhsp_flags_has(pipe, IS_RUNNING);
  584 +}
  585 +
  586 +void usbhs_pipe_running(struct usbhs_pipe *pipe, int running)
  587 +{
  588 + if (running)
  589 + usbhsp_flags_set(pipe, IS_RUNNING);
  590 + else
  591 + usbhsp_flags_clr(pipe, IS_RUNNING);
  592 +}
  593 +
581 594 void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
582 595 {
583 596 u16 mask = (SQCLR | SQSET);
drivers/usb/renesas_usbhs/pipe.h
... ... @@ -36,6 +36,7 @@
36 36 #define USBHS_PIPE_FLAGS_IS_USED (1 << 0)
37 37 #define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1)
38 38 #define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2)
  39 +#define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3)
39 40  
40 41 struct usbhs_pkt_handle *handler;
41 42  
... ... @@ -80,6 +81,9 @@
80 81 void usbhs_pipe_remove(struct usbhs_priv *priv);
81 82 int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
82 83 int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe);
  84 +int usbhs_pipe_is_running(struct usbhs_pipe *pipe);
  85 +void usbhs_pipe_running(struct usbhs_pipe *pipe, int running);
  86 +
83 87 void usbhs_pipe_init(struct usbhs_priv *priv,
84 88 int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
85 89 int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);