]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/net/ethernet/mellanox/mlx5/core/ipoib/ipoib.c
net/mlx5e: IPoIB, Set the netdevice sw mtu in ipoib enhanced flow
[mirror_ubuntu-hirsute-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / ipoib / ipoib.c
CommitLineData
48935bbb
SM
1/*
2 * Copyright (c) 2017, Mellanox Technologies. All rights reserved.
3 *
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:
9 *
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
12 * conditions are met:
13 *
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer.
17 *
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.
22 *
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
30 * SOFTWARE.
31 */
32
693dfd5a 33#include <rdma/ib_verbs.h>
48935bbb
SM
34#include <linux/mlx5/fs.h>
35#include "en.h"
36#include "ipoib.h"
37
ec8fd927 38#define IB_DEFAULT_Q_KEY 0xb1b
b6dc510f 39#define MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE 9
ec8fd927 40
603f4a45
SM
41static int mlx5i_open(struct net_device *netdev);
42static int mlx5i_close(struct net_device *netdev);
807c4415 43static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu);
603f4a45
SM
44
45static const struct net_device_ops mlx5i_netdev_ops = {
46 .ndo_open = mlx5i_open,
47 .ndo_stop = mlx5i_close,
48 .ndo_init = mlx5i_dev_init,
49 .ndo_uninit = mlx5i_dev_cleanup,
807c4415 50 .ndo_change_mtu = mlx5i_change_mtu,
1170fbd8 51 .ndo_do_ioctl = mlx5i_ioctl,
603f4a45
SM
52};
53
48935bbb 54/* IPoIB mlx5 netdev profile */
b6dc510f
ES
55static void mlx5i_build_nic_params(struct mlx5_core_dev *mdev,
56 struct mlx5e_params *params)
57{
58 /* Override RQ params as IPoIB supports only LINKED LIST RQ for now */
2ccb0a79
TT
59 MLX5E_SET_PFLAG(params, MLX5E_PFLAG_RX_STRIDING_RQ, false);
60 mlx5e_set_rq_type(mdev, params);
2a0f561b 61 mlx5e_init_rq_type_params(mdev, params);
b6dc510f
ES
62
63 /* RQ size in ipoib by default is 512 */
73281b78 64 params->log_rq_mtu_frames = is_kdump_kernel() ?
b6dc510f
ES
65 MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE :
66 MLX5I_PARAMS_DEFAULT_LOG_RQ_SIZE;
67
68 params->lro_en = false;
472a1e44 69 params->hard_mtu = MLX5_IB_GRH_BYTES + MLX5_IPOIB_HARD_LEN;
b6dc510f 70}
48935bbb
SM
71
72/* Called directly after IPoIB netdevice was created to initialize SW structs */
4c6c615e
AV
73void mlx5i_init(struct mlx5_core_dev *mdev,
74 struct net_device *netdev,
75 const struct mlx5e_profile *profile,
76 void *ppriv)
48935bbb
SM
77{
78 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
8e1d162d 79 u16 max_mtu;
48935bbb 80
c139dbfd 81 /* priv init */
8f493ffd
SM
82 priv->mdev = mdev;
83 priv->netdev = netdev;
84 priv->profile = profile;
85 priv->ppriv = ppriv;
c139dbfd 86 mutex_init(&priv->state_lock);
8f493ffd 87
8e1d162d
FD
88 mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
89 netdev->mtu = max_mtu;
90
472a1e44
TT
91 mlx5e_build_nic_params(mdev, &priv->channels.params,
92 profile->max_nch(mdev), netdev->mtu);
b6dc510f 93 mlx5i_build_nic_params(mdev, &priv->channels.params);
5360fd47 94
237f258c
FD
95 mlx5e_timestamp_init(priv);
96
c139dbfd 97 /* netdev init */
603f4a45
SM
98 netdev->hw_features |= NETIF_F_SG;
99 netdev->hw_features |= NETIF_F_IP_CSUM;
100 netdev->hw_features |= NETIF_F_IPV6_CSUM;
101 netdev->hw_features |= NETIF_F_GRO;
102 netdev->hw_features |= NETIF_F_TSO;
103 netdev->hw_features |= NETIF_F_TSO6;
104 netdev->hw_features |= NETIF_F_RXCSUM;
105 netdev->hw_features |= NETIF_F_RXHASH;
106
107 netdev->netdev_ops = &mlx5i_netdev_ops;
076b0936 108 netdev->ethtool_ops = &mlx5i_ethtool_ops;
48935bbb
SM
109}
110
111/* Called directly before IPoIB netdevice is destroyed to cleanup SW structs */
112static void mlx5i_cleanup(struct mlx5e_priv *priv)
113{
114 /* Do nothing .. */
115}
116
af98cebc 117int mlx5i_init_underlay_qp(struct mlx5e_priv *priv)
c8249eda
AV
118{
119 struct mlx5_core_dev *mdev = priv->mdev;
120 struct mlx5i_priv *ipriv = priv->ppriv;
121 struct mlx5_core_qp *qp = &ipriv->qp;
122 struct mlx5_qp_context *context;
123 int ret;
124
125 /* QP states */
126 context = kzalloc(sizeof(*context), GFP_KERNEL);
127 if (!context)
128 return -ENOMEM;
129
130 context->flags = cpu_to_be32(MLX5_QP_PM_MIGRATED << 11);
131 context->pri_path.port = 1;
da34f1a8 132 context->pri_path.pkey_index = cpu_to_be16(ipriv->pkey_index);
c8249eda
AV
133 context->qkey = cpu_to_be32(IB_DEFAULT_Q_KEY);
134
135 ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RST2INIT_QP, 0, context, qp);
136 if (ret) {
137 mlx5_core_err(mdev, "Failed to modify qp RST2INIT, err: %d\n", ret);
138 goto err_qp_modify_to_err;
139 }
140 memset(context, 0, sizeof(*context));
141
142 ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_INIT2RTR_QP, 0, context, qp);
143 if (ret) {
144 mlx5_core_err(mdev, "Failed to modify qp INIT2RTR, err: %d\n", ret);
145 goto err_qp_modify_to_err;
146 }
147
148 ret = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_RTR2RTS_QP, 0, context, qp);
149 if (ret) {
150 mlx5_core_err(mdev, "Failed to modify qp RTR2RTS, err: %d\n", ret);
151 goto err_qp_modify_to_err;
152 }
153
154 kfree(context);
155 return 0;
156
157err_qp_modify_to_err:
158 mlx5_core_qp_modify(mdev, MLX5_CMD_OP_2ERR_QP, 0, &context, qp);
159 kfree(context);
160 return ret;
161}
162
af98cebc 163void mlx5i_uninit_underlay_qp(struct mlx5e_priv *priv)
c8249eda
AV
164{
165 struct mlx5i_priv *ipriv = priv->ppriv;
166 struct mlx5_core_dev *mdev = priv->mdev;
167 struct mlx5_qp_context context;
168 int err;
169
170 err = mlx5_core_qp_modify(mdev, MLX5_CMD_OP_2RST_QP, 0, &context,
171 &ipriv->qp);
172 if (err)
173 mlx5_core_err(mdev, "Failed to modify qp 2RST, err: %d\n", err);
174}
175
ec8fd927
SM
176#define MLX5_QP_ENHANCED_ULP_STATELESS_MODE 2
177
4c6c615e 178int mlx5i_create_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp)
ec8fd927 179{
ec8fd927
SM
180 u32 *in = NULL;
181 void *addr_path;
182 int ret = 0;
183 int inlen;
184 void *qpc;
185
186 inlen = MLX5_ST_SZ_BYTES(create_qp_in);
1b9a07ee 187 in = kvzalloc(inlen, GFP_KERNEL);
ec8fd927
SM
188 if (!in)
189 return -ENOMEM;
190
191 qpc = MLX5_ADDR_OF(create_qp_in, in, qpc);
192 MLX5_SET(qpc, qpc, st, MLX5_QP_ST_UD);
193 MLX5_SET(qpc, qpc, pm_state, MLX5_QP_PM_MIGRATED);
194 MLX5_SET(qpc, qpc, ulp_stateless_offload_mode,
195 MLX5_QP_ENHANCED_ULP_STATELESS_MODE);
196
197 addr_path = MLX5_ADDR_OF(qpc, qpc, primary_address_path);
32f69e4b 198 MLX5_SET(ads, addr_path, vhca_port_num, 1);
ec8fd927
SM
199 MLX5_SET(ads, addr_path, grh, 1);
200
201 ret = mlx5_core_create_qp(mdev, qp, in, inlen);
202 if (ret) {
203 mlx5_core_err(mdev, "Failed creating IPoIB QP err : %d\n", ret);
204 goto out;
205 }
206
ec8fd927 207out:
ec8fd927
SM
208 kvfree(in);
209 return ret;
210}
211
4c6c615e 212void mlx5i_destroy_underlay_qp(struct mlx5_core_dev *mdev, struct mlx5_core_qp *qp)
ec8fd927
SM
213{
214 mlx5_core_destroy_qp(mdev, qp);
215}
216
48935bbb
SM
217static int mlx5i_init_tx(struct mlx5e_priv *priv)
218{
5426a0b2
SM
219 struct mlx5i_priv *ipriv = priv->ppriv;
220 int err;
221
ec8fd927
SM
222 err = mlx5i_create_underlay_qp(priv->mdev, &ipriv->qp);
223 if (err) {
224 mlx5_core_warn(priv->mdev, "create underlay QP failed, %d\n", err);
225 return err;
226 }
5426a0b2
SM
227
228 err = mlx5e_create_tis(priv->mdev, 0 /* tc */, ipriv->qp.qpn, &priv->tisn[0]);
229 if (err) {
230 mlx5_core_warn(priv->mdev, "create tis failed, %d\n", err);
c8249eda 231 goto err_destroy_underlay_qp;
5426a0b2
SM
232 }
233
48935bbb 234 return 0;
c8249eda
AV
235
236err_destroy_underlay_qp:
237 mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp);
238 return err;
48935bbb
SM
239}
240
a7082ef0 241static void mlx5i_cleanup_tx(struct mlx5e_priv *priv)
48935bbb 242{
ec8fd927
SM
243 struct mlx5i_priv *ipriv = priv->ppriv;
244
5426a0b2 245 mlx5e_destroy_tis(priv->mdev, priv->tisn[0]);
ec8fd927 246 mlx5i_destroy_underlay_qp(priv->mdev, &ipriv->qp);
48935bbb
SM
247}
248
bc81b9d3
SM
249static int mlx5i_create_flow_steering(struct mlx5e_priv *priv)
250{
1ae1df3a
OG
251 struct ttc_params ttc_params = {};
252 int tt, err;
bc81b9d3
SM
253
254 priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
255 MLX5_FLOW_NAMESPACE_KERNEL);
256
257 if (!priv->fs.ns)
258 return -EINVAL;
259
260 err = mlx5e_arfs_create_tables(priv);
261 if (err) {
262 netdev_err(priv->netdev, "Failed to create arfs tables, err=%d\n",
263 err);
264 priv->netdev->hw_features &= ~NETIF_F_NTUPLE;
265 }
266
1ae1df3a
OG
267 mlx5e_set_ttc_basic_params(priv, &ttc_params);
268 mlx5e_set_inner_ttc_ft_params(&ttc_params);
269 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
270 ttc_params.indir_tirn[tt] = priv->inner_indir_tir[tt].tirn;
271
272 err = mlx5e_create_inner_ttc_table(priv, &ttc_params, &priv->fs.inner_ttc);
458821c7
FD
273 if (err) {
274 netdev_err(priv->netdev, "Failed to create inner ttc table, err=%d\n",
275 err);
276 goto err_destroy_arfs_tables;
277 }
278
1ae1df3a
OG
279 mlx5e_set_ttc_ft_params(&ttc_params);
280 for (tt = 0; tt < MLX5E_NUM_INDIR_TIRS; tt++)
468330e8 281 ttc_params.indir_tirn[tt] = priv->indir_tir[tt].tirn;
1ae1df3a
OG
282
283 err = mlx5e_create_ttc_table(priv, &ttc_params, &priv->fs.ttc);
bc81b9d3
SM
284 if (err) {
285 netdev_err(priv->netdev, "Failed to create ttc table, err=%d\n",
286 err);
458821c7 287 goto err_destroy_inner_ttc_table;
bc81b9d3
SM
288 }
289
290 return 0;
291
458821c7 292err_destroy_inner_ttc_table:
1ae1df3a 293 mlx5e_destroy_inner_ttc_table(priv, &priv->fs.inner_ttc);
bc81b9d3
SM
294err_destroy_arfs_tables:
295 mlx5e_arfs_destroy_tables(priv);
296
297 return err;
298}
299
300static void mlx5i_destroy_flow_steering(struct mlx5e_priv *priv)
301{
1ae1df3a
OG
302 mlx5e_destroy_ttc_table(priv, &priv->fs.ttc);
303 mlx5e_destroy_inner_ttc_table(priv, &priv->fs.inner_ttc);
bc81b9d3
SM
304 mlx5e_arfs_destroy_tables(priv);
305}
306
48935bbb
SM
307static int mlx5i_init_rx(struct mlx5e_priv *priv)
308{
8f493ffd
SM
309 int err;
310
311 err = mlx5e_create_indirect_rqt(priv);
312 if (err)
313 return err;
314
315 err = mlx5e_create_direct_rqts(priv);
316 if (err)
317 goto err_destroy_indirect_rqts;
318
319 err = mlx5e_create_indirect_tirs(priv);
320 if (err)
321 goto err_destroy_direct_rqts;
322
323 err = mlx5e_create_direct_tirs(priv);
324 if (err)
325 goto err_destroy_indirect_tirs;
326
58569ef8
AV
327 err = mlx5i_create_flow_steering(priv);
328 if (err)
dae37456 329 goto err_destroy_direct_tirs;
58569ef8 330
48935bbb 331 return 0;
8f493ffd 332
bc81b9d3
SM
333err_destroy_direct_tirs:
334 mlx5e_destroy_direct_tirs(priv);
8f493ffd
SM
335err_destroy_indirect_tirs:
336 mlx5e_destroy_indirect_tirs(priv);
337err_destroy_direct_rqts:
338 mlx5e_destroy_direct_rqts(priv);
339err_destroy_indirect_rqts:
340 mlx5e_destroy_rqt(priv, &priv->indir_rqt);
341 return err;
48935bbb
SM
342}
343
344static void mlx5i_cleanup_rx(struct mlx5e_priv *priv)
345{
bc81b9d3 346 mlx5i_destroy_flow_steering(priv);
8f493ffd
SM
347 mlx5e_destroy_direct_tirs(priv);
348 mlx5e_destroy_indirect_tirs(priv);
349 mlx5e_destroy_direct_rqts(priv);
350 mlx5e_destroy_rqt(priv, &priv->indir_rqt);
48935bbb
SM
351}
352
353static const struct mlx5e_profile mlx5i_nic_profile = {
354 .init = mlx5i_init,
355 .cleanup = mlx5i_cleanup,
356 .init_tx = mlx5i_init_tx,
357 .cleanup_tx = mlx5i_cleanup_tx,
358 .init_rx = mlx5i_init_rx,
359 .cleanup_rx = mlx5i_cleanup_rx,
360 .enable = NULL, /* mlx5i_enable */
361 .disable = NULL, /* mlx5i_disable */
362 .update_stats = NULL, /* mlx5i_update_stats */
363 .max_nch = mlx5e_get_max_num_channels,
7ca42c80 364 .update_carrier = NULL, /* no HW update in IB link */
9d6bd752
SM
365 .rx_handlers.handle_rx_cqe = mlx5i_handle_rx_cqe,
366 .rx_handlers.handle_rx_cqe_mpwqe = NULL, /* Not supported */
48935bbb
SM
367 .max_tc = MLX5I_MAX_NUM_TC,
368};
369
603f4a45
SM
370/* mlx5i netdev NDos */
371
807c4415
ES
372static int mlx5i_change_mtu(struct net_device *netdev, int new_mtu)
373{
374 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
375 struct mlx5e_channels new_channels = {};
472a1e44 376 struct mlx5e_params *params;
807c4415
ES
377 int err = 0;
378
379 mutex_lock(&priv->state_lock);
380
472a1e44 381 params = &priv->channels.params;
807c4415 382
472a1e44
TT
383 if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
384 params->sw_mtu = new_mtu;
385 netdev->mtu = params->sw_mtu;
807c4415 386 goto out;
472a1e44 387 }
807c4415 388
472a1e44
TT
389 new_channels.params = *params;
390 new_channels.params.sw_mtu = new_mtu;
807c4415 391 err = mlx5e_open_channels(priv, &new_channels);
472a1e44 392 if (err)
807c4415 393 goto out;
807c4415
ES
394
395 mlx5e_switch_priv_channels(priv, &new_channels, NULL);
472a1e44 396 netdev->mtu = new_channels.params.sw_mtu;
807c4415
ES
397
398out:
399 mutex_unlock(&priv->state_lock);
400 return err;
401}
402
af98cebc 403int mlx5i_dev_init(struct net_device *dev)
603f4a45
SM
404{
405 struct mlx5e_priv *priv = mlx5i_epriv(dev);
406 struct mlx5i_priv *ipriv = priv->ppriv;
407
408 /* Set dev address using underlay QP */
409 dev->dev_addr[1] = (ipriv->qp.qpn >> 16) & 0xff;
410 dev->dev_addr[2] = (ipriv->qp.qpn >> 8) & 0xff;
411 dev->dev_addr[3] = (ipriv->qp.qpn) & 0xff;
412
7e7f4780
AV
413 /* Add QPN to net-device mapping to HT */
414 mlx5i_pkey_add_qpn(dev ,ipriv->qp.qpn);
415
603f4a45
SM
416 return 0;
417}
418
08437c57 419int mlx5i_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1170fbd8
FD
420{
421 struct mlx5e_priv *priv = mlx5i_epriv(dev);
422
423 switch (cmd) {
424 case SIOCSHWTSTAMP:
425 return mlx5e_hwstamp_set(priv, ifr);
426 case SIOCGHWTSTAMP:
427 return mlx5e_hwstamp_get(priv, ifr);
428 default:
429 return -EOPNOTSUPP;
430 }
431}
432
af98cebc 433void mlx5i_dev_cleanup(struct net_device *dev)
603f4a45 434{
ec8fd927 435 struct mlx5e_priv *priv = mlx5i_epriv(dev);
7e7f4780 436 struct mlx5i_priv *ipriv = priv->ppriv;
ec8fd927 437
c8249eda 438 mlx5i_uninit_underlay_qp(priv);
7e7f4780
AV
439
440 /* Delete QPN to net-device mapping from HT */
441 mlx5i_pkey_del_qpn(dev, ipriv->qp.qpn);
603f4a45
SM
442}
443
444static int mlx5i_open(struct net_device *netdev)
445{
dae37456
AV
446 struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
447 struct mlx5i_priv *ipriv = epriv->ppriv;
448 struct mlx5_core_dev *mdev = epriv->mdev;
603f4a45
SM
449 int err;
450
dae37456 451 mutex_lock(&epriv->state_lock);
603f4a45 452
dae37456 453 set_bit(MLX5E_STATE_OPENED, &epriv->state);
603f4a45 454
dae37456
AV
455 err = mlx5i_init_underlay_qp(epriv);
456 if (err) {
457 mlx5_core_warn(mdev, "prepare underlay qp state failed, %d\n", err);
603f4a45 458 goto err_clear_state_opened_flag;
dae37456
AV
459 }
460
461 err = mlx5_fs_add_rx_underlay_qpn(mdev, ipriv->qp.qpn);
462 if (err) {
463 mlx5_core_warn(mdev, "attach underlay qp to ft failed, %d\n", err);
464 goto err_reset_qp;
465 }
603f4a45 466
dae37456
AV
467 err = mlx5e_open_channels(epriv, &epriv->channels);
468 if (err)
469 goto err_remove_fs_underlay_qp;
7ca42c80 470
dae37456
AV
471 mlx5e_refresh_tirs(epriv, false);
472 mlx5e_activate_priv_channels(epriv);
dae37456
AV
473
474 mutex_unlock(&epriv->state_lock);
603f4a45
SM
475 return 0;
476
dae37456
AV
477err_remove_fs_underlay_qp:
478 mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn);
479err_reset_qp:
480 mlx5i_uninit_underlay_qp(epriv);
603f4a45 481err_clear_state_opened_flag:
dae37456
AV
482 clear_bit(MLX5E_STATE_OPENED, &epriv->state);
483 mutex_unlock(&epriv->state_lock);
603f4a45
SM
484 return err;
485}
486
487static int mlx5i_close(struct net_device *netdev)
488{
dae37456
AV
489 struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
490 struct mlx5i_priv *ipriv = epriv->ppriv;
491 struct mlx5_core_dev *mdev = epriv->mdev;
603f4a45
SM
492
493 /* May already be CLOSED in case a previous configuration operation
494 * (e.g RX/TX queue size change) that involves close&open failed.
495 */
dae37456 496 mutex_lock(&epriv->state_lock);
603f4a45 497
dae37456 498 if (!test_bit(MLX5E_STATE_OPENED, &epriv->state))
603f4a45
SM
499 goto unlock;
500
dae37456 501 clear_bit(MLX5E_STATE_OPENED, &epriv->state);
603f4a45 502
dae37456
AV
503 netif_carrier_off(epriv->netdev);
504 mlx5_fs_remove_rx_underlay_qpn(mdev, ipriv->qp.qpn);
505 mlx5i_uninit_underlay_qp(epriv);
506 mlx5e_deactivate_priv_channels(epriv);
4c5386ba 507 mlx5e_close_channels(&epriv->channels);
603f4a45 508unlock:
dae37456 509 mutex_unlock(&epriv->state_lock);
603f4a45
SM
510 return 0;
511}
512
48935bbb 513/* IPoIB RDMA netdev callbacks */
a7082ef0 514static int mlx5i_attach_mcast(struct net_device *netdev, struct ib_device *hca,
693dfd5a
ES
515 union ib_gid *gid, u16 lid, int set_qkey,
516 u32 qkey)
ec8fd927
SM
517{
518 struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
519 struct mlx5_core_dev *mdev = epriv->mdev;
520 struct mlx5i_priv *ipriv = epriv->ppriv;
521 int err;
522
523 mlx5_core_dbg(mdev, "attaching QPN 0x%x, MGID %pI6\n", ipriv->qp.qpn, gid->raw);
524 err = mlx5_core_attach_mcg(mdev, gid, ipriv->qp.qpn);
525 if (err)
526 mlx5_core_warn(mdev, "failed attaching QPN 0x%x, MGID %pI6\n",
527 ipriv->qp.qpn, gid->raw);
528
693dfd5a
ES
529 if (set_qkey) {
530 mlx5_core_dbg(mdev, "%s setting qkey 0x%x\n",
531 netdev->name, qkey);
532 ipriv->qkey = qkey;
533 }
534
ec8fd927
SM
535 return err;
536}
537
a7082ef0
SH
538static int mlx5i_detach_mcast(struct net_device *netdev, struct ib_device *hca,
539 union ib_gid *gid, u16 lid)
ec8fd927
SM
540{
541 struct mlx5e_priv *epriv = mlx5i_epriv(netdev);
542 struct mlx5_core_dev *mdev = epriv->mdev;
543 struct mlx5i_priv *ipriv = epriv->ppriv;
544 int err;
545
546 mlx5_core_dbg(mdev, "detaching QPN 0x%x, MGID %pI6\n", ipriv->qp.qpn, gid->raw);
547
548 err = mlx5_core_detach_mcg(mdev, gid, ipriv->qp.qpn);
549 if (err)
53378898 550 mlx5_core_dbg(mdev, "failed detaching QPN 0x%x, MGID %pI6\n",
ec8fd927
SM
551 ipriv->qp.qpn, gid->raw);
552
553 return err;
554}
48935bbb 555
a7082ef0 556static int mlx5i_xmit(struct net_device *dev, struct sk_buff *skb,
693dfd5a 557 struct ib_ah *address, u32 dqpn)
25854544
SM
558{
559 struct mlx5e_priv *epriv = mlx5i_epriv(dev);
560 struct mlx5e_txqsq *sq = epriv->txq2sq[skb_get_queue_mapping(skb)];
561 struct mlx5_ib_ah *mah = to_mah(address);
693dfd5a 562 struct mlx5i_priv *ipriv = epriv->ppriv;
25854544 563
693dfd5a 564 return mlx5i_sq_xmit(sq, skb, &mah->av, dqpn, ipriv->qkey);
25854544
SM
565}
566
da34f1a8
AV
567static void mlx5i_set_pkey_index(struct net_device *netdev, int id)
568{
569 struct mlx5i_priv *ipriv = netdev_priv(netdev);
570
571 ipriv->pkey_index = (u16)id;
572}
573
48935bbb
SM
574static int mlx5i_check_required_hca_cap(struct mlx5_core_dev *mdev)
575{
576 if (MLX5_CAP_GEN(mdev, port_type) != MLX5_CAP_PORT_TYPE_IB)
577 return -EOPNOTSUPP;
578
579 if (!MLX5_CAP_GEN(mdev, ipoib_enhanced_offloads)) {
580 mlx5_core_warn(mdev, "IPoIB enhanced offloads are not supported\n");
693dfd5a 581 return -EOPNOTSUPP;
48935bbb
SM
582 }
583
584 return 0;
585}
586
693dfd5a
ES
587struct net_device *mlx5_rdma_netdev_alloc(struct mlx5_core_dev *mdev,
588 struct ib_device *ibdev,
589 const char *name,
590 void (*setup)(struct net_device *))
48935bbb 591{
b5ae5777 592 const struct mlx5e_profile *profile;
48935bbb
SM
593 struct net_device *netdev;
594 struct mlx5i_priv *ipriv;
595 struct mlx5e_priv *epriv;
693dfd5a 596 struct rdma_netdev *rn;
b5ae5777
AV
597 bool sub_interface;
598 int nch;
48935bbb
SM
599 int err;
600
601 if (mlx5i_check_required_hca_cap(mdev)) {
602 mlx5_core_warn(mdev, "Accelerated mode is not supported\n");
603 return ERR_PTR(-EOPNOTSUPP);
604 }
605
b5ae5777
AV
606 /* TODO: Need to find a better way to check if child device*/
607 sub_interface = (mdev->mlx5e_res.pdn != 0);
608
609 if (sub_interface)
610 profile = mlx5i_pkey_get_profile();
611 else
612 profile = &mlx5i_nic_profile;
613
614 nch = profile->max_nch(mdev);
48935bbb
SM
615
616 netdev = alloc_netdev_mqs(sizeof(struct mlx5i_priv) + sizeof(struct mlx5e_priv),
617 name, NET_NAME_UNKNOWN,
618 setup,
619 nch * MLX5E_MAX_NUM_TC,
620 nch);
621 if (!netdev) {
622 mlx5_core_warn(mdev, "alloc_netdev_mqs failed\n");
b5ae5777 623 return NULL;
48935bbb
SM
624 }
625
626 ipriv = netdev_priv(netdev);
627 epriv = mlx5i_epriv(netdev);
628
629 epriv->wq = create_singlethread_workqueue("mlx5i");
630 if (!epriv->wq)
631 goto err_free_netdev;
632
b5ae5777
AV
633 ipriv->sub_interface = sub_interface;
634 if (!ipriv->sub_interface) {
635 err = mlx5i_pkey_qpn_ht_init(netdev);
636 if (err) {
637 mlx5_core_warn(mdev, "allocate qpn_to_netdev ht failed\n");
638 goto destroy_wq;
639 }
640
641 /* This should only be called once per mdev */
642 err = mlx5e_create_mdev_resources(mdev);
643 if (err)
644 goto destroy_ht;
7e7f4780
AV
645 }
646
48935bbb
SM
647 profile->init(mdev, netdev, profile, ipriv);
648
649 mlx5e_attach_netdev(epriv);
650 netif_carrier_off(netdev);
651
693dfd5a
ES
652 /* set rdma_netdev func pointers */
653 rn = &ipriv->rn;
654 rn->hca = ibdev;
655 rn->send = mlx5i_xmit;
656 rn->attach_mcast = mlx5i_attach_mcast;
657 rn->detach_mcast = mlx5i_detach_mcast;
da34f1a8 658 rn->set_id = mlx5i_set_pkey_index;
693dfd5a 659
48935bbb
SM
660 return netdev;
661
b5ae5777
AV
662destroy_ht:
663 mlx5i_pkey_qpn_ht_cleanup(netdev);
7e7f4780
AV
664destroy_wq:
665 destroy_workqueue(epriv->wq);
48935bbb
SM
666err_free_netdev:
667 free_netdev(netdev);
6905e5a5 668
48935bbb
SM
669 return NULL;
670}
671EXPORT_SYMBOL(mlx5_rdma_netdev_alloc);
672
693dfd5a 673void mlx5_rdma_netdev_free(struct net_device *netdev)
48935bbb 674{
b5ae5777
AV
675 struct mlx5e_priv *priv = mlx5i_epriv(netdev);
676 struct mlx5i_priv *ipriv = priv->ppriv;
48935bbb
SM
677 const struct mlx5e_profile *profile = priv->profile;
678
679 mlx5e_detach_netdev(priv);
680 profile->cleanup(priv);
681 destroy_workqueue(priv->wq);
48935bbb 682
b5ae5777
AV
683 if (!ipriv->sub_interface) {
684 mlx5i_pkey_qpn_ht_cleanup(netdev);
685 mlx5e_destroy_mdev_resources(priv->mdev);
686 }
687 free_netdev(netdev);
48935bbb
SM
688}
689EXPORT_SYMBOL(mlx5_rdma_netdev_free);