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