Torsten Duwe e6c0ef
From 5ee52118ac1481dd8a8f7e6a9bfe6ee05ac6ec92 Mon Sep 17 00:00:00 2001
Torsten Duwe e6c0ef
From: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Torsten Duwe e6c0ef
Date: Mon, 27 Jun 2022 09:36:49 +0100
Torsten Duwe e6c0ef
Subject: [PATCH] crypto: qat - expose device state through sysfs for 4xxx
Torsten Duwe e6c0ef
Git-commit: 5ee52118ac1481dd8a8f7e6a9bfe6ee05ac6ec92
Torsten Duwe e6c0ef
Patch-mainline: v6.0-rc1
Torsten Duwe e6c0ef
References: jsc#PED-1073
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
Expose the device state through an attribute in sysfs and allow to
Torsten Duwe e6c0ef
change it. This is to stop and shutdown a QAT device in order to change
Torsten Duwe e6c0ef
its configuration.
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
The state attribute has been added to a newly created `qat` attribute
Torsten Duwe e6c0ef
group which will contain all _QAT specific_ attributes.
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
The logic that implements the sysfs entries is part of a new file,
Torsten Duwe e6c0ef
adf_sysfs.c. This exposes an entry point to allow the driver to create
Torsten Duwe e6c0ef
attributes.
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
The function that creates the sysfs attributes is called from the probe
Torsten Duwe e6c0ef
function of the driver and not in the state machine init function to
Torsten Duwe e6c0ef
allow the change of states even if the device is in the down state.
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
In order to restore the device configuration between a transition from
Torsten Duwe e6c0ef
down to up, the function that configures the devices has been abstracted
Torsten Duwe e6c0ef
into the HW data structure.
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
The `state` attribute is only exposed for qat_4xxx devices.
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
Signed-off-by: Giovanni Cabiddu <giovanni.cabiddu@intel.com>
Torsten Duwe e6c0ef
Co-developed-by: Tomasz Kowallik <tomaszx.kowalik@intel.com>
Torsten Duwe e6c0ef
Signed-off-by: Tomasz Kowallik <tomaszx.kowalik@intel.com>
Torsten Duwe e6c0ef
Reviewed-by: Adam Guerin <adam.guerin@intel.com>
Torsten Duwe e6c0ef
Reviewed-by: Fiona Trahe <fiona.trahe@intel.com>
Torsten Duwe e6c0ef
Reviewed-by: Wojciech Ziemba <wojciech.ziemba@intel.com>
Torsten Duwe e6c0ef
Reviewed-by: Vladis Dronov <vdronov@redhat.com>
Torsten Duwe e6c0ef
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Torsten Duwe e6c0ef
Signed-off-by: Torsten Duwe <duwe@suse.de>
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
---
Torsten Duwe e6c0ef
 Documentation/ABI/testing/sysfs-driver-qat    |  21 ++++
Torsten Duwe e6c0ef
 .../crypto/qat/qat_4xxx/adf_4xxx_hw_data.c    |   1 +
Torsten Duwe e6c0ef
 .../crypto/qat/qat_4xxx/adf_4xxx_hw_data.h    |   1 +
Torsten Duwe e6c0ef
 drivers/crypto/qat/qat_4xxx/adf_drv.c         |   6 +-
Torsten Duwe e6c0ef
 drivers/crypto/qat/qat_common/Makefile        |   1 +
Torsten Duwe e6c0ef
 .../crypto/qat/qat_common/adf_accel_devices.h |   1 +
Torsten Duwe e6c0ef
 .../crypto/qat/qat_common/adf_common_drv.h    |   2 +
Torsten Duwe e6c0ef
 drivers/crypto/qat/qat_common/adf_sysfs.c     | 119 ++++++++++++++++++
Torsten Duwe e6c0ef
 8 files changed, 151 insertions(+), 1 deletion(-)
Torsten Duwe e6c0ef
 create mode 100644 Documentation/ABI/testing/sysfs-driver-qat
Torsten Duwe e6c0ef
 create mode 100644 drivers/crypto/qat/qat_common/adf_sysfs.c
