Commit a516c618 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull dmaengine fixes from Vinod Koul:
 "A bunch of driver fixes with idxd ones being the biggest:

   - Xilinx regmap init error handling, dma_device directions, residue
     calculation, and reset related timeout fixes

   - Renesas CHCTRL updates and driver list fixes

   - DW HDMA cycle bits and MSI data programming fix

   - IDXD pile of fixes for memeory leak and FLR fixes"

* tag 'dmaengine-fix-7.0' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine: (21 commits)
  dmaengine: xilinx_dma: Fix reset related timeout with two-channel AXIDMA
  dmaengine: xilinx: xilinx_dma: Fix unmasked residue subtraction
  dmaengine: xilinx: xilinx_dma: Fix residue calculation for cyclic DMA
  dmaengine: xilinx: xilinx_dma: Fix dma_device directions
  dmaengine: sh: rz-dmac: Move CHCTRL updates under spinlock
  dmaengine: sh: rz-dmac: Protect the driver specific lists
  dmaengine: idxd: fix possible wrong descriptor completion in llist_abort_desc()
  dmaengine: xilinx: xdma: Fix regmap init error handling
  dmaengine: dw-edma: Fix multiple times setting of the CYCLE_STATE and CYCLE_BIT bits for HDMA.
  dmaengine: idxd: Fix leaking event log memory
  dmaengine: idxd: Fix freeing the allocated ida too late
  dmaengine: idxd: Fix memory leak when a wq is reset
  dmaengine: idxd: Fix not releasing workqueue on .release()
  dmaengine: idxd: Wait for submitted operations on .device_synchronize()
  dmaengine: idxd: Flush all pending descriptors
  dmaengine: idxd: Flush kernel workqueues on Function Level Reset
  dmaengine: idxd: Fix possible invalid memory access after FLR
  dmaengine: idxd: Fix crash when the event log is disabled
  dmaengine: idxd: Fix lockdep warnings when calling idxd_device_config()
  dmaengine: dw-edma: fix MSI data programming for multi-IRQ case
  ...
parents 32ee88da a17ce4bc
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -844,6 +844,7 @@ static int dw_edma_irq_request(struct dw_edma *dw,
{
	struct dw_edma_chip *chip = dw->chip;
	struct device *dev = dw->chip->dev;
	struct msi_desc *msi_desc;
	u32 wr_mask = 1;
	u32 rd_mask = 1;
	int i, err = 0;
@@ -895,9 +896,12 @@ static int dw_edma_irq_request(struct dw_edma *dw,
					  &dw->irq[i]);
			if (err)
				goto err_irq_free;

			if (irq_get_msi_desc(irq))
			msi_desc = irq_get_msi_desc(irq);
			if (msi_desc) {
				get_cached_msi_msg(irq, &dw->irq[i].msi);
				if (!msi_desc->pci.msi_attrib.is_msix)
					dw->irq[i].msi.data = dw->irq[0].msi.data + i;
			}
		}

		dw->nr_irqs = i;
+3 −3
Original line number Diff line number Diff line
@@ -252,10 +252,10 @@ static void dw_hdma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
			  lower_32_bits(chunk->ll_region.paddr));
		SET_CH_32(dw, chan->dir, chan->id, llp.msb,
			  upper_32_bits(chunk->ll_region.paddr));
	}
		/* Set consumer cycle */
		SET_CH_32(dw, chan->dir, chan->id, cycle_sync,
			HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT);
	}

	dw_hdma_v0_sync_ll_data(chunk);

+11 −15
Original line number Diff line number Diff line
@@ -317,10 +317,8 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
			return NULL;
		i = fsl_chan - fsl_edma->chans;

		fsl_chan->priority = dma_spec->args[1];
		fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
		fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
		fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
		if (!b_chmux && i != dma_spec->args[0])
			continue;

		if ((dma_spec->args[2] & FSL_EDMA_EVEN_CH) && (i & 0x1))
			continue;
@@ -328,18 +326,16 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
		if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1))
			continue;

		if (!b_chmux && i == dma_spec->args[0]) {
			chan = dma_get_slave_channel(chan);
			chan->device->privatecnt++;
			return chan;
		} else if (b_chmux && !fsl_chan->srcid) {
			/* if controller support channel mux, choose a free channel */
		fsl_chan->srcid = dma_spec->args[0];
		fsl_chan->priority = dma_spec->args[1];
		fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
		fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
		fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;

		chan = dma_get_slave_channel(chan);
		chan->device->privatecnt++;
			fsl_chan->srcid = dma_spec->args[0];
		return chan;
	}
	}
	return NULL;
}

