File Index
Files and directories
Sign in
FILE

hnae3.c

File preview with syntax highlighting.

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