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

dmaengine: idxd: don't load pasid config until needed



The driver currently programs the system pasid to the WQ preemptively when
system pasid is enabled. Given that a dwq will reprogram the pasid and
possibly a different pasid, the programming is not necessary. The pasid_en
bit can be set for swq as it does not need pasid programming but
needs the pasid_en bit. Remove system pasid programming on device config
write. Add pasid programming for kernel wq type on wq driver enable. The
char dev driver already reprograms the dwq on ->open() call so there's no
change.

Signed-off-by: default avatarDave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/164935607115.1660372.6734518676950372366.stgit@djiang5-desk3.ch.intel.com


Signed-off-by: default avatarVinod Koul <vkoul@kernel.org>
parent 80380f89
Loading
Loading
Loading
Loading
+52 −14
Original line number Diff line number Diff line
@@ -299,24 +299,46 @@ void idxd_wqs_unmap_portal(struct idxd_device *idxd)
	}
}

int idxd_wq_set_pasid(struct idxd_wq *wq, int pasid)
static void __idxd_wq_set_priv_locked(struct idxd_wq *wq, int priv)
{
	struct idxd_device *idxd = wq->idxd;
	int rc;
	union wqcfg wqcfg;
	unsigned int offset;

	rc = idxd_wq_disable(wq, false);
	if (rc < 0)
		return rc;
	offset = WQCFG_OFFSET(idxd, wq->id, WQCFG_PRIVL_IDX);
	spin_lock(&idxd->dev_lock);
	wqcfg.bits[WQCFG_PRIVL_IDX] = ioread32(idxd->reg_base + offset);
	wqcfg.priv = priv;
	wq->wqcfg->bits[WQCFG_PRIVL_IDX] = wqcfg.bits[WQCFG_PRIVL_IDX];
	iowrite32(wqcfg.bits[WQCFG_PRIVL_IDX], idxd->reg_base + offset);
	spin_unlock(&idxd->dev_lock);
}

static void __idxd_wq_set_pasid_locked(struct idxd_wq *wq, int pasid)
{
	struct idxd_device *idxd = wq->idxd;
	union wqcfg wqcfg;
	unsigned int offset;

	offset = WQCFG_OFFSET(idxd, wq->id, WQCFG_PASID_IDX);
	spin_lock(&idxd->dev_lock);
	wqcfg.bits[WQCFG_PASID_IDX] = ioread32(idxd->reg_base + offset);
	wqcfg.pasid_en = 1;
	wqcfg.pasid = pasid;
	wq->wqcfg->bits[WQCFG_PASID_IDX] = wqcfg.bits[WQCFG_PASID_IDX];
	iowrite32(wqcfg.bits[WQCFG_PASID_IDX], idxd->reg_base + offset);
	spin_unlock(&idxd->dev_lock);
}

int idxd_wq_set_pasid(struct idxd_wq *wq, int pasid)
{
	int rc;

	rc = idxd_wq_disable(wq, false);
	if (rc < 0)
		return rc;

	__idxd_wq_set_pasid_locked(wq, pasid);

	rc = idxd_wq_enable(wq);
	if (rc < 0)
@@ -797,7 +819,7 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	 */
	for (i = 0; i < WQCFG_STRIDES(idxd); i++) {
		wq_offset = WQCFG_OFFSET(idxd, wq->id, i);
		wq->wqcfg->bits[i] = ioread32(idxd->reg_base + wq_offset);
		wq->wqcfg->bits[i] |= ioread32(idxd->reg_base + wq_offset);
	}

	if (wq->size == 0 && wq->type != IDXD_WQT_NONE)
@@ -813,14 +835,8 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	if (wq_dedicated(wq))
		wq->wqcfg->mode = 1;

	if (device_pasid_enabled(idxd)) {
		wq->wqcfg->pasid_en = 1;
		if (wq->type == IDXD_WQT_KERNEL && wq_dedicated(wq))
			wq->wqcfg->pasid = idxd->pasid;
	}

	/*
	 * Here the priv bit is set depending on the WQ type. priv = 1 if the
	 * The WQ priv bit is set depending on the WQ type. priv = 1 if the
	 * WQ type is kernel to indicate privileged access. This setting only
	 * matters for dedicated WQ. According to the DSA spec:
	 * If the WQ is in dedicated mode, WQ PASID Enable is 1, and the
@@ -830,7 +846,6 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
	 * In the case of a dedicated kernel WQ that is not able to support
	 * the PASID cap, then the configuration will be rejected.
	 */
	wq->wqcfg->priv = !!(wq->type == IDXD_WQT_KERNEL);
	if (wq_dedicated(wq) && wq->wqcfg->pasid_en &&
	    !idxd_device_pasid_priv_enabled(idxd) &&
	    wq->type == IDXD_WQT_KERNEL) {
@@ -1263,6 +1278,29 @@ int __drv_enable_wq(struct idxd_wq *wq)
		}
	}

	/*
	 * In the event that the WQ is configurable for pasid and priv bits.
	 * For kernel wq, the driver should setup the pasid, pasid_en, and priv bit.
	 * However, for non-kernel wq, the driver should only set the pasid_en bit for
	 * shared wq. A dedicated wq that is not 'kernel' type will configure pasid and
	 * pasid_en later on so there is no need to setup.
	 */
	if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) {
		int priv = 0;

		if (device_pasid_enabled(idxd)) {
			if (is_idxd_wq_kernel(wq) || wq_shared(wq)) {
				u32 pasid = wq_dedicated(wq) ? idxd->pasid : 0;

				__idxd_wq_set_pasid_locked(wq, pasid);
			}
		}

		if (is_idxd_wq_kernel(wq))
			priv = 1;
		__idxd_wq_set_priv_locked(wq, priv);
	}

	rc = 0;
	spin_lock(&idxd->dev_lock);
	if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
+1 −0
Original line number Diff line number Diff line
@@ -353,6 +353,7 @@ union wqcfg {
} __packed;

#define WQCFG_PASID_IDX                2
#define WQCFG_PRIVL_IDX		2
#define WQCFG_OCCUP_IDX		6

#define WQCFG_OCCUP_MASK	0xffff