cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hnae3.c (9689B)


      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);