]> git.proxmox.com Git - mirror_ubuntu-kernels.git/blame - drivers/net/ethernet/hisilicon/hns3/hnae3.c
Merge tag 'for-5.16/block-2021-10-29' of git://git.kernel.dk/linux-block
[mirror_ubuntu-kernels.git] / drivers / net / ethernet / hisilicon / hns3 / hnae3.c
CommitLineData
d71d8381
JS
1// SPDX-License-Identifier: GPL-2.0+
2// Copyright (c) 2016-2017 Hisilicon Limited.
38caee9d
S
3
4#include <linux/list.h>
38caee9d
S
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
0dd8a25f
PL
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
38caee9d
S
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
b69c9737 40static bool hnae3_client_match(enum hnae3_client_type client_type)
38caee9d 41{
b69c9737
YL
42 if (client_type == HNAE3_CLIENT_KNIC ||
43 client_type == HNAE3_CLIENT_ROCE)
38caee9d
S
44 return true;
45
46 return false;
47}
48
d9f28fc2 49void hnae3_set_client_init_flag(struct hnae3_client *client,
ebaf1908
WL
50 struct hnae3_ae_dev *ae_dev,
51 unsigned int inited)
90b99b09 52{
bdd59d66
YL
53 if (!client || !ae_dev)
54 return;
55
90b99b09
PL
56 switch (client->type) {
57 case HNAE3_CLIENT_KNIC:
e4e87715 58 hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
90b99b09 59 break;
90b99b09 60 case HNAE3_CLIENT_ROCE:
e4e87715 61 hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited);
90b99b09
PL
62 break;
63 default:
64 break;
65 }
66}
d9f28fc2 67EXPORT_SYMBOL(hnae3_set_client_init_flag);
90b99b09
PL
68
69static int hnae3_get_client_init_flag(struct hnae3_client *client,
37417c66 70 struct hnae3_ae_dev *ae_dev)
90b99b09
PL
71{
72 int inited = 0;
73
74 switch (client->type) {
75 case HNAE3_CLIENT_KNIC:
e4e87715 76 inited = hnae3_get_bit(ae_dev->flag,
90b99b09
PL
77 HNAE3_KNIC_CLIENT_INITED_B);
78 break;
90b99b09 79 case HNAE3_CLIENT_ROCE:
e4e87715
PL
80 inited = hnae3_get_bit(ae_dev->flag,
81 HNAE3_ROCE_CLIENT_INITED_B);
90b99b09
PL
82 break;
83 default:
84 break;
85 }
86
87 return inited;
88}
89
d223dfa4
JS
90static int hnae3_init_client_instance(struct hnae3_client *client,
91 struct hnae3_ae_dev *ae_dev)
38caee9d
S
92{
93 int ret;
94
38caee9d 95 /* check if this client matches the type of ae_dev */
b69c9737 96 if (!(hnae3_client_match(client->type) &&
e4e87715 97 hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
38caee9d
S
98 return 0;
99 }
38caee9d 100
d223dfa4
JS
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);
e3afa963 105
d223dfa4
JS
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 */
b69c9737 113 if (!(hnae3_client_match(client->type) &&
d223dfa4
JS
114 hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)))
115 return;
e3afa963 116
90b99b09 117 if (hnae3_get_client_init_flag(client, ae_dev)) {
e3afa963
FL
118 ae_dev->ops->uninit_client_instance(client, ae_dev);
119
90b99b09 120 hnae3_set_client_init_flag(client, ae_dev, 0);
38caee9d 121 }
38caee9d
S
122}
123
124int hnae3_register_client(struct hnae3_client *client)
125{
126 struct hnae3_client *client_tmp;
127 struct hnae3_ae_dev *ae_dev;
38caee9d 128
bdd59d66
YL
129 if (!client)
130 return -ENODEV;
131
38caee9d
S
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 */
cdd332ac 146 int ret = hnae3_init_client_instance(client, ae_dev);
38caee9d
S
147 if (ret)
148 dev_err(&ae_dev->pdev->dev,
ccc2bef8
PL
149 "match and instantiation failed for port, ret = %d\n",
150 ret);
38caee9d
S
151 }
152
153exit:
154 mutex_unlock(&hnae3_common_lock);
155
0c698257 156 return 0;
38caee9d
S
157}
158EXPORT_SYMBOL(hnae3_register_client);
159
160void hnae3_unregister_client(struct hnae3_client *client)
161{
b7cf22b7 162 struct hnae3_client *client_tmp;
38caee9d 163 struct hnae3_ae_dev *ae_dev;
b7cf22b7 164 bool existed = false;
38caee9d 165
bdd59d66
YL
166 if (!client)
167 return;
168
38caee9d 169 mutex_lock(&hnae3_common_lock);
9e690456 170 /* one system should only have one client for every type */
b7cf22b7
PL
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
38caee9d
S
184 /* un-initialize the client on every matched port */
185 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
d223dfa4 186 hnae3_uninit_client_instance(client, ae_dev);
38caee9d
S
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 */
854cf33a 198void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
38caee9d
S
199{
200 const struct pci_device_id *id;
201 struct hnae3_ae_dev *ae_dev;
202 struct hnae3_client *client;
cdd332ac 203 int ret;
38caee9d 204
bdd59d66
YL
205 if (!ae_algo)
206 return;
207
38caee9d
S
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
676131f7
YL
218 if (!ae_algo->ops) {
219 dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
220 continue;
221 }
38caee9d 222 ae_dev->ops = ae_algo->ops;
676131f7 223
38caee9d
S
224 ret = ae_algo->ops->init_ae_dev(ae_dev);
225 if (ret) {
ccc2bef8
PL
226 dev_err(&ae_dev->pdev->dev,
227 "init ae_dev error, ret = %d\n", ret);
38caee9d
S
228 continue;
229 }
230
676131f7 231 /* ae_dev init should set flag */
e4e87715 232 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
38caee9d
S
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) {
d223dfa4 238 ret = hnae3_init_client_instance(client, ae_dev);
38caee9d
S
239 if (ret)
240 dev_err(&ae_dev->pdev->dev,
ccc2bef8
PL
241 "match and instantiation failed, ret = %d\n",
242 ret);
38caee9d
S
243 }
244 }
245
246 mutex_unlock(&hnae3_common_lock);
38caee9d
S
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;
38caee9d 258
bdd59d66
YL
259 if (!ae_algo)
260 return;
261
38caee9d
S
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) {
e4e87715 265 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
3e249d3b
FL
266 continue;
267
38caee9d
S
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 */
90f7b11a 275 list_for_each_entry(client, &hnae3_client_list, node)
d223dfa4 276 hnae3_uninit_client_instance(client, ae_dev);
38caee9d
S
277
278 ae_algo->ops->uninit_ae_dev(ae_dev);
e4e87715 279 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
594a81b3 280 ae_dev->ops = NULL;
38caee9d
S
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 */
74354140 292int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
38caee9d
S
293{
294 const struct pci_device_id *id;
295 struct hnae3_ae_algo *ae_algo;
296 struct hnae3_client *client;
cdd332ac 297 int ret;
424eb834 298
bdd59d66
YL
299 if (!ae_dev)
300 return -ENODEV;
301
2312e050 302 mutex_lock(&hnae3_common_lock);
38caee9d 303
38caee9d
S
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
676131f7
YL
312 if (!ae_algo->ops) {
313 dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
74354140 314 ret = -EOPNOTSUPP;
38caee9d
S
315 goto out_err;
316 }
676131f7 317 ae_dev->ops = ae_algo->ops;
38caee9d 318
38caee9d
S
319 ret = ae_dev->ops->init_ae_dev(ae_dev);
320 if (ret) {
ccc2bef8
PL
321 dev_err(&ae_dev->pdev->dev,
322 "init ae_dev error, ret = %d\n", ret);
38caee9d
S
323 goto out_err;
324 }
325
676131f7 326 /* ae_dev init should set flag */
e4e87715 327 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
38caee9d
S
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) {
d223dfa4 335 ret = hnae3_init_client_instance(client, ae_dev);
38caee9d
S
336 if (ret)
337 dev_err(&ae_dev->pdev->dev,
ccc2bef8
PL
338 "match and instantiation failed, ret = %d\n",
339 ret);
38caee9d
S
340 }
341
74354140
HT
342 mutex_unlock(&hnae3_common_lock);
343
344 return 0;
345
38caee9d 346out_err:
74354140 347 list_del(&ae_dev->node);
38caee9d 348 mutex_unlock(&hnae3_common_lock);
74354140
HT
349
350 return ret;
38caee9d
S
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;
38caee9d 362
bdd59d66
YL
363 if (!ae_dev)
364 return;
365
38caee9d
S
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) {
e4e87715 369 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
3e249d3b
FL
370 continue;
371
38caee9d
S
372 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
373 if (!id)
374 continue;
375
90f7b11a 376 list_for_each_entry(client, &hnae3_client_list, node)
d223dfa4 377 hnae3_uninit_client_instance(client, ae_dev);
38caee9d
S
378
379 ae_algo->ops->uninit_ae_dev(ae_dev);
e4e87715 380 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
594a81b3 381 ae_dev->ops = NULL;
38caee9d
S
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");
3c7624d8 392MODULE_VERSION(HNAE3_MOD_VERSION);