Skip to content

Commit 4cadc71

Browse files
Peter Ujfalusigregkh
authored andcommitted
usb: musb: tusb6010_omap: Allocate DMA channels upfront
Instead of requesting the DMA channel in tusb_omap_dma_allocate() do it when the controller is created and in runtime work from the DMA channel pool. This change is needed for the DMAengine conversion of the driver since the tusb_omap_dma_allocate() is called in interrupt context which might lead to lock within the DMAengine API when requesting channel. Signed-off-by: Peter Ujfalusi <[email protected]> Tested-by: Tony Lindgren <[email protected]> Signed-off-by: Bin Liu <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 1df9d9e commit 4cadc71

File tree

1 file changed

+92
-93
lines changed

1 file changed

+92
-93
lines changed

drivers/usb/musb/tusb6010_omap.c

Lines changed: 92 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ struct tusb_omap_dma_ch {
4545
u8 tx;
4646
struct musb_hw_ep *hw_ep;
4747

48-
struct tusb_dma_data dma_data;
48+
struct tusb_dma_data *dma_data;
4949

5050
struct tusb_omap_dma *tusb_dma;
5151

@@ -62,7 +62,7 @@ struct tusb_omap_dma {
6262
struct dma_controller controller;
6363
void __iomem *tbase;
6464

65-
struct tusb_dma_data dma_data;
65+
struct tusb_dma_data dma_pool[MAX_DMAREQ];
6666
unsigned multichannel:1;
6767
};
6868

@@ -120,10 +120,7 @@ static void tusb_omap_dma_cb(int lch, u16 ch_status, void *data)
120120

121121
spin_lock_irqsave(&musb->lock, flags);
122122

123-
if (tusb_dma->multichannel)
124-
ch = chdat->dma_data.ch;
125-
else
126-
ch = tusb_dma->dma_data.ch;
123+
ch = chdat->dma_data->ch;
127124

128125
if (ch_status != OMAP_DMA_BLOCK_IRQ)
129126
printk(KERN_ERR "TUSB DMA error status: %i\n", ch_status);
@@ -248,7 +245,8 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
248245
dma_remaining = TUSB_EP_CONFIG_XFR_SIZE(dma_remaining);
249246
if (dma_remaining) {
250247
dev_dbg(musb->controller, "Busy %s dma ch%i, not using: %08x\n",
251-
chdat->tx ? "tx" : "rx", chdat->dma_data.ch,
248+
chdat->tx ? "tx" : "rx",
249+
chdat->dma_data ? chdat->dma_data->ch : -1,
252250
dma_remaining);
253251
return false;
254252
}
@@ -260,11 +258,8 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
260258
else
261259
chdat->transfer_packet_sz = packet_sz;
262260

263-
if (tusb_dma->multichannel) {
264-
dma_data = &chdat->dma_data;
265-
} else {
266-
dma_data = &tusb_dma->dma_data;
267-
261+
dma_data = chdat->dma_data;
262+
if (!tusb_dma->multichannel) {
268263
if (tusb_omap_use_shared_dmareq(chdat) != 0) {
269264
dev_dbg(musb->controller, "could not get dma for ep%i\n", chdat->epnum);
270265
return false;
@@ -276,10 +271,10 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
276271
WARN_ON(1);
277272
return false;
278273
}
279-
280-
omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
281274
}
282275

276+
omap_set_dma_callback(dma_data->ch, tusb_omap_dma_cb, channel);
277+
283278
chdat->packet_sz = packet_sz;
284279
chdat->len = len;
285280
channel->actual_len = 0;
@@ -410,19 +405,9 @@ static int tusb_omap_dma_program(struct dma_channel *channel, u16 packet_sz,
410405
static int tusb_omap_dma_abort(struct dma_channel *channel)
411406
{
412407
struct tusb_omap_dma_ch *chdat = to_chdat(channel);
413-
struct tusb_omap_dma *tusb_dma = chdat->tusb_dma;
414-
struct tusb_dma_data *dma_data = &tusb_dma->dma_data;
415408

416-
if (!tusb_dma->multichannel) {
417-
if (dma_data->ch >= 0) {
418-
omap_stop_dma(dma_data->ch);
419-
omap_free_dma(dma_data->ch);
420-
dma_data->ch = -1;
421-
}
422-
423-
dma_data->dmareq = -1;
424-
dma_data->sync_dev = -1;
425-
}
409+
if (chdat->dma_data)
410+
omap_stop_dma(chdat->dma_data->ch);
426411

427412
channel->status = MUSB_DMA_STATUS_FREE;
428413

@@ -434,15 +419,6 @@ static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
434419
u32 reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
435420
int i, dmareq_nr = -1;
436421

437-
const int sync_dev[6] = {
438-
OMAP24XX_DMA_EXT_DMAREQ0,
439-
OMAP24XX_DMA_EXT_DMAREQ1,
440-
OMAP242X_DMA_EXT_DMAREQ2,
441-
OMAP242X_DMA_EXT_DMAREQ3,
442-
OMAP242X_DMA_EXT_DMAREQ4,
443-
OMAP242X_DMA_EXT_DMAREQ5,
444-
};
445-
446422
for (i = 0; i < MAX_DMAREQ; i++) {
447423
int cur = (reg & (0xf << (i * 5))) >> (i * 5);
448424
if (cur == 0) {
@@ -459,8 +435,7 @@ static inline int tusb_omap_dma_allocate_dmareq(struct tusb_omap_dma_ch *chdat)
459435
reg |= ((1 << 4) << (dmareq_nr * 5));
460436
musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
461437

462-
chdat->dma_data.dmareq = dmareq_nr;
463-
chdat->dma_data.sync_dev = sync_dev[chdat->dma_data.dmareq];
438+
chdat->dma_data = &chdat->tusb_dma->dma_pool[dmareq_nr];
464439

465440
return 0;
466441
}
@@ -469,15 +444,14 @@ static inline void tusb_omap_dma_free_dmareq(struct tusb_omap_dma_ch *chdat)
469444
{
470445
u32 reg;
471446

472-
if (!chdat || chdat->dma_data.dmareq < 0)
447+
if (!chdat || !chdat->dma_data || chdat->dma_data->dmareq < 0)
473448
return;
474449

475450
reg = musb_readl(chdat->tbase, TUSB_DMA_EP_MAP);
476-
reg &= ~(0x1f << (chdat->dma_data.dmareq * 5));
451+
reg &= ~(0x1f << (chdat->dma_data->dmareq * 5));
477452
musb_writel(chdat->tbase, TUSB_DMA_EP_MAP, reg);
478453

479-
chdat->dma_data.dmareq = -1;
480-
chdat->dma_data.sync_dev = -1;
454+
chdat->dma_data = NULL;
481455
}
482456

483457
static struct dma_channel *dma_channel_pool[MAX_DMAREQ];
@@ -488,8 +462,6 @@ tusb_omap_dma_allocate(struct dma_controller *c,
488462
u8 tx)
489463
{
490464
int ret, i;
491-
const char *dev_name;
492-
void *cb_data;
493465
struct tusb_omap_dma *tusb_dma;
494466
struct musb *musb;
495467
void __iomem *tbase;
@@ -543,46 +515,22 @@ tusb_omap_dma_allocate(struct dma_controller *c,
543515
channel->desired_mode = 0;
544516
channel->actual_len = 0;
545517

546-
if (tusb_dma->multichannel) {
547-
dma_data = &chdat->dma_data;
548-
ret = tusb_omap_dma_allocate_dmareq(chdat);
549-
if (ret != 0)
550-
goto free_dmareq;
551-
552-
if (chdat->tx)
553-
dev_name = "TUSB transmit";
554-
else
555-
dev_name = "TUSB receive";
556-
cb_data = channel;
557-
} else if (tusb_dma->dma_data.ch == -1) {
558-
dma_data = &tusb_dma->dma_data;
559-
dma_data->dmareq = 0;
560-
dma_data->sync_dev = OMAP24XX_DMA_EXT_DMAREQ0;
561-
562-
dev_name = "TUSB shared";
563-
/* Callback data gets set later in the shared dmareq case */
564-
cb_data = NULL;
565-
566-
chdat->dma_data.dmareq = -1;
567-
chdat->dma_data.ch = -1;
568-
chdat->dma_data.sync_dev = -1;
518+
if (!chdat->dma_data) {
519+
if (tusb_dma->multichannel) {
520+
ret = tusb_omap_dma_allocate_dmareq(chdat);
521+
if (ret != 0)
522+
goto free_dmareq;
523+
} else {
524+
chdat->dma_data = &tusb_dma->dma_pool[0];
525+
}
569526
}
570527

571-
if (dma_data) {
572-
ret = omap_request_dma(dma_data->sync_dev, dev_name,
573-
tusb_omap_dma_cb, cb_data,
574-
&dma_data->ch);
575-
if (ret != 0)
576-
goto free_dmareq;
577-
} else {
578-
/* Already allocated shared, single DMA channel. */
579-
dma_data = &tusb_dma->dma_data;
580-
}
528+
dma_data = chdat->dma_data;
581529

582530
dev_dbg(musb->controller, "ep%i %s dma: %s dma%i dmareq%i sync%i\n",
583531
chdat->epnum,
584532
chdat->tx ? "tx" : "rx",
585-
chdat->dma_data.ch >= 0 ? "dedicated" : "shared",
533+
tusb_dma->multichannel ? "shared" : "dedicated",
586534
dma_data->ch, dma_data->dmareq, dma_data->sync_dev);
587535

588536
return channel;
@@ -604,7 +552,7 @@ static void tusb_omap_dma_release(struct dma_channel *channel)
604552
u32 reg;
605553

606554
dev_dbg(musb->controller, "ep%i ch%i\n", chdat->epnum,
607-
chdat->dma_data.ch);
555+
chdat->dma_data->ch);
608556

609557
reg = musb_readl(tbase, TUSB_DMA_INT_MASK);
610558
if (chdat->tx)
@@ -622,14 +570,8 @@ static void tusb_omap_dma_release(struct dma_channel *channel)
622570

623571
channel->status = MUSB_DMA_STATUS_UNKNOWN;
624572

625-
if (chdat->dma_data.ch >= 0) {
626-
omap_stop_dma(chdat->dma_data.ch);
627-
omap_free_dma(chdat->dma_data.ch);
628-
chdat->dma_data.ch = -1;
629-
}
630-
631-
if (chdat->dma_data.dmareq >= 0)
632-
tusb_omap_dma_free_dmareq(chdat);
573+
omap_stop_dma(chdat->dma_data->ch);
574+
tusb_omap_dma_free_dmareq(chdat);
633575

634576
channel = NULL;
635577
}
@@ -646,15 +588,73 @@ void tusb_dma_controller_destroy(struct dma_controller *c)
646588
kfree(ch->private_data);
647589
kfree(ch);
648590
}
649-
}
650591

651-
if (tusb_dma && !tusb_dma->multichannel && tusb_dma->dma_data.ch >= 0)
652-
omap_free_dma(tusb_dma->dma_data.ch);
592+
/* Free up the DMA channels */
593+
if (tusb_dma && tusb_dma->dma_pool[i].ch >= 0)
594+
omap_free_dma(tusb_dma->dma_pool[i].ch);
595+
}
653596

654597
kfree(tusb_dma);
655598
}
656599
EXPORT_SYMBOL_GPL(tusb_dma_controller_destroy);
657600

601+
static int tusb_omap_allocate_dma_pool(struct tusb_omap_dma *tusb_dma)
602+
{
603+
int i;
604+
int ret = 0;
605+
const int sync_dev[6] = {
606+
OMAP24XX_DMA_EXT_DMAREQ0,
607+
OMAP24XX_DMA_EXT_DMAREQ1,
608+
OMAP242X_DMA_EXT_DMAREQ2,
609+
OMAP242X_DMA_EXT_DMAREQ3,
610+
OMAP242X_DMA_EXT_DMAREQ4,
611+
OMAP242X_DMA_EXT_DMAREQ5,
612+
};
613+
614+
for (i = 0; i < MAX_DMAREQ; i++) {
615+
struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
616+
617+
/*
618+
* Request DMA channels:
619+
* - one channel in case of non multichannel mode
620+
* - MAX_DMAREQ number of channels in multichannel mode
621+
*/
622+
if (i == 0 || tusb_dma->multichannel) {
623+
char ch_name[8];
624+
625+
sprintf(ch_name, "dmareq%d", i);
626+
dma_data->sync_dev = sync_dev[i];
627+
dma_data->ch = -1;
628+
/* callback data is ngoing to be set later */
629+
ret = omap_request_dma(dma_data->sync_dev, ch_name,
630+
tusb_omap_dma_cb, NULL, &dma_data->ch);
631+
if (ret != 0) {
632+
dev_err(tusb_dma->controller.musb->controller,
633+
"Failed to request %s\n", ch_name);
634+
goto dma_error;
635+
}
636+
637+
dma_data->dmareq = i;
638+
} else {
639+
dma_data->dmareq = -1;
640+
dma_data->sync_dev = -1;
641+
dma_data->ch = -1;
642+
}
643+
}
644+
645+
return 0;
646+
647+
dma_error:
648+
for (; i >= 0; i--) {
649+
struct tusb_dma_data *dma_data = &tusb_dma->dma_pool[i];
650+
651+
if (dma_data->ch >= 0)
652+
omap_free_dma(dma_data->ch);
653+
}
654+
655+
return ret;
656+
}
657+
658658
struct dma_controller *
659659
tusb_dma_controller_create(struct musb *musb, void __iomem *base)
660660
{
@@ -679,10 +679,6 @@ tusb_dma_controller_create(struct musb *musb, void __iomem *base)
679679
tusb_dma->controller.musb = musb;
680680
tusb_dma->tbase = musb->ctrl_base;
681681

682-
tusb_dma->dma_data.ch = -1;
683-
tusb_dma->dma_data.dmareq = -1;
684-
tusb_dma->dma_data.sync_dev = -1;
685-
686682
tusb_dma->controller.channel_alloc = tusb_omap_dma_allocate;
687683
tusb_dma->controller.channel_release = tusb_omap_dma_release;
688684
tusb_dma->controller.channel_program = tusb_omap_dma_program;
@@ -709,6 +705,9 @@ tusb_dma_controller_create(struct musb *musb, void __iomem *base)
709705
ch->private_data = chdat;
710706
}
711707

708+
if (tusb_omap_allocate_dma_pool(tusb_dma))
709+
goto cleanup;
710+
712711
return &tusb_dma->controller;
713712

714713
cleanup:

0 commit comments

Comments
 (0)