1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33#include <linux/mlx5/fs.h>
34#include <net/switchdev.h>
35#include <net/pkt_cls.h>
36#include <net/act_api.h>
37#include <net/devlink.h>
38#include <net/ipv6_stubs.h>
39
40#include "eswitch.h"
41#include "en.h"
42#include "en_rep.h"
43#include "en/params.h"
44#include "en/txrx.h"
45#include "en_tc.h"
46#include "en/rep/tc.h"
47#include "en/rep/neigh.h"
48#include "en/rep/bridge.h"
49#include "en/devlink.h"
50#include "fs_core.h"
51#include "lib/mlx5.h"
52#include "lib/devcom.h"
53#define CREATE_TRACE_POINTS
54#include "diag/en_rep_tracepoint.h"
55#include "en_accel/ipsec.h"
56
57#define MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE \
58 max(0x7, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
59#define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1
60
61static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
62
63static void mlx5e_rep_get_drvinfo(struct net_device *dev,
64 struct ethtool_drvinfo *drvinfo)
65{
66 struct mlx5e_priv *priv = netdev_priv(dev);
67 struct mlx5_core_dev *mdev = priv->mdev;
68
69 strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
70 sizeof(drvinfo->driver));
71 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
72 "%d.%d.%04d (%.16s)",
73 fw_rev_maj(mdev), fw_rev_min(mdev),
74 fw_rev_sub(mdev), mdev->board_id);
75}
76
77static const struct counter_desc sw_rep_stats_desc[] = {
78 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) },
79 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) },
80 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) },
81 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) },
82};
83
84struct vport_stats {
85 u64 vport_rx_packets;
86 u64 vport_tx_packets;
87 u64 vport_rx_bytes;
88 u64 vport_tx_bytes;
89};
90
91static const struct counter_desc vport_rep_stats_desc[] = {
92 { MLX5E_DECLARE_STAT(struct vport_stats, vport_rx_packets) },
93 { MLX5E_DECLARE_STAT(struct vport_stats, vport_rx_bytes) },
94 { MLX5E_DECLARE_STAT(struct vport_stats, vport_tx_packets) },
95 { MLX5E_DECLARE_STAT(struct vport_stats, vport_tx_bytes) },
96};
97
98#define NUM_VPORT_REP_SW_COUNTERS ARRAY_SIZE(sw_rep_stats_desc)
99#define NUM_VPORT_REP_HW_COUNTERS ARRAY_SIZE(vport_rep_stats_desc)
100
101static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(sw_rep)
102{
103 return NUM_VPORT_REP_SW_COUNTERS;
104}
105
106static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(sw_rep)
107{
108 int i;
109
110 for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++)
111 strcpy(data + (idx++) * ETH_GSTRING_LEN,
112 sw_rep_stats_desc[i].format);
113 return idx;
114}
115
116static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(sw_rep)
117{
118 int i;
119
120 for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++)
121 data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.sw,
122 sw_rep_stats_desc, i);
123 return idx;
124}
125
126static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(sw_rep)
127{
128 struct mlx5e_sw_stats *s = &priv->stats.sw;
129 struct rtnl_link_stats64 stats64 = {};
130
131 memset(s, 0, sizeof(*s));
132 mlx5e_fold_sw_stats64(priv, &stats64);
133
134 s->rx_packets = stats64.rx_packets;
135 s->rx_bytes = stats64.rx_bytes;
136 s->tx_packets = stats64.tx_packets;
137 s->tx_bytes = stats64.tx_bytes;
138 s->tx_queue_dropped = stats64.tx_dropped;
139}
140
141static MLX5E_DECLARE_STATS_GRP_OP_NUM_STATS(vport_rep)
142{
143 return NUM_VPORT_REP_HW_COUNTERS;
144}
145
146static MLX5E_DECLARE_STATS_GRP_OP_FILL_STRS(vport_rep)
147{
148 int i;
149
150 for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++)
151 strcpy(data + (idx++) * ETH_GSTRING_LEN, vport_rep_stats_desc[i].format);
152 return idx;
153}
154
155static MLX5E_DECLARE_STATS_GRP_OP_FILL_STATS(vport_rep)
156{
157 int i;
158
159 for (i = 0; i < NUM_VPORT_REP_HW_COUNTERS; i++)
160 data[idx++] = MLX5E_READ_CTR64_CPU(&priv->stats.vf_vport,
161 vport_rep_stats_desc, i);
162 return idx;
163}
164
165static MLX5E_DECLARE_STATS_GRP_OP_UPDATE_STATS(vport_rep)
166{
167 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
168 struct mlx5e_rep_priv *rpriv = priv->ppriv;
169 struct mlx5_eswitch_rep *rep = rpriv->rep;
170 struct rtnl_link_stats64 *vport_stats;
171 struct ifla_vf_stats vf_stats;
172 int err;
173
174 err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats);
175 if (err) {
176 netdev_warn(priv->netdev, "vport %d error %d reading stats\n",
177 rep->vport, err);
178 return;
179 }
180
181 vport_stats = &priv->stats.vf_vport;
182
183 vport_stats->rx_packets = vf_stats.tx_packets;
184 vport_stats->rx_bytes = vf_stats.tx_bytes;
185 vport_stats->tx_packets = vf_stats.rx_packets;
186 vport_stats->tx_bytes = vf_stats.rx_bytes;
187}
188
189static void mlx5e_rep_get_strings(struct net_device *dev,
190 u32 stringset, uint8_t *data)
191{
192 struct mlx5e_priv *priv = netdev_priv(dev);
193
194 switch (stringset) {
195 case ETH_SS_STATS:
196 mlx5e_stats_fill_strings(priv, data);
197 break;
198 }
199}
200
201static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
202 struct ethtool_stats *stats, u64 *data)
203{
204 struct mlx5e_priv *priv = netdev_priv(dev);
205
206 mlx5e_ethtool_get_ethtool_stats(priv, stats, data);
207}
208
209static int mlx5e_rep_get_sset_count(struct net_device *dev, int sset)
210{
211 struct mlx5e_priv *priv = netdev_priv(dev);
212
213 switch (sset) {
214 case ETH_SS_STATS:
215 return mlx5e_stats_total_num(priv);
216 default:
217 return -EOPNOTSUPP;
218 }
219}
220
221static void mlx5e_rep_get_ringparam(struct net_device *dev,
222 struct ethtool_ringparam *param)
223{
224 struct mlx5e_priv *priv = netdev_priv(dev);
225
226 mlx5e_ethtool_get_ringparam(priv, param);
227}
228
229static int mlx5e_rep_set_ringparam(struct net_device *dev,
230 struct ethtool_ringparam *param)
231{
232 struct mlx5e_priv *priv = netdev_priv(dev);
233
234 return mlx5e_ethtool_set_ringparam(priv, param);
235}
236
237static void mlx5e_rep_get_channels(struct net_device *dev,
238 struct ethtool_channels *ch)
239{
240 struct mlx5e_priv *priv = netdev_priv(dev);
241
242 mlx5e_ethtool_get_channels(priv, ch);
243}
244
245static int mlx5e_rep_set_channels(struct net_device *dev,
246 struct ethtool_channels *ch)
247{
248 struct mlx5e_priv *priv = netdev_priv(dev);
249
250 return mlx5e_ethtool_set_channels(priv, ch);
251}
252
253static int mlx5e_rep_get_coalesce(struct net_device *netdev,
254 struct ethtool_coalesce *coal,
255 struct kernel_ethtool_coalesce *kernel_coal,
256 struct netlink_ext_ack *extack)
257{
258 struct mlx5e_priv *priv = netdev_priv(netdev);
259
260 return mlx5e_ethtool_get_coalesce(priv, coal);
261}
262
263static int mlx5e_rep_set_coalesce(struct net_device *netdev,
264 struct ethtool_coalesce *coal,
265 struct kernel_ethtool_coalesce *kernel_coal,
266 struct netlink_ext_ack *extack)
267{
268 struct mlx5e_priv *priv = netdev_priv(netdev);
269
270 return mlx5e_ethtool_set_coalesce(priv, coal);
271}
272
273static u32 mlx5e_rep_get_rxfh_key_size(struct net_device *netdev)
274{
275 struct mlx5e_priv *priv = netdev_priv(netdev);
276
277 return mlx5e_ethtool_get_rxfh_key_size(priv);
278}
279
280static u32 mlx5e_rep_get_rxfh_indir_size(struct net_device *netdev)
281{
282 struct mlx5e_priv *priv = netdev_priv(netdev);
283
284 return mlx5e_ethtool_get_rxfh_indir_size(priv);
285}
286
287static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
288 .supported_coalesce_params = ETHTOOL_COALESCE_USECS |
289 ETHTOOL_COALESCE_MAX_FRAMES |
290 ETHTOOL_COALESCE_USE_ADAPTIVE,
291 .get_drvinfo = mlx5e_rep_get_drvinfo,
292 .get_link = ethtool_op_get_link,
293 .get_strings = mlx5e_rep_get_strings,
294 .get_sset_count = mlx5e_rep_get_sset_count,
295 .get_ethtool_stats = mlx5e_rep_get_ethtool_stats,
296 .get_ringparam = mlx5e_rep_get_ringparam,
297 .set_ringparam = mlx5e_rep_set_ringparam,
298 .get_channels = mlx5e_rep_get_channels,
299 .set_channels = mlx5e_rep_set_channels,
300 .get_coalesce = mlx5e_rep_get_coalesce,
301 .set_coalesce = mlx5e_rep_set_coalesce,
302 .get_rxfh_key_size = mlx5e_rep_get_rxfh_key_size,
303 .get_rxfh_indir_size = mlx5e_rep_get_rxfh_indir_size,
304};
305
306static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
307 struct mlx5_eswitch_rep *rep)
308{
309 struct mlx5e_rep_sq *rep_sq, *tmp;
310 struct mlx5e_rep_priv *rpriv;
311
312 if (esw->mode != MLX5_ESWITCH_OFFLOADS)
313 return;
314
315 rpriv = mlx5e_rep_to_rep_priv(rep);
316 list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) {
317 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
318 if (rep_sq->send_to_vport_rule_peer)
319 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
320 list_del(&rep_sq->list);
321 kfree(rep_sq);
322 }
323}
324
325static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
326 struct mlx5_eswitch_rep *rep,
327 u32 *sqns_array, int sqns_num)
328{
329 struct mlx5_eswitch *peer_esw = NULL;
330 struct mlx5_flow_handle *flow_rule;
331 struct mlx5e_rep_priv *rpriv;
332 struct mlx5e_rep_sq *rep_sq;
333 int err;
334 int i;
335
336 if (esw->mode != MLX5_ESWITCH_OFFLOADS)
337 return 0;
338
339 rpriv = mlx5e_rep_to_rep_priv(rep);
340 if (mlx5_devcom_is_paired(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS))
341 peer_esw = mlx5_devcom_get_peer_data(esw->dev->priv.devcom,
342 MLX5_DEVCOM_ESW_OFFLOADS);
343
344 for (i = 0; i < sqns_num; i++) {
345 rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL);
346 if (!rep_sq) {
347 err = -ENOMEM;
348 goto out_err;
349 }
350
351
352 flow_rule = mlx5_eswitch_add_send_to_vport_rule(esw, esw, rep,
353 sqns_array[i]);
354 if (IS_ERR(flow_rule)) {
355 err = PTR_ERR(flow_rule);
356 kfree(rep_sq);
357 goto out_err;
358 }
359 rep_sq->send_to_vport_rule = flow_rule;
360 rep_sq->sqn = sqns_array[i];
361
362 if (peer_esw) {
363 flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw,
364 rep, sqns_array[i]);
365 if (IS_ERR(flow_rule)) {
366 err = PTR_ERR(flow_rule);
367 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
368 kfree(rep_sq);
369 goto out_err;
370 }
371 rep_sq->send_to_vport_rule_peer = flow_rule;
372 }
373
374 list_add(&rep_sq->list, &rpriv->vport_sqs_list);
375 }
376
377 if (peer_esw)
378 mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
379
380 return 0;
381
382out_err:
383 mlx5e_sqs2vport_stop(esw, rep);
384
385 if (peer_esw)
386 mlx5_devcom_release_peer_data(esw->dev->priv.devcom, MLX5_DEVCOM_ESW_OFFLOADS);
387
388 return err;
389}
390
391int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
392{
393 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
394 struct mlx5e_rep_priv *rpriv = priv->ppriv;
395 struct mlx5_eswitch_rep *rep = rpriv->rep;
396 struct mlx5e_channel *c;
397 int n, tc, num_sqs = 0;
398 int err = -ENOMEM;
399 u32 *sqs;
400
401 sqs = kcalloc(priv->channels.num * mlx5e_get_dcb_num_tc(&priv->channels.params),
402 sizeof(*sqs), GFP_KERNEL);
403 if (!sqs)
404 goto out;
405
406 for (n = 0; n < priv->channels.num; n++) {
407 c = priv->channels.c[n];
408 for (tc = 0; tc < c->num_tc; tc++)
409 sqs[num_sqs++] = c->sq[tc].sqn;
410 }
411
412 err = mlx5e_sqs2vport_start(esw, rep, sqs, num_sqs);
413 kfree(sqs);
414
415out:
416 if (err)
417 netdev_warn(priv->netdev, "Failed to add SQs FWD rules %d\n", err);
418 return err;
419}
420
421void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
422{
423 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
424 struct mlx5e_rep_priv *rpriv = priv->ppriv;
425 struct mlx5_eswitch_rep *rep = rpriv->rep;
426
427 mlx5e_sqs2vport_stop(esw, rep);
428}
429
430static int mlx5e_rep_open(struct net_device *dev)
431{
432 struct mlx5e_priv *priv = netdev_priv(dev);
433 struct mlx5e_rep_priv *rpriv = priv->ppriv;
434 struct mlx5_eswitch_rep *rep = rpriv->rep;
435 int err;
436
437 mutex_lock(&priv->state_lock);
438 err = mlx5e_open_locked(dev);
439 if (err)
440 goto unlock;
441
442 if (!mlx5_modify_vport_admin_state(priv->mdev,
443 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
444 rep->vport, 1,
445 MLX5_VPORT_ADMIN_STATE_UP))
446 netif_carrier_on(dev);
447
448unlock:
449 mutex_unlock(&priv->state_lock);
450 return err;
451}
452
453static int mlx5e_rep_close(struct net_device *dev)
454{
455 struct mlx5e_priv *priv = netdev_priv(dev);
456 struct mlx5e_rep_priv *rpriv = priv->ppriv;
457 struct mlx5_eswitch_rep *rep = rpriv->rep;
458 int ret;
459
460 mutex_lock(&priv->state_lock);
461 mlx5_modify_vport_admin_state(priv->mdev,
462 MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
463 rep->vport, 1,
464 MLX5_VPORT_ADMIN_STATE_DOWN);
465 ret = mlx5e_close_locked(dev);
466 mutex_unlock(&priv->state_lock);
467 return ret;
468}
469
470bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
471{
472 struct mlx5e_rep_priv *rpriv = priv->ppriv;
473 struct mlx5_eswitch_rep *rep;
474
475 if (!MLX5_ESWITCH_MANAGER(priv->mdev))
476 return false;
477
478 if (!rpriv)
479 return false;
480
481 rep = rpriv->rep;
482 return (rep->vport == MLX5_VPORT_UPLINK);
483}
484
485bool mlx5e_rep_has_offload_stats(const struct net_device *dev, int attr_id)
486{
487 switch (attr_id) {
488 case IFLA_OFFLOAD_XSTATS_CPU_HIT:
489 return true;
490 }
491
492 return false;
493}
494
495static int
496mlx5e_get_sw_stats64(const struct net_device *dev,
497 struct rtnl_link_stats64 *stats)
498{
499 struct mlx5e_priv *priv = netdev_priv(dev);
500
501 mlx5e_fold_sw_stats64(priv, stats);
502 return 0;
503}
504
505int mlx5e_rep_get_offload_stats(int attr_id, const struct net_device *dev,
506 void *sp)
507{
508 switch (attr_id) {
509 case IFLA_OFFLOAD_XSTATS_CPU_HIT:
510 return mlx5e_get_sw_stats64(dev, sp);
511 }
512
513 return -EINVAL;
514}
515
516static void
517mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
518{
519 struct mlx5e_priv *priv = netdev_priv(dev);
520
521
522 mlx5e_queue_update_stats(priv);
523 memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
524}
525
526static int mlx5e_rep_change_mtu(struct net_device *netdev, int new_mtu)
527{
528 return mlx5e_change_mtu(netdev, new_mtu, NULL);
529}
530
531static struct devlink_port *mlx5e_rep_get_devlink_port(struct net_device *netdev)
532{
533 struct mlx5e_priv *priv = netdev_priv(netdev);
534 struct mlx5e_rep_priv *rpriv = priv->ppriv;
535 struct mlx5_core_dev *dev = priv->mdev;
536
537 return mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
538}
539
540static int mlx5e_rep_change_carrier(struct net_device *dev, bool new_carrier)
541{
542 struct mlx5e_priv *priv = netdev_priv(dev);
543 struct mlx5e_rep_priv *rpriv = priv->ppriv;
544 struct mlx5_eswitch_rep *rep = rpriv->rep;
545 int err;
546
547 if (new_carrier) {
548 err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
549 rep->vport, 1, MLX5_VPORT_ADMIN_STATE_UP);
550 if (err)
551 return err;
552 netif_carrier_on(dev);
553 } else {
554 err = mlx5_modify_vport_admin_state(priv->mdev, MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
555 rep->vport, 1, MLX5_VPORT_ADMIN_STATE_DOWN);
556 if (err)
557 return err;
558 netif_carrier_off(dev);
559 }
560 return 0;
561}
562
563static const struct net_device_ops mlx5e_netdev_ops_rep = {
564 .ndo_open = mlx5e_rep_open,
565 .ndo_stop = mlx5e_rep_close,
566 .ndo_start_xmit = mlx5e_xmit,
567 .ndo_setup_tc = mlx5e_rep_setup_tc,
568 .ndo_get_devlink_port = mlx5e_rep_get_devlink_port,
569 .ndo_get_stats64 = mlx5e_rep_get_stats,
570 .ndo_has_offload_stats = mlx5e_rep_has_offload_stats,
571 .ndo_get_offload_stats = mlx5e_rep_get_offload_stats,
572 .ndo_change_mtu = mlx5e_rep_change_mtu,
573 .ndo_change_carrier = mlx5e_rep_change_carrier,
574};
575
576bool mlx5e_eswitch_uplink_rep(const struct net_device *netdev)
577{
578 return netdev->netdev_ops == &mlx5e_netdev_ops &&
579 mlx5e_is_uplink_rep(netdev_priv(netdev));
580}
581
582bool mlx5e_eswitch_vf_rep(const struct net_device *netdev)
583{
584 return netdev->netdev_ops == &mlx5e_netdev_ops_rep;
585}
586
587static void mlx5e_build_rep_params(struct net_device *netdev)
588{
589 struct mlx5e_priv *priv = netdev_priv(netdev);
590 struct mlx5e_rep_priv *rpriv = priv->ppriv;
591 struct mlx5_eswitch_rep *rep = rpriv->rep;
592 struct mlx5_core_dev *mdev = priv->mdev;
593 struct mlx5e_params *params;
594
595 u8 cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
596 MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
597 MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
598
599 params = &priv->channels.params;
600
601 params->num_channels = MLX5E_REP_PARAMS_DEF_NUM_CHANNELS;
602 params->hard_mtu = MLX5E_ETH_HARD_MTU;
603 params->sw_mtu = netdev->mtu;
604
605
606 if (rep->vport == MLX5_VPORT_UPLINK)
607 params->log_sq_size = MLX5E_PARAMS_DEFAULT_LOG_SQ_SIZE;
608 else
609 params->log_sq_size = MLX5E_REP_PARAMS_DEF_LOG_SQ_SIZE;
610
611
612 mlx5e_build_rq_params(mdev, params);
613
614
615 params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
616 mlx5e_set_rx_cq_mode_params(params, cq_period_mode);
617
618 params->mqprio.num_tc = 1;
619 params->tunneled_offload_en = false;
620
621
622
623
624 priv->num_tc_x_num_ch = params->num_channels * params->mqprio.num_tc;
625
626 mlx5_query_min_inline(mdev, ¶ms->tx_min_inline_mode);
627}
628
629static void mlx5e_build_rep_netdev(struct net_device *netdev,
630 struct mlx5_core_dev *mdev)
631{
632 SET_NETDEV_DEV(netdev, mdev->device);
633 netdev->netdev_ops = &mlx5e_netdev_ops_rep;
634 eth_hw_addr_random(netdev);
635 netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
636
637 netdev->watchdog_timeo = 15 * HZ;
638
639#if IS_ENABLED(CONFIG_MLX5_CLS_ACT)
640 netdev->hw_features |= NETIF_F_HW_TC;
641#endif
642 netdev->hw_features |= NETIF_F_SG;
643 netdev->hw_features |= NETIF_F_IP_CSUM;
644 netdev->hw_features |= NETIF_F_IPV6_CSUM;
645 netdev->hw_features |= NETIF_F_GRO;
646 netdev->hw_features |= NETIF_F_TSO;
647 netdev->hw_features |= NETIF_F_TSO6;
648 netdev->hw_features |= NETIF_F_RXCSUM;
649
650 netdev->features |= netdev->hw_features;
651 netdev->features |= NETIF_F_NETNS_LOCAL;
652}
653
654static int mlx5e_init_rep(struct mlx5_core_dev *mdev,
655 struct net_device *netdev)
656{
657 struct mlx5e_priv *priv = netdev_priv(netdev);
658
659 mlx5e_build_rep_params(netdev);
660 mlx5e_timestamp_init(priv);
661
662 return 0;
663}
664
665static int mlx5e_init_ul_rep(struct mlx5_core_dev *mdev,
666 struct net_device *netdev)
667{
668 struct mlx5e_priv *priv = netdev_priv(netdev);
669 int err;
670
671 err = mlx5e_ipsec_init(priv);
672 if (err)
673 mlx5_core_err(mdev, "Uplink rep IPsec initialization failed, %d\n", err);
674
675 mlx5e_vxlan_set_netdev_info(priv);
676 return mlx5e_init_rep(mdev, netdev);
677}
678
679static void mlx5e_cleanup_rep(struct mlx5e_priv *priv)
680{
681 mlx5e_ipsec_cleanup(priv);
682}
683
684static int mlx5e_create_rep_ttc_table(struct mlx5e_priv *priv)
685{
686 struct mlx5e_rep_priv *rpriv = priv->ppriv;
687 struct mlx5_eswitch_rep *rep = rpriv->rep;
688 struct ttc_params ttc_params = {};
689 int err;
690
691 priv->fs.ns = mlx5_get_flow_namespace(priv->mdev,
692 MLX5_FLOW_NAMESPACE_KERNEL);
693
694
695 mlx5e_set_ttc_params(priv, &ttc_params, false);
696
697 if (rep->vport != MLX5_VPORT_UPLINK)
698
699 ttc_params.ft_attr.level = MLX5E_TTC_FT_LEVEL + 1;
700
701 priv->fs.ttc = mlx5_create_ttc_table(priv->mdev, &ttc_params);
702 if (IS_ERR(priv->fs.ttc)) {
703 err = PTR_ERR(priv->fs.ttc);
704 netdev_err(priv->netdev, "Failed to create rep ttc table, err=%d\n",
705 err);
706 return err;
707 }
708 return 0;
709}
710
711static int mlx5e_create_rep_root_ft(struct mlx5e_priv *priv)
712{
713 struct mlx5e_rep_priv *rpriv = priv->ppriv;
714 struct mlx5_eswitch_rep *rep = rpriv->rep;
715 struct mlx5_flow_table_attr ft_attr = {};
716 struct mlx5_flow_namespace *ns;
717 int err = 0;
718
719 if (rep->vport != MLX5_VPORT_UPLINK) {
720
721
722
723 rpriv->root_ft = mlx5_get_ttc_flow_table(priv->fs.ttc);
724 return 0;
725 }
726
727
728 ns = mlx5_get_flow_namespace(priv->mdev, MLX5_FLOW_NAMESPACE_OFFLOADS);
729 if (!ns) {
730 netdev_err(priv->netdev, "Failed to get reps offloads namespace\n");
731 return -EOPNOTSUPP;
732 }
733
734 ft_attr.max_fte = 0;
735 ft_attr.prio = 1;
736 ft_attr.level = 1;
737
738 rpriv->root_ft = mlx5_create_flow_table(ns, &ft_attr);
739 if (IS_ERR(rpriv->root_ft)) {
740 err = PTR_ERR(rpriv->root_ft);
741 rpriv->root_ft = NULL;
742 }
743
744 return err;
745}
746
747static void mlx5e_destroy_rep_root_ft(struct mlx5e_priv *priv)
748{
749 struct mlx5e_rep_priv *rpriv = priv->ppriv;
750 struct mlx5_eswitch_rep *rep = rpriv->rep;
751
752 if (rep->vport != MLX5_VPORT_UPLINK)
753 return;
754 mlx5_destroy_flow_table(rpriv->root_ft);
755}
756
757static int mlx5e_create_rep_vport_rx_rule(struct mlx5e_priv *priv)
758{
759 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
760 struct mlx5e_rep_priv *rpriv = priv->ppriv;
761 struct mlx5_eswitch_rep *rep = rpriv->rep;
762 struct mlx5_flow_handle *flow_rule;
763 struct mlx5_flow_destination dest;
764
765 dest.type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
766 dest.ft = rpriv->root_ft;
767
768 flow_rule = mlx5_eswitch_create_vport_rx_rule(esw, rep->vport, &dest);
769 if (IS_ERR(flow_rule))
770 return PTR_ERR(flow_rule);
771 rpriv->vport_rx_rule = flow_rule;
772 return 0;
773}
774
775static void rep_vport_rx_rule_destroy(struct mlx5e_priv *priv)
776{
777 struct mlx5e_rep_priv *rpriv = priv->ppriv;
778
779 if (!rpriv->vport_rx_rule)
780 return;
781
782 mlx5_del_flow_rules(rpriv->vport_rx_rule);
783 rpriv->vport_rx_rule = NULL;
784}
785
786int mlx5e_rep_bond_update(struct mlx5e_priv *priv, bool cleanup)
787{
788 rep_vport_rx_rule_destroy(priv);
789
790 return cleanup ? 0 : mlx5e_create_rep_vport_rx_rule(priv);
791}
792
793static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
794{
795 struct mlx5_core_dev *mdev = priv->mdev;
796 struct mlx5e_lro_param lro_param;
797 int err;
798
799 priv->rx_res = mlx5e_rx_res_alloc();
800 if (!priv->rx_res)
801 return -ENOMEM;
802
803 mlx5e_init_l2_addr(priv);
804
805 err = mlx5e_open_drop_rq(priv, &priv->drop_rq);
806 if (err) {
807 mlx5_core_err(mdev, "open drop rq failed, %d\n", err);
808 return err;
809 }
810
811 lro_param = mlx5e_get_lro_param(&priv->channels.params);
812 err = mlx5e_rx_res_init(priv->rx_res, priv->mdev, 0,
813 priv->max_nch, priv->drop_rq.rqn, &lro_param,
814 priv->channels.params.num_channels);
815 if (err)
816 goto err_close_drop_rq;
817
818 err = mlx5e_create_rep_ttc_table(priv);
819 if (err)
820 goto err_destroy_rx_res;
821
822 err = mlx5e_create_rep_root_ft(priv);
823 if (err)
824 goto err_destroy_ttc_table;
825
826 err = mlx5e_create_rep_vport_rx_rule(priv);
827 if (err)
828 goto err_destroy_root_ft;
829
830 mlx5e_ethtool_init_steering(priv);
831
832 return 0;
833
834err_destroy_root_ft:
835 mlx5e_destroy_rep_root_ft(priv);
836err_destroy_ttc_table:
837 mlx5_destroy_ttc_table(priv->fs.ttc);
838err_destroy_rx_res:
839 mlx5e_rx_res_destroy(priv->rx_res);
840err_close_drop_rq:
841 mlx5e_close_drop_rq(&priv->drop_rq);
842 mlx5e_rx_res_free(priv->rx_res);
843 priv->rx_res = NULL;
844 return err;
845}
846
847static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
848{
849 mlx5e_ethtool_cleanup_steering(priv);
850 rep_vport_rx_rule_destroy(priv);
851 mlx5e_destroy_rep_root_ft(priv);
852 mlx5_destroy_ttc_table(priv->fs.ttc);
853 mlx5e_rx_res_destroy(priv->rx_res);
854 mlx5e_close_drop_rq(&priv->drop_rq);
855 mlx5e_rx_res_free(priv->rx_res);
856 priv->rx_res = NULL;
857}
858
859static int mlx5e_init_ul_rep_rx(struct mlx5e_priv *priv)
860{
861 mlx5e_create_q_counters(priv);
862 return mlx5e_init_rep_rx(priv);
863}
864
865static void mlx5e_cleanup_ul_rep_rx(struct mlx5e_priv *priv)
866{
867 mlx5e_cleanup_rep_rx(priv);
868 mlx5e_destroy_q_counters(priv);
869}
870
871static int mlx5e_init_uplink_rep_tx(struct mlx5e_rep_priv *rpriv)
872{
873 struct mlx5_rep_uplink_priv *uplink_priv;
874 struct net_device *netdev;
875 struct mlx5e_priv *priv;
876 int err;
877
878 netdev = rpriv->netdev;
879 priv = netdev_priv(netdev);
880 uplink_priv = &rpriv->uplink_priv;
881
882 err = mlx5e_rep_tc_init(rpriv);
883 if (err)
884 return err;
885
886 mlx5_init_port_tun_entropy(&uplink_priv->tun_entropy, priv->mdev);
887
888 mlx5e_rep_bond_init(rpriv);
889 err = mlx5e_rep_tc_netdevice_event_register(rpriv);
890 if (err) {
891 mlx5_core_err(priv->mdev, "Failed to register netdev notifier, err: %d\n",
892 err);
893 goto err_event_reg;
894 }
895
896 return 0;
897
898err_event_reg:
899 mlx5e_rep_bond_cleanup(rpriv);
900 mlx5e_rep_tc_cleanup(rpriv);
901 return err;
902}
903
904static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
905{
906 struct mlx5e_rep_priv *rpriv = priv->ppriv;
907 int err;
908
909 err = mlx5e_create_tises(priv);
910 if (err) {
911 mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
912 return err;
913 }
914
915 if (rpriv->rep->vport == MLX5_VPORT_UPLINK) {
916 err = mlx5e_init_uplink_rep_tx(rpriv);
917 if (err)
918 goto destroy_tises;
919 }
920
921 return 0;
922
923destroy_tises:
924 mlx5e_destroy_tises(priv);
925 return err;
926}
927
928static void mlx5e_cleanup_uplink_rep_tx(struct mlx5e_rep_priv *rpriv)
929{
930 mlx5e_rep_tc_netdevice_event_unregister(rpriv);
931 mlx5e_rep_bond_cleanup(rpriv);
932 mlx5e_rep_tc_cleanup(rpriv);
933}
934
935static void mlx5e_cleanup_rep_tx(struct mlx5e_priv *priv)
936{
937 struct mlx5e_rep_priv *rpriv = priv->ppriv;
938
939 mlx5e_destroy_tises(priv);
940
941 if (rpriv->rep->vport == MLX5_VPORT_UPLINK)
942 mlx5e_cleanup_uplink_rep_tx(rpriv);
943}
944
945static void mlx5e_rep_enable(struct mlx5e_priv *priv)
946{
947 struct mlx5e_rep_priv *rpriv = priv->ppriv;
948
949 mlx5e_set_netdev_mtu_boundaries(priv);
950 mlx5e_rep_neigh_init(rpriv);
951}
952
953static void mlx5e_rep_disable(struct mlx5e_priv *priv)
954{
955 struct mlx5e_rep_priv *rpriv = priv->ppriv;
956
957 mlx5e_rep_neigh_cleanup(rpriv);
958}
959
960static int mlx5e_update_rep_rx(struct mlx5e_priv *priv)
961{
962 return 0;
963}
964
965static int uplink_rep_async_event(struct notifier_block *nb, unsigned long event, void *data)
966{
967 struct mlx5e_priv *priv = container_of(nb, struct mlx5e_priv, events_nb);
968
969 if (event == MLX5_EVENT_TYPE_PORT_CHANGE) {
970 struct mlx5_eqe *eqe = data;
971
972 switch (eqe->sub_type) {
973 case MLX5_PORT_CHANGE_SUBTYPE_DOWN:
974 case MLX5_PORT_CHANGE_SUBTYPE_ACTIVE:
975 queue_work(priv->wq, &priv->update_carrier_work);
976 break;
977 default:
978 return NOTIFY_DONE;
979 }
980
981 return NOTIFY_OK;
982 }
983
984 if (event == MLX5_DEV_EVENT_PORT_AFFINITY)
985 return mlx5e_rep_tc_event_port_affinity(priv);
986
987 return NOTIFY_DONE;
988}
989
990static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv)
991{
992 struct mlx5e_rep_priv *rpriv = priv->ppriv;
993 struct net_device *netdev = priv->netdev;
994 struct mlx5_core_dev *mdev = priv->mdev;
995 u16 max_mtu;
996
997 netdev->min_mtu = ETH_MIN_MTU;
998 mlx5_query_port_max_mtu(priv->mdev, &max_mtu, 1);
999 netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
1000 mlx5e_set_dev_port_mtu(priv);
1001
1002 mlx5e_rep_tc_enable(priv);
1003
1004 if (MLX5_CAP_GEN(mdev, uplink_follow))
1005 mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK,
1006 0, 0, MLX5_VPORT_ADMIN_STATE_AUTO);
1007 mlx5_lag_add_netdev(mdev, netdev);
1008 priv->events_nb.notifier_call = uplink_rep_async_event;
1009 mlx5_notifier_register(mdev, &priv->events_nb);
1010 mlx5e_dcbnl_initialize(priv);
1011 mlx5e_dcbnl_init_app(priv);
1012 mlx5e_rep_neigh_init(rpriv);
1013 mlx5e_rep_bridge_init(priv);
1014
1015 netdev->wanted_features |= NETIF_F_HW_TC;
1016
1017 rtnl_lock();
1018 if (netif_running(netdev))
1019 mlx5e_open(netdev);
1020 netif_device_attach(netdev);
1021 rtnl_unlock();
1022}
1023
1024static void mlx5e_uplink_rep_disable(struct mlx5e_priv *priv)
1025{
1026 struct mlx5e_rep_priv *rpriv = priv->ppriv;
1027 struct mlx5_core_dev *mdev = priv->mdev;
1028
1029 rtnl_lock();
1030 if (netif_running(priv->netdev))
1031 mlx5e_close(priv->netdev);
1032 netif_device_detach(priv->netdev);
1033 rtnl_unlock();
1034
1035 mlx5e_rep_bridge_cleanup(priv);
1036 mlx5e_rep_neigh_cleanup(rpriv);
1037 mlx5e_dcbnl_delete_app(priv);
1038 mlx5_notifier_unregister(mdev, &priv->events_nb);
1039 mlx5e_rep_tc_disable(priv);
1040 mlx5_lag_remove_netdev(mdev, priv->netdev);
1041}
1042
1043static MLX5E_DEFINE_STATS_GRP(sw_rep, 0);
1044static MLX5E_DEFINE_STATS_GRP(vport_rep, MLX5E_NDO_UPDATE_STATS);
1045
1046
1047static mlx5e_stats_grp_t mlx5e_rep_stats_grps[] = {
1048 &MLX5E_STATS_GRP(sw_rep),
1049 &MLX5E_STATS_GRP(vport_rep),
1050};
1051
1052static unsigned int mlx5e_rep_stats_grps_num(struct mlx5e_priv *priv)
1053{
1054 return ARRAY_SIZE(mlx5e_rep_stats_grps);
1055}
1056
1057
1058static mlx5e_stats_grp_t mlx5e_ul_rep_stats_grps[] = {
1059 &MLX5E_STATS_GRP(sw),
1060 &MLX5E_STATS_GRP(qcnt),
1061 &MLX5E_STATS_GRP(vnic_env),
1062 &MLX5E_STATS_GRP(vport),
1063 &MLX5E_STATS_GRP(802_3),
1064 &MLX5E_STATS_GRP(2863),
1065 &MLX5E_STATS_GRP(2819),
1066 &MLX5E_STATS_GRP(phy),
1067 &MLX5E_STATS_GRP(eth_ext),
1068 &MLX5E_STATS_GRP(pcie),
1069 &MLX5E_STATS_GRP(per_prio),
1070 &MLX5E_STATS_GRP(pme),
1071 &MLX5E_STATS_GRP(channels),
1072 &MLX5E_STATS_GRP(per_port_buff_congest),
1073};
1074
1075static unsigned int mlx5e_ul_rep_stats_grps_num(struct mlx5e_priv *priv)
1076{
1077 return ARRAY_SIZE(mlx5e_ul_rep_stats_grps);
1078}
1079
1080static const struct mlx5e_profile mlx5e_rep_profile = {
1081 .init = mlx5e_init_rep,
1082 .cleanup = mlx5e_cleanup_rep,
1083 .init_rx = mlx5e_init_rep_rx,
1084 .cleanup_rx = mlx5e_cleanup_rep_rx,
1085 .init_tx = mlx5e_init_rep_tx,
1086 .cleanup_tx = mlx5e_cleanup_rep_tx,
1087 .enable = mlx5e_rep_enable,
1088 .disable = mlx5e_rep_disable,
1089 .update_rx = mlx5e_update_rep_rx,
1090 .update_stats = mlx5e_stats_update_ndo_stats,
1091 .rx_handlers = &mlx5e_rx_handlers_rep,
1092 .max_tc = 1,
1093 .rq_groups = MLX5E_NUM_RQ_GROUPS(REGULAR),
1094 .stats_grps = mlx5e_rep_stats_grps,
1095 .stats_grps_num = mlx5e_rep_stats_grps_num,
1096 .rx_ptp_support = false,
1097};
1098
1099static const struct mlx5e_profile mlx5e_uplink_rep_profile = {
1100 .init = mlx5e_init_ul_rep,
1101 .cleanup = mlx5e_cleanup_rep,
1102 .init_rx = mlx5e_init_ul_rep_rx,
1103 .cleanup_rx = mlx5e_cleanup_ul_rep_rx,
1104 .init_tx = mlx5e_init_rep_tx,
1105 .cleanup_tx = mlx5e_cleanup_rep_tx,
1106 .enable = mlx5e_uplink_rep_enable,
1107 .disable = mlx5e_uplink_rep_disable,
1108 .update_rx = mlx5e_update_rep_rx,
1109 .update_stats = mlx5e_stats_update_ndo_stats,
1110 .update_carrier = mlx5e_update_carrier,
1111 .rx_handlers = &mlx5e_rx_handlers_rep,
1112 .max_tc = MLX5E_MAX_NUM_TC,
1113
1114 .rq_groups = MLX5E_NUM_RQ_GROUPS(XSK),
1115 .stats_grps = mlx5e_ul_rep_stats_grps,
1116 .stats_grps_num = mlx5e_ul_rep_stats_grps_num,
1117 .rx_ptp_support = false,
1118};
1119
1120
1121static int
1122mlx5e_vport_uplink_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1123{
1124 struct mlx5e_priv *priv = netdev_priv(mlx5_uplink_netdev_get(dev));
1125 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1126 struct devlink_port *dl_port;
1127 int err;
1128
1129 rpriv->netdev = priv->netdev;
1130
1131 err = mlx5e_netdev_change_profile(priv, &mlx5e_uplink_rep_profile,
1132 rpriv);
1133 if (err)
1134 return err;
1135
1136 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
1137 if (dl_port)
1138 devlink_port_type_eth_set(dl_port, rpriv->netdev);
1139
1140 return 0;
1141}
1142
1143static void
1144mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
1145{
1146 struct net_device *netdev = rpriv->netdev;
1147 struct devlink_port *dl_port;
1148 struct mlx5_core_dev *dev;
1149 struct mlx5e_priv *priv;
1150
1151 priv = netdev_priv(netdev);
1152 dev = priv->mdev;
1153
1154 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
1155 if (dl_port)
1156 devlink_port_type_clear(dl_port);
1157 mlx5e_netdev_attach_nic_profile(priv);
1158}
1159
1160static int
1161mlx5e_vport_vf_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1162{
1163 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1164 const struct mlx5e_profile *profile;
1165 struct devlink_port *dl_port;
1166 struct net_device *netdev;
1167 struct mlx5e_priv *priv;
1168 unsigned int txqs, rxqs;
1169 int nch, err;
1170
1171 profile = &mlx5e_rep_profile;
1172 nch = mlx5e_get_max_num_channels(dev);
1173 txqs = nch * profile->max_tc;
1174 rxqs = nch * profile->rq_groups;
1175 netdev = mlx5e_create_netdev(dev, profile, txqs, rxqs);
1176 if (!netdev) {
1177 mlx5_core_warn(dev,
1178 "Failed to create representor netdev for vport %d\n",
1179 rep->vport);
1180 return -EINVAL;
1181 }
1182
1183 mlx5e_build_rep_netdev(netdev, dev);
1184 rpriv->netdev = netdev;
1185
1186 priv = netdev_priv(netdev);
1187 priv->profile = profile;
1188 priv->ppriv = rpriv;
1189 err = profile->init(dev, netdev);
1190 if (err) {
1191 netdev_warn(netdev, "rep profile init failed, %d\n", err);
1192 goto err_destroy_netdev;
1193 }
1194
1195 err = mlx5e_attach_netdev(netdev_priv(netdev));
1196 if (err) {
1197 netdev_warn(netdev,
1198 "Failed to attach representor netdev for vport %d\n",
1199 rep->vport);
1200 goto err_cleanup_profile;
1201 }
1202
1203 err = register_netdev(netdev);
1204 if (err) {
1205 netdev_warn(netdev,
1206 "Failed to register representor netdev for vport %d\n",
1207 rep->vport);
1208 goto err_detach_netdev;
1209 }
1210
1211 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
1212 if (dl_port)
1213 devlink_port_type_eth_set(dl_port, netdev);
1214 return 0;
1215
1216err_detach_netdev:
1217 mlx5e_detach_netdev(netdev_priv(netdev));
1218
1219err_cleanup_profile:
1220 priv->profile->cleanup(priv);
1221
1222err_destroy_netdev:
1223 mlx5e_destroy_netdev(netdev_priv(netdev));
1224 return err;
1225}
1226
1227static int
1228mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1229{
1230 struct mlx5e_rep_priv *rpriv;
1231 int err;
1232
1233 rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
1234 if (!rpriv)
1235 return -ENOMEM;
1236
1237
1238 rpriv->rep = rep;
1239 rep->rep_data[REP_ETH].priv = rpriv;
1240 INIT_LIST_HEAD(&rpriv->vport_sqs_list);
1241
1242 if (rep->vport == MLX5_VPORT_UPLINK)
1243 err = mlx5e_vport_uplink_rep_load(dev, rep);
1244 else
1245 err = mlx5e_vport_vf_rep_load(dev, rep);
1246
1247 if (err)
1248 kfree(rpriv);
1249
1250 return err;
1251}
1252
1253static void
1254mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
1255{
1256 struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1257 struct net_device *netdev = rpriv->netdev;
1258 struct mlx5e_priv *priv = netdev_priv(netdev);
1259 struct mlx5_core_dev *dev = priv->mdev;
1260 struct devlink_port *dl_port;
1261 void *ppriv = priv->ppriv;
1262
1263 if (rep->vport == MLX5_VPORT_UPLINK) {
1264 mlx5e_vport_uplink_rep_unload(rpriv);
1265 goto free_ppriv;
1266 }
1267
1268 dl_port = mlx5_esw_offloads_devlink_port(dev->priv.eswitch, rpriv->rep->vport);
1269 if (dl_port)
1270 devlink_port_type_clear(dl_port);
1271 unregister_netdev(netdev);
1272 mlx5e_detach_netdev(priv);
1273 priv->profile->cleanup(priv);
1274 mlx5e_destroy_netdev(priv);
1275free_ppriv:
1276 kfree(ppriv);
1277}
1278
1279static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
1280{
1281 struct mlx5e_rep_priv *rpriv;
1282
1283 rpriv = mlx5e_rep_to_rep_priv(rep);
1284
1285 return rpriv->netdev;
1286}
1287
1288static void mlx5e_vport_rep_event_unpair(struct mlx5_eswitch_rep *rep)
1289{
1290 struct mlx5e_rep_priv *rpriv;
1291 struct mlx5e_rep_sq *rep_sq;
1292
1293 rpriv = mlx5e_rep_to_rep_priv(rep);
1294 list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
1295 if (!rep_sq->send_to_vport_rule_peer)
1296 continue;
1297 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule_peer);
1298 rep_sq->send_to_vport_rule_peer = NULL;
1299 }
1300}
1301
1302static int mlx5e_vport_rep_event_pair(struct mlx5_eswitch *esw,
1303 struct mlx5_eswitch_rep *rep,
1304 struct mlx5_eswitch *peer_esw)
1305{
1306 struct mlx5_flow_handle *flow_rule;
1307 struct mlx5e_rep_priv *rpriv;
1308 struct mlx5e_rep_sq *rep_sq;
1309
1310 rpriv = mlx5e_rep_to_rep_priv(rep);
1311 list_for_each_entry(rep_sq, &rpriv->vport_sqs_list, list) {
1312 if (rep_sq->send_to_vport_rule_peer)
1313 continue;
1314 flow_rule = mlx5_eswitch_add_send_to_vport_rule(peer_esw, esw, rep, rep_sq->sqn);
1315 if (IS_ERR(flow_rule))
1316 goto err_out;
1317 rep_sq->send_to_vport_rule_peer = flow_rule;
1318 }
1319
1320 return 0;
1321err_out:
1322 mlx5e_vport_rep_event_unpair(rep);
1323 return PTR_ERR(flow_rule);
1324}
1325
1326static int mlx5e_vport_rep_event(struct mlx5_eswitch *esw,
1327 struct mlx5_eswitch_rep *rep,
1328 enum mlx5_switchdev_event event,
1329 void *data)
1330{
1331 int err = 0;
1332
1333 if (event == MLX5_SWITCHDEV_EVENT_PAIR)
1334 err = mlx5e_vport_rep_event_pair(esw, rep, data);
1335 else if (event == MLX5_SWITCHDEV_EVENT_UNPAIR)
1336 mlx5e_vport_rep_event_unpair(rep);
1337
1338 return err;
1339}
1340
1341static const struct mlx5_eswitch_rep_ops rep_ops = {
1342 .load = mlx5e_vport_rep_load,
1343 .unload = mlx5e_vport_rep_unload,
1344 .get_proto_dev = mlx5e_vport_rep_get_proto_dev,
1345 .event = mlx5e_vport_rep_event,
1346};
1347
1348static int mlx5e_rep_probe(struct auxiliary_device *adev,
1349 const struct auxiliary_device_id *id)
1350{
1351 struct mlx5_adev *edev = container_of(adev, struct mlx5_adev, adev);
1352 struct mlx5_core_dev *mdev = edev->mdev;
1353 struct mlx5_eswitch *esw;
1354
1355 esw = mdev->priv.eswitch;
1356 mlx5_eswitch_register_vport_reps(esw, &rep_ops, REP_ETH);
1357 return 0;
1358}
1359
1360static void mlx5e_rep_remove(struct auxiliary_device *adev)
1361{
1362 struct mlx5_adev *vdev = container_of(adev, struct mlx5_adev, adev);
1363 struct mlx5_core_dev *mdev = vdev->mdev;
1364 struct mlx5_eswitch *esw;
1365
1366 esw = mdev->priv.eswitch;
1367 mlx5_eswitch_unregister_vport_reps(esw, REP_ETH);
1368}
1369
1370static const struct auxiliary_device_id mlx5e_rep_id_table[] = {
1371 { .name = MLX5_ADEV_NAME ".eth-rep", },
1372 {},
1373};
1374
1375MODULE_DEVICE_TABLE(auxiliary, mlx5e_rep_id_table);
1376
1377static struct auxiliary_driver mlx5e_rep_driver = {
1378 .name = "eth-rep",
1379 .probe = mlx5e_rep_probe,
1380 .remove = mlx5e_rep_remove,
1381 .id_table = mlx5e_rep_id_table,
1382};
1383
1384int mlx5e_rep_init(void)
1385{
1386 return auxiliary_driver_register(&mlx5e_rep_driver);
1387}
1388
1389void mlx5e_rep_cleanup(void)
1390{
1391 auxiliary_driver_unregister(&mlx5e_rep_driver);
1392}
1393