1/*
2 * Copyright (c) 2006, 2007 Cisco Systems, Inc. All rights reserved.
3 * Copyright (c) 2007, 2008 Mellanox Technologies. All rights reserved.
4 *
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
10 *
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
13 * conditions are met:
14 *
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer.
18 *
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31 * SOFTWARE.
32 */
33
34#include <linux/slab.h>
35#include <linux/export.h>
36#include <linux/errno.h>
37#include <net/devlink.h>
38
39#include "mlx4.h"
40
41static DEFINE_MUTEX(intf_mutex);
42static DEFINE_IDA(mlx4_adev_ida);
43
44static bool is_eth_supported(struct mlx4_dev *dev)
45{
46 for (int port = 1; port <= dev->caps.num_ports; port++)
47 if (dev->caps.port_type[port] == MLX4_PORT_TYPE_ETH)
48 return true;
49
50 return false;
51}
52
53static bool is_ib_supported(struct mlx4_dev *dev)
54{
55 for (int port = 1; port <= dev->caps.num_ports; port++)
56 if (dev->caps.port_type[port] == MLX4_PORT_TYPE_IB)
57 return true;
58
59 if (dev->caps.flags & MLX4_DEV_CAP_FLAG_IBOE)
60 return true;
61
62 return false;
63}
64
65static const struct mlx4_adev_device {
66 const char *suffix;
67 bool (*is_supported)(struct mlx4_dev *dev);
68} mlx4_adev_devices[] = {
69 { "eth", is_eth_supported },
70 { "ib", is_ib_supported },
71};
72
73int mlx4_adev_init(struct mlx4_dev *dev)
74{
75 struct mlx4_priv *priv = mlx4_priv(dev);
76
77 priv->adev_idx = ida_alloc(ida: &mlx4_adev_ida, GFP_KERNEL);
78 if (priv->adev_idx < 0)
79 return priv->adev_idx;
80
81 priv->adev = kcalloc(ARRAY_SIZE(mlx4_adev_devices),
82 size: sizeof(struct mlx4_adev *), GFP_KERNEL);
83 if (!priv->adev) {
84 ida_free(&mlx4_adev_ida, id: priv->adev_idx);
85 return -ENOMEM;
86 }
87
88 return 0;
89}
90
91void mlx4_adev_cleanup(struct mlx4_dev *dev)
92{
93 struct mlx4_priv *priv = mlx4_priv(dev);
94
95 kfree(objp: priv->adev);
96 ida_free(&mlx4_adev_ida, id: priv->adev_idx);
97}
98
99static void adev_release(struct device *dev)
100{
101 struct mlx4_adev *mlx4_adev =
102 container_of(dev, struct mlx4_adev, adev.dev);
103 struct mlx4_priv *priv = mlx4_priv(dev: mlx4_adev->mdev);
104 int idx = mlx4_adev->idx;
105
106 kfree(objp: mlx4_adev);
107 priv->adev[idx] = NULL;
108}
109
110static struct mlx4_adev *add_adev(struct mlx4_dev *dev, int idx)
111{
112 struct mlx4_priv *priv = mlx4_priv(dev);
113 const char *suffix = mlx4_adev_devices[idx].suffix;
114 struct auxiliary_device *adev;
115 struct mlx4_adev *madev;
116 int ret;
117
118 madev = kzalloc(size: sizeof(*madev), GFP_KERNEL);
119 if (!madev)
120 return ERR_PTR(error: -ENOMEM);
121
122 adev = &madev->adev;
123 adev->id = priv->adev_idx;
124 adev->name = suffix;
125 adev->dev.parent = &dev->persist->pdev->dev;
126 adev->dev.release = adev_release;
127 madev->mdev = dev;
128 madev->idx = idx;
129
130 ret = auxiliary_device_init(auxdev: adev);
131 if (ret) {
132 kfree(objp: madev);
133 return ERR_PTR(error: ret);
134 }
135
136 ret = auxiliary_device_add(adev);
137 if (ret) {
138 auxiliary_device_uninit(auxdev: adev);
139 return ERR_PTR(error: ret);
140 }
141 return madev;
142}
143
144static void del_adev(struct auxiliary_device *adev)
145{
146 auxiliary_device_delete(auxdev: adev);
147 auxiliary_device_uninit(auxdev: adev);
148}
149
150int mlx4_register_auxiliary_driver(struct mlx4_adrv *madrv)
151{
152 return auxiliary_driver_register(&madrv->adrv);
153}
154EXPORT_SYMBOL_GPL(mlx4_register_auxiliary_driver);
155
156void mlx4_unregister_auxiliary_driver(struct mlx4_adrv *madrv)
157{
158 auxiliary_driver_unregister(auxdrv: &madrv->adrv);
159}
160EXPORT_SYMBOL_GPL(mlx4_unregister_auxiliary_driver);
161
162int mlx4_do_bond(struct mlx4_dev *dev, bool enable)
163{
164 struct mlx4_priv *priv = mlx4_priv(dev);
165 int i, ret;
166
167 if (!(dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_PORT_REMAP))
168 return -EOPNOTSUPP;
169
170 ret = mlx4_disable_rx_port_check(dev, dis: enable);
171 if (ret) {
172 mlx4_err(dev, "Fail to %s rx port check\n",
173 enable ? "enable" : "disable");
174 return ret;
175 }
176 if (enable) {
177 dev->flags |= MLX4_FLAG_BONDED;
178 } else {
179 ret = mlx4_virt2phy_port_map(dev, port1: 1, port2: 2);
180 if (ret) {
181 mlx4_err(dev, "Fail to reset port map\n");
182 return ret;
183 }
184 dev->flags &= ~MLX4_FLAG_BONDED;
185 }
186
187 mutex_lock(&intf_mutex);
188
189 for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) {
190 struct mlx4_adev *madev = priv->adev[i];
191 struct mlx4_adrv *madrv;
192 enum mlx4_protocol protocol;
193
194 if (!madev)
195 continue;
196
197 device_lock(dev: &madev->adev.dev);
198 if (!madev->adev.dev.driver) {
199 device_unlock(dev: &madev->adev.dev);
200 continue;
201 }
202
203 madrv = container_of(madev->adev.dev.driver, struct mlx4_adrv,
204 adrv.driver);
205 if (!(madrv->flags & MLX4_INTFF_BONDING)) {
206 device_unlock(dev: &madev->adev.dev);
207 continue;
208 }
209
210 if (mlx4_is_mfunc(dev)) {
211 mlx4_dbg(dev,
212 "SRIOV, disabled HA mode for intf proto %d\n",
213 madrv->protocol);
214 device_unlock(dev: &madev->adev.dev);
215 continue;
216 }
217
218 protocol = madrv->protocol;
219 device_unlock(dev: &madev->adev.dev);
220
221 del_adev(adev: &madev->adev);
222 priv->adev[i] = add_adev(dev, idx: i);
223 if (IS_ERR(ptr: priv->adev[i])) {
224 mlx4_warn(dev, "Device[%d] (%s) failed to load\n", i,
225 mlx4_adev_devices[i].suffix);
226 priv->adev[i] = NULL;
227 continue;
228 }
229
230 mlx4_dbg(dev,
231 "Interface for protocol %d restarted with bonded mode %s\n",
232 protocol, enable ? "enabled" : "disabled");
233 }
234
235 mutex_unlock(lock: &intf_mutex);
236
237 return 0;
238}
239
240void mlx4_dispatch_event(struct mlx4_dev *dev, enum mlx4_dev_event type,
241 void *param)
242{
243 struct mlx4_priv *priv = mlx4_priv(dev);
244
245 atomic_notifier_call_chain(nh: &priv->event_nh, val: type, v: param);
246}
247
248int mlx4_register_event_notifier(struct mlx4_dev *dev,
249 struct notifier_block *nb)
250{
251 struct mlx4_priv *priv = mlx4_priv(dev);
252
253 return atomic_notifier_chain_register(nh: &priv->event_nh, nb);
254}
255EXPORT_SYMBOL(mlx4_register_event_notifier);
256
257int mlx4_unregister_event_notifier(struct mlx4_dev *dev,
258 struct notifier_block *nb)
259{
260 struct mlx4_priv *priv = mlx4_priv(dev);
261
262 return atomic_notifier_chain_unregister(nh: &priv->event_nh, nb);
263}
264EXPORT_SYMBOL(mlx4_unregister_event_notifier);
265
266static int add_drivers(struct mlx4_dev *dev)
267{
268 struct mlx4_priv *priv = mlx4_priv(dev);
269 int i, ret = 0;
270
271 for (i = 0; i < ARRAY_SIZE(mlx4_adev_devices); i++) {
272 bool is_supported = false;
273
274 if (priv->adev[i])
275 continue;
276
277 if (mlx4_adev_devices[i].is_supported)
278 is_supported = mlx4_adev_devices[i].is_supported(dev);
279
280 if (!is_supported)
281 continue;
282
283 priv->adev[i] = add_adev(dev, idx: i);
284 if (IS_ERR(ptr: priv->adev[i])) {
285 mlx4_warn(dev, "Device[%d] (%s) failed to load\n", i,
286 mlx4_adev_devices[i].suffix);
287 /* We continue to rescan drivers and leave to the caller
288 * to make decision if to release everything or
289 * continue. */
290 ret = PTR_ERR(ptr: priv->adev[i]);
291 priv->adev[i] = NULL;
292 }
293 }
294 return ret;
295}
296
297static void delete_drivers(struct mlx4_dev *dev)
298{
299 struct mlx4_priv *priv = mlx4_priv(dev);
300 bool delete_all;
301 int i;
302
303 delete_all = !(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP);
304
305 for (i = ARRAY_SIZE(mlx4_adev_devices) - 1; i >= 0; i--) {
306 bool is_supported = false;
307
308 if (!priv->adev[i])
309 continue;
310
311 if (mlx4_adev_devices[i].is_supported && !delete_all)
312 is_supported = mlx4_adev_devices[i].is_supported(dev);
313
314 if (is_supported)
315 continue;
316
317 del_adev(adev: &priv->adev[i]->adev);
318 priv->adev[i] = NULL;
319 }
320}
321
322/* This function is used after mlx4_dev is reconfigured.
323 */
324static int rescan_drivers_locked(struct mlx4_dev *dev)
325{
326 lockdep_assert_held(&intf_mutex);
327
328 delete_drivers(dev);
329 if (!(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP))
330 return 0;
331
332 return add_drivers(dev);
333}
334
335int mlx4_register_device(struct mlx4_dev *dev)
336{
337 int ret;
338
339 mutex_lock(&intf_mutex);
340
341 dev->persist->interface_state |= MLX4_INTERFACE_STATE_UP;
342
343 ret = rescan_drivers_locked(dev);
344
345 mutex_unlock(lock: &intf_mutex);
346
347 if (ret) {
348 mlx4_unregister_device(dev);
349 return ret;
350 }
351
352 mlx4_start_catas_poll(dev);
353
354 return ret;
355}
356
357void mlx4_unregister_device(struct mlx4_dev *dev)
358{
359 if (!(dev->persist->interface_state & MLX4_INTERFACE_STATE_UP))
360 return;
361
362 mlx4_stop_catas_poll(dev);
363 if (dev->persist->interface_state & MLX4_INTERFACE_STATE_DELETION &&
364 mlx4_is_slave(dev)) {
365 /* In mlx4_remove_one on a VF */
366 u32 slave_read =
367 swab32(readl(&mlx4_priv(dev)->mfunc.comm->slave_read));
368
369 if (mlx4_comm_internal_err(slave_read)) {
370 mlx4_dbg(dev, "%s: comm channel is down, entering error state.\n",
371 __func__);
372 mlx4_enter_error_state(persist: dev->persist);
373 }
374 }
375 mutex_lock(&intf_mutex);
376
377 dev->persist->interface_state &= ~MLX4_INTERFACE_STATE_UP;
378
379 rescan_drivers_locked(dev);
380
381 mutex_unlock(lock: &intf_mutex);
382}
383
384struct devlink_port *mlx4_get_devlink_port(struct mlx4_dev *dev, int port)
385{
386 struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
387
388 return &info->devlink_port;
389}
390EXPORT_SYMBOL_GPL(mlx4_get_devlink_port);
391

source code of linux/drivers/net/ethernet/mellanox/mlx4/intf.c