dmaengine: idxd: expose IAA CAP register via sysfs knob
authorDave Jiang <dave.jiang@intel.com>
Fri, 3 Mar 2023 21:37:32 +0000 (13:37 -0800)
committerVinod Koul <vkoul@kernel.org>
Fri, 31 Mar 2023 11:56:53 +0000 (17:26 +0530)
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@intel.com>
Co-developed-by: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: Fenghua Yu <fenghua.yu@intel.com>
Link: https://lore.kernel.org/r/20230303213732.3357494-3-fenghua.yu@intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
Documentation/ABI/stable/sysfs-driver-dma-idxd
drivers/dma/idxd/idxd.h
drivers/dma/idxd/init.c
drivers/dma/idxd/registers.h
drivers/dma/idxd/sysfs.c

index 3becc9a82bdf6fbb28012e84763811dd6c091450..d5e3dd3d843475f22a722be553f58b448282b922 100644 (file)
@@ -136,6 +136,14 @@ Description:       The last executed device administrative command's status/error.
                Also last configuration error overloaded.
                Writing to it will clear the status.
 
+What:          /sys/bus/dsa/devices/dsa<m>/iaa_cap
+Date:          Sept 14, 2022
+KernelVersion: 6.0.0
+Contact:       dmaengine@vger.kernel.org
+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
index ad7a1e8a0e1cbe46d84ef97c9c0cf2d564e2024e..eca2c9d76db6e9020fbed7e8f695f0c2eb6cf6f3 100644 (file)
@@ -232,6 +232,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 {
index bddff1d4359d293f7d362f372c678a6a69120396..a78cfd361c04a173e56920e2b8fcf535930ebc34 100644 (file)
@@ -460,6 +460,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)
index fe3b8d04f9db165d5df454a31e0a6b398f9451e4..338289a66f00804bb1b4c066b6640432325806fa 100644 (file)
@@ -276,6 +276,27 @@ union sw_err_reg {
        u64 bits[4];
 } __packed;
 
+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;
index 927c9d64512199c0b99148cf04c6de3f6c1150c5..2eba8cab25a1e93660311571642cecf3ae95281e 100644 (file)
@@ -1561,6 +1561,18 @@ static ssize_t cmd_status_store(struct device *dev, struct device_attribute *att
 }
 static DEVICE_ATTR_RW(cmd_status);
 
+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)
 {
@@ -1583,6 +1595,14 @@ static bool idxd_device_attr_read_buffers_invisible(struct attribute *attr,
                idxd->data->type == IDXD_TYPE_IAX;
 }
 
+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)
 {
@@ -1595,6 +1615,9 @@ static umode_t idxd_device_attr_visible(struct kobject *kobj,
        if (idxd_device_attr_read_buffers_invisible(attr, idxd))
                return 0;
 
+       if (idxd_device_attr_iaa_cap_invisible(attr, idxd))
+               return 0;
+
        return attr->mode;
 }
 
@@ -1620,6 +1643,7 @@ static struct attribute *idxd_device_attributes[] = {
        &dev_attr_read_buffer_limit.attr,
        &dev_attr_cdev_major.attr,
        &dev_attr_cmd_status.attr,
+       &dev_attr_iaa_cap.attr,
        NULL,
 };