crypto: qat - expose pm_idle_enabled through sysfs
authorLucas Segarra Fernandez <lucas.segarra.fernandez@intel.com>
Fri, 9 Jun 2023 17:06:14 +0000 (19:06 +0200)
committerHerbert Xu <herbert@gondor.apana.org.au>
Fri, 16 Jun 2023 12:30:57 +0000 (20:30 +0800)
Expose 'pm_idle_enabled' sysfs attribute. This attribute controls how
idle conditions are handled. If it is set to 1 (idle support enabled)
when the device detects an idle condition, the driver will transition
the device to the 'MIN' power configuration.

In order to set the value of this attribute for a device, the device
must be in the 'down' state.

This only applies to qat_4xxx generation.

Signed-off-by: Lucas Segarra Fernandez <lucas.segarra.fernandez@intel.com>
Reviewed-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Documentation/ABI/testing/sysfs-driver-qat
drivers/crypto/intel/qat/qat_common/adf_cfg_strings.h
drivers/crypto/intel/qat/qat_common/adf_gen4_pm.c
drivers/crypto/intel/qat/qat_common/adf_gen4_pm.h
drivers/crypto/intel/qat/qat_common/adf_sysfs.c

index e6d427c41beeb8a8d240fc2042f706939e4602e0..ef6d6c57105efbf199495f3c9718a2ae9e0eb68f 100644 (file)
@@ -58,3 +58,38 @@ Description: (RW) Reports the current configuration of the QAT device.
                        dc
 
                This attribute is only available for qat_4xxx devices.
+
+What:          /sys/bus/pci/devices/<BDF>/qat/pm_idle_enabled
+Date:          June 2023
+KernelVersion: 6.5
+Contact:       qat-linux@intel.com
+Description:   (RW) This configuration option provides a way to force the device into remaining in
+               the MAX power state.
+               If idle support is enabled the device will transition to the `MIN` power state when
+               idle, otherwise will stay in the MAX power state.
+               Write to the file to enable or disable idle support.
+
+               The values are:
+
+               * 0: idle support is disabled
+               * 1: idle support is enabled
+
+               Default value is 1.
+
+               It is possible to set the pm_idle_enabled value only if the device
+               is in the `down` state (see /sys/bus/pci/devices/<BDF>/qat/state)
+
+               The following example shows how to change the pm_idle_enabled of
+               a device::
+
+                       # cat /sys/bus/pci/devices/<BDF>/qat/state
+                       up
+                       # cat /sys/bus/pci/devices/<BDF>/qat/pm_idle_enabled
+                       1
+                       # echo down > /sys/bus/pci/devices/<BDF>/qat/state
+                       # echo 0 > /sys/bus/pci/devices/<BDF>/qat/pm_idle_enabled
+                       # echo up > /sys/bus/pci/devices/<BDF>/qat/state
+                       # cat /sys/bus/pci/devices/<BDF>/qat/pm_idle_enabled
+                       0
+
+               This attribute is only available for qat_4xxx devices.
index b6a9abe6d98ce3d119a7b1782e72971c0438afb1..3ae1e5caee0ee2a6833e2b941d68037fa891c7ad 100644 (file)
@@ -33,6 +33,7 @@
 #define ADF_CFG_SYM_DC "sym;dc"
 #define ADF_CFG_DC_SYM "dc;sym"
 #define ADF_SERVICES_ENABLED "ServicesEnabled"
+#define ADF_PM_IDLE_SUPPORT "PmIdleSupport"
 #define ADF_ETRMGR_COALESCING_ENABLED "InterruptCoalescingEnabled"
 #define ADF_ETRMGR_COALESCING_ENABLED_FORMAT \
        ADF_ETRMGR_BANK "%d" ADF_ETRMGR_COALESCING_ENABLED
