• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
state_show(struct device * dev,struct device_attribute * attr,char * buf)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 
state_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)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 		ret = adf_dev_down(accel_dev, true);
56 		if (ret < 0)
57 			return -EINVAL;
58 
59 		break;
60 	case DEV_UP:
61 		dev_info(dev, "Starting device qat_dev%d\n", accel_id);
62 
63 		ret = adf_dev_up(accel_dev, true);
64 		if (ret == -EALREADY) {
65 			break;
66 		} else if (ret) {
67 			dev_err(dev, "Failed to start device qat_dev%d\n",
68 				accel_id);
69 			adf_dev_down(accel_dev, true);
70 			return ret;
71 		}
72 		break;
73 	default:
74 		return -EINVAL;
75 	}
76 
77 	return count;
78 }
79 
80 static const char * const services_operations[] = {
81 	ADF_CFG_CY,
82 	ADF_CFG_DC,
83 };
84 
cfg_services_show(struct device * dev,struct device_attribute * attr,char * buf)85 static ssize_t cfg_services_show(struct device *dev, struct device_attribute *attr,
86 				 char *buf)
87 {
88 	char services[ADF_CFG_MAX_VAL_LEN_IN_BYTES] = {0};
89 	struct adf_accel_dev *accel_dev;
90 	int ret;
91 
92 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
93 	if (!accel_dev)
94 		return -EINVAL;
95 
96 	ret = adf_cfg_get_param_value(accel_dev, ADF_GENERAL_SEC,
97 				      ADF_SERVICES_ENABLED, services);
98 	if (ret)
99 		return ret;
100 
101 	return sysfs_emit(buf, "%s\n", services);
102 }
103 
adf_sysfs_update_dev_config(struct adf_accel_dev * accel_dev,const char * services)104 static int adf_sysfs_update_dev_config(struct adf_accel_dev *accel_dev,
105 				       const char *services)
106 {
107 	return adf_cfg_add_key_value_param(accel_dev, ADF_GENERAL_SEC,
108 					   ADF_SERVICES_ENABLED, services,
109 					   ADF_STR);
110 }
111 
cfg_services_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)112 static ssize_t cfg_services_store(struct device *dev, struct device_attribute *attr,
113 				  const char *buf, size_t count)
114 {
115 	struct adf_hw_device_data *hw_data;
116 	struct adf_accel_dev *accel_dev;
117 	int ret;
118 
119 	ret = sysfs_match_string(services_operations, buf);
120 	if (ret < 0)
121 		return ret;
122 
123 	accel_dev = adf_devmgr_pci_to_accel_dev(to_pci_dev(dev));
124 	if (!accel_dev)
125 		return -EINVAL;
126 
127 	if (adf_dev_started(accel_dev)) {
128 		dev_info(dev, "Device qat_dev%d must be down to reconfigure the service.\n",
129 			 accel_dev->accel_id);
130 		return -EINVAL;
131 	}
132 
133 	ret = adf_sysfs_update_dev_config(accel_dev, services_operations[ret]);
134 	if (ret < 0)
135 		return ret;
136 
137 	hw_data = GET_HW_DATA(accel_dev);
138 
139 	/* Update capabilities mask after change in configuration.
140 	 * A call to this function is required as capabilities are, at the
141 	 * moment, tied to configuration
142 	 */
143 	hw_data->accel_capabilities_mask = hw_data->get_accel_cap(accel_dev);
144 	if (!hw_data->accel_capabilities_mask)
145 		return -EINVAL;
146 
147 	return count;
148 }
149 
150 static DEVICE_ATTR_RW(state);
151 static DEVICE_ATTR_RW(cfg_services);
152 
153 static struct attribute *qat_attrs[] = {
154 	&dev_attr_state.attr,
155 	&dev_attr_cfg_services.attr,
156 	NULL,
157 };
158 
159 static struct attribute_group qat_group = {
160 	.attrs = qat_attrs,
161 	.name = "qat",
162 };
163 
adf_sysfs_init(struct adf_accel_dev * accel_dev)164 int adf_sysfs_init(struct adf_accel_dev *accel_dev)
165 {
166 	int ret;
167 
168 	ret = devm_device_add_group(&GET_DEV(accel_dev), &qat_group);
169 	if (ret) {
170 		dev_err(&GET_DEV(accel_dev),
171 			"Failed to create qat attribute group: %d\n", ret);
172 	}
173 
174 	return ret;
175 }
176 EXPORT_SYMBOL_GPL(adf_sysfs_init);
177