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