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