Commit b0325aef authored by Dave Jiang's avatar Dave Jiang Committed by Vinod Koul
Browse files

dmaengine: idxd: add WQ operation cap restriction support



DSA 2.0 add the capability of configuring DMA ops on a per workqueue basis.
This means that certain ops can be disabled by the system administrator for
certain wq. By default, all ops are available. A bitmap is used to store
the ops due to total op size of 256 bits and it is more convenient to use a
range list to specify which bits are enabled.

One of the usage to support this is for VM migration between different
iteration of devices. The newer ops are disabled in order to allow guest to
migrate to a host that only support older ops. Another usage is to
restrict the WQ to certain operations for QoS of performance.

A sysfs of ops_config attribute is added per wq. It is only usable when the
ops_config bit is set under WQ_CAP register. This means that this attribute
will return -EOPNOTSUPP on DSA 1.x devices. The expected input is a range
list for the bits per operation the WQ supports.

Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Co-developed-by: default avatarFenghua Yu <fenghua.yu@intel.com>
Signed-off-by: default avatarFenghua Yu <fenghua.yu@intel.com>
Link: https://lore.kernel.org/r/20220917161222.2835172-4-fenghua.yu@intel.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent a8563a33
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -227,6 +227,17 @@ Contact: dmaengine@vger.kernel.org
Description:	Indicate the number of retires for an enqcmds submission on a sharedwq.
		A max value to set attribute is capped at 64.

What:		/sys/bus/dsa/devices/wq<m>.<n>/op_config
Date:		Sept 14, 2022
KernelVersion:	6.0.0
Contact:	dmaengine@vger.kernel.org
Description:	Shows the operation capability bits displayed in bitmap format
		presented by %*pb printk() output format specifier.
		The attribute can be configured when the WQ is disabled in
		order to configure the WQ to accept specific bits that
		correlates to the operations allowed. It's visible only
		on platforms that support the capability.

What:           /sys/bus/dsa/devices/engine<m>.<n>/group_id
Date:           Oct 25, 2019
KernelVersion:  5.6.0
+14 −1
Original line number Diff line number Diff line
@@ -391,6 +391,8 @@ static void idxd_wq_disable_cleanup(struct idxd_wq *wq)
	memset(wq->name, 0, WQ_NAME_SIZE);
	wq->max_xfer_bytes = WQ_DEFAULT_MAX_XFER;
	wq->max_batch_size = WQ_DEFAULT_MAX_BATCH;
	if (wq->opcap_bmap)
		bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
}

static void idxd_wq_device_reset_cleanup(struct idxd_wq *wq)
@@ -809,7 +811,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	struct idxd_device *idxd = wq->idxd;
	struct device *dev = &idxd->pdev->dev;
	u32 wq_offset;
	int i;
	int i, n;

	if (!wq->group)
		return 0;
@@ -867,6 +869,17 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes);
	wq->wqcfg->max_batch_shift = ilog2(wq->max_batch_size);

	/* bytes 32-63 */
	if (idxd->hw.wq_cap.op_config && wq->opcap_bmap) {
		memset(wq->wqcfg->op_config, 0, IDXD_MAX_OPCAP_BITS / 8);
		for_each_set_bit(n, wq->opcap_bmap, IDXD_MAX_OPCAP_BITS) {
			int pos = n % BITS_PER_LONG_LONG;
			int idx = n / BITS_PER_LONG_LONG;

			wq->wqcfg->op_config[idx] |= BIT(pos);
		}
	}

	dev_dbg(dev, "WQ %d CFGs\n", wq->id);
	for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
		wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
+2 −0
Original line number Diff line number Diff line
@@ -196,6 +196,8 @@ struct idxd_wq {
	enum idxd_wq_state state;
	unsigned long flags;
	union wqcfg *wqcfg;
	unsigned long *opcap_bmap;

	struct dsa_hw_desc **hw_descs;
	int num_descs;
	union {
+10 −0
Original line number Diff line number Diff line
@@ -191,6 +191,16 @@ static int idxd_setup_wqs(struct idxd_device *idxd)
			rc = -ENOMEM;
			goto err;
		}

		if (idxd->hw.wq_cap.op_config) {
			wq->opcap_bmap = bitmap_zalloc(IDXD_MAX_OPCAP_BITS, GFP_KERNEL);
			if (!wq->opcap_bmap) {
				put_device(conf_dev);
				rc = -ENOMEM;
				goto err;
			}
			bitmap_copy(wq->opcap_bmap, idxd->opcap_bmap, IDXD_MAX_OPCAP_BITS);
		}
		idxd->wqs[i] = wq;
	}

+6 −2
Original line number Diff line number Diff line
@@ -54,7 +54,8 @@ union wq_cap_reg {
		u64 priority:1;
		u64 occupancy:1;
		u64 occupancy_int:1;
		u64 rsvd3:10;
		u64 op_config:1;
		u64 rsvd3:9;
	};
	u64 bits;
} __packed;
@@ -350,8 +351,11 @@ union wqcfg {

		/* bytes 28-31 */
		u32 rsvd8;

		/* bytes 32-63 */
		u64 op_config[4];
	};
	u32 bits[8];
	u32 bits[16];
} __packed;

#define WQCFG_PASID_IDX                2
Loading