2 * Copyright (c) 2013-2015, Mellanox Technologies. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/mlx5/driver.h>
34 #include "mlx5_core.h"
36 static LIST_HEAD(intf_list
);
37 static LIST_HEAD(mlx5_dev_list
);
38 /* intf dev list mutex */
39 static DEFINE_MUTEX(mlx5_intf_mutex
);
41 struct mlx5_device_context
{
42 struct list_head list
;
43 struct mlx5_interface
*intf
;
50 MLX5_INTERFACE_ATTACHED
,
53 void mlx5_add_device(struct mlx5_interface
*intf
, struct mlx5_priv
*priv
)
55 struct mlx5_device_context
*dev_ctx
;
56 struct mlx5_core_dev
*dev
= container_of(priv
, struct mlx5_core_dev
, priv
);
58 if (!mlx5_lag_intf_add(intf
, priv
))
61 dev_ctx
= kzalloc(sizeof(*dev_ctx
), GFP_KERNEL
);
66 dev_ctx
->context
= intf
->add(dev
);
67 set_bit(MLX5_INTERFACE_ADDED
, &dev_ctx
->state
);
69 set_bit(MLX5_INTERFACE_ATTACHED
, &dev_ctx
->state
);
71 if (dev_ctx
->context
) {
72 spin_lock_irq(&priv
->ctx_lock
);
73 list_add_tail(&dev_ctx
->list
, &priv
->ctx_list
);
74 spin_unlock_irq(&priv
->ctx_lock
);
80 static struct mlx5_device_context
*mlx5_get_device(struct mlx5_interface
*intf
,
81 struct mlx5_priv
*priv
)
83 struct mlx5_device_context
*dev_ctx
;
85 list_for_each_entry(dev_ctx
, &priv
->ctx_list
, list
)
86 if (dev_ctx
->intf
== intf
)
91 void mlx5_remove_device(struct mlx5_interface
*intf
, struct mlx5_priv
*priv
)
93 struct mlx5_device_context
*dev_ctx
;
94 struct mlx5_core_dev
*dev
= container_of(priv
, struct mlx5_core_dev
, priv
);
96 dev_ctx
= mlx5_get_device(intf
, priv
);
100 spin_lock_irq(&priv
->ctx_lock
);
101 list_del(&dev_ctx
->list
);
102 spin_unlock_irq(&priv
->ctx_lock
);
104 if (test_bit(MLX5_INTERFACE_ADDED
, &dev_ctx
->state
))
105 intf
->remove(dev
, dev_ctx
->context
);
110 static void mlx5_attach_interface(struct mlx5_interface
*intf
, struct mlx5_priv
*priv
)
112 struct mlx5_device_context
*dev_ctx
;
113 struct mlx5_core_dev
*dev
= container_of(priv
, struct mlx5_core_dev
, priv
);
115 dev_ctx
= mlx5_get_device(intf
, priv
);
120 if (test_bit(MLX5_INTERFACE_ATTACHED
, &dev_ctx
->state
))
122 intf
->attach(dev
, dev_ctx
->context
);
123 set_bit(MLX5_INTERFACE_ATTACHED
, &dev_ctx
->state
);
125 if (test_bit(MLX5_INTERFACE_ADDED
, &dev_ctx
->state
))
127 dev_ctx
->context
= intf
->add(dev
);
128 set_bit(MLX5_INTERFACE_ADDED
, &dev_ctx
->state
);
132 void mlx5_attach_device(struct mlx5_core_dev
*dev
)
134 struct mlx5_priv
*priv
= &dev
->priv
;
135 struct mlx5_interface
*intf
;
137 mutex_lock(&mlx5_intf_mutex
);
138 list_for_each_entry(intf
, &intf_list
, list
)
139 mlx5_attach_interface(intf
, priv
);
140 mutex_unlock(&mlx5_intf_mutex
);
143 static void mlx5_detach_interface(struct mlx5_interface
*intf
, struct mlx5_priv
*priv
)
145 struct mlx5_device_context
*dev_ctx
;
146 struct mlx5_core_dev
*dev
= container_of(priv
, struct mlx5_core_dev
, priv
);
148 dev_ctx
= mlx5_get_device(intf
, priv
);
153 if (!test_bit(MLX5_INTERFACE_ATTACHED
, &dev_ctx
->state
))
155 intf
->detach(dev
, dev_ctx
->context
);
156 clear_bit(MLX5_INTERFACE_ATTACHED
, &dev_ctx
->state
);
158 if (!test_bit(MLX5_INTERFACE_ADDED
, &dev_ctx
->state
))
160 intf
->remove(dev
, dev_ctx
->context
);
161 clear_bit(MLX5_INTERFACE_ADDED
, &dev_ctx
->state
);
165 void mlx5_detach_device(struct mlx5_core_dev
*dev
)
167 struct mlx5_priv
*priv
= &dev
->priv
;
168 struct mlx5_interface
*intf
;
170 mutex_lock(&mlx5_intf_mutex
);
171 list_for_each_entry(intf
, &intf_list
, list
)
172 mlx5_detach_interface(intf
, priv
);
173 mutex_unlock(&mlx5_intf_mutex
);
176 bool mlx5_device_registered(struct mlx5_core_dev
*dev
)
178 struct mlx5_priv
*priv
;
181 mutex_lock(&mlx5_intf_mutex
);
182 list_for_each_entry(priv
, &mlx5_dev_list
, dev_list
)
183 if (priv
== &dev
->priv
)
185 mutex_unlock(&mlx5_intf_mutex
);
190 int mlx5_register_device(struct mlx5_core_dev
*dev
)
192 struct mlx5_priv
*priv
= &dev
->priv
;
193 struct mlx5_interface
*intf
;
195 mutex_lock(&mlx5_intf_mutex
);
196 list_add_tail(&priv
->dev_list
, &mlx5_dev_list
);
197 list_for_each_entry(intf
, &intf_list
, list
)
198 mlx5_add_device(intf
, priv
);
199 mutex_unlock(&mlx5_intf_mutex
);
204 void mlx5_unregister_device(struct mlx5_core_dev
*dev
)
206 struct mlx5_priv
*priv
= &dev
->priv
;
207 struct mlx5_interface
*intf
;
209 mutex_lock(&mlx5_intf_mutex
);
210 list_for_each_entry(intf
, &intf_list
, list
)
211 mlx5_remove_device(intf
, priv
);
212 list_del(&priv
->dev_list
);
213 mutex_unlock(&mlx5_intf_mutex
);
216 int mlx5_register_interface(struct mlx5_interface
*intf
)
218 struct mlx5_priv
*priv
;
220 if (!intf
->add
|| !intf
->remove
)
223 mutex_lock(&mlx5_intf_mutex
);
224 list_add_tail(&intf
->list
, &intf_list
);
225 list_for_each_entry(priv
, &mlx5_dev_list
, dev_list
)
226 mlx5_add_device(intf
, priv
);
227 mutex_unlock(&mlx5_intf_mutex
);
231 EXPORT_SYMBOL(mlx5_register_interface
);
233 void mlx5_unregister_interface(struct mlx5_interface
*intf
)
235 struct mlx5_priv
*priv
;
237 mutex_lock(&mlx5_intf_mutex
);
238 list_for_each_entry(priv
, &mlx5_dev_list
, dev_list
)
239 mlx5_remove_device(intf
, priv
);
240 list_del(&intf
->list
);
241 mutex_unlock(&mlx5_intf_mutex
);
243 EXPORT_SYMBOL(mlx5_unregister_interface
);
245 void *mlx5_get_protocol_dev(struct mlx5_core_dev
*mdev
, int protocol
)
247 struct mlx5_priv
*priv
= &mdev
->priv
;
248 struct mlx5_device_context
*dev_ctx
;
252 spin_lock_irqsave(&priv
->ctx_lock
, flags
);
254 list_for_each_entry(dev_ctx
, &mdev
->priv
.ctx_list
, list
)
255 if ((dev_ctx
->intf
->protocol
== protocol
) &&
256 dev_ctx
->intf
->get_dev
) {
257 result
= dev_ctx
->intf
->get_dev(dev_ctx
->context
);
261 spin_unlock_irqrestore(&priv
->ctx_lock
, flags
);
265 EXPORT_SYMBOL(mlx5_get_protocol_dev
);
267 /* Must be called with intf_mutex held */
268 void mlx5_add_dev_by_protocol(struct mlx5_core_dev
*dev
, int protocol
)
270 struct mlx5_interface
*intf
;
272 list_for_each_entry(intf
, &intf_list
, list
)
273 if (intf
->protocol
== protocol
) {
274 mlx5_add_device(intf
, &dev
->priv
);
279 /* Must be called with intf_mutex held */
280 void mlx5_remove_dev_by_protocol(struct mlx5_core_dev
*dev
, int protocol
)
282 struct mlx5_interface
*intf
;
284 list_for_each_entry(intf
, &intf_list
, list
)
285 if (intf
->protocol
== protocol
) {
286 mlx5_remove_device(intf
, &dev
->priv
);
291 static u16
mlx5_gen_pci_id(struct mlx5_core_dev
*dev
)
293 return (u16
)((dev
->pdev
->bus
->number
<< 8) |
294 PCI_SLOT(dev
->pdev
->devfn
));
297 /* Must be called with intf_mutex held */
298 struct mlx5_core_dev
*mlx5_get_next_phys_dev(struct mlx5_core_dev
*dev
)
300 u16 pci_id
= mlx5_gen_pci_id(dev
);
301 struct mlx5_core_dev
*res
= NULL
;
302 struct mlx5_core_dev
*tmp_dev
;
303 struct mlx5_priv
*priv
;
305 list_for_each_entry(priv
, &mlx5_dev_list
, dev_list
) {
306 tmp_dev
= container_of(priv
, struct mlx5_core_dev
, priv
);
307 if ((dev
!= tmp_dev
) && (mlx5_gen_pci_id(tmp_dev
) == pci_id
)) {
316 void mlx5_core_event(struct mlx5_core_dev
*dev
, enum mlx5_dev_event event
,
319 struct mlx5_priv
*priv
= &dev
->priv
;
320 struct mlx5_device_context
*dev_ctx
;
323 spin_lock_irqsave(&priv
->ctx_lock
, flags
);
325 list_for_each_entry(dev_ctx
, &priv
->ctx_list
, list
)
326 if (dev_ctx
->intf
->event
)
327 dev_ctx
->intf
->event(dev
, dev_ctx
->context
, event
, param
);
329 spin_unlock_irqrestore(&priv
->ctx_lock
, flags
);
332 void mlx5_dev_list_lock(void)
334 mutex_lock(&mlx5_intf_mutex
);
337 void mlx5_dev_list_unlock(void)
339 mutex_unlock(&mlx5_intf_mutex
);
342 int mlx5_dev_list_trylock(void)
344 return mutex_trylock(&mlx5_intf_mutex
);