mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-10-28 15:20:41 +00:00
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: Dave Jiang <dave.jiang@intel.com> Link: https://lore.kernel.org/r/164935607115.1660372.6734518676950372366.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
80380f89d0
commit
3157dd0a36
2 changed files with 53 additions and 14 deletions
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue