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