GNU Linux-libre 4.19.245-gnu1
[releases.git] / drivers / net / ethernet / hisilicon / hns3 / hnae3.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
9 static LIST_HEAD(hnae3_ae_algo_list);
10 static LIST_HEAD(hnae3_client_list);
11 static LIST_HEAD(hnae3_ae_dev_list);
12
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                         pci_disable_sriov(ae_dev->pdev);
30         }
31 }
32 EXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare);
33
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  */
38 static DEFINE_MUTEX(hnae3_common_lock);
39
40 static bool hnae3_client_match(enum hnae3_client_type client_type,
41                                enum hnae3_dev_type dev_type)
42 {
43         if ((dev_type == HNAE3_DEV_KNIC) && (client_type == HNAE3_CLIENT_KNIC ||
44                                              client_type == HNAE3_CLIENT_ROCE))
45                 return true;
46
47         if (dev_type == HNAE3_DEV_UNIC && client_type == HNAE3_CLIENT_UNIC)
48                 return true;
49
50         return false;
51 }
52
53 void hnae3_set_client_init_flag(struct hnae3_client *client,
54                                 struct hnae3_ae_dev *ae_dev, int inited)
55 {
56         switch (client->type) {
57         case HNAE3_CLIENT_KNIC:
58                 hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
59                 break;
60         case HNAE3_CLIENT_UNIC:
61                 hnae3_set_bit(ae_dev->flag, HNAE3_UNIC_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 }
70 EXPORT_SYMBOL(hnae3_set_client_init_flag);
71
72 static 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_UNIC:
83                 inited = hnae3_get_bit(ae_dev->flag,
84                                        HNAE3_UNIC_CLIENT_INITED_B);
85                 break;
86         case HNAE3_CLIENT_ROCE:
87                 inited = hnae3_get_bit(ae_dev->flag,
88                                        HNAE3_ROCE_CLIENT_INITED_B);
89                 break;
90         default:
91                 break;
92         }
93
94         return inited;
95 }
96
97 static int hnae3_match_n_instantiate(struct hnae3_client *client,
98                                      struct hnae3_ae_dev *ae_dev, bool is_reg)
99 {
100         int ret;
101
102         /* check if this client matches the type of ae_dev */
103         if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
104               hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
105                 return 0;
106         }
107
108         /* now, (un-)instantiate client by calling lower layer */
109         if (is_reg) {
110                 ret = ae_dev->ops->init_client_instance(client, ae_dev);
111                 if (ret)
112                         dev_err(&ae_dev->pdev->dev,
113                                 "fail to instantiate client, ret = %d\n", ret);
114
115                 return ret;
116         }
117
118         if (hnae3_get_client_init_flag(client, ae_dev)) {
119                 ae_dev->ops->uninit_client_instance(client, ae_dev);
120
121                 hnae3_set_client_init_flag(client, ae_dev, 0);
122         }
123
124         return 0;
125 }
126
127 int hnae3_register_client(struct hnae3_client *client)
128 {
129         struct hnae3_client *client_tmp;
130         struct hnae3_ae_dev *ae_dev;
131         int ret = 0;
132
133         mutex_lock(&hnae3_common_lock);
134         /* one system should only have one client for every type */
135         list_for_each_entry(client_tmp, &hnae3_client_list, node) {
136                 if (client_tmp->type == client->type)
137                         goto exit;
138         }
139
140         list_add_tail(&client->node, &hnae3_client_list);
141
142         /* initialize the client on every matched port */
143         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
144                 /* if the client could not be initialized on current port, for
145                  * any error reasons, move on to next available port
146                  */
147                 ret = hnae3_match_n_instantiate(client, ae_dev, true);
148                 if (ret)
149                         dev_err(&ae_dev->pdev->dev,
150                                 "match and instantiation failed for port, ret = %d\n",
151                                 ret);
152         }
153
154 exit:
155         mutex_unlock(&hnae3_common_lock);
156
157         return 0;
158 }
159 EXPORT_SYMBOL(hnae3_register_client);
160
161 void hnae3_unregister_client(struct hnae3_client *client)
162 {
163         struct hnae3_ae_dev *ae_dev;
164
165         mutex_lock(&hnae3_common_lock);
166         /* un-initialize the client on every matched port */
167         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
168                 hnae3_match_n_instantiate(client, ae_dev, false);
169         }
170
171         list_del(&client->node);
172         mutex_unlock(&hnae3_common_lock);
173 }
174 EXPORT_SYMBOL(hnae3_unregister_client);
175
176 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
177  * @ae_algo: AE algorithm
178  * NOTE: the duplicated name will not be checked
179  */
180 void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
181 {
182         const struct pci_device_id *id;
183         struct hnae3_ae_dev *ae_dev;
184         struct hnae3_client *client;
185         int ret = 0;
186
187         mutex_lock(&hnae3_common_lock);
188
189         list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
190
191         /* Check if this algo/ops matches the list of ae_devs */
192         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
193                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
194                 if (!id)
195                         continue;
196
197                 if (!ae_algo->ops) {
198                         dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
199                         continue;
200                 }
201                 ae_dev->ops = ae_algo->ops;
202
203                 ret = ae_algo->ops->init_ae_dev(ae_dev);
204                 if (ret) {
205                         dev_err(&ae_dev->pdev->dev,
206                                 "init ae_dev error, ret = %d\n", ret);
207                         continue;
208                 }
209
210                 /* ae_dev init should set flag */
211                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
212
213                 /* check the client list for the match with this ae_dev type and
214                  * initialize the figure out client instance
215                  */
216                 list_for_each_entry(client, &hnae3_client_list, node) {
217                         ret = hnae3_match_n_instantiate(client, ae_dev, true);
218                         if (ret)
219                                 dev_err(&ae_dev->pdev->dev,
220                                         "match and instantiation failed, ret = %d\n",
221                                         ret);
222                 }
223         }
224
225         mutex_unlock(&hnae3_common_lock);
226 }
227 EXPORT_SYMBOL(hnae3_register_ae_algo);
228
229 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
230  * @ae_algo: the AE algorithm to unregister
231  */
232 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
233 {
234         const struct pci_device_id *id;
235         struct hnae3_ae_dev *ae_dev;
236         struct hnae3_client *client;
237
238         mutex_lock(&hnae3_common_lock);
239         /* Check if there are matched ae_dev */
240         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
241                 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
242                         continue;
243
244                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
245                 if (!id)
246                         continue;
247
248                 /* check the client list for the match with this ae_dev type and
249                  * un-initialize the figure out client instance
250                  */
251                 list_for_each_entry(client, &hnae3_client_list, node)
252                         hnae3_match_n_instantiate(client, ae_dev, false);
253
254                 ae_algo->ops->uninit_ae_dev(ae_dev);
255                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
256                 ae_dev->ops = NULL;
257         }
258
259         list_del(&ae_algo->node);
260         mutex_unlock(&hnae3_common_lock);
261 }
262 EXPORT_SYMBOL(hnae3_unregister_ae_algo);
263
264 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
265  * @ae_dev: the AE device
266  * NOTE: the duplicated name will not be checked
267  */
268 int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
269 {
270         const struct pci_device_id *id;
271         struct hnae3_ae_algo *ae_algo;
272         struct hnae3_client *client;
273         int ret = 0;
274
275         mutex_lock(&hnae3_common_lock);
276
277         list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
278
279         /* Check if there are matched ae_algo */
280         list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
281                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
282                 if (!id)
283                         continue;
284
285                 if (!ae_algo->ops) {
286                         dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
287                         ret = -EOPNOTSUPP;
288                         goto out_err;
289                 }
290                 ae_dev->ops = ae_algo->ops;
291
292                 ret = ae_dev->ops->init_ae_dev(ae_dev);
293                 if (ret) {
294                         dev_err(&ae_dev->pdev->dev,
295                                 "init ae_dev error, ret = %d\n", ret);
296                         goto out_err;
297                 }
298
299                 /* ae_dev init should set flag */
300                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
301                 break;
302         }
303
304         /* check the client list for the match with this ae_dev type and
305          * initialize the figure out client instance
306          */
307         list_for_each_entry(client, &hnae3_client_list, node) {
308                 ret = hnae3_match_n_instantiate(client, ae_dev, true);
309                 if (ret)
310                         dev_err(&ae_dev->pdev->dev,
311                                 "match and instantiation failed, ret = %d\n",
312                                 ret);
313         }
314
315         mutex_unlock(&hnae3_common_lock);
316
317         return 0;
318
319 out_err:
320         list_del(&ae_dev->node);
321         mutex_unlock(&hnae3_common_lock);
322
323         return ret;
324 }
325 EXPORT_SYMBOL(hnae3_register_ae_dev);
326
327 /* hnae3_unregister_ae_dev - unregisters a AE device
328  * @ae_dev: the AE device to unregister
329  */
330 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
331 {
332         const struct pci_device_id *id;
333         struct hnae3_ae_algo *ae_algo;
334         struct hnae3_client *client;
335
336         mutex_lock(&hnae3_common_lock);
337         /* Check if there are matched ae_algo */
338         list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
339                 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
340                         continue;
341
342                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
343                 if (!id)
344                         continue;
345
346                 list_for_each_entry(client, &hnae3_client_list, node)
347                         hnae3_match_n_instantiate(client, ae_dev, false);
348
349                 ae_algo->ops->uninit_ae_dev(ae_dev);
350                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
351                 ae_dev->ops = NULL;
352         }
353
354         list_del(&ae_dev->node);
355         mutex_unlock(&hnae3_common_lock);
356 }
357 EXPORT_SYMBOL(hnae3_unregister_ae_dev);
358
359 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
360 MODULE_LICENSE("GPL");
361 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
362 MODULE_VERSION(HNAE3_MOD_VERSION);