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