Skip to content

Commit

Permalink
Merge tag 'dmaengine-fix-5.8-rc6' of git://git.kernel.org/pub/scm/lin…
Browse files Browse the repository at this point in the history
…ux/kernel/git/vkoul/dmaengine into master

Pull dmaengine fixes from Vinod Koul:

 - update dmaengine tree location to kernel.org

 - dmatest fix for completing threads

 - driver fixes for k3dma, fsl-dma, idxd, ,tegra, and few other drivers

* tag 'dmaengine-fix-5.8-rc6' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (21 commits)
  dmaengine: ioat setting ioat timeout as module parameter
  dmaengine: fsl-edma: fix wrong tcd endianness for big-endian cpu
  dmaengine: dmatest: stop completed threads when running without set channel
  dmaengine: fsl-edma-common: correct DSIZE_32BYTE
  dmaengine: dw: Initialize channel before each transfer
  dmaengine: idxd: fix misc interrupt handler thread unmasking
  dmaengine: idxd: cleanup workqueue config after disabling
  dmaengine: tegra210-adma: Fix runtime PM imbalance on error
  dmaengine: mcf-edma: Fix NULL pointer exception in mcf_edma_tx_handler
  dmaengine: fsl-edma: Fix NULL pointer exception in fsl_edma_tx_handler
  dmaengine: fsl-edma: Add lockdep assert for exported function
  dmaengine: idxd: fix hw descriptor fields for delta record
  dmaengine: ti: k3-udma: add missing put_device() call in of_xudma_dev_get()
  dmaengine: sh: usb-dmac: set tx_result parameters
  dmaengine: ti: k3-udma: Fix delayed_work usage for tx drain workaround
  dmaengine: idxd: fix cdev locking for open and release
  dmaengine: imx-sdma: Fix: Remove 'always true' comparison
  MAINTAINERS: switch dmaengine tree to kernel.org
  dmaengine: ti: k3-udma: Fix the running channel handling in alloc_chan_resources
  dmaengine: ti: k3-udma: Fix cleanup code for alloc_chan_resources
  ...
  • Loading branch information
torvalds committed Jul 15, 2020
2 parents 6cbba1f + 87730cc commit 0665a4e
Show file tree
Hide file tree
Showing 20 changed files with 128 additions and 60 deletions.
2 changes: 1 addition & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5112,7 +5112,7 @@ M: Vinod Koul <vkoul@kernel.org>
L: dmaengine@vger.kernel.org
S: Maintained
Q: https://patchwork.kernel.org/project/linux-dmaengine/list/
T: git git://git.infradead.org/users/vkoul/slave-dma.git
T: git git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git
F: Documentation/devicetree/bindings/dma/
F: Documentation/driver-api/dmaengine/
F: drivers/dma/
Expand Down
2 changes: 2 additions & 0 deletions drivers/dma/dmatest.c
Original file line number Diff line number Diff line change
Expand Up @@ -1176,6 +1176,8 @@ static int dmatest_run_set(const char *val, const struct kernel_param *kp)
} else if (dmatest_run) {
if (!is_threaded_test_pending(info)) {
pr_info("No channels configured, continue with any\n");
if (!is_threaded_test_run(info))
stop_threaded_test(info);
add_threaded_test(info);
}
start_threaded_tests(info);
Expand Down
12 changes: 0 additions & 12 deletions drivers/dma/dw/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -118,16 +118,11 @@ static void dwc_initialize(struct dw_dma_chan *dwc)
{
struct dw_dma *dw = to_dw_dma(dwc->chan.device);

if (test_bit(DW_DMA_IS_INITIALIZED, &dwc->flags))
return;

dw->initialize_chan(dwc);

/* Enable interrupts */
channel_set_bit(dw, MASK.XFER, dwc->mask);
channel_set_bit(dw, MASK.ERROR, dwc->mask);

set_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);
}

/*----------------------------------------------------------------------*/
Expand Down Expand Up @@ -954,8 +949,6 @@ static void dwc_issue_pending(struct dma_chan *chan)

void do_dw_dma_off(struct dw_dma *dw)
{
unsigned int i;

dma_writel(dw, CFG, 0);

channel_clear_bit(dw, MASK.XFER, dw->all_chan_mask);
Expand All @@ -966,9 +959,6 @@ void do_dw_dma_off(struct dw_dma *dw)

while (dma_readl(dw, CFG) & DW_CFG_DMA_EN)
cpu_relax();

for (i = 0; i < dw->dma.chancnt; i++)
clear_bit(DW_DMA_IS_INITIALIZED, &dw->chan[i].flags);
}

void do_dw_dma_on(struct dw_dma *dw)
Expand Down Expand Up @@ -1032,8 +1022,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
/* Clear custom channel configuration */
memset(&dwc->dws, 0, sizeof(struct dw_dma_slave));

