Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 // Copyright (c) 2016-2017 Hisilicon Limited.
0003 
0004 #include <linux/list.h>
0005 #include <linux/spinlock.h>
0006 
0007 #include "hnae3.h"
0008 
0009 static LIST_HEAD(hnae3_ae_algo_list);
0010 static LIST_HEAD(hnae3_client_list);
0011 static LIST_HEAD(hnae3_ae_dev_list);
0012 
0013 void hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo)
0014 {
0015     const struct pci_device_id *pci_id;
0016     struct hnae3_ae_dev *ae_dev;
0017 
0018     if (!ae_algo)
0019         return;
0020 
0021     list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
0022         if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
0023             continue;
0024 
0025         pci_id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
0026         if (!pci_id)
0027             continue;
0028         if (IS_ENABLED(CONFIG_PCI_IOV))
0029             pci_disable_sriov(ae_dev->pdev);
0030     }
0031 }
0032 EXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare);
0033 
0034 /* we are keeping things simple and using single lock for all the
0035  * list. This is a non-critical code so other updations, if happen
0036  * in parallel, can wait.
0037  */
0038 static DEFINE_MUTEX(hnae3_common_lock);
0039 
0040 static bool hnae3_client_match(enum hnae3_client_type client_type)
0041 {
0042     if (client_type == HNAE3_CLIENT_KNIC ||
0043         client_type == HNAE3_CLIENT_ROCE)
0044         return true;
0045 
0046     return false;
0047 }
0048 
0049 void hnae3_set_client_init_flag(struct hnae3_client *client,
0050                 struct hnae3_ae_dev *ae_dev,
0051                 unsigned int inited)
0052 {
0053     if (!client || !ae_dev)
0054         return;
0055 
0056     switch (client->type) {
0057     case HNAE3_CLIENT_KNIC:
0058         hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
0059         break;
0060     case HNAE3_CLIENT_ROCE:
0061         hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited);
0062         break;
0063     default:
0064         break;
0065     }
0066 }
0067 EXPORT_SYMBOL(hnae3_set_client_init_flag);
0068 
0069 static int hnae3_get_client_init_flag(struct hnae3_client *client,
0070                       struct hnae3_ae_dev *ae_dev)
0071 {
0072     int inited = 0;
0073 
0074     switch (client->type) {
0075     case HNAE3_CLIENT_KNIC:
0076         inited = hnae3_get_bit(ae_dev->flag,
0077                        HNAE3_KNIC_CLIENT_INITED_B);
0078         break;
0079     case HNAE3_CLIENT_ROCE:
0080         inited = hnae3_get_bit(ae_dev->flag,
0081                        HNAE3_ROCE_CLIENT_INITED_B);
0082         break;
0083     default:
0084         break;
0085     }
0086 
0087     return inited;
0088 }
0089 
0090 static int hnae3_init_client_instance(struct hnae3_client *client,
0091                       struct hnae3_ae_dev *ae_dev)
0092 {
0093     int ret;
0094 
0095     /* check if this client matches the type of ae_dev */
0096     if (!(hnae3_client_match(client->type) &&
0097           hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
0098         return 0;
0099     }
0100 
0101     ret = ae_dev->ops->init_client_instance(client, ae_dev);
0102     if (ret)
0103         dev_err(&ae_dev->pdev->dev,
0104             "fail to instantiate client, ret = %d\n", ret);
0105 
0106     return ret;
0107 }
0108 
0109 static void hnae3_uninit_client_instance(struct hnae3_client *client,
0110                      struct hnae3_ae_dev *ae_dev)
0111 {
0112     /* check if this client matches the type of ae_dev */
0113     if (!(hnae3_client_match(client->type) &&
0114           hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)))
0115         return;
0116 
0117     if (hnae3_get_client_init_flag(client, ae_dev)) {
0118         ae_dev->ops->uninit_client_instance(client, ae_dev);
0119 
0120         hnae3_set_client_init_flag(client, ae_dev, 0);
0121     }
0122 }
0123 
0124 int hnae3_register_client(struct hnae3_client *client)
0125 {
0126     struct hnae3_client *client_tmp;
0127     struct hnae3_ae_dev *ae_dev;
0128 
0129     if (!client)
0130         return -ENODEV;
0131 
0132     mutex_lock(&hnae3_common_lock);
0133     /* one system should only have one client for every type */
0134     list_for_each_entry(client_tmp, &hnae3_client_list, node) {
0135         if (client_tmp->type == client->type)
0136             goto exit;
0137     }
0138 
0139     list_add_tail(&client->node, &hnae3_client_list);
0140 
0141     /* initialize the client on every matched port */
0142     list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
0143         /* if the client could not be initialized on current port, for
0144          * any error reasons, move on to next available port
0145          */
0146         int ret = hnae3_init_client_instance(client, ae_dev);
0147         if (ret)
0148             dev_err(&ae_dev->pdev->dev,
0149                 "match and instantiation failed for port, ret = %d\n",
0150                 ret);
0151     }
0152 
0153 exit:
0154     mutex_unlock(&hnae3_common_lock);
0155 
0156     return 0;
0157 }
0158 EXPORT_SYMBOL(hnae3_register_client);
0159 
0160 void hnae3_unregister_client(struct hnae3_client *client)
0161 {
0162     struct hnae3_client *client_tmp;
0163     struct hnae3_ae_dev *ae_dev;
0164     bool existed = false;
0165 
0166     if (!client)
0167         return;
0168 
0169     mutex_lock(&hnae3_common_lock);
0170     /* one system should only have one client for every type */
0171     list_for_each_entry(client_tmp, &hnae3_client_list, node) {
0172         if (client_tmp->type == client->type) {
0173             existed = true;
0174             break;
0175         }
0176     }
0177 
0178     if (!existed) {
0179         mutex_unlock(&hnae3_common_lock);
0180         pr_err("client %s does not exist!\n", client->name);
0181         return;
0182     }
0183 
0184     /* un-initialize the client on every matched port */
0185     list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
0186         hnae3_uninit_client_instance(client, ae_dev);
0187     }
0188 
0189     list_del(&client->node);
0190     mutex_unlock(&hnae3_common_lock);
0191 }
0192 EXPORT_SYMBOL(hnae3_unregister_client);
0193 
0194 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
0195  * @ae_algo: AE algorithm
0196  * NOTE: the duplicated name will not be checked
0197  */
0198 void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
0199 {
0200     const struct pci_device_id *id;
0201     struct hnae3_ae_dev *ae_dev;
0202     struct hnae3_client *client;
0203     int ret;
0204 
0205     if (!ae_algo)
0206         return;
0207 
0208     mutex_lock(&hnae3_common_lock);
0209 
0210     list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
0211 
0212     /* Check if this algo/ops matches the list of ae_devs */
0213     list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
0214         id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
0215         if (!id)
0216             continue;
0217 
0218         if (!ae_algo->ops) {
0219             dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
0220             continue;
0221         }
0222         ae_dev->ops = ae_algo->ops;
0223 
0224         ret = ae_algo->ops->init_ae_dev(ae_dev);
0225         if (ret) {
0226             dev_err(&ae_dev->pdev->dev,
0227                 "init ae_dev error, ret = %d\n", ret);
0228             continue;
0229         }
0230 
0231         /* ae_dev init should set flag */
0232         hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
0233 
0234         /* check the client list for the match with this ae_dev type and
0235          * initialize the figure out client instance
0236          */
0237         list_for_each_entry(client, &hnae3_client_list, node) {
0238             ret = hnae3_init_client_instance(client, ae_dev);
0239             if (ret)
0240                 dev_err(&ae_dev->pdev->dev,
0241                     "match and instantiation failed, ret = %d\n",
0242                     ret);
0243         }
0244     }
0245 
0246     mutex_unlock(&hnae3_common_lock);
0247 }
0248 EXPORT_SYMBOL(hnae3_register_ae_algo);
0249 
0250 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
0251  * @ae_algo: the AE algorithm to unregister
0252  */
0253 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
0254 {
0255     const struct pci_device_id *id;
0256     struct hnae3_ae_dev *ae_dev;
0257     struct hnae3_client *client;
0258 
0259     if (!ae_algo)
0260         return;
0261 
0262     mutex_lock(&hnae3_common_lock);
0263     /* Check if there are matched ae_dev */
0264     list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
0265         if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
0266             continue;
0267 
0268         id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
0269         if (!id)
0270             continue;
0271 
0272         /* check the client list for the match with this ae_dev type and
0273          * un-initialize the figure out client instance
0274          */
0275         list_for_each_entry(client, &hnae3_client_list, node)
0276             hnae3_uninit_client_instance(client, ae_dev);
0277 
0278         ae_algo->ops->uninit_ae_dev(ae_dev);
0279         hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
0280         ae_dev->ops = NULL;
0281     }
0282 
0283     list_del(&ae_algo->node);
0284     mutex_unlock(&hnae3_common_lock);
0285 }
0286 EXPORT_SYMBOL(hnae3_unregister_ae_algo);
0287 
0288 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
0289  * @ae_dev: the AE device
0290  * NOTE: the duplicated name will not be checked
0291  */
0292 int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
0293 {
0294     const struct pci_device_id *id;
0295     struct hnae3_ae_algo *ae_algo;
0296     struct hnae3_client *client;
0297     int ret;
0298 
0299     if (!ae_dev)
0300         return -ENODEV;
0301 
0302     mutex_lock(&hnae3_common_lock);
0303 
0304     list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
0305 
0306     /* Check if there are matched ae_algo */
0307     list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
0308         id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
0309         if (!id)
0310             continue;
0311 
0312         if (!ae_algo->ops) {
0313             dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
0314             ret = -EOPNOTSUPP;
0315             goto out_err;
0316         }
0317         ae_dev->ops = ae_algo->ops;
0318 
0319         ret = ae_dev->ops->init_ae_dev(ae_dev);
0320         if (ret) {
0321             dev_err(&ae_dev->pdev->dev,
0322                 "init ae_dev error, ret = %d\n", ret);
0323             goto out_err;
0324         }
0325 
0326         /* ae_dev init should set flag */
0327         hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
0328         break;
0329     }
0330 
0331     /* check the client list for the match with this ae_dev type and
0332      * initialize the figure out client instance
0333      */
0334     list_for_each_entry(client, &hnae3_client_list, node) {
0335         ret = hnae3_init_client_instance(client, ae_dev);
0336         if (ret)
0337             dev_err(&ae_dev->pdev->dev,
0338                 "match and instantiation failed, ret = %d\n",
0339                 ret);
0340     }
0341 
0342     mutex_unlock(&hnae3_common_lock);
0343 
0344     return 0;
0345 
0346 out_err:
0347     list_del(&ae_dev->node);
0348     mutex_unlock(&hnae3_common_lock);
0349 
0350     return ret;
0351 }
0352 EXPORT_SYMBOL(hnae3_register_ae_dev);
0353 
0354 /* hnae3_unregister_ae_dev - unregisters a AE device
0355  * @ae_dev: the AE device to unregister
0356  */
0357 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
0358 {
0359     const struct pci_device_id *id;
0360     struct hnae3_ae_algo *ae_algo;
0361     struct hnae3_client *client;
0362 
0363     if (!ae_dev)
0364         return;
0365 
0366     mutex_lock(&hnae3_common_lock);
0367     /* Check if there are matched ae_algo */
0368     list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
0369         if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
0370             continue;
0371 
0372         id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
0373         if (!id)
0374             continue;
0375 
0376         list_for_each_entry(client, &hnae3_client_list, node)
0377             hnae3_uninit_client_instance(client, ae_dev);
0378 
0379         ae_algo->ops->uninit_ae_dev(ae_dev);
0380         hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
0381         ae_dev->ops = NULL;
0382     }
0383 
0384     list_del(&ae_dev->node);
0385     mutex_unlock(&hnae3_common_lock);
0386 }
0387 EXPORT_SYMBOL(hnae3_unregister_ae_dev);
0388 
0389 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
0390 MODULE_LICENSE("GPL");
0391 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
0392 MODULE_VERSION(HNAE3_MOD_VERSION);