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 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 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 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 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 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 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 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 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