index 7037c0892a8a2737f085f3c1c578ab4b2bea84da..34c6cd8e27c0b58d16db092e0a1cbc875c0dd1e6 100644 (file)
@@ -23,15 +23,25 @@ struct adf_gen4_pm_data {
 
 static int send_host_msg(struct adf_accel_dev *accel_dev)
 {
+       char pm_idle_support_cfg[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
        void __iomem *pmisc = adf_get_pmisc_base(accel_dev);
+       bool pm_idle_support;
        u32 msg;
+       int ret;
 
        msg = ADF_CSR_RD(pmisc, ADF_GEN4_PM_HOST_MSG);
        if (msg & ADF_GEN4_PM_MSG_PENDING)
                return -EBUSY;
 
+       adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
+                               ADF_PM_IDLE_SUPPORT, pm_idle_support_cfg);
+       ret = kstrtobool(pm_idle_support_cfg, &pm_idle_support);
+       if (ret)
+               pm_idle_support = true;
+
        /* Send HOST_MSG */
-       msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK, PM_SET_MIN);
+       msg = FIELD_PREP(ADF_GEN4_PM_MSG_PAYLOAD_BIT_MASK,
+                        pm_idle_support ? PM_SET_MIN : PM_NO_CHANGE);
        msg |= ADF_GEN4_PM_MSG_PENDING;
        ADF_CSR_WR(pmisc, ADF_GEN4_PM_HOST_MSG, msg);
 
index f8f8a9ee29e5b9b6bf58f90a03098fb0111bd8f3..dd112923e006d0276ff24d53f8057079007de1d6 100644 (file)
@@ -37,6 +37,7 @@
 
 #define ADF_GEN4_PM_DEFAULT_IDLE_FILTER                (0x0)
 #define ADF_GEN4_PM_MAX_IDLE_FILTER            (0x7)
+#define ADF_GEN4_PM_DEFAULT_IDLE_SUPPORT       (0x1)
 
 int adf_gen4_enable_pm(struct adf_accel_dev *accel_dev);
 bool adf_gen4_handle_pm_interrupt(struct adf_accel_dev *accel_dev);
index b2ec92322dd801f4a382aa947884c3c1ed58ce74..a74d2f93036709375c7939f553543ea34223bf74 100644 (file)
@@ -152,12 +152,65 @@ static ssize_t cfg_services_store(struct device *dev, struct device_attribute *a
        return count;
 }
 
+static ssize_t pm_idle_enabled_show(struct device *dev, struct device_attribute *attr,
+                                   char *buf)
+{
+       char pm_idle_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
+       struct adf_accel_dev *accel_dev;
+       int ret;
+
+       accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+       if (!accel_dev)
+               return -EINVAL;
+
+       ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
+                                     ADF_PM_IDLE_SUPPORT, pm_idle_enabled);
+       if (ret)
+               return sysfs_emit(buf, "1\n");
+
+       return sysfs_emit(buf, "%s\n", pm_idle_enabled);
+}
+
+static ssize_t pm_idle_enabled_store(struct device *dev, struct device_attribute *attr,
+                                    const char *buf, size_t count)
+{
+       unsigned long pm_idle_enabled_cfg_val;
+       struct adf_accel_dev *accel_dev;
+       bool pm_idle_enabled;
+       int ret;
+
+       ret = kstrtobool(buf, &pm_idle_enabled);
+       if (ret)
+               return ret;
+
+       pm_idle_enabled_cfg_val = pm_idle_enabled;
+       accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
+       if (!accel_dev)
+               return -EINVAL;
+
+       if (adf_dev_started(accel_dev)) {
+               dev_info(dev, "Device qat_dev%d must be down to set pm_idle_enabled.\n",
+                        accel_dev->accel_id);
+               return -EINVAL;
+       }
+
+       ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
+                                         ADF_PM_IDLE_SUPPORT, &pm_idle_enabled_cfg_val,
+                                         ADF_DEC);
+       if (ret)
+               return ret;
+
+       return count;
+}
+static DEVICE_ATTR_RW(pm_idle_enabled);
+
 static DEVICE_ATTR_RW(state);
 static DEVICE_ATTR_RW(cfg_services);
 
 static struct attribute *qat_attrs[] = {
        &dev_attr_state.attr,
        &dev_attr_cfg_services.attr,
+       &dev_attr_pm_idle_enabled.attr,
        NULL,
 };