linux/drivers/net/ethernet/hisilicon/hns3/hnae3.c
<<
>>
Prefs
   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
   9static LIST_HEAD(hnae3_ae_algo_list);
  10static LIST_HEAD(hnae3_client_list);
  11static LIST_HEAD(hnae3_ae_dev_list);
  12
  13void 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}
  32EXPORT_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 */
  38static DEFINE_MUTEX(hnae3_common_lock);
  39
  40static 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
  49void 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}
  67EXPORT_SYMBOL(hnae3_set_client_init_flag);
  68
  69static 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
  90static 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
 109static 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
 124int 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
 153exit:
 154        mutex_unlock(&hnae3_common_lock);
 155
 156        return 0;
 157}
 158EXPORT_SYMBOL(hnae3_register_client);
 159
 160void 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}
 192EXPORT_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 */
 198void 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}
 248EXPORT_SYMBOL(hnae3_register_ae_algo);
 249
 250/* hnae3_unregister_ae_algo - unregisters a AE algorithm
 251 * @ae_algo: the AE algorithm to unregister
 252 */
 253void 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}
 286EXPORT_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 */
 292int 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
 346out_err:
 347        list_del(&ae_dev->node);
 348        mutex_unlock(&hnae3_common_lock);
 349
 350        return ret;
 351}
 352EXPORT_SYMBOL(hnae3_register_ae_dev);
 353
 354/* hnae3_unregister_ae_dev - unregisters a AE device
 355 * @ae_dev: the AE device to unregister
 356 */
 357void 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}
 387EXPORT_SYMBOL(hnae3_unregister_ae_dev);
 388
 389MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
 390MODULE_LICENSE("GPL");
 391MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
 392MODULE_VERSION(HNAE3_MOD_VERSION);
 393