Commit 5613970a authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dmaengine-fix-5.5-rc5' of git://git.infradead.org/users/vkoul/slave-dma

Pull dmaengine fixes from Vinod Koul:
 "A bunch of fixes for:

   - uninitialized dma_slave_caps access

   - virt-dma use after free in vchan_complete()

   - driver fixes for ioat, k3dma and jz4780"

* tag 'dmaengine-fix-5.5-rc5' of git://git.infradead.org/users/vkoul/slave-dma:
  ioat: ioat_alloc_ring() failure handling.
  dmaengine: virt-dma: Fix access after free in vchan_complete()
  dmaengine: k3dma: Avoid null pointer traversal
  dmaengine: dma-jz4780: Also break descriptor chains on JZ4725B
  dmaengine: Fix access to uninitialized dma_slave_caps
parents 50978df3 b0b5ce10
...@@ -999,7 +999,8 @@ static const struct jz4780_dma_soc_data jz4740_dma_soc_data = { ...@@ -999,7 +999,8 @@ static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = { static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
.nb_channels = 6, .nb_channels = 6,
.transfer_ord_max = 5, .transfer_ord_max = 5,
.flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC, .flags = JZ_SOC_DATA_PER_CHAN_PM | JZ_SOC_DATA_NO_DCKES_DCKEC |
JZ_SOC_DATA_BREAK_LINKS,
}; };
static const struct jz4780_dma_soc_data jz4770_dma_soc_data = { static const struct jz4780_dma_soc_data jz4770_dma_soc_data = {
......
...@@ -377,10 +377,11 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags) ...@@ -377,10 +377,11 @@ ioat_alloc_ring(struct dma_chan *c, int order, gfp_t flags)
descs->virt = dma_alloc_coherent(to_dev(ioat_chan), descs->virt = dma_alloc_coherent(to_dev(ioat_chan),
SZ_2M, &descs->hw, flags); SZ_2M, &descs->hw, flags);
if (!descs->virt && (i > 0)) { if (!descs->virt) {
int idx; int idx;
for (idx = 0; idx < i; idx++) { for (idx = 0; idx < i; idx++) {
descs = &ioat_chan->descs[idx];
dma_free_coherent(to_dev(ioat_chan), SZ_2M, dma_free_coherent(to_dev(ioat_chan), SZ_2M,
descs->virt, descs->hw); descs->virt, descs->hw);
descs->virt = NULL; descs->virt = NULL;
......
...@@ -229,9 +229,11 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id) ...@@ -229,9 +229,11 @@ static irqreturn_t k3_dma_int_handler(int irq, void *dev_id)
c = p->vchan; c = p->vchan;
if (c && (tc1 & BIT(i))) { if (c && (tc1 & BIT(i))) {
spin_lock_irqsave(&c->vc.lock, flags); spin_lock_irqsave(&c->vc.lock, flags);
if (p->ds_run != NULL) {
vchan_cookie_complete(&p->ds_run->vd); vchan_cookie_complete(&p->ds_run->vd);
p->ds_done = p->ds_run; p->ds_done = p->ds_run;
p->ds_run = NULL; p->ds_run = NULL;
}
spin_unlock_irqrestore(&c->vc.lock, flags); spin_unlock_irqrestore(&c->vc.lock, flags);
} }
if (c && (tc2 & BIT(i))) { if (c && (tc2 & BIT(i))) {
...@@ -271,6 +273,10 @@ static int k3_dma_start_txd(struct k3_dma_chan *c) ...@@ -271,6 +273,10 @@ static int k3_dma_start_txd(struct k3_dma_chan *c)
if (BIT(c->phy->idx) & k3_dma_get_chan_stat(d)) if (BIT(c->phy->idx) & k3_dma_get_chan_stat(d))
return -EAGAIN; return -EAGAIN;
/* Avoid losing track of ds_run if a transaction is in flight */
if (c->phy->ds_run)
return -EAGAIN;
if (vd) { if (vd) {
struct k3_dma_desc_sw *ds = struct k3_dma_desc_sw *ds =
container_of(vd, struct k3_dma_desc_sw, vd); container_of(vd, struct k3_dma_desc_sw, vd);
......
...@@ -104,9 +104,8 @@ static void vchan_complete(unsigned long arg) ...@@ -104,9 +104,8 @@ static void vchan_complete(unsigned long arg)
dmaengine_desc_get_callback(&vd->tx, &cb); dmaengine_desc_get_callback(&vd->tx, &cb);
list_del(&vd->node); list_del(&vd->node);
vchan_vdesc_fini(vd);
dmaengine_desc_callback_invoke(&cb, &vd->tx_result); dmaengine_desc_callback_invoke(&cb, &vd->tx_result);
vchan_vdesc_fini(vd);
} }
} }
......
...@@ -1364,8 +1364,11 @@ static inline int dma_get_slave_caps(struct dma_chan *chan, ...@@ -1364,8 +1364,11 @@ static inline int dma_get_slave_caps(struct dma_chan *chan,
static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx) static inline int dmaengine_desc_set_reuse(struct dma_async_tx_descriptor *tx)
{ {
struct dma_slave_caps caps; struct dma_slave_caps caps;
int ret;
dma_get_slave_caps(tx->chan, &caps); ret = dma_get_slave_caps(tx->chan, &caps);
if (ret)
return ret;
if (caps.descriptor_reuse) { if (caps.descriptor_reuse) {
tx->flags |= DMA_CTRL_REUSE; tx->flags |= DMA_CTRL_REUSE;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment