Skip to content

Commit f80ea85

Browse files
nikhilpraovinodkoul
authored andcommitted
dmaengine: idxd: drain ATS translations when disabling WQ
There's an errata[1], for the Disable WQ command that it does not guaranteee that address translations are drained. If WQ configuration is updated, pending address translations can use an updated WQ configuration, resulting an invalid translation response that is cached in the device translation cache. Replace the Disable WQ command with a Drain WQ command followed by a Reset WQ command, this guarantees that all ATS translations are drained from the device before changing WQ configuration. [1] https://cdrdv2.intel.com/v1/dl/getcontent/843306 ("Intel DSA May Cause Invalid Translation Caching") Signed-off-by: Nikhil Rao <nikhil.rao@intel.com> Signed-off-by: Fenghua Yu <fenghua.yu@intel.com> Signed-off-by: Vinicius Costa Gomes <vinicius.gomes@intel.com> Reviewed-by: Dave Jiang <dave.jiang@intel.com> Signed-off-by: Vinod Koul <vkoul@kernel.org>
1 parent bc2c396 commit f80ea85

1 file changed

Lines changed: 17 additions & 2 deletions

File tree

drivers/dma/idxd/device.c

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ static void idxd_cmd_exec(struct idxd_device *idxd, int cmd_code, u32 operand,
1616
u32 *status);
1717
static void idxd_device_wqs_clear_state(struct idxd_device *idxd);
1818
static void idxd_wq_disable_cleanup(struct idxd_wq *wq);
19+
static int idxd_wq_config_write(struct idxd_wq *wq);
1920

2021
/* Interrupt control bits */
2122
void idxd_unmask_error_interrupts(struct idxd_device *idxd)
@@ -215,14 +216,28 @@ int idxd_wq_disable(struct idxd_wq *wq, bool reset_config)
215216
return 0;
216217
}
217218

219+
/*
220+
* Disable WQ does not drain address translations, if WQ attributes are
221+
* changed before translations are drained, pending translations can
222+
* be issued using updated WQ attibutes, resulting in invalid
223+
* translations being cached in the device translation cache.
224+
*
225+
* To make sure pending translations are drained before WQ
226+
* attributes are changed, we use a WQ Drain followed by WQ Reset and
227+
* then restore the WQ configuration.
228+
*/
229+
idxd_wq_drain(wq);
230+
218231
operand = BIT(wq->id % 16) | ((wq->id / 16) << 16);
219-
idxd_cmd_exec(idxd, IDXD_CMD_DISABLE_WQ, operand, &status);
232+
idxd_cmd_exec(idxd, IDXD_CMD_RESET_WQ, operand, &status);
220233

221234
if (status != IDXD_CMDSTS_SUCCESS) {
222-
dev_dbg(dev, "WQ disable failed: %#x\n", status);
235+
dev_dbg(dev, "WQ reset failed: %#x\n", status);
223236
return -ENXIO;
224237
}
225238

239+
idxd_wq_config_write(wq);
240+
226241
if (reset_config)
227242
idxd_wq_disable_cleanup(wq);
228243
clear_bit(wq->id, idxd->wq_enable_map);

0 commit comments

Comments
 (0)