dmaengine: idxd: move wq pasid configuration until when needed

commit 098159e3d405124cbc2020d93f529dff0eb7869e Intel-BKC.

The main issue is that when we program wq with pasid of 0 but pasid_en set
for shared wq, it confuses the VDCM. Remove the WQ pasid setting during
configuration programming of the device as the driver does not have enough
information at that point to make that decision. Program the WQCFG pasid
and pasid_en at the time when it is needed. Add support in VDCM to
understand what pasid_en=1 and pasid=0 means.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Signed-off-by: Chen Zhuo <sagazchen@tencent.com>
Signed-off-by: Xinghui Li <korantli@tencent.com>
This commit is contained in:
Dave Jiang 2022-03-10 09:08:23 -07:00 committed by Jianping Liu
parent 2f7442edee
commit 589a7fc3bf
2 changed files with 32 additions and 23 deletions

View File

@ -443,6 +443,7 @@ static void __idxd_wq_set_priv_locked(struct idxd_wq *wq)
spin_lock(&idxd->dev_lock);
wqcfg.bits[WQCFG_PRIV_IDX] = ioread32(idxd->reg_base + offset);
wqcfg.priv = 1;
wq->wqcfg->bits[WQCFG_PRIV_IDX] = wqcfg.bits[WQCFG_PRIV_IDX];
iowrite32(wqcfg.bits[WQCFG_PRIV_IDX], idxd->reg_base + offset);
spin_unlock(&idxd->dev_lock);
}
@ -458,6 +459,7 @@ static void __idxd_wq_set_pasid_locked(struct idxd_wq *wq, int pasid)
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);
}
@ -987,7 +989,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)
@ -1003,16 +1005,6 @@ static int idxd_wq_config_write(struct idxd_wq *wq)
if (wq_dedicated(wq))
wq->wqcfg->mode = 1;
/*
* Enable this for shared WQ. swq does not need to program the pasid field,
* but pasid_en needs to be set. Programming here prevents swq being disabled
* and re-enabled, which is something to avoid.
*/
if ((is_idxd_wq_kernel(wq) && device_pasid_enabled(idxd)) ||
((is_idxd_wq_user(wq) || is_idxd_wq_mdev(wq)) &&
device_user_pasid_enabled(idxd)))
wq->wqcfg->pasid_en = 1;
/*
* Here the priv bit is set depending on the WQ type. priv = 1 if the
* WQ type is kernel to indicate privileged access. This setting only
@ -1210,12 +1202,6 @@ static int idxd_wq_load_config(struct idxd_wq *wq)
if (wq->wqcfg->bof)
set_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags);
if (device_pasid_enabled(idxd) && wq->wqcfg->mode == 1) {
wq->wqcfg->pasid_en = 1;
wqcfg_offset = WQCFG_OFFSET(idxd, wq->id, WQCFG_PASID_IDX);
iowrite32(wq->wqcfg->bits[WQCFG_PASID_IDX], idxd->reg_base + wqcfg_offset);
}
if (wq->wqcfg->mode_support)
set_bit(WQ_FLAG_MODE_1, &wq->flags);
@ -1471,11 +1457,27 @@ 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 will configure pasid and pasid_en later on so
* there is no need to setup.
*/
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags) ||
test_bit(WQ_FLAG_MODE_1, &wq->flags)) {
if (is_idxd_wq_kernel(wq)) {
if (device_pasid_enabled(idxd)) {
u32 pasid = wq_dedicated(wq) ? idxd->pasid : 0;
__idxd_wq_set_pasid_locked(wq, pasid);
}
__idxd_wq_set_priv_locked(wq);
} else {
if (device_user_pasid_enabled(idxd) && wq_shared(wq))
__idxd_wq_set_pasid_locked(wq, 0);
}
if (is_idxd_wq_kernel(wq)) {
if (device_pasid_enabled(idxd) && wq_dedicated(wq))
__idxd_wq_set_pasid_locked(wq, idxd->pasid);
__idxd_wq_set_priv_locked(wq);
}
rc = 0;

View File

@ -1191,8 +1191,15 @@ static void vidxd_wq_enable(struct vdcm_idxd *vidxd, int wq_id)
priv = vwqcfg->priv;
gpasid = vwqcfg->pasid;
rc = idxd_mdev_get_host_pasid(mdev, gpasid, &wq_pasid);
dev_dbg(dev, "guest pasid enabled, translate gpasid: %d\n", gpasid);
if (gpasid == 0) {
rc = idxd_mdev_get_pasid(mdev, &wq_pasid);
dev_dbg(dev, "shared wq, pasid 0, use default host: %u\n",
wq_pasid);
} else {
rc = idxd_mdev_get_host_pasid(mdev, gpasid, &wq_pasid);
dev_dbg(dev, "guest pasid enabled, translate gpasid: %d\n", gpasid);
}
} else {
priv = 1;
rc = idxd_mdev_get_pasid(mdev, &wq_pasid);