root/drivers/net/ethernet/hisilicon/hns3/hnae3.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. hnae3_client_match
  2. hnae3_set_client_init_flag
  3. hnae3_get_client_init_flag
  4. hnae3_init_client_instance
  5. hnae3_uninit_client_instance
  6. hnae3_register_client
  7. hnae3_unregister_client
  8. hnae3_register_ae_algo
  9. hnae3_unregister_ae_algo
  10. hnae3_register_ae_dev
  11. hnae3_unregister_ae_dev

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

/* [<][>][^][v][top][bottom][index][help] */