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
, bool is_reg
)
44 /* check if this client matches the type of ae_dev */
45 if (!(hnae3_client_match(client
->type
, ae_dev
->dev_type
) &&
46 hnae_get_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
))) {
50 /* now, (un-)instantiate client by calling lower layer */
52 ret
= ae_dev
->ops
->init_client_instance(client
, ae_dev
);
54 dev_err(&ae_dev
->pdev
->dev
,
55 "fail to instantiate client\n");
59 hnae_set_bit(ae_dev
->flag
, HNAE3_CLIENT_INITED_B
, 1);
63 if (hnae_get_bit(ae_dev
->flag
, HNAE3_CLIENT_INITED_B
)) {
64 ae_dev
->ops
->uninit_client_instance(client
, ae_dev
);
66 hnae_set_bit(ae_dev
->flag
, HNAE3_CLIENT_INITED_B
, 0);
72 int hnae3_register_client(struct hnae3_client
*client
)
74 struct hnae3_client
*client_tmp
;
75 struct hnae3_ae_dev
*ae_dev
;
78 mutex_lock(&hnae3_common_lock
);
79 /* one system should only have one client for every type */
80 list_for_each_entry(client_tmp
, &hnae3_client_list
, node
) {
81 if (client_tmp
->type
== client
->type
)
85 list_add_tail(&client
->node
, &hnae3_client_list
);
87 /* initialize the client on every matched port */
88 list_for_each_entry(ae_dev
, &hnae3_ae_dev_list
, node
) {
89 /* if the client could not be initialized on current port, for
90 * any error reasons, move on to next available port
92 ret
= hnae3_match_n_instantiate(client
, ae_dev
, true);
94 dev_err(&ae_dev
->pdev
->dev
,
95 "match and instantiation failed for port\n");
99 mutex_unlock(&hnae3_common_lock
);
103 EXPORT_SYMBOL(hnae3_register_client
);
105 void hnae3_unregister_client(struct hnae3_client
*client
)
107 struct hnae3_ae_dev
*ae_dev
;
109 mutex_lock(&hnae3_common_lock
);
110 /* un-initialize the client on every matched port */
111 list_for_each_entry(ae_dev
, &hnae3_ae_dev_list
, node
) {
112 hnae3_match_n_instantiate(client
, ae_dev
, false);
115 list_del(&client
->node
);
116 mutex_unlock(&hnae3_common_lock
);
118 EXPORT_SYMBOL(hnae3_unregister_client
);
120 /* hnae3_register_ae_algo - register a AE algorithm to hnae3 framework
121 * @ae_algo: AE algorithm
122 * NOTE: the duplicated name will not be checked
124 int hnae3_register_ae_algo(struct hnae3_ae_algo
*ae_algo
)
126 const struct pci_device_id
*id
;
127 struct hnae3_ae_dev
*ae_dev
;
128 struct hnae3_client
*client
;
131 mutex_lock(&hnae3_common_lock
);
133 list_add_tail(&ae_algo
->node
, &hnae3_ae_algo_list
);
135 /* Check if this algo/ops matches the list of ae_devs */
136 list_for_each_entry(ae_dev
, &hnae3_ae_dev_list
, node
) {
137 id
= pci_match_id(ae_algo
->pdev_id_table
, ae_dev
->pdev
);
141 /* ae_dev init should set flag */
142 ae_dev
->ops
= ae_algo
->ops
;
143 ret
= ae_algo
->ops
->init_ae_dev(ae_dev
);
145 dev_err(&ae_dev
->pdev
->dev
, "init ae_dev error.\n");
149 hnae_set_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
, 1);
151 /* check the client list for the match with this ae_dev type and
152 * initialize the figure out client instance
154 list_for_each_entry(client
, &hnae3_client_list
, node
) {
155 ret
= hnae3_match_n_instantiate(client
, ae_dev
, true);
157 dev_err(&ae_dev
->pdev
->dev
,
158 "match and instantiation failed\n");
162 mutex_unlock(&hnae3_common_lock
);
166 EXPORT_SYMBOL(hnae3_register_ae_algo
);
168 /* hnae3_unregister_ae_algo - unregisters a AE algorithm
169 * @ae_algo: the AE algorithm to unregister
171 void hnae3_unregister_ae_algo(struct hnae3_ae_algo
*ae_algo
)
173 const struct pci_device_id
*id
;
174 struct hnae3_ae_dev
*ae_dev
;
175 struct hnae3_client
*client
;
177 mutex_lock(&hnae3_common_lock
);
178 /* Check if there are matched ae_dev */
179 list_for_each_entry(ae_dev
, &hnae3_ae_dev_list
, node
) {
180 if (!hnae_get_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
))
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);
193 ae_algo
->ops
->uninit_ae_dev(ae_dev
);
194 hnae_set_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
, 0);
197 list_del(&ae_algo
->node
);
198 mutex_unlock(&hnae3_common_lock
);
200 EXPORT_SYMBOL(hnae3_unregister_ae_algo
);
202 /* hnae3_register_ae_dev - registers a AE device to hnae3 framework
203 * @ae_dev: the AE device
204 * NOTE: the duplicated name will not be checked
206 int hnae3_register_ae_dev(struct hnae3_ae_dev
*ae_dev
)
208 const struct pci_device_id
*id
;
209 struct hnae3_ae_algo
*ae_algo
;
210 struct hnae3_client
*client
;
213 mutex_lock(&hnae3_common_lock
);
215 list_add_tail(&ae_dev
->node
, &hnae3_ae_dev_list
);
217 /* Check if there are matched ae_algo */
218 list_for_each_entry(ae_algo
, &hnae3_ae_algo_list
, node
) {
219 id
= pci_match_id(ae_algo
->pdev_id_table
, ae_dev
->pdev
);
223 ae_dev
->ops
= ae_algo
->ops
;
226 dev_err(&ae_dev
->pdev
->dev
, "ae_dev ops are null\n");
231 /* ae_dev init should set flag */
232 ret
= ae_dev
->ops
->init_ae_dev(ae_dev
);
234 dev_err(&ae_dev
->pdev
->dev
, "init ae_dev error\n");
238 hnae_set_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
, 1);
242 /* check the client list for the match with this ae_dev type and
243 * initialize the figure out client instance
245 list_for_each_entry(client
, &hnae3_client_list
, node
) {
246 ret
= hnae3_match_n_instantiate(client
, ae_dev
, true);
248 dev_err(&ae_dev
->pdev
->dev
,
249 "match and instantiation failed\n");
253 mutex_unlock(&hnae3_common_lock
);
257 EXPORT_SYMBOL(hnae3_register_ae_dev
);
259 /* hnae3_unregister_ae_dev - unregisters a AE device
260 * @ae_dev: the AE device to unregister
262 void hnae3_unregister_ae_dev(struct hnae3_ae_dev
*ae_dev
)
264 const struct pci_device_id
*id
;
265 struct hnae3_ae_algo
*ae_algo
;
266 struct hnae3_client
*client
;
268 mutex_lock(&hnae3_common_lock
);
269 /* Check if there are matched ae_algo */
270 list_for_each_entry(ae_algo
, &hnae3_ae_algo_list
, node
) {
271 if (!hnae_get_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
))
274 id
= pci_match_id(ae_algo
->pdev_id_table
, ae_dev
->pdev
);
278 list_for_each_entry(client
, &hnae3_client_list
, node
)
279 hnae3_match_n_instantiate(client
, ae_dev
, false);
281 ae_algo
->ops
->uninit_ae_dev(ae_dev
);
282 hnae_set_bit(ae_dev
->flag
, HNAE3_DEV_INITED_B
, 0);
285 list_del(&ae_dev
->node
);
286 mutex_unlock(&hnae3_common_lock
);
288 EXPORT_SYMBOL(hnae3_unregister_ae_dev
);
290 MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
291 MODULE_LICENSE("GPL");
292 MODULE_DESCRIPTION("HNAE3(Hisilicon Network Acceleration Engine) Framework");