Commit bd4d74e8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull dmaengine fixes from Vinod Koul:
 "A solitary core fix and a few driver fixes:

  Core:

   - channel_register error handling

  Driver fixes:

   - idxd: wq config registers programming and mapping of portal size

   - ioatdma: unused fn removal

   - pl330: fix burst size

   - ti: pm fix on busy and -Wenum-conversion warns

   - xilinx: SG capability check, usage of xilinx_aximcdma_tx_segment,
     readl_poll_timeout_atomic variant"

* tag 'dmaengine-fix-5.10-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine:
  dmaengine: fix error codes in channel_register()
  dmaengine: pl330: _prep_dma_memcpy: Fix wrong burst size
  dmaengine: ioatdma: remove unused function missed during dma_v2 removal
  dmaengine: idxd: fix mapping of portal size
  dmaengine: ti: omap-dma: Block PM if SDMA is busy to fix audio
  dmaengine: xilinx_dma: Fix SG capability check for MCDMA
  dmaengine: xilinx_dma: Fix usage of xilinx_aximcdma_tx_segment
  dmaengine: xilinx_dma: use readl_poll_timeout_atomic variant
  dmaengine: ti: k3-udma: fix -Wenum-conversion warning
  dmaengine: idxd: fix wq config registers offset programming
parents fc8299f9 7e4be129
Loading
Loading
Loading
Loading
+9 −8
Original line number Diff line number Diff line
@@ -1039,16 +1039,15 @@ static int get_dma_id(struct dma_device *device)
static int __dma_async_device_channel_register(struct dma_device *device,
					       struct dma_chan *chan)
{
	int rc = 0;
	int rc;

	chan->local = alloc_percpu(typeof(*chan->local));
	if (!chan->local)
		goto err_out;
		return -ENOMEM;
	chan->dev = kzalloc(sizeof(*chan->dev), GFP_KERNEL);
	if (!chan->dev) {
		free_percpu(chan->local);
		chan->local = NULL;
		goto err_out;
		rc = -ENOMEM;
		goto err_free_local;
	}

	/*
@@ -1061,7 +1060,8 @@ static int __dma_async_device_channel_register(struct dma_device *device,
	if (chan->chan_id < 0) {
		pr_err("%s: unable to alloc ida for chan: %d\n",
		       __func__, chan->chan_id);
		goto err_out;
		rc = chan->chan_id;
		goto err_free_dev;
	}

	chan->dev->device.class = &dma_devclass;
@@ -1082,9 +1082,10 @@ static int __dma_async_device_channel_register(struct dma_device *device,
	mutex_lock(&device->chan_mutex);
	ida_free(&device->chan_ida, chan->chan_id);
	mutex_unlock(&device->chan_mutex);
 err_out:
	free_percpu(chan->local);
 err_free_dev:
	kfree(chan->dev);
 err_free_local:
	free_percpu(chan->local);
	return rc;
}

+15 −16
Original line number Diff line number Diff line
@@ -271,7 +271,7 @@ int idxd_wq_map_portal(struct idxd_wq *wq)
	resource_size_t start;

	start = pci_resource_start(pdev, IDXD_WQ_BAR);
	start = start + wq->id * IDXD_PORTAL_SIZE;
	start += idxd_get_wq_portal_full_offset(wq->id, IDXD_PORTAL_LIMITED);

	wq->dportal = devm_ioremap(dev, start, IDXD_PORTAL_SIZE);
	if (!wq->dportal)
@@ -295,7 +295,7 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
	int i, wq_offset;

	lockdep_assert_held(&idxd->dev_lock);
	memset(&wq->wqcfg, 0, sizeof(wq->wqcfg));
	memset(wq->wqcfg, 0, idxd->wqcfg_size);
	wq->type = IDXD_WQT_NONE;
	wq->size = 0;
	wq->group = NULL;
@@ -304,8 +304,8 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq)
	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);
	for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
		wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
		iowrite32(0, idxd->reg_base + wq_offset);
		dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n",
			wq->id, i, wq_offset,
@@ -539,10 +539,10 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	if (!wq->group)
		return 0;

	memset(&wq->wqcfg, 0, sizeof(union wqcfg));
	memset(wq->wqcfg, 0, idxd->wqcfg_size);

	/* byte 0-3 */
	wq->wqcfg.wq_size = wq->size;
	wq->wqcfg->wq_size = wq->size;

	if (wq->size == 0) {
		dev_warn(dev, "Incorrect work queue size: 0\n");
@@ -550,22 +550,21 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	}

	/* bytes 4-7 */
	wq->wqcfg.wq_thresh = wq->threshold;
	wq->wqcfg->wq_thresh = wq->threshold;

