Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

dmaengine: idxd: add ATS disable knob for work queues

With the DSA spec 1.1 update, a knob to disable ATS for individually is
introduced. Add enabling code to allow a system admin to make the
configuration through sysfs.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/160530810593.1288392.2561048329116529566.stgit@djiang5-desk3.ch.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Dave Jiang and committed by
Vinod Koul
92de5fa2 5d051f37

+49 -2
+7
Documentation/ABI/stable/sysfs-driver-dma-idxd
··· 204 204 Description: The max batch size for this workqueue. Cannot exceed device 205 205 max batch size. Configurable parameter. 206 206 207 + What: /sys/bus/dsa/devices/wq<m>.<n>/ats_disable 208 + Date: Nov 13, 2020 209 + KernelVersion: 5.11.0 210 + Contact: dmaengine@vger.kernel.org 211 + Description: Indicate whether ATS disable is turned on for the workqueue. 212 + 0 indicates ATS is on, and 1 indicates ATS is off for the workqueue. 213 + 207 214 What: /sys/bus/dsa/devices/engine<m>.<n>/group_id 208 215 Date: Oct 25, 2019 209 216 KernelVersion: 5.6.0
+4
drivers/dma/idxd/device.c
··· 354 354 wq->group = NULL; 355 355 wq->threshold = 0; 356 356 wq->priority = 0; 357 + wq->ats_dis = 0; 357 358 clear_bit(WQ_FLAG_DEDICATED, &wq->flags); 358 359 memset(wq->name, 0, WQ_NAME_SIZE); 359 360 ··· 631 630 if (idxd->hw.gen_cap.block_on_fault && 632 631 test_bit(WQ_FLAG_BLOCK_ON_FAULT, &wq->flags)) 633 632 wq->wqcfg->bof = 1; 633 + 634 + if (idxd->hw.wq_cap.wq_ats_support) 635 + wq->wqcfg->wq_ats_disable = wq->ats_dis; 634 636 635 637 /* bytes 12-15 */ 636 638 wq->wqcfg->max_xfer_shift = ilog2(wq->max_xfer_bytes);
+1
drivers/dma/idxd/idxd.h
··· 123 123 char name[WQ_NAME_SIZE + 1]; 124 124 u64 max_xfer_bytes; 125 125 u32 max_batch_size; 126 + bool ats_dis; 126 127 }; 127 128 128 129 struct idxd_engine {
+3 -2
drivers/dma/idxd/registers.h
··· 47 47 u64 rsvd:20; 48 48 u64 shared_mode:1; 49 49 u64 dedicated_mode:1; 50 - u64 rsvd2:1; 50 + u64 wq_ats_support:1; 51 51 u64 priority:1; 52 52 u64 occupancy:1; 53 53 u64 occupancy_int:1; ··· 303 303 /* bytes 8-11 */ 304 304 u32 mode:1; /* shared or dedicated */ 305 305 u32 bof:1; /* block on fault */ 306 - u32 rsvd2:2; 306 + u32 wq_ats_disable:1; 307 + u32 rsvd2:1; 307 308 u32 priority:4; 308 309 u32 pasid:20; 309 310 u32 pasid_en:1;
+34
drivers/dma/idxd/sysfs.c
··· 1261 1261 static struct device_attribute dev_attr_wq_max_batch_size = 1262 1262 __ATTR(max_batch_size, 0644, wq_max_batch_size_show, wq_max_batch_size_store); 1263 1263 1264 + static ssize_t wq_ats_disable_show(struct device *dev, struct device_attribute *attr, char *buf) 1265 + { 1266 + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 1267 + 1268 + return sprintf(buf, "%u\n", wq->ats_dis); 1269 + } 1270 + 1271 + static ssize_t wq_ats_disable_store(struct device *dev, struct device_attribute *attr, 1272 + const char *buf, size_t count) 1273 + { 1274 + struct idxd_wq *wq = container_of(dev, struct idxd_wq, conf_dev); 1275 + struct idxd_device *idxd = wq->idxd; 1276 + bool ats_dis; 1277 + int rc; 1278 + 1279 + if (wq->state != IDXD_WQ_DISABLED) 1280 + return -EPERM; 1281 + 1282 + if (!idxd->hw.wq_cap.wq_ats_support) 1283 + return -EOPNOTSUPP; 1284 + 1285 + rc = kstrtobool(buf, &ats_dis); 1286 + if (rc < 0) 1287 + return rc; 1288 + 1289 + wq->ats_dis = ats_dis; 1290 + 1291 + return count; 1292 + } 1293 + 1294 + static struct device_attribute dev_attr_wq_ats_disable = 1295 + __ATTR(ats_disable, 0644, wq_ats_disable_show, wq_ats_disable_store); 1296 + 1264 1297 static struct attribute *idxd_wq_attributes[] = { 1265 1298 &dev_attr_wq_clients.attr, 1266 1299 &dev_attr_wq_state.attr, ··· 1308 1275 &dev_attr_wq_cdev_minor.attr, 1309 1276 &dev_attr_wq_max_transfer_size.attr, 1310 1277 &dev_attr_wq_max_batch_size.attr, 1278 + &dev_attr_wq_ats_disable.attr, 1311 1279 NULL, 1312 1280 }; 1313 1281