+4 −4
Original line number Diff line number Diff line
@@ -158,11 +158,7 @@ static const struct device_type idxd_cdev_file_type = {
static void idxd_cdev_dev_release(struct device *dev)
{
	struct idxd_cdev *idxd_cdev = dev_to_cdev(dev);
	struct idxd_cdev_context *cdev_ctx;
	struct idxd_wq *wq = idxd_cdev->wq;

	cdev_ctx = &ictx[wq->idxd->data->type];
	ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
	kfree(idxd_cdev);
}

@@ -582,11 +578,15 @@ int idxd_wq_add_cdev(struct idxd_wq *wq)

void idxd_wq_del_cdev(struct idxd_wq *wq)
{
	struct idxd_cdev_context *cdev_ctx;
	struct idxd_cdev *idxd_cdev;

	idxd_cdev = wq->idxd_cdev;
	wq->idxd_cdev = NULL;
	cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));

	cdev_ctx = &ictx[wq->idxd->data->type];
	ida_free(&cdev_ctx->minor_ida, idxd_cdev->minor);
	put_device(cdev_dev(idxd_cdev));
}

+31 −14
Original line number Diff line number Diff line
@@ -175,6 +175,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq)
	free_descs(wq);
	dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
	sbitmap_queue_free(&wq->sbq);
	wq->type = IDXD_WQT_NONE;
}
EXPORT_SYMBOL_NS_GPL(idxd_wq_free_resources, "IDXD");

@@ -382,7 +383,6 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
	lockdep_assert_held(&wq->wq_lock);
	wq->state = IDXD_WQ_DISABLED;
	memset(wq->wqcfg, 0, idxd->wqcfg_size);
	wq->type = IDXD_WQT_NONE;
	wq->threshold = 0;
	wq->priority = 0;
	wq->enqcmds_retries = IDXD_ENQCMDS_RETRIES;
@@ -831,8 +831,7 @@ static void idxd_device_evl_free(struct idxd_device *idxd)
	struct device *dev = &idxd->pdev->dev;
	struct idxd_evl *evl = idxd->evl;

	gencfg.bits = ioread32(idxd->reg_base + IDXD_GENCFG_OFFSET);
	if (!gencfg.evl_en)
	if (!evl)
		return;

	mutex_lock(&evl->lock);
@@ -1125,7 +1124,11 @@ int idxd_device_config(struct idxd_device *idxd)
{
	int rc;

	lockdep_assert_held(&idxd->dev_lock);
	guard(spinlock)(&idxd->dev_lock);

	if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
		return 0;

	rc = idxd_wqs_setup(idxd);
	if (rc < 0)
		return rc;
@@ -1332,6 +1335,11 @@ void idxd_wq_free_irq(struct idxd_wq *wq)

	free_irq(ie->vector, ie);
	idxd_flush_pending_descs(ie);

	/* The interrupt might have been already released by FLR */
	if (ie->int_handle == INVALID_INT_HANDLE)
		return;

	if (idxd->request_int_handles)
		idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
	idxd_device_clear_perm_entry(idxd, ie);
@@ -1340,6 +1348,23 @@ void idxd_wq_free_irq(struct idxd_wq *wq)
	ie->pasid = IOMMU_PASID_INVALID;
}

void idxd_wq_flush_descs(struct idxd_wq *wq)
{
	struct idxd_irq_entry *ie = &wq->ie;
	struct idxd_device *idxd = wq->idxd;

	guard(mutex)(&wq->wq_lock);

	if (wq->state != IDXD_WQ_ENABLED || wq->type != IDXD_WQT_KERNEL)
		return;

	idxd_flush_pending_descs(ie);
	if (idxd->request_int_handles)
		idxd_device_release_int_handle(idxd, ie->int_handle, IDXD_IRQ_MSIX);
	idxd_device_clear_perm_entry(idxd, ie);
	ie->int_handle = INVALID_INT_HANDLE;
}

int idxd_wq_request_irq(struct idxd_wq *wq)
{
	struct idxd_device *idxd = wq->idxd;
@@ -1454,11 +1479,7 @@ int idxd_drv_enable_wq(struct idxd_wq *wq)
		}
	}

	rc = 0;
	spin_lock(&idxd->dev_lock);
	if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
	rc = idxd_device_config(idxd);
	spin_unlock(&idxd->dev_lock);
	if (rc < 0) {
		dev_dbg(dev, "Writing wq %d config failed: %d\n", wq->id, rc);
		goto err;
@@ -1533,7 +1554,6 @@ void idxd_drv_disable_wq(struct idxd_wq *wq)
	idxd_wq_reset(wq);
	idxd_wq_free_resources(wq);
	percpu_ref_exit(&wq->wq_active);
	wq->type = IDXD_WQT_NONE;
	wq->client_count = 0;
}
EXPORT_SYMBOL_NS_GPL(idxd_drv_disable_wq, "IDXD");
@@ -1554,10 +1574,7 @@ int idxd_device_drv_probe(struct idxd_dev *idxd_dev)
	}

	/* Device configuration */
	spin_lock(&idxd->dev_lock);
	if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
	rc = idxd_device_config(idxd);
	spin_unlock(&idxd->dev_lock);
	if (rc < 0)
		return -ENXIO;

Loading