net: hns3: Add get_media_type ops support for VF
[linux-2.6-microblaze.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 /* we are keeping things simple and using single lock for all the
14  * list. This is a non-critical code so other updations, if happen
15  * in parallel, can wait.
16  */
17 static DEFINE_MUTEX(hnae3_common_lock);
18
19 static bool hnae3_client_match(enum hnae3_client_type client_type,
20                                enum hnae3_dev_type dev_type)
21 {
22         if ((dev_type == HNAE3_DEV_KNIC) && (client_type == HNAE3_CLIENT_KNIC ||
23                                              client_type == HNAE3_CLIENT_ROCE))
24                 return true;
25
26         if (dev_type == HNAE3_DEV_UNIC && client_type == HNAE3_CLIENT_UNIC)
27                 return true;
28
29         return false;
30 }
31
32 void hnae3_set_client_init_flag(struct hnae3_client *client,
33                                 struct hnae3_ae_dev *ae_dev, int inited)
34 {
35         switch (client->type) {
36         case HNAE3_CLIENT_KNIC:
37                 hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
38                 break;
39         case HNAE3_CLIENT_UNIC:
40                 hnae3_set_bit(ae_dev->flag, HNAE3_UNIC_CLIENT_INITED_B, inited);
41                 break;
42         case HNAE3_CLIENT_ROCE:
43                 hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited);
44                 break;
45         default:
46                 break;
47         }
48 }
49 EXPORT_SYMBOL(hnae3_set_client_init_flag);
50
51 static int hnae3_get_client_init_flag(struct hnae3_client *client,
52                                        struct hnae3_ae_dev *ae_dev)
53 {
54         int inited = 0;
55
56         switch (client->type) {
57         case HNAE3_CLIENT_KNIC:
58                 inited = hnae3_get_bit(ae_dev->flag,
59                                        HNAE3_KNIC_CLIENT_INITED_B);
60                 break;
61         case HNAE3_CLIENT_UNIC:
62                 inited = hnae3_get_bit(ae_dev->flag,
63                                        HNAE3_UNIC_CLIENT_INITED_B);
64                 break;
65         case HNAE3_CLIENT_ROCE:
66                 inited = hnae3_get_bit(ae_dev->flag,
67                                        HNAE3_ROCE_CLIENT_INITED_B);
68                 break;
69         default:
70                 break;
71         }
72
73         return inited;
74 }
75
76 static int hnae3_match_n_instantiate(struct hnae3_client *client,
77                                      struct hnae3_ae_dev *ae_dev, bool is_reg)
78 {
79         int ret;
80
81         /* check if this client matches the type of ae_dev */
82         if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
83               hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
84                 return 0;
85         }
86
87         /* now, (un-)instantiate client by calling lower layer */
88         if (is_reg) {
89                 ret = ae_dev->ops->init_client_instance(client, ae_dev);
90                 if (ret)
91                         dev_err(&ae_dev->pdev->dev,
92                                 "fail to instantiate client, ret = %d\n", ret);
93
94                 return ret;
95         }
96
97         if (hnae3_get_client_init_flag(client, ae_dev)) {
98                 ae_dev->ops->uninit_client_instance(client, ae_dev);
99
100                 hnae3_set_client_init_flag(client, ae_dev, 0);
101         }
102
103         return 0;
104 }
105
106 int hnae3_register_client(struct hnae3_client *client)
107 {
108         struct hnae3_client *client_tmp;
109         struct hnae3_ae_dev *ae_dev;
110         int ret = 0;
111
112         mutex_lock(&hnae3_common_lock);
113         /* one system should only have one client for every type */
114         list_for_each_entry(client_tmp, &hnae3_client_list, node) {
115                 if (client_tmp->type == client->type)
116                         goto exit;
117         }
118
119         list_add_tail(&client->node, &hnae3_client_list);
120
121         /* initialize the client on every matched port */
122         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
123                 /* if the client could not be initialized on current port, for
124                  * any error reasons, move on to next available port
125                  */
126                 ret = hnae3_match_n_instantiate(client, ae_dev, true);
127                 if (ret)
128                         dev_err(&ae_dev->pdev->dev,
129                                 "match and instantiation failed for port, ret = %d\n",
130                                 ret);
131         }
132
133 exit:
134         mutex_unlock(&hnae3_common_lock);
135
136         return 0;
137 }
138 EXPORT_SYMBOL(hnae3_register_client);
139
140 void hnae3_unregister_client(struct hnae3_client *client)
141 {
142         struct hnae3_ae_dev *ae_dev;
143
144         mutex_lock(&hnae3_common_lock);
145         /* un-initialize the client on every matched port */
146         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
147                 hnae3_match_n_instantiate(client, ae_dev, false);
148         }
149
150         list_del(&client->node);
151         mutex_unlock(&hnae3_common_lock);
152 }
153 EXPORT_SYMBOL(hnae3_unregister_client);
154
155 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
156  * @ae_algo: AE algorithm
157  * NOTE: the duplicated name will not be checked
158  */
159 void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
160 {
161         const struct pci_device_id *id;
162         struct hnae3_ae_dev *ae_dev;
163         struct hnae3_client *client;
164         int ret = 0;
165
166         mutex_lock(&hnae3_common_lock);
167
168         list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
169
170         /* Check if this algo/ops matches the list of ae_devs */
171         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
172                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
173                 if (!id)
174                         continue;
175
176                 /* ae_dev init should set flag */
177                 ae_dev->ops = ae_algo->ops;
178                 ret = ae_algo->ops->init_ae_dev(ae_dev);
179                 if (ret) {
180                         dev_err(&ae_dev->pdev->dev,
181                                 "init ae_dev error, ret = %d\n", ret);
182                         continue;
183                 }
184
185                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
186
187                 /* check the client list for the match with this ae_dev type and
188                  * initialize the figure out client instance
189                  */
190                 list_for_each_entry(client, &hnae3_client_list, node) {
191                         ret = hnae3_match_n_instantiate(client, ae_dev, true);
192                         if (ret)
193                                 dev_err(&ae_dev->pdev->dev,
194                                         "match and instantiation failed, ret = %d\n",
195                                         ret);
196                 }
197         }
198
199         mutex_unlock(&hnae3_common_lock);
200 }
201 EXPORT_SYMBOL(hnae3_register_ae_algo);
202
203 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
204  * @ae_algo: the AE algorithm to unregister
205  */
206 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
207 {
208         const struct pci_device_id *id;
209         struct hnae3_ae_dev *ae_dev;
210         struct hnae3_client *client;
211
212         mutex_lock(&hnae3_common_lock);
213         /* Check if there are matched ae_dev */
214         list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
215                 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
216                         continue;
217
218                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
219                 if (!id)
220                         continue;
221
222                 /* check the client list for the match with this ae_dev type and
223                  * un-initialize the figure out client instance
224                  */
225                 list_for_each_entry(client, &hnae3_client_list, node)
226                         hnae3_match_n_instantiate(client, ae_dev, false);
227
228                 ae_algo->ops->uninit_ae_dev(ae_dev);
229                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
230         }
231
232         list_del(&ae_algo->node);
233         mutex_unlock(&hnae3_common_lock);
234 }
235 EXPORT_SYMBOL(hnae3_unregister_ae_algo);
236
237 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
238  * @ae_dev: the AE device
239  * NOTE: the duplicated name will not be checked
240  */
241 void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
242 {
243         const struct pci_device_id *id;
244         struct hnae3_ae_algo *ae_algo;
245         struct hnae3_client *client;
246         int ret = 0;
247
248         mutex_lock(&hnae3_common_lock);
249
250         list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
251
252         /* Check if there are matched ae_algo */
253         list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
254                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
255                 if (!id)
256                         continue;
257
258                 ae_dev->ops = ae_algo->ops;
259
260                 if (!ae_dev->ops) {
261                         dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
262                         goto out_err;
263                 }
264
265                 /* ae_dev init should set flag */
266                 ret = ae_dev->ops->init_ae_dev(ae_dev);
267                 if (ret) {
268                         dev_err(&ae_dev->pdev->dev,
269                                 "init ae_dev error, ret = %d\n", ret);
270                         goto out_err;
271                 }
272
273                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
274                 break;
275         }
276
277         /* check the client list for the match with this ae_dev type and
278          * initialize the figure out client instance
279          */
280         list_for_each_entry(client, &hnae3_client_list, node) {
281                 ret = hnae3_match_n_instantiate(client, ae_dev, true);
282                 if (ret)
283                         dev_err(&ae_dev->pdev->dev,
284                                 "match and instantiation failed, ret = %d\n",
285                                 ret);
286         }
287
288 out_err:
289         mutex_unlock(&hnae3_common_lock);
290 }
291 EXPORT_SYMBOL(hnae3_register_ae_dev);
292
293 /* hnae3_unregister_ae_dev - unregisters a AE device
294  * @ae_dev: the AE device to unregister
295  */
296 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
297 {
298         const struct pci_device_id *id;
299         struct hnae3_ae_algo *ae_algo;
300         struct hnae3_client *client;
301
302         mutex_lock(&hnae3_common_lock);
303         /* Check if there are matched ae_algo */
304         list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
305                 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
306                         continue;
307
308                 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
309                 if (!id)
310                         continue;
311
312                 list_for_each_entry(client, &hnae3_client_list, node)
313                         hnae3_match_n_instantiate(client, ae_dev, false);
314
315                 ae_algo->ops->uninit_ae_dev(ae_dev);
316                 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
317         }
318
319         list_del(&ae_dev->node);
320         mutex_unlock(&hnae3_common_lock);
321 }
322 EXPORT_SYMBOL(hnae3_unregister_ae_dev);
323
324 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
325 MODULE_LICENSE("GPL");
326 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
327 MODULE_VERSION(HNAE3_MOD_VERSION);