1 // SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) 2 /* Copyright(c) 2014 - 2020 Intel Corporation */ 3 #include <linux/mutex.h> 4 #include <linux/list.h> 5 #include "adf_cfg.h" 6 #include "adf_common_drv.h" 7 8 static LIST_HEAD(accel_table); 9 static LIST_HEAD(vfs_table); 10 static DEFINE_MUTEX(table_lock); 11 static u32 num_devices; 12 static u8 id_map[ADF_MAX_DEVICES]; 13 14 struct vf_id_map { 15 u32 bdf; 16 u32 id; 17 u32 fake_id; 18 bool attached; 19 struct list_head list; 20 }; 21 22 static int adf_get_vf_id(struct adf_accel_dev *vf) 23 { 24 return ((7 * (PCI_SLOT(accel_to_pci_dev(vf)->devfn) - 1)) + 25 PCI_FUNC(accel_to_pci_dev(vf)->devfn) + 26 (PCI_SLOT(accel_to_pci_dev(vf)->devfn) - 1)); 27 } 28 29 static int adf_get_vf_num(struct adf_accel_dev *vf) 30 { 31 return (accel_to_pci_dev(vf)->bus->number << 8) | adf_get_vf_id(vf); 32 } 33 34 static struct vf_id_map *adf_find_vf(u32 bdf) 35 { 36 struct list_head *itr; 37 38 list_for_each(itr, &vfs_table) { 39 struct vf_id_map *ptr = 40 list_entry(itr, struct vf_id_map, list); 41 42 if (ptr->bdf == bdf) 43 return ptr; 44 } 45 return NULL; 46 } 47 48 /** 49 * adf_clean_vf_map() - Cleans VF id mappings 50 * @vf: flag indicating whether mappings is cleaned 51 * for vfs only or for vfs and pfs 52 * 53 * Function cleans internal ids for virtual functions. 54 */ 55 void adf_clean_vf_map(bool vf) 56 { 57 struct vf_id_map *map; 58 struct list_head *ptr, *tmp; 59 60 mutex_lock(&table_lock); 61 list_for_each_safe(ptr, tmp, &vfs_table) { 62 map = list_entry(ptr, struct vf_id_map, list); 63 if (map->bdf != -1) { 64 id_map[map->id] = 0; 65 num_devices--; 66 } 67 68 if (vf && map->bdf == -1) 69 continue; 70 71 list_del(ptr); 72 kfree(map); 73 } 74 mutex_unlock(&table_lock); 75 } 76 EXPORT_SYMBOL_GPL(adf_clean_vf_map); 77 78 /** 79 * adf_devmgr_update_class_index() - Update internal index 80 * @hw_data: Pointer to internal device data. 81 * 82 * Function updates internal dev index for VFs 83 */ 84 void adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data) 85 { 86 struct adf_hw_device_class *class = hw_data->dev_class; 87 struct list_head *itr; 88 int i = 0; 89 90 list_for_each(itr, &accel_table) { 91 struct adf_accel_dev *ptr = 92 list_entry(itr, struct adf_accel_dev, list); 93 94 if (ptr->hw_device->dev_class == class) 95 ptr->hw_device->instance_id = i++; 96 97 if (i == class->instances) 98 break; 99 } 100 } 101 EXPORT_SYMBOL_GPL(adf_devmgr_update_class_index); 102 103 static unsigned int adf_find_free_id(void) 104 { 105 unsigned int i; 106 107 for (i = 0; i < ADF_MAX_DEVICES; i++) { 108 if (!id_map[i]) { 109 id_map[i] = 1; 110 return i; 111 } 112 } 113 return ADF_MAX_DEVICES + 1; 114 } 115 116 /** 117 * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework 118 * @accel_dev: Pointer to acceleration device. 119 * @pf: Corresponding PF if the accel_dev is a VF 120 * 121 * Function adds acceleration device to the acceleration framework. 122 * To be used by QAT device specific drivers. 123 * 124 * Return: 0 on success, error code otherwise. 125 */ 126 int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, 127 struct adf_accel_dev *pf) 128 { 129 struct list_head *itr; 130 int ret = 0; 131 132 if (num_devices == ADF_MAX_DEVICES) { 133 dev_err(&GET_DEV(accel_dev), "Only support up to %d devices\n", 134 ADF_MAX_DEVICES); 135 return -EFAULT; 136 } 137 138 mutex_lock(&table_lock); 139 atomic_set(&accel_dev->ref_count, 0); 140 141 /* PF on host or VF on guest - optimized to remove redundant is_vf */ 142 if (!accel_dev->is_vf || !pf) { 143 struct vf_id_map *map; 144 145 list_for_each(itr, &accel_table) { 146 struct adf_accel_dev *ptr = 147 list_entry(itr, struct adf_accel_dev, list); 148 149 if (ptr == accel_dev) { 150 ret = -EEXIST; 151 goto unlock; 152 } 153 } 154 155 list_add_tail(&accel_dev->list, &accel_table); 156 accel_dev->accel_id = adf_find_free_id(); 157 if (accel_dev->accel_id > ADF_MAX_DEVICES) { 158 ret = -EFAULT; 159 goto unlock; 160 } 161 num_devices++; 162 map = kzalloc_obj(*map); 163 if (!map) { 164 ret = -ENOMEM; 165 goto unlock; 166 } 167 map->bdf = ~0; 168 map->id = accel_dev->accel_id; 169 map->fake_id = map->id; 170 map->attached = true; 171 list_add_tail(&map->list, &vfs_table); 172 } else if (accel_dev->is_vf && pf) { 173 /* VF on host */ 174 struct vf_id_map *map; 175 176 map = adf_find_vf(adf_get_vf_num(accel_dev)); 177 if (map) { 178 struct vf_id_map *next; 179 180 accel_dev->accel_id = map->id; 181 list_add_tail(&accel_dev->list, &accel_table); 182 map->fake_id++; 183 map->attached = true; 184 next = list_next_entry(map, list); 185 while (next && &next->list != &vfs_table) { 186 next->fake_id++; 187 next = list_next_entry(next, list); 188 } 189 190 ret = 0; 191 goto unlock; 192 } 193 194 map = kzalloc_obj(*map); 195 if (!map) { 196 ret = -ENOMEM; 197 goto unlock; 198 } 199 accel_dev->accel_id = adf_find_free_id(); 200 if (accel_dev->accel_id > ADF_MAX_DEVICES) { 201 kfree(map); 202 ret = -EFAULT; 203 goto unlock; 204 } 205 num_devices++; 206 list_add_tail(&accel_dev->list, &accel_table); 207 map->bdf = adf_get_vf_num(accel_dev); 208 map->id = accel_dev->accel_id; 209 map->fake_id = map->id; 210 map->attached = true; 211 list_add_tail(&map->list, &vfs_table); 212 } 213 mutex_init(&accel_dev->state_lock); 214 unlock: 215 mutex_unlock(&table_lock); 216 return ret; 217 } 218 EXPORT_SYMBOL_GPL(adf_devmgr_add_dev); 219 220 struct list_head *adf_devmgr_get_head(void) 221 { 222 return &accel_table; 223 } 224 225 /** 226 * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework. 227 * @accel_dev: Pointer to acceleration device. 228 * @pf: Corresponding PF if the accel_dev is a VF 229 * 230 * Function removes acceleration device from the acceleration framework. 231 * To be used by QAT device specific drivers. 232 * 233 * Return: void 234 */ 235 void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, 236 struct adf_accel_dev *pf) 237 { 238 mutex_lock(&table_lock); 239 /* PF on host or VF on guest - optimized to remove redundant is_vf */ 240 if (!accel_dev->is_vf || !pf) { 241 id_map[accel_dev->accel_id] = 0; 242 num_devices--; 243 } else if (accel_dev->is_vf && pf) { 244 struct vf_id_map *map, *next; 245 246 map = adf_find_vf(adf_get_vf_num(accel_dev)); 247 if (!map) { 248 dev_err(&GET_DEV(accel_dev), "Failed to find VF map\n"); 249 goto unlock; 250 } 251 map->fake_id--; 252 map->attached = false; 253 next = list_next_entry(map, list); 254 while (next && &next->list != &vfs_table) { 255 next->fake_id--; 256 next = list_next_entry(next, list); 257 } 258 } 259 unlock: 260 mutex_destroy(&accel_dev->state_lock); 261 list_del(&accel_dev->list); 262 mutex_unlock(&table_lock); 263 } 264 EXPORT_SYMBOL_GPL(adf_devmgr_rm_dev); 265 266 /** 267 * adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev. 268 * @pci_dev: Pointer to PCI device. 269 * 270 * Function returns acceleration device associated with the given PCI device. 271 * To be used by QAT device specific drivers. 272 * 273 * Return: pointer to accel_dev or NULL if not found. 274 */ 275 struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev) 276 { 277 struct list_head *itr; 278 279 mutex_lock(&table_lock); 280 list_for_each(itr, &accel_table) { 281 struct adf_accel_dev *ptr = 282 list_entry(itr, struct adf_accel_dev, list); 283 284 if (ptr->accel_pci_dev.pci_dev == pci_dev) { 285 mutex_unlock(&table_lock); 286 return ptr; 287 } 288 } 289 mutex_unlock(&table_lock); 290 return NULL; 291 } 292 EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev); 293 294 /** 295 * adf_dev_in_use() - Check whether accel_dev is currently in use 296 * @accel_dev: Pointer to acceleration device. 297 * 298 * To be used by QAT device specific drivers. 299 * 300 * Return: 1 when device is in use, 0 otherwise. 301 */ 302 int adf_dev_in_use(struct adf_accel_dev *accel_dev) 303 { 304 return atomic_read(&accel_dev->ref_count) != 0; 305 } 306 EXPORT_SYMBOL_GPL(adf_dev_in_use); 307 308 /** 309 * adf_dev_get() - Increment accel_dev reference count 310 * @accel_dev: Pointer to acceleration device. 311 * 312 * Increment the accel_dev refcount and if this is the first time 313 * incrementing it during this period the accel_dev is in use, 314 * increment the module refcount too. 315 * To be used by QAT device specific drivers. 316 * 317 * Return: 0 when successful, EFAULT when fail to bump module refcount 318 */ 319 int adf_dev_get(struct adf_accel_dev *accel_dev) 320 { 321 if (atomic_add_return(1, &accel_dev->ref_count) == 1) 322 if (!try_module_get(accel_dev->owner)) 323 return -EFAULT; 324 return 0; 325 } 326 EXPORT_SYMBOL_GPL(adf_dev_get); 327 328 /** 329 * adf_dev_put() - Decrement accel_dev reference count 330 * @accel_dev: Pointer to acceleration device. 331 * 332 * Decrement the accel_dev refcount and if this is the last time 333 * decrementing it during this period the accel_dev is in use, 334 * decrement the module refcount too. 335 * To be used by QAT device specific drivers. 336 * 337 * Return: void 338 */ 339 void adf_dev_put(struct adf_accel_dev *accel_dev) 340 { 341 if (atomic_sub_return(1, &accel_dev->ref_count) == 0) 342 module_put(accel_dev->owner); 343 } 344 EXPORT_SYMBOL_GPL(adf_dev_put); 345 346 /** 347 * adf_devmgr_in_reset() - Check whether device is in reset 348 * @accel_dev: Pointer to acceleration device. 349 * 350 * To be used by QAT device specific drivers. 351 * 352 * Return: 1 when the device is being reset, 0 otherwise. 353 */ 354 int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev) 355 { 356 return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status); 357 } 358 EXPORT_SYMBOL_GPL(adf_devmgr_in_reset); 359 360 /** 361 * adf_dev_started() - Check whether device has started 362 * @accel_dev: Pointer to acceleration device. 363 * 364 * To be used by QAT device specific drivers. 365 * 366 * Return: 1 when the device has started, 0 otherwise 367 */ 368 int adf_dev_started(struct adf_accel_dev *accel_dev) 369 { 370 return test_bit(ADF_STATUS_STARTED, &accel_dev->status); 371 } 372 EXPORT_SYMBOL_GPL(adf_dev_started); 373