diff options
Diffstat (limited to 'drivers/dma/ti/k3-udma.c')
-rw-r--r-- | drivers/dma/ti/k3-udma.c | 75 |
1 files changed, 31 insertions, 44 deletions
diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 945b7c604f91..49d0d3af6311 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -170,7 +170,7 @@ struct udma_desc { void *metadata; /* pointer to provided metadata buffer (EPIP, PSdata) */ unsigned int hwdesc_count; - struct udma_hwdesc hwdesc[0]; + struct udma_hwdesc hwdesc[]; }; enum udma_chan_state { @@ -1418,17 +1418,12 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) if (ret) return ret; - uc->tchan->t_ring = k3_ringacc_request_ring(ud->ringacc, - uc->tchan->id, 0); - if (!uc->tchan->t_ring) { - ret = -EBUSY; - goto err_tx_ring; - } - - uc->tchan->tc_ring = k3_ringacc_request_ring(ud->ringacc, -1, 0); - if (!uc->tchan->tc_ring) { + ret = k3_ringacc_request_rings_pair(ud->ringacc, uc->tchan->id, -1, + &uc->tchan->t_ring, + &uc->tchan->tc_ring); + if (ret) { ret = -EBUSY; - goto err_txc_ring; + goto err_ring; } memset(&ring_cfg, 0, sizeof(ring_cfg)); @@ -1447,10 +1442,9 @@ static int udma_alloc_tx_resources(struct udma_chan *uc) err_ringcfg: k3_ringacc_ring_free(uc->tchan->tc_ring); uc->tchan->tc_ring = NULL; -err_txc_ring: k3_ringacc_ring_free(uc->tchan->t_ring); uc->tchan->t_ring = NULL; -err_tx_ring: +err_ring: udma_put_tchan(uc); return ret; @@ -1499,16 +1493,11 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) rflow = uc->rflow; fd_ring_id = ud->tchan_cnt + ud->echan_cnt + uc->rchan->id; - rflow->fd_ring = k3_ringacc_request_ring(ud->ringacc, fd_ring_id, 0); - if (!rflow->fd_ring) { - ret = -EBUSY; - goto err_rx_ring; - } - - rflow->r_ring = k3_ringacc_request_ring(ud->ringacc, -1, 0); - if (!rflow->r_ring) { + ret = k3_ringacc_request_rings_pair(ud->ringacc, fd_ring_id, -1, + &rflow->fd_ring, &rflow->r_ring); + if (ret) { ret = -EBUSY; - goto err_rxc_ring; + goto err_ring; } memset(&ring_cfg, 0, sizeof(ring_cfg)); @@ -1533,10 +1522,9 @@ static int udma_alloc_rx_resources(struct udma_chan *uc) err_ringcfg: k3_ringacc_ring_free(rflow->r_ring); rflow->r_ring = NULL; -err_rxc_ring: k3_ringacc_ring_free(rflow->fd_ring); rflow->fd_ring = NULL; -err_rx_ring: +err_ring: udma_put_rflow(uc); err_rflow: udma_put_rchan(uc); @@ -1753,7 +1741,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) dev_err(ud->ddev.dev, "Descriptor pool allocation failed\n"); uc->use_dma_pool = false; - return -ENOMEM; + ret = -ENOMEM; + goto err_cleanup; } } @@ -1773,16 +1762,18 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) ret = udma_get_chan_pair(uc); if (ret) - return ret; + goto err_cleanup; ret = udma_alloc_tx_resources(uc); - if (ret) - return ret; + if (ret) { + udma_put_rchan(uc); + goto err_cleanup; + } ret = udma_alloc_rx_resources(uc); if (ret) { udma_free_tx_resources(uc); - return ret; + goto err_cleanup; } uc->config.src_thread = ud->psil_base + uc->tchan->id; @@ -1800,10 +1791,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) uc->id); ret = udma_alloc_tx_resources(uc); - if (ret) { - uc->config.remote_thread_id = -1; - return ret; - } + if (ret) + goto err_cleanup; uc->config.src_thread = ud->psil_base + uc->tchan->id; uc->config.dst_thread = uc->config.remote_thread_id; @@ -1820,10 +1809,8 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) uc->id); ret = udma_alloc_rx_resources(uc); - if (ret) { - uc->config.remote_thread_id = -1; - return ret; - } + if (ret) + goto err_cleanup; uc->config.src_thread = uc->config.remote_thread_id; uc->config.dst_thread = (ud->psil_base + uc->rchan->id) | @@ -1838,7 +1825,9 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) /* Can not happen */ dev_err(uc->ud->dev, "%s: chan%d invalid direction (%u)\n", __func__, uc->id, uc->config.dir); - return -EINVAL; + ret = -EINVAL; + goto err_cleanup; + } /* check if the channel configuration was successful */ @@ -1847,7 +1836,7 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) if (udma_is_chan_running(uc)) { dev_warn(ud->dev, "chan%d: is running!\n", uc->id); - udma_stop(uc); + udma_reset_chan(uc, false); if (udma_is_chan_running(uc)) { dev_err(ud->dev, "chan%d: won't stop!\n", uc->id); ret = -EBUSY; @@ -1906,8 +1895,6 @@ static int udma_alloc_chan_resources(struct dma_chan *chan) udma_reset_rings(uc); - INIT_DELAYED_WORK_ONSTACK(&uc->tx_drain.work, - udma_check_tx_completion); return 0; err_irq_free: @@ -1919,7 +1906,7 @@ err_psi_free: err_res_free: udma_free_tx_resources(uc); udma_free_rx_resources(uc); - +err_cleanup: udma_reset_uchan(uc); if (uc->use_dma_pool) { @@ -3019,7 +3006,6 @@ static void udma_free_chan_resources(struct dma_chan *chan) } cancel_delayed_work_sync(&uc->tx_drain.work); - destroy_delayed_work_on_stack(&uc->tx_drain.work); if (uc->irq_num_ring > 0) { free_irq(uc->irq_num_ring, uc); @@ -3593,7 +3579,7 @@ static int udma_probe(struct platform_device *pdev) return ret; } - ret = of_property_read_u32(navss_node, "ti,udma-atype", &ud->atype); + ret = of_property_read_u32(dev->of_node, "ti,udma-atype", &ud->atype); if (!ret && ud->atype > 2) { dev_err(dev, "Invalid atype: %u\n", ud->atype); return -EINVAL; @@ -3711,6 +3697,7 @@ static int udma_probe(struct platform_device *pdev) tasklet_init(&uc->vc.task, udma_vchan_complete, (unsigned long)&uc->vc); init_completion(&uc->teardown_completed); + INIT_DELAYED_WORK(&uc->tx_drain.work, udma_check_tx_completion); } ret = dma_async_device_register(&ud->ddev); |