]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - drivers/net/ethernet/hisilicon/hns3/hnae3.c
UBUNTU: SAUCE: {topost} net: hns3: extraction an interface for state state init|uninit
[mirror_ubuntu-bionic-kernel.git] / drivers / net / ethernet / hisilicon / hns3 / hnae3.c
CommitLineData
38caee9d
S
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>
38caee9d
S
11#include <linux/spinlock.h>
12
13#include "hnae3.h"
14
15static LIST_HEAD(hnae3_ae_algo_list);
16static LIST_HEAD(hnae3_client_list);
17static 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 */
23static DEFINE_MUTEX(hnae3_common_lock);
24
25static 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
b46e2efa
PL
38static 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
56static 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
38caee9d 81static int hnae3_match_n_instantiate(struct hnae3_client *client,
90f7b11a 82 struct hnae3_ae_dev *ae_dev, bool is_reg)
38caee9d
S
83{
84 int ret;
85
38caee9d
S
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 }
38caee9d
S
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);
90400e41 95 if (ret) {
38caee9d
S
96 dev_err(&ae_dev->pdev->dev,
97 "fail to instantiate client\n");
90400e41
FL
98 return ret;
99 }
100
b46e2efa 101 hnae3_set_client_init_flag(client, ae_dev, 1);
90400e41
FL
102 return 0;
103 }
104
b46e2efa 105 if (hnae3_get_client_init_flag(client, ae_dev)) {
90400e41
FL
106 ae_dev->ops->uninit_client_instance(client, ae_dev);
107
b46e2efa 108 hnae3_set_client_init_flag(client, ae_dev, 0);
38caee9d
S
109 }
110
38caee9d
S
111 return 0;
112}
113
114int hnae3_register_client(struct hnae3_client *client)
115{
116 struct hnae3_client *client_tmp;
117 struct hnae3_ae_dev *ae_dev;
38caee9d
S
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 */
90f7b11a 134 ret = hnae3_match_n_instantiate(client, ae_dev, true);
38caee9d
S
135 if (ret)
136 dev_err(&ae_dev->pdev->dev,
137 "match and instantiation failed for port\n");
138 }
139
140exit:
141 mutex_unlock(&hnae3_common_lock);
142
e57c1f76 143 return 0;
38caee9d
S
144}
145EXPORT_SYMBOL(hnae3_register_client);
146
147void hnae3_unregister_client(struct hnae3_client *client)
148{
149 struct hnae3_ae_dev *ae_dev;
38caee9d
S
150
151 mutex_lock(&hnae3_common_lock);
152 /* un-initialize the client on every matched port */
153 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
90f7b11a 154 hnae3_match_n_instantiate(client, ae_dev, false);
38caee9d
S
155 }
156
157 list_del(&client->node);
158 mutex_unlock(&hnae3_common_lock);
159}
160EXPORT_SYMBOL(hnae3_unregister_client);
161
162/* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
163 * @ae_algo: AE algorithm
164 * NOTE: the duplicated name will not be checked
165 */
a4d090cc 166void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
38caee9d
S
167{
168 const struct pci_device_id *id;
169 struct hnae3_ae_dev *ae_dev;
170 struct hnae3_client *client;
38caee9d
S
171 int ret = 0;
172
173 mutex_lock(&hnae3_common_lock);
174
175 list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
176
177 /* Check if this algo/ops matches the list of ae_devs */
178 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
179 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
180 if (!id)
181 continue;
182
183 /* ae_dev init should set flag */
184 ae_dev->ops = ae_algo->ops;
185 ret = ae_algo->ops->init_ae_dev(ae_dev);
186 if (ret) {
187 dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
188 continue;
189 }
190
191 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
192
193 /* check the client list for the match with this ae_dev type and
194 * initialize the figure out client instance
195 */
196 list_for_each_entry(client, &hnae3_client_list, node) {
90f7b11a 197 ret = hnae3_match_n_instantiate(client, ae_dev, true);
38caee9d
S
198 if (ret)
199 dev_err(&ae_dev->pdev->dev,
200 "match and instantiation failed\n");
38caee9d
S
201 }
202 }
203
204 mutex_unlock(&hnae3_common_lock);
38caee9d
S
205}
206EXPORT_SYMBOL(hnae3_register_ae_algo);
207
208/* hnae3_unregister_ae_algo - unregisters a AE algorithm
209 * @ae_algo: the AE algorithm to unregister
210 */
211void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
212{
213 const struct pci_device_id *id;
214 struct hnae3_ae_dev *ae_dev;
215 struct hnae3_client *client;
38caee9d
S
216
217 mutex_lock(&hnae3_common_lock);
218 /* Check if there are matched ae_dev */
219 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
6c46284e
FL
220 if (!hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
221 continue;
222
38caee9d
S
223 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
224 if (!id)
225 continue;
226
227 /* check the client list for the match with this ae_dev type and
228 * un-initialize the figure out client instance
229 */
90f7b11a
L
230 list_for_each_entry(client, &hnae3_client_list, node)
231 hnae3_match_n_instantiate(client, ae_dev, false);
38caee9d
S
232
233 ae_algo->ops->uninit_ae_dev(ae_dev);
234 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
235 }
236
237 list_del(&ae_algo->node);
238 mutex_unlock(&hnae3_common_lock);
239}
240EXPORT_SYMBOL(hnae3_unregister_ae_algo);
241
242/* hnae3_register_ae_dev - registers a AE device to hnae3 framework
243 * @ae_dev: the AE device
244 * NOTE: the duplicated name will not be checked
245 */
fb919349 246void hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
38caee9d
S
247{
248 const struct pci_device_id *id;
249 struct hnae3_ae_algo *ae_algo;
250 struct hnae3_client *client;
bc59f827 251 int ret = 0;
a9c89a3f 252
bc59f827 253 mutex_lock(&hnae3_common_lock);
38caee9d 254
38caee9d
S
255 list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
256
257 /* Check if there are matched ae_algo */
258 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
259 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
260 if (!id)
261 continue;
262
263 ae_dev->ops = ae_algo->ops;
264
265 if (!ae_dev->ops) {
266 dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
267 goto out_err;
268 }
269
270 /* ae_dev init should set flag */
271 ret = ae_dev->ops->init_ae_dev(ae_dev);
272 if (ret) {
273 dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
274 goto out_err;
275 }
276
277 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
278 break;
279 }
280
281 /* check the client list for the match with this ae_dev type and
282 * initialize the figure out client instance
283 */
284 list_for_each_entry(client, &hnae3_client_list, node) {
90f7b11a 285 ret = hnae3_match_n_instantiate(client, ae_dev, true);
38caee9d
S
286 if (ret)
287 dev_err(&ae_dev->pdev->dev,
288 "match and instantiation failed\n");
38caee9d
S
289 }
290
291out_err:
292 mutex_unlock(&hnae3_common_lock);
38caee9d
S
293}
294EXPORT_SYMBOL(hnae3_register_ae_dev);
295
296/* hnae3_unregister_ae_dev - unregisters a AE device
297 * @ae_dev: the AE device to unregister
298 */
299void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
300{
301 const struct pci_device_id *id;
302 struct hnae3_ae_algo *ae_algo;
303 struct hnae3_client *client;
38caee9d
S
304
305 mutex_lock(&hnae3_common_lock);
306 /* Check if there are matched ae_algo */
307 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
6c46284e
FL
308 if (!hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
309 continue;
310
38caee9d
S
311 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
312 if (!id)
313 continue;
314
90f7b11a
L
315 list_for_each_entry(client, &hnae3_client_list, node)
316 hnae3_match_n_instantiate(client, ae_dev, false);
38caee9d
S
317
318 ae_algo->ops->uninit_ae_dev(ae_dev);
319 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
320 }
321
322 list_del(&ae_dev->node);
323 mutex_unlock(&hnae3_common_lock);
324}
325EXPORT_SYMBOL(hnae3_unregister_ae_dev);
326
327MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
328MODULE_LICENSE("GPL");
329MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
4786ad87 330MODULE_VERSION(HNAE3_MOD_VERSION);