2 * Copyright (c) 2016-2017 Hisilicon Limited.
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.
10 #include <linux/list.h>
11 #include <linux/slab.h>
12 #include <linux/spinlock.h>
16 static LIST_HEAD(hnae3_ae_algo_list);
17 static LIST_HEAD(hnae3_client_list);
18 static LIST_HEAD(hnae3_ae_dev_list);
20 /* we are keeping things simple and using single lock for all the
21 * list. This is a non-critical code so other updations, if happen
22 * in parallel, can wait.
24 static DEFINE_MUTEX(hnae3_common_lock);
26 static bool hnae3_client_match(enum hnae3_client_type client_type,
27 enum hnae3_dev_type dev_type)
29 if ((dev_type == HNAE3_DEV_KNIC) && (client_type == HNAE3_CLIENT_KNIC ||
30 client_type == HNAE3_CLIENT_ROCE))
33 if (dev_type == HNAE3_DEV_UNIC && client_type == HNAE3_CLIENT_UNIC)
39 static int hnae3_match_n_instantiate(struct hnae3_client *client,
40 struct hnae3_ae_dev *ae_dev,
41 bool is_reg, bool *matched)
47 /* check if this client matches the type of ae_dev */
48 if (!(hnae3_client_match(client->type, ae_dev->dev_type) &&
49 hnae_get_bit(ae_dev->flag, HNAE3_DEV_INITED_B))) {
52 /* there is a match of client and dev */
55 /* now, (un-)instantiate client by calling lower layer */
57 ret = ae_dev->ops->init_client_instance(client, ae_dev);
59 dev_err(&ae_dev->pdev->dev,
60 "fail to instantiate client\n");
64 ae_dev->ops->uninit_client_instance(client, ae_dev);
68 int hnae3_register_client(struct hnae3_client *client)
70 struct hnae3_client *client_tmp;
71 struct hnae3_ae_dev *ae_dev;
75 mutex_lock(&hnae3_common_lock);
76 /* one system should only have one client for every type */
77 list_for_each_entry(client_tmp, &hnae3_client_list, node) {
78 if (client_tmp->type == client->type)
82 list_add_tail(&client->node, &hnae3_client_list);
84 /* initialize the client on every matched port */
85 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
86 /* if the client could not be initialized on current port, for
87 * any error reasons, move on to next available port
89 ret = hnae3_match_n_instantiate(client, ae_dev, true, &matched);
91 dev_err(&ae_dev->pdev->dev,
92 "match and instantiation failed for port\n");
96 mutex_unlock(&hnae3_common_lock);
100 EXPORT_SYMBOL(hnae3_register_client);
102 void hnae3_unregister_client(struct hnae3_client *client)
104 struct hnae3_ae_dev *ae_dev;
107 mutex_lock(&hnae3_common_lock);
108 /* un-initialize the client on every matched port */
109 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
110 hnae3_match_n_instantiate(client, ae_dev, false, &matched);
113 list_del(&client->node);
114 mutex_unlock(&hnae3_common_lock);
116 EXPORT_SYMBOL(hnae3_unregister_client);
118 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
119 * @ae_algo: AE algorithm
120 * NOTE: the duplicated name will not be checked
122 int hnae3_register_ae_algo(struct hnae3_ae_algo *ae_algo)
124 const struct pci_device_id *id;
125 struct hnae3_ae_dev *ae_dev;
126 struct hnae3_client *client;
130 mutex_lock(&hnae3_common_lock);
132 list_add_tail(&ae_algo->node, &hnae3_ae_algo_list);
134 /* Check if this algo/ops matches the list of ae_devs */
135 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
136 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
140 /* ae_dev init should set flag */
141 ae_dev->ops = ae_algo->ops;
142 ret = ae_algo->ops->init_ae_dev(ae_dev);
144 dev_err(&ae_dev->pdev->dev, "init ae_dev error.\n");
148 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
150 /* check the client list for the match with this ae_dev type and
151 * initialize the figure out client instance
153 list_for_each_entry(client, &hnae3_client_list, node) {
154 ret = hnae3_match_n_instantiate(client, ae_dev, true,
157 dev_err(&ae_dev->pdev->dev,
158 "match and instantiation failed\n");
164 mutex_unlock(&hnae3_common_lock);
168 EXPORT_SYMBOL(hnae3_register_ae_algo);
170 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
171 * @ae_algo: the AE algorithm to unregister
173 void hnae3_unregister_ae_algo(struct hnae3_ae_algo *ae_algo)
175 const struct pci_device_id *id;
176 struct hnae3_ae_dev *ae_dev;
177 struct hnae3_client *client;
180 mutex_lock(&hnae3_common_lock);
181 /* Check if there are matched ae_dev */
182 list_for_each_entry(ae_dev, &hnae3_ae_dev_list, node) {
183 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
187 /* check the client list for the match with this ae_dev type and
188 * un-initialize the figure out client instance
190 list_for_each_entry(client, &hnae3_client_list, node) {
191 hnae3_match_n_instantiate(client, ae_dev, false,
197 ae_algo->ops->uninit_ae_dev(ae_dev);
198 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
201 list_del(&ae_algo->node);
202 mutex_unlock(&hnae3_common_lock);
204 EXPORT_SYMBOL(hnae3_unregister_ae_algo);
206 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
207 * @ae_dev: the AE device
208 * NOTE: the duplicated name will not be checked
210 int hnae3_register_ae_dev(struct hnae3_ae_dev *ae_dev)
212 const struct pci_device_id *id;
213 struct hnae3_ae_algo *ae_algo;
214 struct hnae3_client *client;
218 mutex_lock(&hnae3_common_lock);
219 list_add_tail(&ae_dev->node, &hnae3_ae_dev_list);
221 /* Check if there are matched ae_algo */
222 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
223 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
227 ae_dev->ops = ae_algo->ops;
230 dev_err(&ae_dev->pdev->dev, "ae_dev ops are null\n");
234 /* ae_dev init should set flag */
235 ret = ae_dev->ops->init_ae_dev(ae_dev);
237 dev_err(&ae_dev->pdev->dev, "init ae_dev error\n");
241 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 1);
245 /* check the client list for the match with this ae_dev type and
246 * initialize the figure out client instance
248 list_for_each_entry(client, &hnae3_client_list, node) {
249 ret = hnae3_match_n_instantiate(client, ae_dev, true,
252 dev_err(&ae_dev->pdev->dev,
253 "match and instantiation failed\n");
259 mutex_unlock(&hnae3_common_lock);
263 EXPORT_SYMBOL(hnae3_register_ae_dev);
265 /* hnae3_unregister_ae_dev - unregisters a AE device
266 * @ae_dev: the AE device to unregister
268 void hnae3_unregister_ae_dev(struct hnae3_ae_dev *ae_dev)
270 const struct pci_device_id *id;
271 struct hnae3_ae_algo *ae_algo;
272 struct hnae3_client *client;
275 mutex_lock(&hnae3_common_lock);
276 /* Check if there are matched ae_algo */
277 list_for_each_entry(ae_algo, &hnae3_ae_algo_list, node) {
278 id = pci_match_id(ae_algo->pdev_id_table, ae_dev->pdev);
282 list_for_each_entry(client, &hnae3_client_list, node) {
283 hnae3_match_n_instantiate(client, ae_dev, false,
289 ae_algo->ops->uninit_ae_dev(ae_dev);
290 hnae_set_bit(ae_dev->flag, HNAE3_DEV_INITED_B, 0);
293 list_del(&ae_dev->node);
294 mutex_unlock(&hnae3_common_lock);
296 EXPORT_SYMBOL(hnae3_unregister_ae_dev);
298 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
299 MODULE_LICENSE("GPL");
300 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");