clear_bit(DW_DMA_IS_INITIALIZED, &dwc->flags);

/* Disable interrupts */
channel_clear_bit(dw, MASK.XFER, dwc->mask);
channel_clear_bit(dw, MASK.BLOCK, dwc->mask);
Expand Down
28 changes: 16 additions & 12 deletions drivers/dma/fsl-edma-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,26 +352,28 @@ static void fsl_edma_set_tcd_regs(struct fsl_edma_chan *fsl_chan,
/*
* TCD parameters are stored in struct fsl_edma_hw_tcd in little
* endian format. However, we need to load the TCD registers in
* big- or little-endian obeying the eDMA engine model endian.
* big- or little-endian obeying the eDMA engine model endian,
* and this is performed from specific edma_write functions
*/
edma_writew(edma, 0, &regs->tcd[ch].csr);
edma_writel(edma, le32_to_cpu(tcd->saddr), &regs->tcd[ch].saddr);
edma_writel(edma, le32_to_cpu(tcd->daddr), &regs->tcd[ch].daddr);

edma_writew(edma, le16_to_cpu(tcd->attr), &regs->tcd[ch].attr);
edma_writew(edma, le16_to_cpu(tcd->soff), &regs->tcd[ch].soff);
edma_writel(edma, (s32)tcd->saddr, &regs->tcd[ch].saddr);
edma_writel(edma, (s32)tcd->daddr, &regs->tcd[ch].daddr);

edma_writel(edma, le32_to_cpu(tcd->nbytes), &regs->tcd[ch].nbytes);
edma_writel(edma, le32_to_cpu(tcd->slast), &regs->tcd[ch].slast);
edma_writew(edma, (s16)tcd->attr, &regs->tcd[ch].attr);
edma_writew(edma, tcd->soff, &regs->tcd[ch].soff);

edma_writew(edma, le16_to_cpu(tcd->citer), &regs->tcd[ch].citer);
edma_writew(edma, le16_to_cpu(tcd->biter), &regs->tcd[ch].biter);
edma_writew(edma, le16_to_cpu(tcd->doff), &regs->tcd[ch].doff);
edma_writel(edma, (s32)tcd->nbytes, &regs->tcd[ch].nbytes);
edma_writel(edma, (s32)tcd->slast, &regs->tcd[ch].slast);

edma_writel(edma, le32_to_cpu(tcd->dlast_sga),
edma_writew(edma, (s16)tcd->citer, &regs->tcd[ch].citer);
edma_writew(edma, (s16)tcd->biter, &regs->tcd[ch].biter);
edma_writew(edma, (s16)tcd->doff, &regs->tcd[ch].doff);

edma_writel(edma, (s32)tcd->dlast_sga,
&regs->tcd[ch].dlast_sga);

edma_writew(edma, le16_to_cpu(tcd->csr), &regs->tcd[ch].csr);
edma_writew(edma, (s16)tcd->csr, &regs->tcd[ch].csr);
}

static inline
Expand Down Expand Up @@ -589,6 +591,8 @@ void fsl_edma_xfer_desc(struct fsl_edma_chan *fsl_chan)
{
struct virt_dma_desc *vdesc;

lockdep_assert_held(&fsl_chan->vchan.lock);

vdesc = vchan_next_desc(&fsl_chan->vchan);
if (!vdesc)
return;
Expand Down
2 changes: 1 addition & 1 deletion drivers/dma/fsl-edma-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
#define EDMA_TCD_ATTR_DSIZE_16BIT BIT(0)
#define EDMA_TCD_ATTR_DSIZE_32BIT BIT(1)
#define EDMA_TCD_ATTR_DSIZE_64BIT (BIT(0) | BIT(1))
#define EDMA_TCD_ATTR_DSIZE_32BYTE (BIT(3) | BIT(0))
#define EDMA_TCD_ATTR_DSIZE_32BYTE (BIT(2) | BIT(0))
#define EDMA_TCD_ATTR_SSIZE_8BIT 0
#define EDMA_TCD_ATTR_SSIZE_16BIT (EDMA_TCD_ATTR_DSIZE_16BIT << 8)
#define EDMA_TCD_ATTR_SSIZE_32BIT (EDMA_TCD_ATTR_DSIZE_32BIT << 8)
Expand Down
7 changes: 7 additions & 0 deletions drivers/dma/fsl-edma.c
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ static irqreturn_t fsl_edma_tx_handler(int irq, void *dev_id)
fsl_chan = &fsl_edma->chans[ch];

spin_lock(&fsl_chan->vchan.lock);

if (!fsl_chan->edesc) {
/* terminate_all called before */
spin_unlock(&fsl_chan->vchan.lock);
continue;
}

if (!fsl_chan->edesc->iscyclic) {
list_del(&fsl_chan->edesc->vdesc.node);
vchan_cookie_complete(&fsl_chan->edesc->vdesc);
Expand Down
19 changes: 16 additions & 3 deletions drivers/dma/idxd/cdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,24 +74,35 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
struct idxd_device *idxd;
struct idxd_wq *wq;
struct device *dev;
int rc = 0;

wq = inode_wq(inode);
idxd = wq->idxd;
dev = &idxd->pdev->dev;

dev_dbg(dev, "%s called: %d\n", __func__, idxd_wq_refcount(wq));

if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq))
return -EBUSY;

ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;

mutex_lock(&wq->wq_lock);

if (idxd_wq_refcount(wq) > 0 && wq_dedicated(wq)) {
rc = -EBUSY;
goto failed;
}

ctx->wq = wq;
filp->private_data = ctx;
idxd_wq_get(wq);
mutex_unlock(&wq->wq_lock);
return 0;

failed:
mutex_unlock(&wq->wq_lock);
kfree(ctx);
return rc;
}

