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