usb: renesas: fix scheduling in atomic context bug
The current renesas_usbhs driver triggers BUG: scheduling while atomic: ksoftirqd/0/3/0x00000102 with enabled CONFIG_DEBUG_ATOMIC_SLEEP, by submitting DMA transfers from an atomic (tasklet) context, which is not supported by the shdma dmaengine driver. Fix it by switching to a work. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
This commit is contained in:
Родитель
d526128694
Коммит
6e4b74e469
|
@ -765,9 +765,9 @@ static int __usbhsf_dma_map_ctrl(struct usbhs_pkt *pkt, int map)
|
|||
}
|
||||
|
||||
static void usbhsf_dma_complete(void *arg);
|
||||
static void usbhsf_dma_prepare_tasklet(unsigned long data)
|
||||
static void xfer_work(struct work_struct *work)
|
||||
{
|
||||
struct usbhs_pkt *pkt = (struct usbhs_pkt *)data;
|
||||
struct usbhs_pkt *pkt = container_of(work, struct usbhs_pkt, work);
|
||||
struct usbhs_pipe *pipe = pkt->pipe;
|
||||
struct usbhs_fifo *fifo = usbhs_pipe_to_fifo(pipe);
|
||||
struct usbhs_priv *priv = usbhs_pipe_to_priv(pipe);
|
||||
|
@ -847,11 +847,8 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
|
|||
|
||||
pkt->trans = len;
|
||||
|
||||
tasklet_init(&fifo->tasklet,
|
||||
usbhsf_dma_prepare_tasklet,
|
||||
(unsigned long)pkt);
|
||||
|
||||
tasklet_schedule(&fifo->tasklet);
|
||||
INIT_WORK(&pkt->work, xfer_work);
|
||||
schedule_work(&pkt->work);
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -941,11 +938,8 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
|
|||
|
||||
pkt->trans = len;
|
||||
|
||||
tasklet_init(&fifo->tasklet,
|
||||
usbhsf_dma_prepare_tasklet,
|
||||
(unsigned long)pkt);
|
||||
|
||||
tasklet_schedule(&fifo->tasklet);
|
||||
INIT_WORK(&pkt->work, xfer_work);
|
||||
schedule_work(&pkt->work);
|
||||
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sh_dma.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <asm/dma.h>
|
||||
#include "pipe.h"
|
||||
|
||||
|
@ -31,7 +32,6 @@ struct usbhs_fifo {
|
|||
u32 ctr; /* xFIFOCTR */
|
||||
|
||||
struct usbhs_pipe *pipe;
|
||||
struct tasklet_struct tasklet;
|
||||
|
||||
struct dma_chan *tx_chan;
|
||||
struct dma_chan *rx_chan;
|
||||
|
@ -53,6 +53,7 @@ struct usbhs_pkt {
|
|||
struct usbhs_pkt_handle *handler;
|
||||
void (*done)(struct usbhs_priv *priv,
|
||||
struct usbhs_pkt *pkt);
|
||||
struct work_struct work;
|
||||
dma_addr_t dma;
|
||||
void *buf;
|
||||
int length;
|
||||
|
|
Загрузка…
Ссылка в новой задаче