1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only)
2 /* Copyright(c) 2022 Intel Corporation */
3 #include <linux/device.h>
4 #include <linux/errno.h>
5 #include <linux/pci.h>
6 #include "adf_accel_devices.h"
7 #include "adf_cfg.h"
8 #include "adf_cfg_services.h"
9 #include "adf_common_drv.h"
10
11 static const char * const state_operations[] = {
12 [DEV_DOWN] = "down",
13 [DEV_UP] = "up",
14 };
15
state_show(struct device * dev,struct device_attribute * attr,char * buf)16 static ssize_t state_show(struct device *dev, struct device_attribute *attr,
17 char *buf)
18 {
19 struct adf_accel_dev *accel_dev;
20 char *state;
21
22 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
23 if (!accel_dev)
24 return -EINVAL;
25
26 state = adf_dev_started(accel_dev) ? "up" : "down";
27 return sysfs_emit(buf, "%s\n", state);
28 }
29
state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)30 static ssize_t state_store(struct device *dev, struct device_attribute *attr,
31 const char *buf, size_t count)
32 {
33 struct adf_accel_dev *accel_dev;
34 u32 accel_id;
35 int ret;
36
37 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
38 if (!accel_dev)
39 return -EINVAL;
40
41 accel_id = accel_dev->accel_id;
42
43 if (adf_devmgr_in_reset(accel_dev) || adf_dev_in_use(accel_dev)) {
44 dev_info(dev, "Device qat_dev%d is busy\n", accel_id);
45 return -EBUSY;
46 }
47
48 ret = sysfs_match_string(state_operations, buf);
49 if (ret < 0)
50 return ret;
51
52 switch (ret) {
53 case DEV_DOWN:
54 dev_info(dev, "Stopping device qat_dev%d\n", accel_id);
55
56 if (!adf_dev_started(accel_dev)) {
57 dev_info(&GET_DEV(accel_dev), "Device qat_dev%d already down\n",
58 accel_id);
59
60 break;
61 }
62
63 ret = adf_dev_down(accel_dev, true);
64 if (ret < 0)
65 return -EINVAL;
66
67 break;
68 case DEV_UP:
69 dev_info(dev, "Starting device qat_dev%d\n", accel_id);
70
71 ret = adf_dev_up(accel_dev, true);
72 if (ret == -EALREADY) {
73 break;
74 } else if (ret) {
75 dev_err(dev, "Failed to start device qat_dev%d\n",
76 accel_id);
77 adf_dev_down(accel_dev, true);
78 return ret;
79 }
80 break;
81 default:
82 return -EINVAL;
83 }
84
85 return count;
86 }
87
cfg_services_show(struct device * dev,struct device_attribute * attr,char * buf)88 static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr,
89 char *buf)
90 {
91 char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
92 struct adf_accel_dev *accel_dev;
93 int ret;
94
95 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
96 if (!accel_dev)
97 return -EINVAL;
98
99 ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
100 ADF_SERVICES_ENABLED, services);
101 if (ret)
102 return ret;
103
104 return sysfs_emit(buf, "%s\n", services);
105 }
106
adf_sysfs_update_dev_config(struct adf_accel_dev * accel_dev,const char * services)107 static int adf_sysfs_update_dev_config(struct adf_accel_dev *accel_dev,
108 const char *services)
109 {
110 return adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
111 ADF_SERVICES_ENABLED, services,
112 ADF_STR);
113 }
114
cfg_services_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)115 static ssize_t cfg_services_store(struct device *dev, struct device_attribute *attr,
116 const char *buf, size_t count)
117 {
118 struct adf_hw_device_data *hw_data;
119 struct adf_accel_dev *accel_dev;
120 int ret;
121
122 ret = sysfs_match_string(adf_cfg_services, buf);
123 if (ret < 0)
124 return ret;
125
126 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
127 if (!accel_dev)
128 return -EINVAL;
129
130 if (adf_dev_started(accel_dev)) {
131 dev_info(dev, "Device qat_dev%d must be down to reconfigure the service.\n",
132 accel_dev->accel_id);
133 return -EINVAL;
134 }
135
136 ret = adf_sysfs_update_dev_config(accel_dev, adf_cfg_services[ret]);
137 if (ret < 0)
138 return ret;
139
140 hw_data = GET_HW_DATA(accel_dev);
141
142 /* Update capabilities mask after change in configuration.
143 * A call to this function is required as capabilities are, at the
144 * moment, tied to configuration
145 */
146 hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev);
147 if (!hw_data->accel_capabilities_mask)
148 return -EINVAL;
149
150 return count;
151 }
152
pm_idle_enabled_show(struct device * dev,struct device_attribute * attr,char * buf)153 static ssize_t pm_idle_enabled_show(struct device *dev, struct device_attribute *attr,
154 char *buf)
155 {
156 char pm_idle_enabled[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {};
157 struct adf_accel_dev *accel_dev;
158 int ret;
159
160 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
161 if (!accel_dev)
162 return -EINVAL;
163
164 ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
165 ADF_PM_IDLE_SUPPORT, pm_idle_enabled);
166 if (ret)
167 return sysfs_emit(buf, "1\n");
168
169 return sysfs_emit(buf, "%s\n", pm_idle_enabled);
170 }
171
pm_idle_enabled_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)172 static ssize_t pm_idle_enabled_store(struct device *dev, struct device_attribute *attr,
173 const char *buf, size_t count)
174 {
175 unsigned long pm_idle_enabled_cfg_val;
176 struct adf_accel_dev *accel_dev;
177 bool pm_idle_enabled;
178 int ret;
179
180 ret = kstrtobool(buf, &pm_idle_enabled);
181 if (ret)
182 return ret;
183
184 pm_idle_enabled_cfg_val = pm_idle_enabled;
185 accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
186 if (!accel_dev)
187 return -EINVAL;
188
189 if (adf_dev_started(accel_dev)) {
190 dev_info(dev, "Device qat_dev%d must be down to set pm_idle_enabled.\n",
191 accel_dev->accel_id);
192 return -EINVAL;
193 }
194
195 ret = adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
196 ADF_PM_IDLE_SUPPORT, &pm_idle_enabled_cfg_val,
197 ADF_DEC);
198 if (ret)
199 return ret;
200
201 return count;
202 }
203 static DEVICE_ATTR_RW(pm_idle_enabled);
204
205 static DEVICE_ATTR_RW(state);
206 static DEVICE_ATTR_RW(cfg_services);
207
208 static struct attribute *qat_attrs[] = {
209 &dev_attr_state.attr,
210 &dev_attr_cfg_services.attr,
211 &dev_attr_pm_idle_enabled.attr,
212 NULL,
213 };
214
215 static struct attribute_group qat_group = {
216 .attrs = qat_attrs,
217 .name = "qat",
218 };
219
adf_sysfs_init(struct adf_accel_dev * accel_dev)220 int adf_sysfs_init(struct adf_accel_dev *accel_dev)
221 {
222 int ret;
223
224 ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_group);
225 if (ret) {
226 dev_err(&GET_DEV(accel_dev),
227 "Failed to create qat attribute group: %d\n", ret);
228 }
229
230 return ret;
231 }
232 EXPORT_SYMBOL_GPL(adf_sysfs_init);
233