Torsten Duwe e6c0ef
Torsten Duwe e6c0ef
diff --git a/Documentation/ABI/testing/sysfs-driver-qat b/Documentation/ABI/testing/sysfs-driver-qat
Torsten Duwe e6c0ef
new file mode 100644
Torsten Duwe e6c0ef
index 0000000000000..769b09cefa897
Torsten Duwe e6c0ef
--- /dev/null
Torsten Duwe e6c0ef
+++ b/Documentation/ABI/testing/sysfs-driver-qat
Torsten Duwe e6c0ef
@@ -0,0 +1,21 @@
Torsten Duwe e6c0ef
+What:		/sys/bus/pci/devices/<BDF>/qat/state
Torsten Duwe e6c0ef
+Date:		June 2022
Torsten Duwe e6c0ef
+KernelVersion:	5.20
Torsten Duwe e6c0ef
+Contact:	qat-linux@intel.com
Torsten Duwe e6c0ef
+Description:	Reports the current state of the QAT device and allows to
Torsten Duwe e6c0ef
+		change it.
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		This attribute is RW.
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		Returned values:
Torsten Duwe e6c0ef
+			up: the device is up and running
Torsten Duwe e6c0ef
+			down: the device is down
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		Allowed values:
Torsten Duwe e6c0ef
+			up: initialize and start the device
Torsten Duwe e6c0ef
+			down: stop the device and bring it down
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		It is possible to transition the device from up to down only
Torsten Duwe e6c0ef
+		if the device is up and vice versa.
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		This attribute is only available for qat_4xxx devices.
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c
Torsten Duwe e6c0ef
index fb5970a684844..fda5f699ff575 100644
Torsten Duwe e6c0ef
--- a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.c
Torsten Duwe e6c0ef
@@ -357,6 +357,7 @@ void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data)
Torsten Duwe e6c0ef
 	hw_data->ring_pair_reset = adf_gen4_ring_pair_reset;
Torsten Duwe e6c0ef
 	hw_data->enable_pm = adf_gen4_enable_pm;
Torsten Duwe e6c0ef
 	hw_data->handle_pm_interrupt = adf_gen4_handle_pm_interrupt;
Torsten Duwe e6c0ef
+	hw_data->dev_config = adf_crypto_dev_config;
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
 	adf_gen4_init_hw_csr_ops(&hw_data->csr_ops);
Torsten Duwe e6c0ef
 	adf_gen4_init_pf_pfvf_ops(&hw_data->pfvf_ops);
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h
Torsten Duwe e6c0ef
index 1034752845ca2..9d49248931f6a 100644
Torsten Duwe e6c0ef
--- a/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_4xxx/adf_4xxx_hw_data.h
Torsten Duwe e6c0ef
@@ -70,5 +70,6 @@ enum icp_qat_4xxx_slice_mask {
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
 void adf_init_hw_data_4xxx(struct adf_hw_device_data *hw_data);
Torsten Duwe e6c0ef
 void adf_clean_hw_data_4xxx(struct adf_hw_device_data *hw_data);
Torsten Duwe e6c0ef
+int adf_crypto_dev_config(struct adf_accel_dev *accel_dev);
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
 #endif
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_4xxx/adf_drv.c b/drivers/crypto/qat/qat_4xxx/adf_drv.c
Torsten Duwe e6c0ef
index 181fa1c8b3c78..2f212561acc47 100644
Torsten Duwe e6c0ef
--- a/drivers/crypto/qat/qat_4xxx/adf_drv.c
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_4xxx/adf_drv.c
Torsten Duwe e6c0ef
@@ -53,7 +53,7 @@ static int adf_cfg_dev_init(struct adf_accel_dev *accel_dev)
Torsten Duwe e6c0ef
 	return 0;
Torsten Duwe e6c0ef
 }
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
-static int adf_crypto_dev_config(struct adf_accel_dev *accel_dev)
Torsten Duwe e6c0ef
+int adf_crypto_dev_config(struct adf_accel_dev *accel_dev)
Torsten Duwe e6c0ef
 {
Torsten Duwe e6c0ef
 	char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES];
Torsten Duwe e6c0ef
 	int banks = GET_MAX_BANKS(accel_dev);
Torsten Duwe e6c0ef
@@ -289,6 +289,10 @@ static int adf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
Torsten Duwe e6c0ef
 		goto out_err_disable_aer;
Torsten Duwe e6c0ef
 	}
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
+	ret = adf_sysfs_init(accel_dev);
Torsten Duwe e6c0ef
+	if (ret)
Torsten Duwe e6c0ef
+		goto out_err_disable_aer;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
 	ret = adf_crypto_dev_config(accel_dev);
Torsten Duwe e6c0ef
 	if (ret)
Torsten Duwe e6c0ef
 		goto out_err_disable_aer;
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_common/Makefile b/drivers/crypto/qat/qat_common/Makefile
Torsten Duwe e6c0ef
index 04f058acc4d37..80919cfcc29da 100644
Torsten Duwe e6c0ef
--- a/drivers/crypto/qat/qat_common/Makefile
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_common/Makefile
Torsten Duwe e6c0ef
@@ -10,6 +10,7 @@ intel_qat-objs := adf_cfg.o \
Torsten Duwe e6c0ef
 	adf_transport.o \
Torsten Duwe e6c0ef
 	adf_admin.o \
Torsten Duwe e6c0ef
 	adf_hw_arbiter.o \
