1 // SPDX-License-Identifier: GPL-2.0+
2 // Copyright (c) 2016-2017 Hisilicon Limited.
4 #include <linux/list.h>
5 #include <linux/spinlock.h>
9 static LIST_HEAD(hnae3_ae_algo_list);
10 static LIST_HEAD(hnae3_client_list);
11 static LIST_HEAD(hnae3_ae_dev_list);
13 void hnae3_unregister_ae_algo_prepare(struct hnae3_ae_algo *ae_algo)
15 const struct pci_device_id *pci_id;
16 struct hnae3_ae_dev *ae_dev;
21 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
22 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
25 pci_id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
28 if (IS_ENABLED(CONFIG_PCI_IOV))
29 pci_disable_sriov(ae_dev->pdev);
32 EXPORT_SYMBOL(hnae3_unregister_ae_algo_prepare);
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.
38 static DEFINE_MUTEX(hnae3_common_lock);
40 static bool hnae3_client_match(enum hnae3_client_type client_type)
42 if (client_type == HNAE3_CLIENT_KNIC ||
43 client_type == HNAE3_CLIENT_ROCE)
49 void hnae3_set_client_init_flag(struct hnae3_client *client,
50 struct hnae3_ae_dev *ae_dev,
53 if (!client || !ae_dev)
56 switch (client->type) {
57 case HNAE3_CLIENT_KNIC:
58 hnae3_set_bit(ae_dev->flag, HNAE3_KNIC_CLIENT_INITED_B, inited);
60 case HNAE3_CLIENT_ROCE:
61 hnae3_set_bit(ae_dev->flag, HNAE3_ROCE_CLIENT_INITED_B, inited);
67 EXPORT_SYMBOL(hnae3_set_client_init_flag);
69 static int hnae3_get_client_init_flag(struct hnae3_client *client,
70 struct hnae3_ae_dev *ae_dev)
74 switch (client->type) {
75 case HNAE3_CLIENT_KNIC:
76 inited = hnae3_get_bit(ae_dev->flag,
77 HNAE3_KNIC_CLIENT_INITED_B);
79 case HNAE3_CLIENT_ROCE:
80 inited = hnae3_get_bit(ae_dev->flag,
81 HNAE3_ROCE_CLIENT_INITED_B);
90 static int hnae3_init_client_instance(struct hnae3_client *client,
91 struct hnae3_ae_dev *ae_dev)
95 /* check if this client matches the type of ae_dev */
96 if (!(hnae3_client_match(client->type) &&
97 hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
101 ret = ae_dev->ops->init_client_instance(client, ae_dev);
103 dev_err(&ae_dev->pdev->dev,
104 "fail to instantiate client, ret = %d\n", ret);
109 static void hnae3_uninit_client_instance(struct hnae3_client *client,
110 struct hnae3_ae_dev *ae_dev)
112 /* check if this client matches the type of ae_dev */
113 if (!(hnae3_client_match(client->type) &&
114 hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B)))
117 if (hnae3_get_client_init_flag(client, ae_dev)) {
118 ae_dev->ops->uninit_client_instance(client, ae_dev);
120 hnae3_set_client_init_flag(client, ae_dev, 0);
124 int hnae3_register_client(struct hnae3_client *client)
126 struct hnae3_client *client_tmp;
127 struct hnae3_ae_dev *ae_dev;
132 mutex_lock(&hnae3_common_lock);
133 /* one system should only have one client for every type */
134 list_for_each_entry(client_tmp, &hnae3_client_list, node) {
135 if (client_tmp->type == client->type)
139 list_add_tail(&client->node, &hnae3_client_list);
141 /* initialize the client on every matched port */
142 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
143 /* if the client could not be initialized on current port, for
144 * any error reasons, move on to next available port
146 int ret = hnae3_init_client_instance(client, ae_dev);
148 dev_err(&ae_dev->pdev->dev,
149 "match and instantiation failed for port, ret = %d\n",
154 mutex_unlock(&hnae3_common_lock);
158 EXPORT_SYMBOL(hnae3_register_client);
160 void hnae3_unregister_client(struct hnae3_client *client)
162 struct hnae3_client *client_tmp;
163 struct hnae3_ae_dev *ae_dev;
164 bool existed = false;
169 mutex_lock(&hnae3_common_lock);
170 /* one system should only have one client for every type */
171 list_for_each_entry(client_tmp, &hnae3_client_list, node) {
172 if (client_tmp->type == client->type) {
179 mutex_unlock(&hnae3_common_lock);
180 pr_err("client %s does not exist!\n", client->name);
184 /* un-initialize the client on every matched port */
185 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
186 hnae3_uninit_client_instance(client, ae_dev);
189 list_del(&client->node);
190 mutex_unlock(&hnae3_common_lock);
192 EXPORT_SYMBOL(hnae3_unregister_client);
194 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
195 * @ae_algo: AE algorithm
196 * NOTE: the duplicated name will not be checked
198 void hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
200 const struct pci_device_id *id;
201 struct hnae3_ae_dev *ae_dev;
202 struct hnae3_client *client;
208 mutex_lock(&hnae3_common_lock);
210 list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
212 /* Check if this algo/ops matches the list of ae_devs */
213 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
214 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
219 dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
222 ae_dev->ops = ae_algo->ops;
224 ret = ae_algo->ops->init_ae_dev(ae_dev);
226 dev_err(&ae_dev->pdev->dev,
227 "init ae_dev error, ret = %d\n", ret);
231 /* ae_dev init should set flag */
232 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
234 /* check the client list for the match with this ae_dev type and
235 * initialize the figure out client instance
237 list_for_each_entry(client, &hnae3_client_list, node) {
238 ret = hnae3_init_client_instance(client, ae_dev);
240 dev_err(&ae_dev->pdev->dev,
241 "match and instantiation failed, ret = %d\n",
246 mutex_unlock(&hnae3_common_lock);
248 EXPORT_SYMBOL(hnae3_register_ae_algo);
250 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
251 * @ae_algo: the AE algorithm to unregister
253 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
255 const struct pci_device_id *id;
256 struct hnae3_ae_dev *ae_dev;
257 struct hnae3_client *client;
262 mutex_lock(&hnae3_common_lock);
263 /* Check if there are matched ae_dev */
264 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
265 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
268 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
272 /* check the client list for the match with this ae_dev type and
273 * un-initialize the figure out client instance
275 list_for_each_entry(client, &hnae3_client_list, node)
276 hnae3_uninit_client_instance(client, ae_dev);
278 ae_algo->ops->uninit_ae_dev(ae_dev);
279 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
283 list_del(&ae_algo->node);
284 mutex_unlock(&hnae3_common_lock);
286 EXPORT_SYMBOL(hnae3_unregister_ae_algo);
288 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
289 * @ae_dev: the AE device
290 * NOTE: the duplicated name will not be checked
292 int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
294 const struct pci_device_id *id;
295 struct hnae3_ae_algo *ae_algo;
296 struct hnae3_client *client;
302 mutex_lock(&hnae3_common_lock);
304 list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
306 /* Check if there are matched ae_algo */
307 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
308 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
313 dev_err(&ae_dev->pdev->dev, "ae_algo ops are null\n");
317 ae_dev->ops = ae_algo->ops;
319 ret = ae_dev->ops->init_ae_dev(ae_dev);
321 dev_err(&ae_dev->pdev->dev,
322 "init ae_dev error, ret = %d\n", ret);
326 /* ae_dev init should set flag */
327 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
331 /* check the client list for the match with this ae_dev type and
332 * initialize the figure out client instance
334 list_for_each_entry(client, &hnae3_client_list, node) {
335 ret = hnae3_init_client_instance(client, ae_dev);
337 dev_err(&ae_dev->pdev->dev,
338 "match and instantiation failed, ret = %d\n",
342 mutex_unlock(&hnae3_common_lock);
347 list_del(&ae_dev->node);
348 mutex_unlock(&hnae3_common_lock);
352 EXPORT_SYMBOL(hnae3_register_ae_dev);
354 /* hnae3_unregister_ae_dev - unregisters a AE device
355 * @ae_dev: the AE device to unregister
357 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
359 const struct pci_device_id *id;
360 struct hnae3_ae_algo *ae_algo;
361 struct hnae3_client *client;
366 mutex_lock(&hnae3_common_lock);
367 /* Check if there are matched ae_algo */
368 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
369 if (!hnae3_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))
372 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
376 list_for_each_entry(client, &hnae3_client_list, node)
377 hnae3_uninit_client_instance(client, ae_dev);
379 ae_algo->ops->uninit_ae_dev(ae_dev);
380 hnae3_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
384 list_del(&ae_dev->node);
385 mutex_unlock(&hnae3_common_lock);
387 EXPORT_SYMBOL(hnae3_unregister_ae_dev);
389 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
390 MODULE_LICENSE("GPL");
391 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");
392 MODULE_VERSION(HNAE3_MOD_VERSION);