Skip to content

Commit 8355b2b

Browse files
shimodayFelipe Balbi
authored and
Felipe Balbi
committed
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: c051c7e 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 <[email protected]> Signed-off-by: Felipe Balbi <[email protected]>
1 parent f0798d6 commit 8355b2b

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

drivers/usb/renesas_usbhs/fifo.c

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -544,6 +544,7 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
544544
usbhsf_send_terminator(pipe, fifo);
545545

546546
usbhsf_tx_irq_ctrl(pipe, !*is_done);
547+
usbhs_pipe_running(pipe, !*is_done);
547548
usbhs_pipe_enable(pipe);
548549

549550
dev_dbg(dev, " send %d (%d/ %d/ %d/ %d)\n",
@@ -570,12 +571,21 @@ static int usbhsf_pio_try_push(struct usbhs_pkt *pkt, int *is_done)
570571
* retry in interrupt
571572
*/
572573
usbhsf_tx_irq_ctrl(pipe, 1);
574+
usbhs_pipe_running(pipe, 1);
573575

574576
return ret;
575577
}
576578

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+
577587
struct usbhs_pkt_handle usbhs_fifo_pio_push_handler = {
578-
.prepare = usbhsf_pio_try_push,
588+
.prepare = usbhsf_pio_prepare_push,
579589
.try_run = usbhsf_pio_try_push,
580590
};
581591

@@ -589,6 +599,9 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
589599
if (usbhs_pipe_is_busy(pipe))
590600
return 0;
591601

602+
if (usbhs_pipe_is_running(pipe))
603+
return 0;
604+
592605
/*
593606
* pipe enable to prepare packet receive
594607
*/
@@ -597,6 +610,7 @@ static int usbhsf_prepare_pop(struct usbhs_pkt *pkt, int *is_done)
597610

598611
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->length);
599612
usbhs_pipe_enable(pipe);
613+
usbhs_pipe_running(pipe, 1);
600614
usbhsf_rx_irq_ctrl(pipe, 1);
601615

602616
return 0;
@@ -642,6 +656,7 @@ static int usbhsf_pio_try_pop(struct usbhs_pkt *pkt, int *is_done)
642656
(total_len < maxp)) { /* short packet */
643657
*is_done = 1;
644658
usbhsf_rx_irq_ctrl(pipe, 0);
659+
usbhs_pipe_running(pipe, 0);
645660
usbhs_pipe_disable(pipe); /* disable pipe first */
646661
}
647662

@@ -805,6 +820,7 @@ static void xfer_work(struct work_struct *work)
805820
dev_dbg(dev, " %s %d (%d/ %d)\n",
806821
fifo->name, usbhs_pipe_number(pipe), pkt->length, pkt->zero);
807822

823+
usbhs_pipe_running(pipe, 1);
808824
usbhs_pipe_set_trans_count_if_bulk(pipe, pkt->trans);
809825
usbhs_pipe_enable(pipe);
810826
usbhsf_dma_start(pipe, fifo);
@@ -836,6 +852,10 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
836852
if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
837853
goto usbhsf_pio_prepare_push;
838854

855+
/* return at this time if the pipe is running */
856+
if (usbhs_pipe_is_running(pipe))
857+
return 0;
858+
839859
/* get enable DMA fifo */
840860
fifo = usbhsf_get_dma_fifo(priv, pkt);
841861
if (!fifo)
@@ -873,6 +893,7 @@ static int usbhsf_dma_push_done(struct usbhs_pkt *pkt, int *is_done)
873893
pkt->actual = pkt->trans;
874894

875895
*is_done = !pkt->zero; /* send zero packet ? */
896+
usbhs_pipe_running(pipe, !*is_done);
876897

877898
usbhsf_dma_stop(pipe, pipe->fifo);
878899
usbhsf_dma_unmap(pkt);
@@ -972,8 +993,10 @@ static int usbhsf_dma_pop_done(struct usbhs_pkt *pkt, int *is_done)
972993
if ((pkt->actual == pkt->length) || /* receive all data */
973994
(pkt->trans < maxp)) { /* short packet */
974995
*is_done = 1;
996+
usbhs_pipe_running(pipe, 0);
975997
} else {
976998
/* re-enable */
999+
usbhs_pipe_running(pipe, 0);
9771000
usbhsf_prepare_pop(pkt, is_done);
9781001
}
9791002

drivers/usb/renesas_usbhs/pipe.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,19 @@ int usbhs_pipe_is_dir_host(struct usbhs_pipe *pipe)
578578
return usbhsp_flags_has(pipe, IS_DIR_HOST);
579579
}
580580

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+
581594
void usbhs_pipe_data_sequence(struct usbhs_pipe *pipe, int sequence)
582595
{
583596
u16 mask = (SQCLR | SQSET);

drivers/usb/renesas_usbhs/pipe.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ struct usbhs_pipe {
3636
#define USBHS_PIPE_FLAGS_IS_USED (1 << 0)
3737
#define USBHS_PIPE_FLAGS_IS_DIR_IN (1 << 1)
3838
#define USBHS_PIPE_FLAGS_IS_DIR_HOST (1 << 2)
39+
#define USBHS_PIPE_FLAGS_IS_RUNNING (1 << 3)
3940

4041
struct usbhs_pkt_handle *handler;
4142

@@ -80,6 +81,9 @@ int usbhs_pipe_probe(struct usbhs_priv *priv);
8081
void usbhs_pipe_remove(struct usbhs_priv *priv);
8182
int usbhs_pipe_is_dir_in(struct usbhs_pipe *pipe);
8283
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+
8387
void usbhs_pipe_init(struct usbhs_priv *priv,
8488
int (*dma_map_ctrl)(struct usbhs_pkt *pkt, int map));
8589
int usbhs_pipe_get_maxpacket(struct usbhs_pipe *pipe);

0 commit comments

Comments
 (0)