static int idxd_cdev_release(struct inode *node, struct file *filep)
Expand All @@ -105,7 +116,9 @@ static int idxd_cdev_release(struct inode *node, struct file *filep)
filep->private_data = NULL;

kfree(ctx);
mutex_lock(&wq->wq_lock);
idxd_wq_put(wq);
mutex_unlock(&wq->wq_lock);
return 0;
}

Expand Down
25 changes: 25 additions & 0 deletions drivers/dma/idxd/device.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,31 @@ void idxd_wq_unmap_portal(struct idxd_wq *wq)
devm_iounmap(dev, wq->dportal);
}

void idxd_wq_disable_cleanup(struct idxd_wq *wq)
{
struct idxd_device *idxd = wq->idxd;
struct device *dev = &idxd->pdev->dev;
int i, wq_offset;

lockdep_assert_held(&idxd->dev_lock);
memset(&wq->wqcfg, 0, sizeof(wq->wqcfg));
wq->type = IDXD_WQT_NONE;
wq->size = 0;
wq->group = NULL;
wq->threshold = 0;
wq->priority = 0;
clear_bit(WQ_FLAG_DEDICATED, &wq->flags);
memset(wq->name, 0, WQ_NAME_SIZE);

for (i = 0; i < 8; i++) {
wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
iowrite32(0, idxd->reg_base + wq_offset);
dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
wq->id, i, wq_offset,
ioread32(idxd->reg_base + wq_offset));
}
}

/* Device control bits */
static inline bool idxd_is_enabled(struct idxd_device *idxd)
{
Expand Down
1 change: 1 addition & 0 deletions drivers/dma/idxd/idxd.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,7 @@ int idxd_wq_enable(struct idxd_wq *wq);
int idxd_wq_disable(struct idxd_wq *wq);
int idxd_wq_map_portal(struct idxd_wq *wq);
void idxd_wq_unmap_portal(struct idxd_wq *wq);
void idxd_wq_disable_cleanup(struct idxd_wq *wq);

/* submission */
int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc);
Expand Down
3 changes: 2 additions & 1 deletion drivers/dma/idxd/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)

iowrite32(cause, idxd->reg_base + IDXD_INTCAUSE_OFFSET);
if (!err)
return IRQ_HANDLED;
goto out;

gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);
if (gensts.state == IDXD_DEVICE_STATE_HALT) {
Expand All @@ -162,6 +162,7 @@ irqreturn_t idxd_misc_thread(int vec, void *data)
spin_unlock_bh(&idxd->dev_lock);
}

out:
idxd_unmask_msix_vector(idxd, irq_entry->id);
return IRQ_HANDLED;
}
Expand Down
5 changes: 5 additions & 0 deletions drivers/dma/idxd/sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,11 @@ static int idxd_config_bus_remove(struct device *dev)
idxd_unregister_dma_device(idxd);
spin_lock_irqsave(&idxd->dev_lock, flags);
rc = idxd_device_disable(idxd);
for (i = 0; i < idxd->max_wqs; i++) {
struct idxd_wq *wq = &idxd->wqs[i];

idxd_wq_disable_cleanup(wq);
}
spin_unlock_irqrestore(&idxd->dev_lock, flags);
module_put(THIS_MODULE);
if (rc < 0)
Expand Down
11 changes: 4 additions & 7 deletions drivers/dma/imx-sdma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1331,8 +1331,7 @@ static void sdma_free_chan_resources(struct dma_chan *chan)

sdma_channel_synchronize(chan);

