xref: /linux/drivers/net/ethernet/hisilicon/hns3/hnae3.c (revision c2933b2befe25309f4c5cfbea0ca80909735fd76)
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 
9 static LIST_HEAD(hnae3_ae_algo_list);
10 static LIST_HEAD(hnae3_client_list);
11 static LIST_HEAD(hnae3_ae_dev_list);
12 
hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo * ae_algo)13 void 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 }
35 EXPORT_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  */
41 static DEFINE_MUTEX(hnae3_common_lock);
42 
43 /* ensure the drivers being unloaded one by one */
44 static DEFINE_MUTEX(hnae3_unload_lock);
45 
hnae3_acquire_unload_lock(void)46 void hnae3_acquire_unload_lock(void)
47 {
48 	mutex_lock(&hnae3_unload_lock);
49 }
50 EXPORT_SYMBOL(hnae3_acquire_unload_lock);
51 
hnae3_release_unload_lock(void)52 void hnae3_release_unload_lock(void)
53 {
54 	mutex_unlock(&hnae3_unload_lock);
55 }
56 EXPORT_SYMBOL(hnae3_release_unload_lock);
57 
hnae3_client_match(enum hnae3_client_type client_type)58 static 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 
hnae3_set_client_init_flag(struct hnae3_client * client,struct hnae3_ae_dev * ae_dev,unsigned int inited)67 void 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 }
85 EXPORT_SYMBOL(hnae3_set_client_init_flag);
86 
hnae3_get_client_init_flag(struct hnae3_client * client,struct hnae3_ae_dev * ae_dev)87 static 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 
hnae3_init_client_instance(struct hnae3_client * client,struct hnae3_ae_dev * ae_dev)108 static 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 
hnae3_uninit_client_instance(struct hnae3_client * client,struct hnae3_ae_dev * ae_dev)127 static 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 
hnae3_register_client(struct hnae3_client * client)142 int 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 
171 exit:
172 	mutex_unlock(&hnae3_common_lock);
173 
174 	return 0;
175 }
176 EXPORT_SYMBOL(hnae3_register_client);
177 
hnae3_unregister_client(struct hnae3_client * client)178 void 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 }
210 EXPORT_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  */
hnae3_register_ae_algo(struct hnae3_ae_algo * ae_algo)216 void 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 }
266 EXPORT_SYMBOL(hnae3_register_ae_algo);
267 
268 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
269  * @ae_algo: the AE algorithm to unregister
270  */
hnae3_unregister_ae_algo(struct hnae3_ae_algo * ae_algo)271 void 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 }
304 EXPORT_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  */
hnae3_register_ae_dev(struct hnae3_ae_dev * ae_dev)310 int 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 
364 out_err:
365 	list_del(&ae_dev->node);
366 	mutex_unlock(&hnae3_common_lock);
367 
368 	return ret;
369 }
370 EXPORT_SYMBOL(hnae3_register_ae_dev);
371 
372 /* hnae3_unregister_ae_dev - unregisters a AE device
373  * @ae_dev: the AE device to unregister
374  */
hnae3_unregister_ae_dev(struct hnae3_ae_dev * ae_dev)375 void 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 }
405 EXPORT_SYMBOL(hnae3_unregister_ae_dev);
406 
407 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
408 MODULE_LICENSE("GPL");
409 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
410 MODULE_VERSION(HNAE3_MOD_VERSION);
411