FILE
adf_dev_mgr.c
File preview with syntax highlighting.
linux-6.19.14/drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c
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 8static LIST_HEAD(accel_table); 9static LIST_HEAD(vfs_table); 10static DEFINE_MUTEX(table_lock); 11static u32 num_devices; 12static u8 id_map[ADF_MAX_DEVICES]; 13 14struct vf_id_map { 15 u32 bdf; 16 u32 id; 17 u32 fake_id; 18 bool attached; 19 struct list_head list; 20}; 21 22static 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 29static 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 34static 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 48static int adf_get_vf_real_id(u32 fake) 49{ 50 struct list_head *itr; 51 52 list_for_each(itr, &vfs_table) { 53 struct vf_id_map *ptr = 54 list_entry(itr, struct vf_id_map, list); 55 if (ptr->fake_id == fake) 56 return ptr->id; 57 } 58 return -1; 59} 60 61/** 62 * adf_clean_vf_map() - Cleans VF id mappings 63 * @vf: flag indicating whether mappings is cleaned 64 * for vfs only or for vfs and pfs 65 * 66 * Function cleans internal ids for virtual functions. 67 */ 68void adf_clean_vf_map(bool vf) 69{ 70 struct vf_id_map *map; 71 struct list_head *ptr, *tmp; 72 73 mutex_lock(&table_lock); 74 list_for_each_safe(ptr, tmp, &vfs_table) { 75 map = list_entry(ptr, struct vf_id_map, list); 76 if (map->bdf != -1) { 77 id_map[map->id] = 0; 78 num_devices--; 79 } 80 81 if (vf && map->bdf == -1) 82 continue; 83 84 list_del(ptr); 85 kfree(map); 86 } 87 mutex_unlock(&table_lock); 88} 89EXPORT_SYMBOL_GPL(adf_clean_vf_map); 90 91/** 92 * adf_devmgr_update_class_index() - Update internal index 93 * @hw_data: Pointer to internal device data. 94 * 95 * Function updates internal dev index for VFs 96 */ 97void adf_devmgr_update_class_index(struct adf_hw_device_data *hw_data) 98{ 99 struct adf_hw_device_class *class = hw_data->dev_class; 100 struct list_head *itr; 101 int i = 0; 102 103 list_for_each(itr, &accel_table) { 104 struct adf_accel_dev *ptr = 105 list_entry(itr, struct adf_accel_dev, list); 106 107 if (ptr->hw_device->dev_class == class) 108 ptr->hw_device->instance_id = i++; 109 110 if (i == class->instances) 111 break; 112 } 113} 114EXPORT_SYMBOL_GPL(adf_devmgr_update_class_index); 115 116static unsigned int adf_find_free_id(void) 117{ 118 unsigned int i; 119 120 for (i = 0; i < ADF_MAX_DEVICES; i++) { 121 if (!id_map[i]) { 122 id_map[i] = 1; 123 return i; 124 } 125 } 126 return ADF_MAX_DEVICES + 1; 127} 128 129/** 130 * adf_devmgr_add_dev() - Add accel_dev to the acceleration framework 131 * @accel_dev: Pointer to acceleration device. 132 * @pf: Corresponding PF if the accel_dev is a VF 133 * 134 * Function adds acceleration device to the acceleration framework. 135 * To be used by QAT device specific drivers. 136 * 137 * Return: 0 on success, error code otherwise. 138 */ 139int adf_devmgr_add_dev(struct adf_accel_dev *accel_dev, 140 struct adf_accel_dev *pf) 141{ 142 struct list_head *itr; 143 int ret = 0; 144 145 if (num_devices == ADF_MAX_DEVICES) { 146 dev_err(&GET_DEV(accel_dev), "Only support up to %d devices\n", 147 ADF_MAX_DEVICES); 148 return -EFAULT; 149 } 150 151 mutex_lock(&table_lock); 152 atomic_set(&accel_dev->ref_count, 0); 153 154 /* PF on host or VF on guest - optimized to remove redundant is_vf */ 155 if (!accel_dev->is_vf || !pf) { 156 struct vf_id_map *map; 157 158 list_for_each(itr, &accel_table) { 159 struct adf_accel_dev *ptr = 160 list_entry(itr, struct adf_accel_dev, list); 161 162 if (ptr == accel_dev) { 163 ret = -EEXIST; 164 goto unlock; 165 } 166 } 167 168 list_add_tail(&accel_dev->list, &accel_table); 169 accel_dev->accel_id = adf_find_free_id(); 170 if (accel_dev->accel_id > ADF_MAX_DEVICES) { 171 ret = -EFAULT; 172 goto unlock; 173 } 174 num_devices++; 175 map = kzalloc(sizeof(*map), GFP_KERNEL); 176 if (!map) { 177 ret = -ENOMEM; 178 goto unlock; 179 } 180 map->bdf = ~0; 181 map->id = accel_dev->accel_id; 182 map->fake_id = map->id; 183 map->attached = true; 184 list_add_tail(&map->list, &vfs_table); 185 } else if (accel_dev->is_vf && pf) { 186 /* VF on host */ 187 struct vf_id_map *map; 188 189 map = adf_find_vf(adf_get_vf_num(accel_dev)); 190 if (map) { 191 struct vf_id_map *next; 192 193 accel_dev->accel_id = map->id; 194 list_add_tail(&accel_dev->list, &accel_table); 195 map->fake_id++; 196 map->attached = true; 197 next = list_next_entry(map, list); 198 while (next && &next->list != &vfs_table) { 199 next->fake_id++; 200 next = list_next_entry(next, list); 201 } 202 203 ret = 0; 204 goto unlock; 205 } 206 207 map = kzalloc(sizeof(*map), GFP_KERNEL); 208 if (!map) { 209 ret = -ENOMEM; 210 goto unlock; 211 } 212 accel_dev->accel_id = adf_find_free_id(); 213 if (accel_dev->accel_id > ADF_MAX_DEVICES) { 214 kfree(map); 215 ret = -EFAULT; 216 goto unlock; 217 } 218 num_devices++; 219 list_add_tail(&accel_dev->list, &accel_table); 220 map->bdf = adf_get_vf_num(accel_dev); 221 map->id = accel_dev->accel_id; 222 map->fake_id = map->id; 223 map->attached = true; 224 list_add_tail(&map->list, &vfs_table); 225 } 226 mutex_init(&accel_dev->state_lock); 227unlock: 228 mutex_unlock(&table_lock); 229 return ret; 230} 231EXPORT_SYMBOL_GPL(adf_devmgr_add_dev); 232 233struct list_head *adf_devmgr_get_head(void) 234{ 235 return &accel_table; 236} 237 238/** 239 * adf_devmgr_rm_dev() - Remove accel_dev from the acceleration framework. 240 * @accel_dev: Pointer to acceleration device. 241 * @pf: Corresponding PF if the accel_dev is a VF 242 * 243 * Function removes acceleration device from the acceleration framework. 244 * To be used by QAT device specific drivers. 245 * 246 * Return: void 247 */ 248void adf_devmgr_rm_dev(struct adf_accel_dev *accel_dev, 249 struct adf_accel_dev *pf) 250{ 251 mutex_lock(&table_lock); 252 /* PF on host or VF on guest - optimized to remove redundant is_vf */ 253 if (!accel_dev->is_vf || !pf) { 254 id_map[accel_dev->accel_id] = 0; 255 num_devices--; 256 } else if (accel_dev->is_vf && pf) { 257 struct vf_id_map *map, *next; 258 259 map = adf_find_vf(adf_get_vf_num(accel_dev)); 260 if (!map) { 261 dev_err(&GET_DEV(accel_dev), "Failed to find VF map\n"); 262 goto unlock; 263 } 264 map->fake_id--; 265 map->attached = false; 266 next = list_next_entry(map, list); 267 while (next && &next->list != &vfs_table) { 268 next->fake_id--; 269 next = list_next_entry(next, list); 270 } 271 } 272unlock: 273 mutex_destroy(&accel_dev->state_lock); 274 list_del(&accel_dev->list); 275 mutex_unlock(&table_lock); 276} 277EXPORT_SYMBOL_GPL(adf_devmgr_rm_dev); 278 279/** 280 * adf_devmgr_pci_to_accel_dev() - Get accel_dev associated with the pci_dev. 281 * @pci_dev: Pointer to PCI device. 282 * 283 * Function returns acceleration device associated with the given PCI device. 284 * To be used by QAT device specific drivers. 285 * 286 * Return: pointer to accel_dev or NULL if not found. 287 */ 288struct adf_accel_dev *adf_devmgr_pci_to_accel_dev(struct pci_dev *pci_dev) 289{ 290 struct list_head *itr; 291 292 mutex_lock(&table_lock); 293 list_for_each(itr, &accel_table) { 294 struct adf_accel_dev *ptr = 295 list_entry(itr, struct adf_accel_dev, list); 296 297 if (ptr->accel_pci_dev.pci_dev == pci_dev) { 298 mutex_unlock(&table_lock); 299 return ptr; 300 } 301 } 302 mutex_unlock(&table_lock); 303 return NULL; 304} 305EXPORT_SYMBOL_GPL(adf_devmgr_pci_to_accel_dev); 306 307struct adf_accel_dev *adf_devmgr_get_dev_by_id(u32 id) 308{ 309 struct list_head *itr; 310 int real_id; 311 312 mutex_lock(&table_lock); 313 real_id = adf_get_vf_real_id(id); 314 if (real_id < 0) 315 goto unlock; 316 317 id = real_id; 318 319 list_for_each(itr, &accel_table) { 320 struct adf_accel_dev *ptr = 321 list_entry(itr, struct adf_accel_dev, list); 322 if (ptr->accel_id == id) { 323 mutex_unlock(&table_lock); 324 return ptr; 325 } 326 } 327unlock: 328 mutex_unlock(&table_lock); 329 return NULL; 330} 331 332int adf_devmgr_verify_id(u32 id) 333{ 334 if (id == ADF_CFG_ALL_DEVICES) 335 return 0; 336 337 if (adf_devmgr_get_dev_by_id(id)) 338 return 0; 339 340 return -ENODEV; 341} 342 343static int adf_get_num_dettached_vfs(void) 344{ 345 struct list_head *itr; 346 int vfs = 0; 347 348 mutex_lock(&table_lock); 349 list_for_each(itr, &vfs_table) { 350 struct vf_id_map *ptr = 351 list_entry(itr, struct vf_id_map, list); 352 if (ptr->bdf != ~0 && !ptr->attached) 353 vfs++; 354 } 355 mutex_unlock(&table_lock); 356 return vfs; 357} 358 359void adf_devmgr_get_num_dev(u32 *num) 360{ 361 *num = num_devices - adf_get_num_dettached_vfs(); 362} 363 364/** 365 * adf_dev_in_use() - Check whether accel_dev is currently in use 366 * @accel_dev: Pointer to acceleration device. 367 * 368 * To be used by QAT device specific drivers. 369 * 370 * Return: 1 when device is in use, 0 otherwise. 371 */ 372int adf_dev_in_use(struct adf_accel_dev *accel_dev) 373{ 374 return atomic_read(&accel_dev->ref_count) != 0; 375} 376EXPORT_SYMBOL_GPL(adf_dev_in_use); 377 378/** 379 * adf_dev_get() - Increment accel_dev reference count 380 * @accel_dev: Pointer to acceleration device. 381 * 382 * Increment the accel_dev refcount and if this is the first time 383 * incrementing it during this period the accel_dev is in use, 384 * increment the module refcount too. 385 * To be used by QAT device specific drivers. 386 * 387 * Return: 0 when successful, EFAULT when fail to bump module refcount 388 */ 389int adf_dev_get(struct adf_accel_dev *accel_dev) 390{ 391 if (atomic_add_return(1, &accel_dev->ref_count) == 1) 392 if (!try_module_get(accel_dev->owner)) 393 return -EFAULT; 394 return 0; 395} 396EXPORT_SYMBOL_GPL(adf_dev_get); 397 398/** 399 * adf_dev_put() - Decrement accel_dev reference count 400 * @accel_dev: Pointer to acceleration device. 401 * 402 * Decrement the accel_dev refcount and if this is the last time 403 * decrementing it during this period the accel_dev is in use, 404 * decrement the module refcount too. 405 * To be used by QAT device specific drivers. 406 * 407 * Return: void 408 */ 409void adf_dev_put(struct adf_accel_dev *accel_dev) 410{ 411 if (atomic_sub_return(1, &accel_dev->ref_count) == 0) 412 module_put(accel_dev->owner); 413} 414EXPORT_SYMBOL_GPL(adf_dev_put); 415 416/** 417 * adf_devmgr_in_reset() - Check whether device is in reset 418 * @accel_dev: Pointer to acceleration device. 419 * 420 * To be used by QAT device specific drivers. 421 * 422 * Return: 1 when the device is being reset, 0 otherwise. 423 */ 424int adf_devmgr_in_reset(struct adf_accel_dev *accel_dev) 425{ 426 return test_bit(ADF_STATUS_RESTARTING, &accel_dev->status); 427} 428EXPORT_SYMBOL_GPL(adf_devmgr_in_reset); 429 430/** 431 * adf_dev_started() - Check whether device has started 432 * @accel_dev: Pointer to acceleration device. 433 * 434 * To be used by QAT device specific drivers. 435 * 436 * Return: 1 when the device has started, 0 otherwise 437 */ 438int adf_dev_started(struct adf_accel_dev *accel_dev) 439{ 440 return test_bit(ADF_STATUS_STARTED, &accel_dev->status); 441} 442EXPORT_SYMBOL_GPL(adf_dev_started);
~/
Read-only file preview.