brintos

brintos / linux-shallow public Read only

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