	/* byte 8-11 */
	wq->wqcfg.priv = !!(wq->type == IDXD_WQT_KERNEL);
	wq->wqcfg.mode = 1;

	wq->wqcfg.priority = wq->priority;
	wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL);
	wq->wqcfg->mode = 1;
	wq->wqcfg->priority = wq->priority;

	/* bytes 12-15 */
	wq->wqcfg.max_xfer_shift = ilog2(wq->max_xfer_bytes);
	wq->wqcfg.max_batch_shift = ilog2(wq->max_batch_size);
	wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes);
	wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size);

	dev_dbg(dev, "WQ %d CFGs\n", wq->id);
	for (i = 0; i < 8; i++) {
		wq_offset = idxd->wqcfg_offset + wq->id * 32 + i * sizeof(u32);
		iowrite32(wq->wqcfg.bits[i], idxd->reg_base + wq_offset);
	for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
		wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
		iowrite32(wq->wqcfg->bits[i], 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));
+2 −1
Original line number Diff line number Diff line
@@ -103,7 +103,7 @@ struct idxd_wq {
	u32 priority;
	enum idxd_wq_state state;
	unsigned long flags;
	union wqcfg wqcfg;
	union wqcfg *wqcfg;
	u32 vec_ptr;		/* interrupt steering */
	struct dsa_hw_desc **hw_descs;
	int num_descs;
@@ -183,6 +183,7 @@ struct idxd_device {
	int max_wq_size;
	int token_limit;
	int nr_tokens;		/* non-reserved tokens */
	unsigned int wqcfg_size;

	union sw_err_reg sw_err;
	wait_queue_head_t cmd_waitq;
+5 −0
Original line number Diff line number Diff line
@@ -178,6 +178,9 @@ static int idxd_setup_internals(struct idxd_device *idxd)
		wq->idxd_cdev.minor = -1;
		wq->max_xfer_bytes = idxd->max_xfer_bytes;
		wq->max_batch_size = idxd->max_batch_size;
		wq->wqcfg = devm_kzalloc(dev, idxd->wqcfg_size, GFP_KERNEL);
		if (!wq->wqcfg)
			return -ENOMEM;
	}

	for (i = 0; i < idxd->max_engines; i++) {
@@ -251,6 +254,8 @@ static void idxd_read_caps(struct idxd_device *idxd)
	dev_dbg(dev, "total workqueue size: %u\n", idxd->max_wq_size);
	idxd->max_wqs = idxd->hw.wq_cap.num_wqs;
	dev_dbg(dev, "max workqueues: %u\n", idxd->max_wqs);
	idxd->wqcfg_size = 1 << (idxd->hw.wq_cap.wqcfg_size + IDXD_WQCFG_MIN);
	dev_dbg(dev, "wqcfg size: %u\n", idxd->wqcfg_size);

	/* reading operation capabilities */
	for (i = 0; i < 4; i++) {
+23 −2
Original line number Diff line number Diff line
@@ -8,7 +8,7 @@

#define IDXD_MMIO_BAR		0
#define IDXD_WQ_BAR		2
#define IDXD_PORTAL_SIZE	0x4000
#define IDXD_PORTAL_SIZE	PAGE_SIZE

/* MMIO Device BAR0 Registers */
#define IDXD_VER_OFFSET			0x00
@@ -43,7 +43,8 @@ union wq_cap_reg {
	struct {
		u64 total_wq_size:16;
		u64 num_wqs:8;
		u64 rsvd:24;
		u64 wqcfg_size:4;
		u64 rsvd:20;
		u64 shared_mode:1;
		u64 dedicated_mode:1;
		u64 rsvd2:1;
@@ -55,6 +56,7 @@ union wq_cap_reg {
	u64 bits;
} __packed;
#define IDXD_WQCAP_OFFSET		0x20
#define IDXD_WQCFG_MIN			5

union group_cap_reg {
	struct {
@@ -333,4 +335,23 @@ union wqcfg {
	};
	u32 bits[8];
} __packed;

/*
 * This macro calculates the offset into the WQCFG register
 * idxd - struct idxd *
 * n - wq id
 * ofs - the index of the 32b dword for the config register
 *
 * The WQCFG register block is divided into groups per each wq. The n index
 * allows us to move to the register group that's for that particular wq.
 * Each register is 32bits. The ofs gives us the number of register to access.
 */
#define WQCFG_OFFSET(_idxd_dev, n, ofs) \
({\
	typeof(_idxd_dev) __idxd_dev = (_idxd_dev);	\
	(__idxd_dev)->wqcfg_offset + (n) * (__idxd_dev)->wqcfg_size + sizeof(u32) * (ofs);	\
})

#define WQCFG_STRIDES(_idxd_dev) ((_idxd_dev)->wqcfg_size / sizeof(u32))

#endif
Loading