162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+
262306a36Sopenharmony_ci// Copyright (c) 2016-2017 Hisilicon Limited.
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/list.h>
562306a36Sopenharmony_ci#include <linux/spinlock.h>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include "hnae3.h"
862306a36Sopenharmony_ci
962306a36Sopenharmony_cistatic LIST_HEAD(hnae3_ae_algo_list);
1062306a36Sopenharmony_cistatic LIST_HEAD(hnae3_client_list);
1162306a36Sopenharmony_cistatic LIST_HEAD(hnae3_ae_dev_list);
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_civoid hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	const struct pci_device_id *pci_id;
1662306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	if (!ae_algo)
1962306a36Sopenharmony_ci		return;
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
2262306a36Sopenharmony_ci		if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
2362306a36Sopenharmony_ci			continue;
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci		pci_id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
2662306a36Sopenharmony_ci		if (!pci_id)
2762306a36Sopenharmony_ci			continue;
2862306a36Sopenharmony_ci		if (IS_ENABLED(CONFIG_PCI_IOV))
2962306a36Sopenharmony_ci			pci_disable_sriov(ae_dev->pdev);
3062306a36Sopenharmony_ci	}
3162306a36Sopenharmony_ci}
3262306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci/* we are keeping things simple and using single lock for all the
3562306a36Sopenharmony_ci * list. This is a non-critical code so other updations, if happen
3662306a36Sopenharmony_ci * in parallel, can wait.
3762306a36Sopenharmony_ci */
3862306a36Sopenharmony_cistatic DEFINE_MUTEX(hnae3_common_lock);
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_cistatic bool hnae3_client_match(enum hnae3_client_type client_type)
4162306a36Sopenharmony_ci{
4262306a36Sopenharmony_ci	if (client_type == HNAE3_CLIENT_KNIC ||
4362306a36Sopenharmony_ci	    client_type == HNAE3_CLIENT_ROCE)
4462306a36Sopenharmony_ci		return true;
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	return false;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_civoid hnae3_set_client_init_flag(struct hnae3_client *client,
5062306a36Sopenharmony_ci				struct hnae3_ae_dev *ae_dev,
5162306a36Sopenharmony_ci				unsigned int inited)
5262306a36Sopenharmony_ci{
5362306a36Sopenharmony_ci	if (!client || !ae_dev)
5462306a36Sopenharmony_ci		return;
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	switch (client->type) {
5762306a36Sopenharmony_ci	case HNAE3_CLIENT_KNIC:
5862306a36Sopenharmony_ci		hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
5962306a36Sopenharmony_ci		break;
6062306a36Sopenharmony_ci	case HNAE3_CLIENT_ROCE:
6162306a36Sopenharmony_ci		hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited);
6262306a36Sopenharmony_ci		break;
6362306a36Sopenharmony_ci	default:
6462306a36Sopenharmony_ci		break;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci}
6762306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_set_client_init_flag);
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic int hnae3_get_client_init_flag(struct hnae3_client *client,
7062306a36Sopenharmony_ci				      struct hnae3_ae_dev *ae_dev)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	int inited = 0;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	switch (client->type) {
7562306a36Sopenharmony_ci	case HNAE3_CLIENT_KNIC:
7662306a36Sopenharmony_ci		inited = hnae3_get_bit(ae_dev->flag,
7762306a36Sopenharmony_ci				       HNAE3_KNIC_CLIENT_INITED_B);
7862306a36Sopenharmony_ci		break;
7962306a36Sopenharmony_ci	case HNAE3_CLIENT_ROCE:
8062306a36Sopenharmony_ci		inited = hnae3_get_bit(ae_dev->flag,
8162306a36Sopenharmony_ci				       HNAE3_ROCE_CLIENT_INITED_B);
8262306a36Sopenharmony_ci		break;
8362306a36Sopenharmony_ci	default:
8462306a36Sopenharmony_ci		break;
8562306a36Sopenharmony_ci	}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	return inited;
8862306a36Sopenharmony_ci}
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_cistatic int hnae3_init_client_instance(struct hnae3_client *client,
9162306a36Sopenharmony_ci				      struct hnae3_ae_dev *ae_dev)
9262306a36Sopenharmony_ci{
9362306a36Sopenharmony_ci	int ret;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	/* check if this client matches the type of ae_dev */
9662306a36Sopenharmony_ci	if (!(hnae3_client_match(client->type) &&
9762306a36Sopenharmony_ci	      hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
9862306a36Sopenharmony_ci		return 0;
9962306a36Sopenharmony_ci	}
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci	ret = ae_dev->ops->init_client_instance(client, ae_dev);
10262306a36Sopenharmony_ci	if (ret)
10362306a36Sopenharmony_ci		dev_err(&ae_dev->pdev->dev,
10462306a36Sopenharmony_ci			"fail to instantiate client, ret = %d\n", ret);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	return ret;
10762306a36Sopenharmony_ci}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_cistatic void hnae3_uninit_client_instance(struct hnae3_client *client,
11062306a36Sopenharmony_ci					 struct hnae3_ae_dev *ae_dev)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	/* check if this client matches the type of ae_dev */
11362306a36Sopenharmony_ci	if (!(hnae3_client_match(client->type) &&
11462306a36Sopenharmony_ci	      hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)))
11562306a36Sopenharmony_ci		return;
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	if (hnae3_get_client_init_flag(client, ae_dev)) {
11862306a36Sopenharmony_ci		ae_dev->ops->uninit_client_instance(client, ae_dev);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci		hnae3_set_client_init_flag(client, ae_dev, 0);
12162306a36Sopenharmony_ci	}
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ciint hnae3_register_client(struct hnae3_client *client)
12562306a36Sopenharmony_ci{
12662306a36Sopenharmony_ci	struct hnae3_client *client_tmp;
12762306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	if (!client)
13062306a36Sopenharmony_ci		return -ENODEV;
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	mutex_lock(&hnae3_common_lock);
13362306a36Sopenharmony_ci	/* one system should only have one client for every type */
13462306a36Sopenharmony_ci	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
13562306a36Sopenharmony_ci		if (client_tmp->type == client->type)
13662306a36Sopenharmony_ci			goto exit;
13762306a36Sopenharmony_ci	}
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	list_add_tail(&client->node, &hnae3_client_list);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	/* initialize the client on every matched port */
14262306a36Sopenharmony_ci	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
14362306a36Sopenharmony_ci		/* if the client could not be initialized on current port, for
14462306a36Sopenharmony_ci		 * any error reasons, move on to next available port
14562306a36Sopenharmony_ci		 */
14662306a36Sopenharmony_ci		int ret = hnae3_init_client_instance(client, ae_dev);
14762306a36Sopenharmony_ci		if (ret)
14862306a36Sopenharmony_ci			dev_err(&ae_dev->pdev->dev,
14962306a36Sopenharmony_ci				"match and instantiation failed for port, ret = %d\n",
15062306a36Sopenharmony_ci				ret);
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ciexit:
15462306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
15562306a36Sopenharmony_ci
15662306a36Sopenharmony_ci	return 0;
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_register_client);
15962306a36Sopenharmony_ci
16062306a36Sopenharmony_civoid hnae3_unregister_client(struct hnae3_client *client)
16162306a36Sopenharmony_ci{
16262306a36Sopenharmony_ci	struct hnae3_client *client_tmp;
16362306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
16462306a36Sopenharmony_ci	bool existed = false;
16562306a36Sopenharmony_ci
16662306a36Sopenharmony_ci	if (!client)
16762306a36Sopenharmony_ci		return;
16862306a36Sopenharmony_ci
16962306a36Sopenharmony_ci	mutex_lock(&hnae3_common_lock);
17062306a36Sopenharmony_ci	/* one system should only have one client for every type */
17162306a36Sopenharmony_ci	list_for_each_entry(client_tmp, &hnae3_client_list, node) {
17262306a36Sopenharmony_ci		if (client_tmp->type == client->type) {
17362306a36Sopenharmony_ci			existed = true;
17462306a36Sopenharmony_ci			break;
17562306a36Sopenharmony_ci		}
17662306a36Sopenharmony_ci	}
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci	if (!existed) {
17962306a36Sopenharmony_ci		mutex_unlock(&hnae3_common_lock);
18062306a36Sopenharmony_ci		pr_err("client %s does not exist!\n", client->name);
18162306a36Sopenharmony_ci		return;
18262306a36Sopenharmony_ci	}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	/* un-initialize the client on every matched port */
18562306a36Sopenharmony_ci	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
18662306a36Sopenharmony_ci		hnae3_uninit_client_instance(client, ae_dev);
18762306a36Sopenharmony_ci	}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci	list_del(&client->node);
19062306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_unregister_client);
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci/* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
19562306a36Sopenharmony_ci * @ae_algo: AE algorithm
19662306a36Sopenharmony_ci * NOTE: the duplicated name will not be checked
19762306a36Sopenharmony_ci */
19862306a36Sopenharmony_civoid hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
19962306a36Sopenharmony_ci{
20062306a36Sopenharmony_ci	const struct pci_device_id *id;
20162306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
20262306a36Sopenharmony_ci	struct hnae3_client *client;
20362306a36Sopenharmony_ci	int ret;
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_ci	if (!ae_algo)
20662306a36Sopenharmony_ci		return;
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci	mutex_lock(&hnae3_common_lock);
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci	list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	/* Check if this algo/ops matches the list of ae_devs */
21362306a36Sopenharmony_ci	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
21462306a36Sopenharmony_ci		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
21562306a36Sopenharmony_ci		if (!id)
21662306a36Sopenharmony_ci			continue;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci		if (!ae_algo->ops) {
21962306a36Sopenharmony_ci			dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
22062306a36Sopenharmony_ci			continue;
22162306a36Sopenharmony_ci		}
22262306a36Sopenharmony_ci		ae_dev->ops = ae_algo->ops;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci		ret = ae_algo->ops->init_ae_dev(ae_dev);
22562306a36Sopenharmony_ci		if (ret) {
22662306a36Sopenharmony_ci			dev_err(&ae_dev->pdev->dev,
22762306a36Sopenharmony_ci				"init ae_dev error, ret = %d\n", ret);
22862306a36Sopenharmony_ci			continue;
22962306a36Sopenharmony_ci		}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci		/* ae_dev init should set flag */
23262306a36Sopenharmony_ci		hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci		/* check the client list for the match with this ae_dev type and
23562306a36Sopenharmony_ci		 * initialize the figure out client instance
23662306a36Sopenharmony_ci		 */
23762306a36Sopenharmony_ci		list_for_each_entry(client, &hnae3_client_list, node) {
23862306a36Sopenharmony_ci			ret = hnae3_init_client_instance(client, ae_dev);
23962306a36Sopenharmony_ci			if (ret)
24062306a36Sopenharmony_ci				dev_err(&ae_dev->pdev->dev,
24162306a36Sopenharmony_ci					"match and instantiation failed, ret = %d\n",
24262306a36Sopenharmony_ci					ret);
24362306a36Sopenharmony_ci		}
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
24762306a36Sopenharmony_ci}
24862306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_register_ae_algo);
24962306a36Sopenharmony_ci
25062306a36Sopenharmony_ci/* hnae3_unregister_ae_algo - unregisters a AE algorithm
25162306a36Sopenharmony_ci * @ae_algo: the AE algorithm to unregister
25262306a36Sopenharmony_ci */
25362306a36Sopenharmony_civoid hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
25462306a36Sopenharmony_ci{
25562306a36Sopenharmony_ci	const struct pci_device_id *id;
25662306a36Sopenharmony_ci	struct hnae3_ae_dev *ae_dev;
25762306a36Sopenharmony_ci	struct hnae3_client *client;
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	if (!ae_algo)
26062306a36Sopenharmony_ci		return;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	mutex_lock(&hnae3_common_lock);
26362306a36Sopenharmony_ci	/* Check if there are matched ae_dev */
26462306a36Sopenharmony_ci	list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
26562306a36Sopenharmony_ci		if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
26662306a36Sopenharmony_ci			continue;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
26962306a36Sopenharmony_ci		if (!id)
27062306a36Sopenharmony_ci			continue;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci		/* check the client list for the match with this ae_dev type and
27362306a36Sopenharmony_ci		 * un-initialize the figure out client instance
27462306a36Sopenharmony_ci		 */
27562306a36Sopenharmony_ci		list_for_each_entry(client, &hnae3_client_list, node)
27662306a36Sopenharmony_ci			hnae3_uninit_client_instance(client, ae_dev);
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci		ae_algo->ops->uninit_ae_dev(ae_dev);
27962306a36Sopenharmony_ci		hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
28062306a36Sopenharmony_ci		ae_dev->ops = NULL;
28162306a36Sopenharmony_ci	}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_ci	list_del(&ae_algo->node);
28462306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
28562306a36Sopenharmony_ci}
28662306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_unregister_ae_algo);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci/* hnae3_register_ae_dev - registers a AE device to hnae3 framework
28962306a36Sopenharmony_ci * @ae_dev: the AE device
29062306a36Sopenharmony_ci * NOTE: the duplicated name will not be checked
29162306a36Sopenharmony_ci */
29262306a36Sopenharmony_ciint hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
29362306a36Sopenharmony_ci{
29462306a36Sopenharmony_ci	const struct pci_device_id *id;
29562306a36Sopenharmony_ci	struct hnae3_ae_algo *ae_algo;
29662306a36Sopenharmony_ci	struct hnae3_client *client;
29762306a36Sopenharmony_ci	int ret;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	if (!ae_dev)
30062306a36Sopenharmony_ci		return -ENODEV;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	mutex_lock(&hnae3_common_lock);
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci	list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	/* Check if there are matched ae_algo */
30762306a36Sopenharmony_ci	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
30862306a36Sopenharmony_ci		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
30962306a36Sopenharmony_ci		if (!id)
31062306a36Sopenharmony_ci			continue;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		if (!ae_algo->ops) {
31362306a36Sopenharmony_ci			dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
31462306a36Sopenharmony_ci			ret = -EOPNOTSUPP;
31562306a36Sopenharmony_ci			goto out_err;
31662306a36Sopenharmony_ci		}
31762306a36Sopenharmony_ci		ae_dev->ops = ae_algo->ops;
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci		ret = ae_dev->ops->init_ae_dev(ae_dev);
32062306a36Sopenharmony_ci		if (ret) {
32162306a36Sopenharmony_ci			dev_err(&ae_dev->pdev->dev,
32262306a36Sopenharmony_ci				"init ae_dev error, ret = %d\n", ret);
32362306a36Sopenharmony_ci			goto out_err;
32462306a36Sopenharmony_ci		}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci		/* ae_dev init should set flag */
32762306a36Sopenharmony_ci		hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
32862306a36Sopenharmony_ci		break;
32962306a36Sopenharmony_ci	}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* check the client list for the match with this ae_dev type and
33262306a36Sopenharmony_ci	 * initialize the figure out client instance
33362306a36Sopenharmony_ci	 */
33462306a36Sopenharmony_ci	list_for_each_entry(client, &hnae3_client_list, node) {
33562306a36Sopenharmony_ci		ret = hnae3_init_client_instance(client, ae_dev);
33662306a36Sopenharmony_ci		if (ret)
33762306a36Sopenharmony_ci			dev_err(&ae_dev->pdev->dev,
33862306a36Sopenharmony_ci				"match and instantiation failed, ret = %d\n",
33962306a36Sopenharmony_ci				ret);
34062306a36Sopenharmony_ci	}
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci	return 0;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ciout_err:
34762306a36Sopenharmony_ci	list_del(&ae_dev->node);
34862306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	return ret;
35162306a36Sopenharmony_ci}
35262306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_register_ae_dev);
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci/* hnae3_unregister_ae_dev - unregisters a AE device
35562306a36Sopenharmony_ci * @ae_dev: the AE device to unregister
35662306a36Sopenharmony_ci */
35762306a36Sopenharmony_civoid hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	const struct pci_device_id *id;
36062306a36Sopenharmony_ci	struct hnae3_ae_algo *ae_algo;
36162306a36Sopenharmony_ci	struct hnae3_client *client;
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_ci	if (!ae_dev)
36462306a36Sopenharmony_ci		return;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	mutex_lock(&hnae3_common_lock);
36762306a36Sopenharmony_ci	/* Check if there are matched ae_algo */
36862306a36Sopenharmony_ci	list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
36962306a36Sopenharmony_ci		if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
37062306a36Sopenharmony_ci			continue;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci		id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
37362306a36Sopenharmony_ci		if (!id)
37462306a36Sopenharmony_ci			continue;
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci		list_for_each_entry(client, &hnae3_client_list, node)
37762306a36Sopenharmony_ci			hnae3_uninit_client_instance(client, ae_dev);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci		ae_algo->ops->uninit_ae_dev(ae_dev);
38062306a36Sopenharmony_ci		hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
38162306a36Sopenharmony_ci		ae_dev->ops = NULL;
38262306a36Sopenharmony_ci	}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	list_del(&ae_dev->node);
38562306a36Sopenharmony_ci	mutex_unlock(&hnae3_common_lock);
38662306a36Sopenharmony_ci}
38762306a36Sopenharmony_ciEXPORT_SYMBOL(hnae3_unregister_ae_dev);
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ciMODULE_AUTHOR("Huawei Tech. Co., Ltd.");
39062306a36Sopenharmony_ciMODULE_LICENSE("GPL");
39162306a36Sopenharmony_ciMODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
39262306a36Sopenharmony_ciMODULE_VERSION(HNAE3_MOD_VERSION);
393