Commit 6b00bc63 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull dmaengine fixes from Vinod Koul:
 "A bunch of driver fixes, notably:

   - More idxd fixes for driver unregister, error handling and bus
     assignment

   - HAS_IOMEM depends fix for few drivers

   - lock fix in pl330 driver

   - xilinx drivers fixes for initialize registers, missing dependencies
     and limiting descriptor IDs

   - mediatek descriptor management fixes"

* tag 'dmaengine-fix-5.13' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine:
  dmaengine: mediatek: use GFP_NOWAIT instead of GFP_ATOMIC in prep_dma
  dmaengine: mediatek: do not issue a new desc if one is still current
  dmaengine: mediatek: free the proper desc in desc_free handler
  dmaengine: ipu: fix doc warning in ipu_irq.c
  dmaengine: rcar-dmac: Fix PM reference leak in rcar_dmac_probe()
  dmaengine: idxd: Fix missing error code in idxd_cdev_open()
  dmaengine: stedma40: add missing iounmap() on error in d40_probe()
  dmaengine: SF_PDMA depends on HAS_IOMEM
  dmaengine: QCOM_HIDMA_MGMT depends on HAS_IOMEM
  dmaengine: ALTERA_MSGDMA depends on HAS_IOMEM
  dmaengine: idxd: Add missing cleanup for early error out in probe call
  dmaengine: xilinx: dpdma: Limit descriptor IDs to 16 bits
  dmaengine: xilinx: dpdma: Add missing dependencies to Kconfig
  dmaengine: stm32-mdma: fix PM reference leak in stm32_mdma_alloc_chan_resourc()
  dmaengine: zynqmp_dma: Fix PM reference leak in zynqmp_dma_alloc_chan_resourc()
  dmaengine: xilinx: dpdma: initialize registers before request_irq
  dmaengine: pl330: fix wrong usage of spinlock flags in dma_cyclc
  dmaengine: fsl-dpaa2-qdma: Fix error return code in two functions
  dmaengine: idxd: add missing dsa driver unregister
  dmaengine: idxd: add engine 'struct device' missing bus type assignment
parents cc9aaa2b 90415753
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,7 @@ config DMA_OF
#devices
config ALTERA_MSGDMA
	tristate "Altera / Intel mSGDMA Engine"
	depends on HAS_IOMEM
	select DMA_ENGINE
	help
	  Enable support for Altera / Intel mSGDMA controller.
@@ -701,6 +702,7 @@ config XILINX_ZYNQMP_DMA

config XILINX_ZYNQMP_DPDMA
	tristate "Xilinx DPDMA Engine"
	depends on HAS_IOMEM && OF
	select DMA_ENGINE
	select DMA_VIRTUAL_CHANNELS
	help
