1a4b16dadSTom Zanussi // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2a4b16dadSTom Zanussi /* Copyright(c) 2022 Intel Corporation */
3a4b16dadSTom Zanussi #include <linux/device.h>
4a4b16dadSTom Zanussi #include <linux/errno.h>
5a4b16dadSTom Zanussi #include <linux/pci.h>
6a4b16dadSTom Zanussi #include "adf_accel_devices.h"
7a4b16dadSTom Zanussi #include "adf_cfg.h"
8*b7284784SGiovanni Cabiddu #include "adf_cfg_services.h"
9a4b16dadSTom Zanussi #include "adf_common_drv.h"
10a4b16dadSTom Zanussi 
11a4b16dadSTom Zanussi static const char * const state_operations[] = {
12a4b16dadSTom Zanussi 	[DEV_DOWN] = "down",
13a4b16dadSTom Zanussi 	[DEV_UP] = "up",
14a4b16dadSTom Zanussi };
15a4b16dadSTom Zanussi 
state_show(struct device * dev,struct device_attribute * attr,char * buf)16a4b16dadSTom Zanussi static ssize_t state_show(struct device *dev, struct device_attribute *attr,
17a4b16dadSTom Zanussi 			  char *buf)
18a4b16dadSTom Zanussi {
19a4b16dadSTom Zanussi 	struct adf_accel_dev *accel_dev;
20a4b16dadSTom Zanussi 	char *state;
21a4b16dadSTom Zanussi 
22a4b16dadSTom Zanussi 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
23a4b16dadSTom Zanussi 	if (!accel_dev)
24a4b16dadSTom Zanussi 		return -EINVAL;
25a4b16dadSTom Zanussi 
26a4b16dadSTom Zanussi 	state = adf_dev_started(accel_dev) ? "up" : "down";
27a4b16dadSTom Zanussi 	return sysfs_emit(buf, "%s\n", state);
28a4b16dadSTom Zanussi }
29a4b16dadSTom Zanussi 
state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)30a4b16dadSTom Zanussi static ssize_t state_store(struct device *dev, struct device_attribute *attr,
31a4b16dadSTom Zanussi 			   const char *buf, size_t count)
32a4b16dadSTom Zanussi {
33a4b16dadSTom Zanussi 	struct adf_accel_dev *accel_dev;
34a4b16dadSTom Zanussi 	u32 accel_id;
35a4b16dadSTom Zanussi 	int ret;
36a4b16dadSTom Zanussi 
37a4b16dadSTom Zanussi 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
38a4b16dadSTom Zanussi 	if (!accel_dev)
39a4b16dadSTom Zanussi 		return -EINVAL;
40a4b16dadSTom Zanussi 
41a4b16dadSTom Zanussi 	accel_id = accel_dev->accel_id;
42a4b16dadSTom Zanussi 
43a4b16dadSTom Zanussi 	if (adf_devmgr_in_reset(accel_dev) || adf_dev_in_use(accel_dev)) {
44a4b16dadSTom Zanussi 		dev_info(dev, "Device qat_dev%d is busy\n", accel_id);
45a4b16dadSTom Zanussi 		return -EBUSY;
46a4b16dadSTom Zanussi 	}
47a4b16dadSTom Zanussi 
48a4b16dadSTom Zanussi 	ret = sysfs_match_string(state_operations, buf);
49a4b16dadSTom Zanussi 	if (ret < 0)
50a4b16dadSTom Zanussi 		return ret;
51a4b16dadSTom Zanussi 
52a4b16dadSTom Zanussi 	switch (ret) {
53a4b16dadSTom Zanussi 	case DEV_DOWN:
54a4b16dadSTom Zanussi 		dev_info(dev, "Stopping device qat_dev%d\n", accel_id);
55a4b16dadSTom Zanussi 
563b97788eSGiovanni Cabiddu 		if (!adf_dev_started(accel_dev)) {
573b97788eSGiovanni Cabiddu 			dev_info(&GET_DEV(accel_dev), "Device qat_dev%d already down\n",
583b97788eSGiovanni Cabiddu 				 accel_id);
593b97788eSGiovanni Cabiddu 
603b97788eSGiovanni Cabiddu 			break;
613b97788eSGiovanni Cabiddu 		}
623b97788eSGiovanni Cabiddu 
63a4b16dadSTom Zanussi 		ret = adf_dev_down(accel_dev, true);
64a4b16dadSTom Zanussi 		if (ret < 0)
65a4b16dadSTom Zanussi 			return -EINVAL;
66a4b16dadSTom Zanussi 
67a4b16dadSTom Zanussi 		break;
68a4b16dadSTom Zanussi 	case DEV_UP:
69a4b16dadSTom Zanussi 		dev_info(dev, "Starting device qat_dev%d\n", accel_id);
70a4b16dadSTom Zanussi 
71a4b16dadSTom Zanussi 		ret = adf_dev_up(accel_dev, true);
72a44d2b83SGiovanni Cabiddu 		if (ret == -EALREADY) {
73a44d2b83SGiovanni Cabiddu 			break;
74a44d2b83SGiovanni Cabiddu 		} else if (ret) {
75a4b16dadSTom Zanussi 			dev_err(dev, "Failed to start device qat_dev%d\n",
76a4b16dadSTom Zanussi 				accel_id);
77a4b16dadSTom Zanussi 			adf_dev_down(accel_dev, true);
78a4b16dadSTom Zanussi 			return ret;
79a4b16dadSTom Zanussi 		}
80a4b16dadSTom Zanussi 		break;
81a4b16dadSTom Zanussi 	default:
82a4b16dadSTom Zanussi 		return -EINVAL;
83a4b16dadSTom Zanussi 	}
84a4b16dadSTom Zanussi 
85a4b16dadSTom Zanussi 	return count;
86a4b16dadSTom Zanussi }
87a4b16dadSTom Zanussi 
cfg_services_show(struct device * dev,struct device_attribute * attr,char * buf)88a4b16dadSTom Zanussi static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr,
89a4b16dadSTom Zanussi 				 char *buf)
90a4b16dadSTom Zanussi {
91a4b16dadSTom Zanussi 	char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
92a4b16dadSTom Zanussi 	struct adf_accel_dev *accel_dev;
93a4b16dadSTom Zanussi 	int ret;
94a4b16dadSTom Zanussi 
95a4b16dadSTom Zanussi 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
96a4b16dadSTom Zanussi 	if (!accel_dev)
97a4b16dadSTom Zanussi 		return -EINVAL;
98a4b16dadSTom Zanussi 
99a4b16dadSTom Zanussi 	ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
100a4b16dadSTom Zanussi 				      ADF_SERVICES_ENABLED, services);
101a4b16dadSTom Zanussi 	if (ret)
102a4b16dadSTom Zanussi 		return ret;
103a4b16dadSTom Zanussi 
104a4b16dadSTom Zanussi 	return sysfs_emit(buf, "%s\n", services);
105a4b16dadSTom Zanussi }
106a4b16dadSTom Zanussi 
adf_sysfs_update_dev_config(struct adf_accel_dev * accel_dev,const char * services)107a4b16dadSTom Zanussi static int adf_sysfs_update_dev_config(struct adf_accel_dev *accel_dev,
108a4b16dadSTom Zanussi 				       const char *services)
109a4b16dadSTom Zanussi {
110a4b16dadSTom Zanussi 	return adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
111a4b16dadSTom Zanussi 					   ADF_SERVICES_ENABLED, services,
112a4b16dadSTom Zanussi 					   ADF_STR);
113a4b16dadSTom Zanussi }
114a4b16dadSTom Zanussi 
cfg_services_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)115a4b16dadSTom Zanussi static ssize_t cfg_services_store(struct device *dev, struct device_attribute *attr,
116a4b16dadSTom Zanussi 				  const char *buf, size_t count)
117a4b16dadSTom Zanussi {
118a4b16dadSTom Zanussi 	struct adf_hw_device_data *hw_data;
119a4b16dadSTom Zanussi 	struct adf_accel_dev *accel_dev;
120a4b16dadSTom Zanussi 	int ret;
121a4b16dadSTom Zanussi 
122*b7284784SGiovanni Cabiddu 	ret = sysfs_match_string(adf_cfg_services, buf);
123a4b16dadSTom Zanussi 	if (ret < 0)
124a4b16dadSTom Zanussi 		return ret;
125a4b16dadSTom Zanussi 
126a4b16dadSTom Zanussi 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
127a4b16dadSTom Zanussi 	if (!accel_dev)
128a4b16dadSTom Zanussi 		return -EINVAL;
129a4b16dadSTom Zanussi 
130a4b16dadSTom Zanussi 	if (adf_dev_started(accel_dev)) {
131a4b16dadSTom Zanussi 		dev_info(dev, "Device qat_dev%d must be down to reconfigure the service.\n",
132a4b16dadSTom Zanussi 			 accel_dev->accel_id);
133a4b16dadSTom Zanussi 		return -EINVAL;
134a4b16dadSTom Zanussi 	}
135a4b16dadSTom Zanussi 
136*b7284784SGiovanni Cabiddu 	ret = adf_sysfs_update_dev_config(accel_dev, adf_cfg_services[ret]);
137a4b16dadSTom Zanussi 	if (ret < 0)
138a4b16dadSTom Zanussi 		return ret;
139a4b16dadSTom Zanussi 
140a4b16dadSTom Zanussi 	hw_data = GET_HW_DATA(accel_dev);
141a4b16dadSTom Zanussi 
142a4b16dadSTom Zanussi 	/* Update capabilities mask after change in configuration.
143a4b16dadSTom Zanussi 	 * A call to this function is required as capabilities are, at the
144a4b16dadSTom Zanussi 	 * moment, tied to configuration
145a4b16dadSTom Zanussi 	 */
146a4b16dadSTom Zanussi 	hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev);
147a4b16dadSTom Zanussi 	if (!hw_data->accel_capabilities_mask)
148a4b16dadSTom Zanussi 		return -EINVAL;
149a4b16dadSTom Zanussi 
150a4b16dadSTom Zanussi 	return count;
151a4b16dadSTom Zanussi }
152a4b16dadSTom Zanussi 
pm_idle_enabled_show(struct device * dev,struct device_attribute * attr,char * buf)1532382b5aeSLucas Segarra Fernandez static ssize_t pm_idle_enabled_show(struct device *dev, struct device_attribute *attr,
1542382b5aeSLucas Segarra Fernandez 				    char *buf)
1552382b5aeSLucas Segarra Fernandez {
1562382b5aeSLucas Segarra Fernandez 	char pm_idle_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
1572382b5aeSLucas Segarra Fernandez 	struct adf_accel_dev *accel_dev;
1582382b5aeSLucas Segarra Fernandez 	int ret;
1592382b5aeSLucas Segarra Fernandez 
1602382b5aeSLucas Segarra Fernandez 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
1612382b5aeSLucas Segarra Fernandez 	if (!accel_dev)
1622382b5aeSLucas Segarra Fernandez 		return -EINVAL;
1632382b5aeSLucas Segarra Fernandez 
1642382b5aeSLucas Segarra Fernandez 	ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
1652382b5aeSLucas Segarra Fernandez 				      ADF_PM_IDLE_SUPPORT, pm_idle_enabled);
1662382b5aeSLucas Segarra Fernandez 	if (ret)
1672382b5aeSLucas Segarra Fernandez 		return sysfs_emit(buf, "1\n");
1682382b5aeSLucas Segarra Fernandez 
1692382b5aeSLucas Segarra Fernandez 	return sysfs_emit(buf, "%s\n", pm_idle_enabled);
1702382b5aeSLucas Segarra Fernandez }
1712382b5aeSLucas Segarra Fernandez 
pm_idle_enabled_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)1722382b5aeSLucas Segarra Fernandez static ssize_t pm_idle_enabled_store(struct device *dev, struct device_attribute *attr,
1732382b5aeSLucas Segarra Fernandez 				     const char *buf, size_t count)
1742382b5aeSLucas Segarra Fernandez {
1752382b5aeSLucas Segarra Fernandez 	unsigned long pm_idle_enabled_cfg_val;
1762382b5aeSLucas Segarra Fernandez 	struct adf_accel_dev *accel_dev;
1772382b5aeSLucas Segarra Fernandez 	bool pm_idle_enabled;
1782382b5aeSLucas Segarra Fernandez 	int ret;
1792382b5aeSLucas Segarra Fernandez 
1802382b5aeSLucas Segarra Fernandez 	ret = kstrtobool(buf, &pm_idle_enabled);
1812382b5aeSLucas Segarra Fernandez 	if (ret)
1822382b5aeSLucas Segarra Fernandez 		return ret;
1832382b5aeSLucas Segarra Fernandez 
1842382b5aeSLucas Segarra Fernandez 	pm_idle_enabled_cfg_val = pm_idle_enabled;
1852382b5aeSLucas Segarra Fernandez 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
1862382b5aeSLucas Segarra Fernandez 	if (!accel_dev)
1872382b5aeSLucas Segarra Fernandez 		return -EINVAL;
1882382b5aeSLucas Segarra Fernandez 
1892382b5aeSLucas Segarra Fernandez 	if (adf_dev_started(accel_dev)) {
1902382b5aeSLucas Segarra Fernandez 		dev_info(dev, "Device qat_dev%d must be down to set pm_idle_enabled.\n",
1912382b5aeSLucas Segarra Fernandez 			 accel_dev->accel_id);
1922382b5aeSLucas Segarra Fernandez 		return -EINVAL;
1932382b5aeSLucas Segarra Fernandez 	}
1942382b5aeSLucas Segarra Fernandez 
1952382b5aeSLucas Segarra Fernandez 	ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
1962382b5aeSLucas Segarra Fernandez 					  ADF_PM_IDLE_SUPPORT, &pm_idle_enabled_cfg_val,
1972382b5aeSLucas Segarra Fernandez 					  ADF_DEC);
1982382b5aeSLucas Segarra Fernandez 	if (ret)
1992382b5aeSLucas Segarra Fernandez 		return ret;
2002382b5aeSLucas Segarra Fernandez 
2012382b5aeSLucas Segarra Fernandez 	return count;
2022382b5aeSLucas Segarra Fernandez }
2032382b5aeSLucas Segarra Fernandez static DEVICE_ATTR_RW(pm_idle_enabled);
2042382b5aeSLucas Segarra Fernandez 
205a4b16dadSTom Zanussi static DEVICE_ATTR_RW(state);
206a4b16dadSTom Zanussi static DEVICE_ATTR_RW(cfg_services);
207a4b16dadSTom Zanussi 
208a4b16dadSTom Zanussi static struct attribute *qat_attrs[] = {
209a4b16dadSTom Zanussi 	&dev_attr_state.attr,
210a4b16dadSTom Zanussi 	&dev_attr_cfg_services.attr,
2112382b5aeSLucas Segarra Fernandez 	&dev_attr_pm_idle_enabled.attr,
212a4b16dadSTom Zanussi 	NULL,
213a4b16dadSTom Zanussi };
214a4b16dadSTom Zanussi 
215a4b16dadSTom Zanussi static struct attribute_group qat_group = {
216a4b16dadSTom Zanussi 	.attrs = qat_attrs,
217a4b16dadSTom Zanussi 	.name = "qat",
218a4b16dadSTom Zanussi };
219a4b16dadSTom Zanussi 
adf_sysfs_init(struct adf_accel_dev * accel_dev)220a4b16dadSTom Zanussi int adf_sysfs_init(struct adf_accel_dev *accel_dev)
221a4b16dadSTom Zanussi {
222a4b16dadSTom Zanussi 	int ret;
223a4b16dadSTom Zanussi 
224a4b16dadSTom Zanussi 	ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_group);
225a4b16dadSTom Zanussi 	if (ret) {
226a4b16dadSTom Zanussi 		dev_err(&GET_DEV(accel_dev),
227a4b16dadSTom Zanussi 			"Failed to create qat attribute group: %d\n", ret);
228a4b16dadSTom Zanussi 	}
229a4b16dadSTom Zanussi 
230a4b16dadSTom Zanussi 	return ret;
231a4b16dadSTom Zanussi }
232a4b16dadSTom Zanussi EXPORT_SYMBOL_GPL(adf_sysfs_init);
233