Torsten Duwe e6c0ef
+	adf_sysfs.o \
Torsten Duwe e6c0ef
 	adf_gen2_hw_data.o \
Torsten Duwe e6c0ef
 	adf_gen4_hw_data.o \
Torsten Duwe e6c0ef
 	adf_gen4_pm.o \
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_common/adf_accel_devices.h b/drivers/crypto/qat/qat_common/adf_accel_devices.h
Torsten Duwe e6c0ef
index ede6458c9dbfd..0a55a4f34dcfd 100644
Torsten Duwe e6c0ef
--- a/drivers/crypto/qat/qat_common/adf_accel_devices.h
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_common/adf_accel_devices.h
Torsten Duwe e6c0ef
@@ -199,6 +199,7 @@ struct adf_hw_device_data {
Torsten Duwe e6c0ef
 	char *(*uof_get_name)(struct adf_accel_dev *accel_dev, u32 obj_num);
Torsten Duwe e6c0ef
 	u32 (*uof_get_num_objs)(void);
Torsten Duwe e6c0ef
 	u32 (*uof_get_ae_mask)(struct adf_accel_dev *accel_dev, u32 obj_num);
Torsten Duwe e6c0ef
+	int (*dev_config)(struct adf_accel_dev *accel_dev);
Torsten Duwe e6c0ef
 	struct adf_pfvf_ops pfvf_ops;
Torsten Duwe e6c0ef
 	struct adf_hw_csr_ops csr_ops;
Torsten Duwe e6c0ef
 	const char *fw_name;
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_common/adf_common_drv.h b/drivers/crypto/qat/qat_common/adf_common_drv.h
Torsten Duwe e6c0ef
index b364bc06c732a..b841e85c8f5d6 100644
Torsten Duwe e6c0ef
--- a/drivers/crypto/qat/qat_common/adf_common_drv.h
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_common/adf_common_drv.h
Torsten Duwe e6c0ef
@@ -127,6 +127,8 @@ void adf_vf_isr_resource_free(struct adf_accel_dev *accel_dev);
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
 int adf_pfvf_comms_disabled(struct adf_accel_dev *accel_dev);
Torsten Duwe e6c0ef
 
Torsten Duwe e6c0ef
+int adf_sysfs_init(struct adf_accel_dev *accel_dev);
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
 int qat_hal_init(struct adf_accel_dev *accel_dev);
Torsten Duwe e6c0ef
 void qat_hal_deinit(struct icp_qat_fw_loader_handle *handle);
Torsten Duwe e6c0ef
 int qat_hal_start(struct icp_qat_fw_loader_handle *handle);
Torsten Duwe e6c0ef
diff --git a/drivers/crypto/qat/qat_common/adf_sysfs.c b/drivers/crypto/qat/qat_common/adf_sysfs.c
Torsten Duwe e6c0ef
new file mode 100644
Torsten Duwe e6c0ef
index 0000000000000..8f47a5694dd70
Torsten Duwe e6c0ef
--- /dev/null
Torsten Duwe e6c0ef
+++ b/drivers/crypto/qat/qat_common/adf_sysfs.c
Torsten Duwe e6c0ef
@@ -0,0 +1,119 @@
Torsten Duwe e6c0ef
+// SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
Torsten Duwe e6c0ef
+/* Copyright(c) 2022 Intel Corporation */
Torsten Duwe e6c0ef
+#include <linux/device.h>
Torsten Duwe e6c0ef
+#include <linux/errno.h>
Torsten Duwe e6c0ef
+#include <linux/pci.h>
Torsten Duwe e6c0ef
+#include "adf_accel_devices.h"
Torsten Duwe e6c0ef
+#include "adf_cfg.h"
Torsten Duwe e6c0ef
+#include "adf_common_drv.h"
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+static const char * const state_operations[] = {
Torsten Duwe e6c0ef
+	[DEV_DOWN] = "down",
Torsten Duwe e6c0ef
+	[DEV_UP] = "up",
Torsten Duwe e6c0ef
+};
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+static ssize_t state_show(struct device *dev, struct device_attribute *attr,
Torsten Duwe e6c0ef
+			  char *buf)
Torsten Duwe e6c0ef
+{
Torsten Duwe e6c0ef
+	struct adf_accel_dev *accel_dev;
Torsten Duwe e6c0ef
+	char *state;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
Torsten Duwe e6c0ef
+	if (!accel_dev)
Torsten Duwe e6c0ef
+		return -EINVAL;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	state = adf_dev_started(accel_dev) ? "up" : "down";
Torsten Duwe e6c0ef
+	return sysfs_emit(buf, "%s\n", state);
Torsten Duwe e6c0ef
+}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+static ssize_t state_store(struct device *dev, struct device_attribute *attr,
Torsten Duwe e6c0ef
+			   const char *buf, size_t count)
Torsten Duwe e6c0ef
+{
Torsten Duwe e6c0ef
+	struct adf_accel_dev *accel_dev;
Torsten Duwe e6c0ef
+	u32 accel_id;
Torsten Duwe e6c0ef
+	int ret;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
Torsten Duwe e6c0ef
+	if (!accel_dev)
Torsten Duwe e6c0ef
+		return -EINVAL;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	accel_id = accel_dev->accel_id;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	if (adf_devmgr_in_reset(accel_dev) || adf_dev_in_use(accel_dev)) {
Torsten Duwe e6c0ef
+		dev_info(dev, "Device qat_dev%d is busy\n", accel_id);
Torsten Duwe e6c0ef
+		return -EBUSY;
Torsten Duwe e6c0ef
+	}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	ret = sysfs_match_string(state_operations, buf);
Torsten Duwe e6c0ef
+	if (ret < 0)
Torsten Duwe e6c0ef
+		return ret;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	switch (ret) {
Torsten Duwe e6c0ef
+	case DEV_DOWN:
Torsten Duwe e6c0ef
+		if (!adf_dev_started(accel_dev)) {
Torsten Duwe e6c0ef
+			dev_info(dev, "Device qat_dev%d already down\n",
Torsten Duwe e6c0ef
+				 accel_id);
Torsten Duwe e6c0ef
+			return -EINVAL;
Torsten Duwe e6c0ef
+		}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		dev_info(dev, "Stopping device qat_dev%d\n", accel_id);
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		adf_dev_stop(accel_dev);
Torsten Duwe e6c0ef
+		adf_dev_shutdown(accel_dev);
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		break;
Torsten Duwe e6c0ef
+	case DEV_UP:
Torsten Duwe e6c0ef
+		if (adf_dev_started(accel_dev)) {
Torsten Duwe e6c0ef
+			dev_info(dev, "Device qat_dev%d already up\n",
Torsten Duwe e6c0ef
+				 accel_id);
Torsten Duwe e6c0ef
+			return -EINVAL;
Torsten Duwe e6c0ef
+		}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		dev_info(dev, "Starting device qat_dev%d\n", accel_id);
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		ret = GET_HW_DATA(accel_dev)->dev_config(accel_dev);
Torsten Duwe e6c0ef
+		if (!ret)
Torsten Duwe e6c0ef
+			ret = adf_dev_init(accel_dev);
Torsten Duwe e6c0ef
+		if (!ret)
Torsten Duwe e6c0ef
+			ret = adf_dev_start(accel_dev);
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+		if (ret < 0) {
Torsten Duwe e6c0ef
+			dev_err(dev, "Failed to start device qat_dev%d\n",
Torsten Duwe e6c0ef
+				accel_id);
Torsten Duwe e6c0ef
+			adf_dev_stop(accel_dev);
Torsten Duwe e6c0ef
+			adf_dev_shutdown(accel_dev);
Torsten Duwe e6c0ef
+			return ret;
Torsten Duwe e6c0ef
+		}
Torsten Duwe e6c0ef
+		break;
Torsten Duwe e6c0ef
+	default:
Torsten Duwe e6c0ef
+		return -EINVAL;
Torsten Duwe e6c0ef
+	}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	return count;
Torsten Duwe e6c0ef
+}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+static DEVICE_ATTR_RW(state);
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+static struct attribute *qat_attrs[] = {
Torsten Duwe e6c0ef
+	&dev_attr_state.attr,
Torsten Duwe e6c0ef
+	NULL,
Torsten Duwe e6c0ef
+};
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+static struct attribute_group qat_group = {
Torsten Duwe e6c0ef
+	.attrs = qat_attrs,
Torsten Duwe e6c0ef
+	.name = "qat",
Torsten Duwe e6c0ef
+};
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+int adf_sysfs_init(struct adf_accel_dev *accel_dev)
Torsten Duwe e6c0ef
+{
Torsten Duwe e6c0ef
+	int ret;
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_group);
Torsten Duwe e6c0ef
+	if (ret) {
Torsten Duwe e6c0ef
+		dev_err(&GET_DEV(accel_dev),
Torsten Duwe e6c0ef
+			"Failed to create qat attribute group: %d\n", ret);
Torsten Duwe e6c0ef
+	}
Torsten Duwe e6c0ef
+
Torsten Duwe e6c0ef
+	return ret;
Torsten Duwe e6c0ef
+}
Torsten Duwe e6c0ef
+EXPORT_SYMBOL_GPL(adf_sysfs_init);
Torsten Duwe e6c0ef
-- 
Torsten Duwe e6c0ef
2.35.3
Torsten Duwe e6c0ef