+3 −0
Original line number Diff line number Diff line
@@ -332,6 +332,7 @@ static int __cold dpaa2_qdma_setup(struct fsl_mc_device *ls_dev)
	}

	if (priv->dpdmai_attr.version.major > DPDMAI_VER_MAJOR) {
		err = -EINVAL;
		dev_err(dev, "DPDMAI major version mismatch\n"
			     "Found %u.%u, supported version is %u.%u\n",
				priv->dpdmai_attr.version.major,
@@ -341,6 +342,7 @@ static int __cold dpaa2_qdma_setup(struct fsl_mc_device *ls_dev)
	}

	if (priv->dpdmai_attr.version.minor > DPDMAI_VER_MINOR) {
		err = -EINVAL;
		dev_err(dev, "DPDMAI minor version mismatch\n"
			     "Found %u.%u, supported version is %u.%u\n",
				priv->dpdmai_attr.version.major,
@@ -475,6 +477,7 @@ static int __cold dpaa2_qdma_dpio_setup(struct dpaa2_qdma_priv *priv)
		ppriv->store =
			dpaa2_io_store_create(DPAA2_QDMA_STORE_SIZE, dev);
		if (!ppriv->store) {
			err = -ENOMEM;
			dev_err(dev, "dpaa2_io_store_create() failed\n");
			goto err_store;
		}
+1 −0
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp)
		pasid = iommu_sva_get_pasid(sva);
		if (pasid == IOMMU_PASID_INVALID) {
			iommu_sva_unbind_device(sva);
			rc = -EINVAL;
			goto failed;
		}

+60 −3
Original line number Diff line number Diff line
@@ -168,6 +168,32 @@ static int idxd_setup_interrupts(struct idxd_device *idxd)
	return rc;
}

static void idxd_cleanup_interrupts(struct idxd_device *idxd)
{
	struct pci_dev *pdev = idxd->pdev;
	struct idxd_irq_entry *irq_entry;
	int i, msixcnt;

	msixcnt = pci_msix_vec_count(pdev);
	if (msixcnt <= 0)
		return;

	irq_entry = &idxd->irq_entries[0];
	free_irq(irq_entry->vector, irq_entry);

	for (i = 1; i < msixcnt; i++) {

		irq_entry = &idxd->irq_entries[i];
		if (idxd->hw.cmd_cap & BIT(IDXD_CMD_RELEASE_INT_HANDLE))
			idxd_device_release_int_handle(idxd, idxd->int_handles[i],
						       IDXD_IRQ_MSIX);
		free_irq(irq_entry->vector, irq_entry);
	}

	idxd_mask_error_interrupts(idxd);
	pci_free_irq_vectors(pdev);
}

static int idxd_setup_wqs(struct idxd_device *idxd)
{
	struct device *dev = &idxd->pdev->dev;
@@ -242,6 +268,7 @@ static int idxd_setup_engines(struct idxd_device *idxd)
		engine->idxd = idxd;
		device_initialize(&engine->conf_dev);
		engine->conf_dev.parent = &idxd->conf_dev;
		engine->conf_dev.bus = &dsa_bus_type;
		engine->conf_dev.type = &idxd_engine_device_type;
		rc = dev_set_name(&engine->conf_dev, "engine%d.%d", idxd->id, engine->id);
		if (rc < 0) {
@@ -303,6 +330,19 @@ static int idxd_setup_groups(struct idxd_device *idxd)
	return rc;
}

static void idxd_cleanup_internals(struct idxd_device *idxd)
{
	int i;

	for (i = 0; i < idxd->max_groups; i++)
		put_device(&idxd->groups[i]->conf_dev);
	for (i = 0; i < idxd->max_engines; i++)
		put_device(&idxd->engines[i]->conf_dev);
	for (i = 0; i < idxd->max_wqs; i++)
		put_device(&idxd->wqs[i]->conf_dev);
	destroy_workqueue(idxd->wq);
}

static int idxd_setup_internals(struct idxd_device *idxd)
{
	struct device *dev = &idxd->pdev->dev;
@@ -531,12 +571,12 @@ static int idxd_probe(struct idxd_device *idxd)
		dev_dbg(dev, "Loading RO device config\n");
		rc = idxd_device_load_config(idxd);
		if (rc < 0)
			goto err;
			goto err_config;
	}

	rc = idxd_setup_interrupts(idxd);
	if (rc)
		goto err;
		goto err_config;

	dev_dbg(dev, "IDXD interrupt setup complete.\n");

@@ -549,6 +589,8 @@ static int idxd_probe(struct idxd_device *idxd)
	dev_dbg(dev, "IDXD device %d probed successfully\n", idxd->id);
	return 0;

 err_config:
	idxd_cleanup_internals(idxd);
 err:
	if (device_pasid_enabled(idxd))
		idxd_disable_system_pasid(idxd);
@@ -556,6 +598,18 @@ static int idxd_probe(struct idxd_device *idxd)
	return rc;
}

static void idxd_cleanup(struct idxd_device *idxd)
{
	struct device *dev = &idxd->pdev->dev;

	perfmon_pmu_remove(idxd);
	idxd_cleanup_interrupts(idxd);
	idxd_cleanup_internals(idxd);
	if (device_pasid_enabled(idxd))
		idxd_disable_system_pasid(idxd);
	iommu_dev_disable_feature(dev, IOMMU_DEV_FEAT_SVA);
}

static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
	struct device *dev = &pdev->dev;
@@ -608,7 +662,7 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
	rc = idxd_register_devices(idxd);
	if (rc) {
		dev_err(dev, "IDXD sysfs setup failed\n");
		goto err;
		goto err_dev_register;
	}

	idxd->state = IDXD_DEV_CONF_READY;
@@ -618,6 +672,8 @@ static int idxd_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)

	return 0;

 err_dev_register:
	idxd_cleanup(idxd);
 err:
	pci_iounmap(pdev, idxd->reg_base);
 err_iomap:
@@ -787,6 +843,7 @@ module_init(idxd_init_module);

static void __exit idxd_exit_module(void)
{
	idxd_unregister_driver();
	pci_unregister_driver(&idxd_pci_driver);
	idxd_cdev_remove();
	idxd_unregister_bus_type();
+1 −1
Original line number Diff line number Diff line
@@ -230,7 +230,7 @@ int ipu_irq_map(unsigned int source)
}

/**
 * ipu_irq_map() - map an IPU interrupt source to an IRQ number
 * ipu_irq_unmap() - unmap an IPU interrupt source
 * @source:	interrupt source bit position (see ipu_irq_map())
 * @return:	0 or negative error code
 */
Loading