if (sdmac->event_id0 >= 0)
sdma_event_disable(sdmac, sdmac->event_id0);
sdma_event_disable(sdmac, sdmac->event_id0);
if (sdmac->event_id1)
sdma_event_disable(sdmac, sdmac->event_id1);

Expand Down Expand Up @@ -1632,11 +1631,9 @@ static int sdma_config(struct dma_chan *chan,
memcpy(&sdmac->slave_config, dmaengine_cfg, sizeof(*dmaengine_cfg));

/* Set ENBLn earlier to make sure dma request triggered after that */
if (sdmac->event_id0 >= 0) {
if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
return -EINVAL;
sdma_event_enable(sdmac, sdmac->event_id0);
}
if (sdmac->event_id0 >= sdmac->sdma->drvdata->num_events)
return -EINVAL;
sdma_event_enable(sdmac, sdmac->event_id0);

if (sdmac->event_id1) {
if (sdmac->event_id1 >= sdmac->sdma->drvdata->num_events)
Expand Down
12 changes: 12 additions & 0 deletions drivers/dma/ioat/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@

#include "../dmaengine.h"

int completion_timeout = 200;
module_param(completion_timeout, int, 0644);
MODULE_PARM_DESC(completion_timeout,
"set ioat completion timeout [msec] (default 200 [msec])");
int idle_timeout = 2000;
module_param(idle_timeout, int, 0644);
MODULE_PARM_DESC(idle_timeout,
"set ioat idel timeout [msec] (default 2000 [msec])");

#define IDLE_TIMEOUT msecs_to_jiffies(idle_timeout)
#define COMPLETION_TIMEOUT msecs_to_jiffies(completion_timeout)

static char *chanerr_str[] = {
"DMA Transfer Source Address Error",
"DMA Transfer Destination Address Error",
Expand Down
2 changes: 0 additions & 2 deletions drivers/dma/ioat/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,8 +104,6 @@ struct ioatdma_chan {
#define IOAT_RUN 5
#define IOAT_CHAN_ACTIVE 6
struct timer_list timer;
#define COMPLETION_TIMEOUT msecs_to_jiffies(100)
#define IDLE_TIMEOUT msecs_to_jiffies(2000)
#define RESET_DELAY msecs_to_jiffies(100)
struct ioatdma_device *ioat_dma;
dma_addr_t completion_dma;
Expand Down
7 changes: 7 additions & 0 deletions drivers/dma/mcf-edma.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,13 @@ static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
mcf_chan = &mcf_edma->chans[ch];

spin_lock(&mcf_chan->vchan.lock);

if (!mcf_chan->edesc) {
/* terminate_all called before */
spin_unlock(&mcf_chan->vchan.lock);
continue;
}

if (!mcf_chan->edesc->iscyclic) {
list_del(&mcf_chan->edesc->vdesc.node);
vchan_cookie_complete(&mcf_chan->edesc->vdesc);
Expand Down
2 changes: 2 additions & 0 deletions drivers/dma/sh/usb-dmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,8 @@ static void usb_dmac_isr_transfer_end(struct usb_dmac_chan *chan)
desc->residue = usb_dmac_get_current_residue(chan, desc,
desc->sg_index - 1);
desc->done_cookie = desc->vd.tx.cookie;
desc->vd.tx_result.result = DMA_TRANS_NOERROR;
desc->vd.tx_result.residue = desc->residue;
vchan_cookie_complete(&desc->vd);

/* Restart the next transfer if this driver has a next desc */
Expand Down
5 changes: 4 additions & 1 deletion drivers/dma/tegra210-adma.c
Original file line number Diff line number Diff line change
Expand Up @@ -658,6 +658,7 @@ static int tegra_adma_alloc_chan_resources(struct dma_chan *dc)

ret = pm_runtime_get_sync(tdc2dev(tdc));
if (ret < 0) {
pm_runtime_put_noidle(tdc2dev(tdc));
free_irq(tdc->irq, tdc);
return ret;
}
Expand Down Expand Up @@ -869,8 +870,10 @@ static int tegra_adma_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);

ret = pm_runtime_get_sync(&pdev->dev);
if (ret < 0)
if (ret < 0) {
pm_runtime_put_noidle(&pdev->dev);
goto rpm_disable;
}

ret = tegra_adma_init(tdma);
if (ret)
Expand Down
1 change: 1 addition & 0 deletions drivers/dma/ti/k3-udma-private.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ struct udma_dev *of_xudma_dev_get(struct device_node *np, const char *property)
ud = platform_get_drvdata(pdev);
if (!ud) {
pr_debug("UDMA has not been probed\n");
put_device(&pdev->dev);
return ERR_PTR(-EPROBE_DEFER);
}

Expand Down
Loading

0 comments on commit 0665a4e

Please sign in to comment.