Commit 708c2e41 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull dmaengine fixes from Vinod Koul:
 "Some late fixes for dmaengine:

  Core:
   - fix channel device_node deletion

  Driver fixes:
   - dw: revert of runtime pm enabling
   - idxd: device state fix, interrupt completion and list corruption
   - ti: resource leak

* tag 'dmaengine-fix2-5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine:
  dmaengine dw: Revert "dmaengine: dw: Enable runtime PM"
  dmaengine: idxd: check device state before issue command
  dmaengine: ti: k3-udma: Fix a resource leak in an error handling path
  dmaengine: move channel device_node deletion to driver
  dmaengine: idxd: fix misc interrupt completion
  dmaengine: idxd: Fix list corruption in description completion
parents 6016bf19 b6c14d7a
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -1110,7 +1110,6 @@ static void __dma_async_device_channel_unregister(struct dma_device *device,
		  "%s called while %d clients hold a reference\n",
		  __func__, chan->client_count);
	mutex_lock(&dma_list_mutex);
	list_del(&chan->device_node);
	device->chancnt--;
	chan->dev->chan = NULL;
	mutex_unlock(&dma_list_mutex);
+0 −6
Original line number Diff line number Diff line
@@ -982,11 +982,8 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)

	dev_vdbg(chan2dev(chan), "%s\n", __func__);

	pm_runtime_get_sync(dw->dma.dev);

	/* ASSERT:  channel is idle */
	if (dma_readl(dw, CH_EN) & dwc->mask) {
		pm_runtime_put_sync_suspend(dw->dma.dev);
		dev_dbg(chan2dev(chan), "DMA channel not idle?\n");
		return -EIO;
	}
@@ -1003,7 +1000,6 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan)
	 * We need controller-specific data to set up slave transfers.
	 */
	if (chan->private && !dw_dma_filter(chan, chan->private)) {
		pm_runtime_put_sync_suspend(dw->dma.dev);
		dev_warn(chan2dev(chan), "Wrong controller-specific data\n");
		return -EINVAL;
	}
@@ -1047,8 +1043,6 @@ static void dwc_free_chan_resources(struct dma_chan *chan)
	if (!dw->in_use)
		do_dw_dma_off(dw);

	pm_runtime_put_sync_suspend(dw->dma.dev);

	dev_vdbg(chan2dev(chan), "%s: done\n", __func__);
}

+22 −1
Original line number Diff line number Diff line
@@ -398,17 +398,31 @@ static inline bool idxd_is_enabled(struct idxd_device *idxd)
	return false;
}

static inline bool idxd_device_is_halted(struct idxd_device *idxd)
{
	union gensts_reg gensts;

	gensts.bits = ioread32(idxd->reg_base + IDXD_GENSTATS_OFFSET);

	return (gensts.state == IDXD_DEVICE_STATE_HALT);
}

/*
 * This is function is only used for reset during probe and will
 * poll for completion. Once the device is setup with interrupts,
 * all commands will be done via interrupt completion.
 */
void idxd_device_init_reset(struct idxd_device *idxd)
int idxd_device_init_reset(struct idxd_device *idxd)
{
	struct device *dev = &idxd->pdev->dev;
	union idxd_command_reg cmd;
	unsigned long flags;

	if (idxd_device_is_halted(idxd)) {
		dev_warn(&idxd->pdev->dev, "Device is HALTED!\n");
		return -ENXIO;
	}

	memset(&cmd, 0, sizeof(cmd));
	cmd.cmd = IDXD_CMD_RESET_DEVICE;
	dev_dbg(dev, "%s: sending reset for init.\n", __func__);
@@ -419,6 +433,7 @@ void idxd_device_init_reset(struct idxd_device *idxd)
	       IDXD_CMDSTS_ACTIVE)
		cpu_relax();
	spin_unlock_irqrestore(&idxd->dev_lock, flags);
	return 0;
}

static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
@@ -428,6 +443,12 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
	DECLARE_COMPLETION_ONSTACK(done);
	unsigned long flags;

	if (idxd_device_is_halted(idxd)) {
		dev_warn(&idxd->pdev->dev, "Device is HALTED!\n");
		*status = IDXD_CMDSTS_HW_ERR;
		return;
	}

	memset(&cmd, 0, sizeof(cmd));
	cmd.cmd = cmd_code;
	cmd.operand = operand;
+4 −1
Original line number Diff line number Diff line
@@ -205,5 +205,8 @@ int idxd_register_dma_channel(struct idxd_wq *wq)

void idxd_unregister_dma_channel(struct idxd_wq *wq)
{
	dma_async_device_channel_unregister(&wq->idxd->dma_dev, &wq->dma_chan);
	struct dma_chan *chan = &wq->dma_chan;

	dma_async_device_channel_unregister(&wq->idxd->dma_dev, chan);
	list_del(&chan->device_node);
}
+1 −1
Original line number Diff line number Diff line
@@ -326,7 +326,7 @@ void idxd_mask_msix_vector(struct idxd_device *idxd, int vec_id);
void idxd_unmask_msix_vector(struct idxd_device *idxd, int vec_id);

/* device control */
void idxd_device_init_reset(struct idxd_device *idxd);
int idxd_device_init_reset(struct idxd_device *idxd);
int idxd_device_enable(struct idxd_device *idxd);
int idxd_device_disable(struct idxd_device *idxd);
void idxd_device_reset(struct idxd_device *idxd);
Loading