[PATCH 2/2] dmaengine: idxd: expose IAA CAP register via sysfs knob

From: Fenghua Yu
Date: Tue Jan 03 2023 - 11:54:12 EST


From: Dave Jiang <dave.jiang@xxxxxxxxx>

Add IAA (IAX) capability mask sysfs attribute to expose to applications.
The mask provides application knowledge of what capabilities this IAA
device supports. This mask is available for IAA 2.0 device or later.

Signed-off-by: Dave Jiang <dave.jiang@xxxxxxxxx>
Co-developed-by: Fenghua Yu <fenghua.yu@xxxxxxxxx>
Signed-off-by: Fenghua Yu <fenghua.yu@xxxxxxxxx>
---
This patch is applied cleanly on top of DSA 2.0 Event Log and Completion
Record Faulting series:
https://lore.kernel.org/dmaengine/20230103163505.1569356-1-fenghua.yu@xxxxxxxxx/T/#m13ba6167994f3add6446d2d7e242ecb637c54426

.../ABI/stable/sysfs-driver-dma-idxd | 8 +++++++
drivers/dma/idxd/idxd.h | 1 +
drivers/dma/idxd/init.c | 4 ++++
drivers/dma/idxd/registers.h | 21 ++++++++++++++++
drivers/dma/idxd/sysfs.c | 24 +++++++++++++++++++
5 files changed, 58 insertions(+)

diff --git a/Documentation/ABI/stable/sysfs-driver-dma-idxd b/Documentation/ABI/stable/sysfs-driver-dma-idxd
index 603869112887..796a5dccdf04 100644
--- a/Documentation/ABI/stable/sysfs-driver-dma-idxd
+++ b/Documentation/ABI/stable/sysfs-driver-dma-idxd
@@ -144,6 +144,14 @@ Description: The event log size to be configured. Default is 64 entries and
occupies 4k size if the evl entry is 64 bytes. It's visible
only on platforms that support the capability.

+What: /sys/bus/dsa/devices/dsa<m>/iaa_cap
+Date: Sept 14, 2022
+KernelVersion: 6.0.0
+Contact: dmaengine@xxxxxxxxxxxxxxx
+Description: IAA (IAX) capability mask. Exported to user space for application
+ consumption. This attribute should only be visible on IAA devices
+ that are version 2 or later.
+
What: /sys/bus/dsa/devices/wq<m>.<n>/block_on_fault
Date: Oct 27, 2020
KernelVersion: 5.11.0
diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h
index e449d905bea3..3a20e4933d07 100644
--- a/drivers/dma/idxd/idxd.h
+++ b/drivers/dma/idxd/idxd.h
@@ -245,6 +245,7 @@ struct idxd_hw {
union engine_cap_reg engine_cap;
struct opcap opcap;
u32 cmd_cap;
+ union iaa_cap_reg iaa_cap;
};

enum idxd_device_state {
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
index 996bd3e4e50f..6c1d1682fce9 100644
--- a/drivers/dma/idxd/init.c
+++ b/drivers/dma/idxd/init.c
@@ -497,6 +497,10 @@ static void idxd_read_caps(struct idxd_device *idxd)
dev_dbg(dev, "opcap[%d]: %#llx\n", i, idxd->hw.opcap.bits[i]);
}
multi_u64_to_bmap(idxd->opcap_bmap, &idxd->hw.opcap.bits[0], 4);
+
+ /* read iaa cap */
+ if (idxd->data->type == IDXD_TYPE_IAX && idxd->hw.version >= DEVICE_VERSION_2)
+ idxd->hw.iaa_cap.bits = ioread64(idxd->reg_base + IDXD_IAACAP_OFFSET);
}

static struct idxd_device *idxd_alloc(struct pci_dev *pdev, struct idxd_driver_data *data)
diff --git a/drivers/dma/idxd/registers.h b/drivers/dma/idxd/registers.h
index 6155dc7d2152..6de810d2d2d8 100644
--- a/drivers/dma/idxd/registers.h
+++ b/drivers/dma/idxd/registers.h
@@ -302,6 +302,27 @@ union evlcfg_reg {
#define IDXD_EVL_SIZE_MIN 0x0040
#define IDXD_EVL_SIZE_MAX 0xffff

+union iaa_cap_reg {
+ struct {
+ u64 dec_aecs_format_ver:1;
+ u64 drop_init_bits:1;
+ u64 chaining:1;
+ u64 force_array_output_mod:1;
+ u64 load_part_aecs:1;
+ u64 comp_early_abort:1;
+ u64 nested_comp:1;
+ u64 diction_comp:1;
+ u64 header_gen:1;
+ u64 crypto_gcm:1;
+ u64 crypto_cfb:1;
+ u64 crypto_xts:1;
+ u64 rsvd:52;
+ };
+ u64 bits;
+} __packed;
+
+#define IDXD_IAACAP_OFFSET 0x180
+
union msix_perm {
struct {
u32 rsvd:2;
diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c
index dae28509e6ed..80a81d441252 100644
--- a/drivers/dma/idxd/sysfs.c
+++ b/drivers/dma/idxd/sysfs.c
@@ -1656,6 +1656,18 @@ static ssize_t event_log_size_store(struct device *dev,
}
static DEVICE_ATTR_RW(event_log_size);

+static ssize_t iaa_cap_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct idxd_device *idxd = confdev_to_idxd(dev);
+
+ if (idxd->hw.version < DEVICE_VERSION_2)
+ return -EOPNOTSUPP;
+
+ return sysfs_emit(buf, "%#llx\n", idxd->hw.iaa_cap.bits);
+}
+static DEVICE_ATTR_RO(iaa_cap);
+
static bool idxd_device_attr_max_batch_size_invisible(struct attribute *attr,
struct idxd_device *idxd)
{
@@ -1685,6 +1697,14 @@ static bool idxd_device_attr_event_log_size_invisible(struct attribute *attr,
!idxd->hw.gen_cap.evl_support);
}

+static bool idxd_device_attr_iaa_cap_invisible(struct attribute *attr,
+ struct idxd_device *idxd)
+{
+ return attr == &dev_attr_iaa_cap.attr &&
+ (idxd->data->type != IDXD_TYPE_IAX ||
+ idxd->hw.version < DEVICE_VERSION_2);
+}
+
static umode_t idxd_device_attr_visible(struct kobject *kobj,
struct attribute *attr, int n)
{
@@ -1700,6 +1720,9 @@ static umode_t idxd_device_attr_visible(struct kobject *kobj,
if (idxd_device_attr_event_log_size_invisible(attr, idxd))
return 0;

+ if (idxd_device_attr_iaa_cap_invisible(attr, idxd))
+ return 0;
+
return attr->mode;
}

@@ -1726,6 +1749,7 @@ static struct attribute *idxd_device_attributes[] = {
&dev_attr_cdev_major.attr,
&dev_attr_cmd_status.attr,
&dev_attr_event_log_size.attr,
+ &dev_attr_iaa_cap.attr,
NULL,
};

--
2.32.0