1 // SPDX-License-Identifier: GPL-2.0+ 2 // Copyright (c) 2016-2017 Hisilicon Limited. 3 4 #include <linux/list.h> 5 #include <linux/spinlock.h> 6 7 #include "hnae3.h" 8 9 static LIST_HEAD(hnae3_ae_algo_list); 10 static LIST_HEAD(hnae3_client_list); 11 static LIST_HEAD(hnae3_ae_dev_list); 12 13 void hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo) 14 { 15 const struct pci_device_id *pci_id; 16 struct hnae3_ae_dev *ae_dev; 17 18 if (!ae_algo) 19 return; 20 21 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { 22 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)) 23 continue; 24 25 pci_id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev); 26 if (!pci_id) 27 continue; 28 if (IS_ENABLED(CONFIG_PCI_IOV)) { 29 device_lock(&ae_dev->pdev->dev); 30 pci_disable_sriov(ae_dev->pdev); 31 device_unlock(&ae_dev->pdev->dev); 32 } 33 } 34 } 35 EXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare); 36 37 /* we are keeping things simple and using single lock for all the 38 * list. This is a non-critical code so other updations, if happen 39 * in parallel, can wait. 40 */ 41 static DEFINE_MUTEX(hnae3_common_lock); 42 43 /* ensure the drivers being unloaded one by one */ 44 static DEFINE_MUTEX(hnae3_unload_lock); 45 46 void hnae3_acquire_unload_lock(void) 47 { 48 mutex_lock(&hnae3_unload_lock); 49 } 50 EXPORT_SYMBOL(hnae3_acquire_unload_lock); 51 52 void hnae3_release_unload_lock(void) 53 { 54 mutex_unlock(&hnae3_unload_lock); 55 } 56 EXPORT_SYMBOL(hnae3_release_unload_lock); 57 58 static bool hnae3_client_match(enum hnae3_client_type client_type) 59 { 60 if (client_type == HNAE3_CLIENT_KNIC || 61 client_type == HNAE3_CLIENT_ROCE) 62 return true; 63 64 return false; 65 } 66 67 void hnae3_set_client_init_flag(struct hnae3_client *client, 68 struct hnae3_ae_dev *ae_dev, 69 unsigned int inited) 70 { 71 if (!client || !ae_dev) 72 return; 73 74 switch (client->type) { 75 case HNAE3_CLIENT_KNIC: 76 hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited); 77 break; 78 case HNAE3_CLIENT_ROCE: 79 hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited); 80 break; 81 default: 82 break; 83 } 84 } 85 EXPORT_SYMBOL(hnae3_set_client_init_flag); 86 87 static int hnae3_get_client_init_flag(struct hnae3_client *client, 88 struct hnae3_ae_dev *ae_dev) 89 { 90 int inited = 0; 91 92 switch (client->type) { 93 case HNAE3_CLIENT_KNIC: 94 inited = hnae3_get_bit(ae_dev->flag, 95 HNAE3_KNIC_CLIENT_INITED_B); 96 break; 97 case HNAE3_CLIENT_ROCE: 98 inited = hnae3_get_bit(ae_dev->flag, 99 HNAE3_ROCE_CLIENT_INITED_B); 100 break; 101 default: 102 break; 103 } 104 105 return inited; 106 } 107 108 static int hnae3_init_client_instance(struct hnae3_client *client, 109 struct hnae3_ae_dev *ae_dev) 110 { 111 int ret; 112 113 /* check if this client matches the type of ae_dev */ 114 if (!(hnae3_client_match(client->type) && 115 hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) { 116 return 0; 117 } 118 119 ret = ae_dev->ops->init_client_instance(client, ae_dev); 120 if (ret) 121 dev_err(&ae_dev->pdev->dev, 122 "fail to instantiate client, ret = %d\n", ret); 123 124 return ret; 125 } 126 127 static void hnae3_uninit_client_instance(struct hnae3_client *client, 128 struct hnae3_ae_dev *ae_dev) 129 { 130 /* check if this client matches the type of ae_dev */ 131 if (!(hnae3_client_match(client->type) && 132 hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) 133 return; 134 135 if (hnae3_get_client_init_flag(client, ae_dev)) { 136 ae_dev->ops->uninit_client_instance(client, ae_dev); 137 138 hnae3_set_client_init_flag(client, ae_dev, 0); 139 } 140 } 141 142 int hnae3_register_client(struct hnae3_client *client) 143 { 144 struct hnae3_client *client_tmp; 145 struct hnae3_ae_dev *ae_dev; 146 147 if (!client) 148 return -ENODEV; 149 150 mutex_lock(&hnae3_common_lock); 151 /* one system should only have one client for every type */ 152 list_for_each_entry(client_tmp, &hnae3_client_list, node) { 153 if (client_tmp->type == client->type) 154 goto exit; 155 } 156 157 list_add_tail(&client->node, &hnae3_client_list); 158 159 /* initialize the client on every matched port */ 160 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { 161 /* if the client could not be initialized on current port, for 162 * any error reasons, move on to next available port 163 */ 164 int ret = hnae3_init_client_instance(client, ae_dev); 165 if (ret) 166 dev_err(&ae_dev->pdev->dev, 167 "match and instantiation failed for port, ret = %d\n", 168 ret); 169 } 170 171 exit: 172 mutex_unlock(&hnae3_common_lock); 173 174 return 0; 175 } 176 EXPORT_SYMBOL(hnae3_register_client); 177 178 void hnae3_unregister_client(struct hnae3_client *client) 179 { 180 struct hnae3_client *client_tmp; 181 struct hnae3_ae_dev *ae_dev; 182 bool existed = false; 183 184 if (!client) 185 return; 186 187 mutex_lock(&hnae3_common_lock); 188 /* one system should only have one client for every type */ 189 list_for_each_entry(client_tmp, &hnae3_client_list, node) { 190 if (client_tmp->type == client->type) { 191 existed = true; 192 break; 193 } 194 } 195 196 if (!existed) { 197 mutex_unlock(&hnae3_common_lock); 198 pr_err("client %s does not exist!\n", client->name); 199 return; 200 } 201 202 /* un-initialize the client on every matched port */ 203 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { 204 hnae3_uninit_client_instance(client, ae_dev); 205 } 206 207 list_del(&client->node); 208 mutex_unlock(&hnae3_common_lock); 209 } 210 EXPORT_SYMBOL(hnae3_unregister_client); 211 212 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework 213 * @ae_algo: AE algorithm 214 * NOTE: the duplicated name will not be checked 215 */ 216 void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo) 217 { 218 const struct pci_device_id *id; 219 struct hnae3_ae_dev *ae_dev; 220 struct hnae3_client *client; 221 int ret; 222 223 if (!ae_algo) 224 return; 225 226 mutex_lock(&hnae3_common_lock); 227 228 list_add_tail(&ae_algo->node, &hnae3_ae_algo_list); 229 230 /* Check if this algo/ops matches the list of ae_devs */ 231 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { 232 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev); 233 if (!id) 234 continue; 235 236 if (!ae_algo->ops) { 237 dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n"); 238 continue; 239 } 240 ae_dev->ops = ae_algo->ops; 241 242 ret = ae_algo->ops->init_ae_dev(ae_dev); 243 if (ret) { 244 dev_err(&ae_dev->pdev->dev, 245 "init ae_dev error, ret = %d\n", ret); 246 continue; 247 } 248 249 /* ae_dev init should set flag */ 250 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1); 251 252 /* check the client list for the match with this ae_dev type and 253 * initialize the figure out client instance 254 */ 255 list_for_each_entry(client, &hnae3_client_list, node) { 256 ret = hnae3_init_client_instance(client, ae_dev); 257 if (ret) 258 dev_err(&ae_dev->pdev->dev, 259 "match and instantiation failed, ret = %d\n", 260 ret); 261 } 262 } 263 264 mutex_unlock(&hnae3_common_lock); 265 } 266 EXPORT_SYMBOL(hnae3_register_ae_algo); 267 268 /* hnae3_unregister_ae_algo - unregisters a AE algorithm 269 * @ae_algo: the AE algorithm to unregister 270 */ 271 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo) 272 { 273 const struct pci_device_id *id; 274 struct hnae3_ae_dev *ae_dev; 275 struct hnae3_client *client; 276 277 if (!ae_algo) 278 return; 279 280 mutex_lock(&hnae3_common_lock); 281 /* Check if there are matched ae_dev */ 282 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) { 283 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)) 284 continue; 285 286 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev); 287 if (!id) 288 continue; 289 290 /* check the client list for the match with this ae_dev type and 291 * un-initialize the figure out client instance 292 */ 293 list_for_each_entry(client, &hnae3_client_list, node) 294 hnae3_uninit_client_instance(client, ae_dev); 295 296 ae_algo->ops->uninit_ae_dev(ae_dev); 297 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0); 298 ae_dev->ops = NULL; 299 } 300 301 list_del(&ae_algo->node); 302 mutex_unlock(&hnae3_common_lock); 303 } 304 EXPORT_SYMBOL(hnae3_unregister_ae_algo); 305 306 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework 307 * @ae_dev: the AE device 308 * NOTE: the duplicated name will not be checked 309 */ 310 int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev) 311 { 312 const struct pci_device_id *id; 313 struct hnae3_ae_algo *ae_algo; 314 struct hnae3_client *client; 315 int ret; 316 317 if (!ae_dev) 318 return -ENODEV; 319 320 mutex_lock(&hnae3_common_lock); 321 322 list_add_tail(&ae_dev->node, &hnae3_ae_dev_list); 323 324 /* Check if there are matched ae_algo */ 325 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) { 326 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev); 327 if (!id) 328 continue; 329 330 if (!ae_algo->ops) { 331 dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n"); 332 ret = -EOPNOTSUPP; 333 goto out_err; 334 } 335 ae_dev->ops = ae_algo->ops; 336 337 ret = ae_dev->ops->init_ae_dev(ae_dev); 338 if (ret) { 339 dev_err(&ae_dev->pdev->dev, 340 "init ae_dev error, ret = %d\n", ret); 341 goto out_err; 342 } 343 344 /* ae_dev init should set flag */ 345 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1); 346 break; 347 } 348 349 /* check the client list for the match with this ae_dev type and 350 * initialize the figure out client instance 351 */ 352 list_for_each_entry(client, &hnae3_client_list, node) { 353 ret = hnae3_init_client_instance(client, ae_dev); 354 if (ret) 355 dev_err(&ae_dev->pdev->dev, 356 "match and instantiation failed, ret = %d\n", 357 ret); 358 } 359 360 mutex_unlock(&hnae3_common_lock); 361 362 return 0; 363 364 out_err: 365 list_del(&ae_dev->node); 366 mutex_unlock(&hnae3_common_lock); 367 368 return ret; 369 } 370 EXPORT_SYMBOL(hnae3_register_ae_dev); 371 372 /* hnae3_unregister_ae_dev - unregisters a AE device 373 * @ae_dev: the AE device to unregister 374 */ 375 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev) 376 { 377 const struct pci_device_id *id; 378 struct hnae3_ae_algo *ae_algo; 379 struct hnae3_client *client; 380 381 if (!ae_dev) 382 return; 383 384 mutex_lock(&hnae3_common_lock); 385 /* Check if there are matched ae_algo */ 386 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) { 387 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)) 388 continue; 389 390 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev); 391 if (!id) 392 continue; 393 394 list_for_each_entry(client, &hnae3_client_list, node) 395 hnae3_uninit_client_instance(client, ae_dev); 396 397 ae_algo->ops->uninit_ae_dev(ae_dev); 398 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0); 399 ae_dev->ops = NULL; 400 } 401 402 list_del(&ae_dev->node); 403 mutex_unlock(&hnae3_common_lock); 404 } 405 EXPORT_SYMBOL(hnae3_unregister_ae_dev); 406 407 MODULE_AUTHOR("Huawei Tech. Co., Ltd."); 408 MODULE_LICENSE("GPL"); 409 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework"); 410 MODULE_VERSION(HNAE3_MOD_VERSION); 411