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);