]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/blame - drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
net/mlx5e: Add neighbour hash table to the representors
[mirror_ubuntu-eoan-kernel.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_rep.c
CommitLineData
cb67b832
HHZ
1/*
2 * Copyright (c) 2016, 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
33#include <generated/utsrelease.h>
34#include <linux/mlx5/fs.h>
35#include <net/switchdev.h>
d957b4e3 36#include <net/pkt_cls.h>
cb67b832
HHZ
37
38#include "eswitch.h"
39#include "en.h"
1d447a39 40#include "en_rep.h"
adb4c123 41#include "en_tc.h"
cb67b832
HHZ
42
43static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
44
45static void mlx5e_rep_get_drvinfo(struct net_device *dev,
46 struct ethtool_drvinfo *drvinfo)
47{
48 strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
49 sizeof(drvinfo->driver));
50 strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
51}
52
53static const struct counter_desc sw_rep_stats_desc[] = {
54 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) },
55 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) },
56 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) },
57 { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) },
58};
59
60#define NUM_VPORT_REP_COUNTERS ARRAY_SIZE(sw_rep_stats_desc)
61
62static void mlx5e_rep_get_strings(struct net_device *dev,
63 u32 stringset, uint8_t *data)
64{
65 int i;
66
67 switch (stringset) {
68 case ETH_SS_STATS:
69 for (i = 0; i < NUM_VPORT_REP_COUNTERS; i++)
70 strcpy(data + (i * ETH_GSTRING_LEN),
71 sw_rep_stats_desc[i].format);
72 break;
73 }
74}
75
370bad0f
OG
76static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
77{
78 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1d447a39
SM
79 struct mlx5e_rep_priv *rpriv = priv->ppriv;
80 struct mlx5_eswitch_rep *rep = rpriv->rep;
370bad0f
OG
81 struct rtnl_link_stats64 *vport_stats;
82 struct ifla_vf_stats vf_stats;
83 int err;
84
85 err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats);
86 if (err) {
87 pr_warn("vport %d error %d reading stats\n", rep->vport, err);
88 return;
89 }
90
91 vport_stats = &priv->stats.vf_vport;
92 /* flip tx/rx as we are reporting the counters for the switch vport */
93 vport_stats->rx_packets = vf_stats.tx_packets;
94 vport_stats->rx_bytes = vf_stats.tx_bytes;
95 vport_stats->tx_packets = vf_stats.rx_packets;
96 vport_stats->tx_bytes = vf_stats.rx_bytes;
97}
98
99static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
cb67b832
HHZ
100{
101 struct mlx5e_sw_stats *s = &priv->stats.sw;
102 struct mlx5e_rq_stats *rq_stats;
103 struct mlx5e_sq_stats *sq_stats;
104 int i, j;
105
106 memset(s, 0, sizeof(*s));
ff9c852f
SM
107 for (i = 0; i < priv->channels.num; i++) {
108 struct mlx5e_channel *c = priv->channels.c[i];
109
110 rq_stats = &c->rq.stats;
cb67b832
HHZ
111
112 s->rx_packets += rq_stats->packets;
113 s->rx_bytes += rq_stats->bytes;
114
6a9764ef 115 for (j = 0; j < priv->channels.params.num_tc; j++) {
ff9c852f 116 sq_stats = &c->sq[j].stats;
cb67b832
HHZ
117
118 s->tx_packets += sq_stats->packets;
119 s->tx_bytes += sq_stats->bytes;
120 }
121 }
122}
123
370bad0f
OG
124static void mlx5e_rep_update_stats(struct mlx5e_priv *priv)
125{
126 mlx5e_rep_update_sw_counters(priv);
127 mlx5e_rep_update_hw_counters(priv);
128}
129
cb67b832
HHZ
130static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
131 struct ethtool_stats *stats, u64 *data)
132{
133 struct mlx5e_priv *priv = netdev_priv(dev);
134 int i;
135
136 if (!data)
137 return;
138
139 mutex_lock(&priv->state_lock);
140 if (test_bit(MLX5E_STATE_OPENED, &priv->state))
370bad0f 141 mlx5e_rep_update_sw_counters(priv);
cb67b832
HHZ
142 mutex_unlock(&priv->state_lock);
143
144 for (i = 0; i < NUM_VPORT_REP_COUNTERS; i++)
145 data[i] = MLX5E_READ_CTR64_CPU(&priv->stats.sw,
146 sw_rep_stats_desc, i);
147}
148
149static int mlx5e_rep_get_sset_count(struct net_device *dev, int sset)
150{
151 switch (sset) {
152 case ETH_SS_STATS:
153 return NUM_VPORT_REP_COUNTERS;
154 default:
155 return -EOPNOTSUPP;
156 }
157}
158
159static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
160 .get_drvinfo = mlx5e_rep_get_drvinfo,
161 .get_link = ethtool_op_get_link,
162 .get_strings = mlx5e_rep_get_strings,
163 .get_sset_count = mlx5e_rep_get_sset_count,
164 .get_ethtool_stats = mlx5e_rep_get_ethtool_stats,
165};
166
167int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
168{
169 struct mlx5e_priv *priv = netdev_priv(dev);
1d447a39
SM
170 struct mlx5e_rep_priv *rpriv = priv->ppriv;
171 struct mlx5_eswitch_rep *rep = rpriv->rep;
cb67b832 172 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
cb67b832
HHZ
173
174 if (esw->mode == SRIOV_NONE)
175 return -EOPNOTSUPP;
176
177 switch (attr->id) {
178 case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
cb67b832 179 attr->u.ppid.id_len = ETH_ALEN;
dbe413e3 180 ether_addr_copy(attr->u.ppid.id, rep->hw_id);
cb67b832
HHZ
181 break;
182 default:
183 return -EOPNOTSUPP;
184 }
185
186 return 0;
187}
188
189int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
cb67b832
HHZ
190{
191 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1d447a39
SM
192 struct mlx5e_rep_priv *rpriv = priv->ppriv;
193 struct mlx5_eswitch_rep *rep = rpriv->rep;
cb67b832 194 struct mlx5e_channel *c;
9008ae07
SM
195 int n, tc, num_sqs = 0;
196 int err = -ENOMEM;
cb67b832
HHZ
197 u16 *sqs;
198
6a9764ef 199 sqs = kcalloc(priv->channels.num * priv->channels.params.num_tc, sizeof(u16), GFP_KERNEL);
cb67b832 200 if (!sqs)
9008ae07 201 goto out;
cb67b832 202
ff9c852f
SM
203 for (n = 0; n < priv->channels.num; n++) {
204 c = priv->channels.c[n];
cb67b832
HHZ
205 for (tc = 0; tc < c->num_tc; tc++)
206 sqs[num_sqs++] = c->sq[tc].sqn;
207 }
208
209 err = mlx5_eswitch_sqs2vport_start(esw, rep, sqs, num_sqs);
cb67b832 210 kfree(sqs);
9008ae07
SM
211
212out:
213 if (err)
214 netdev_warn(priv->netdev, "Failed to add SQs FWD rules %d\n", err);
cb67b832
HHZ
215 return err;
216}
217
cb67b832
HHZ
218void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
219{
220 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1d447a39
SM
221 struct mlx5e_rep_priv *rpriv = priv->ppriv;
222 struct mlx5_eswitch_rep *rep = rpriv->rep;
cb67b832
HHZ
223
224 mlx5_eswitch_sqs2vport_stop(esw, rep);
225}
226
37b498ff
HHZ
227static const struct rhashtable_params mlx5e_neigh_ht_params = {
228 .head_offset = offsetof(struct mlx5e_neigh_hash_entry, rhash_node),
229 .key_offset = offsetof(struct mlx5e_neigh_hash_entry, m_neigh),
230 .key_len = sizeof(struct mlx5e_neigh),
231 .automatic_shrinking = true,
232};
233
234static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
235{
236 struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
237
238 INIT_LIST_HEAD(&neigh_update->neigh_list);
239 return rhashtable_init(&neigh_update->neigh_ht, &mlx5e_neigh_ht_params);
240}
241
242static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
243{
244 struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
245
246 rhashtable_destroy(&neigh_update->neigh_ht);
247}
248
249static int mlx5e_rep_neigh_entry_insert(struct mlx5e_priv *priv,
250 struct mlx5e_neigh_hash_entry *nhe)
251{
252 struct mlx5e_rep_priv *rpriv = priv->ppriv;
253 int err;
254
255 err = rhashtable_insert_fast(&rpriv->neigh_update.neigh_ht,
256 &nhe->rhash_node,
257 mlx5e_neigh_ht_params);
258 if (err)
259 return err;
260
261 list_add(&nhe->neigh_list, &rpriv->neigh_update.neigh_list);
262
263 return err;
264}
265
266static void mlx5e_rep_neigh_entry_remove(struct mlx5e_priv *priv,
267 struct mlx5e_neigh_hash_entry *nhe)
268{
269 struct mlx5e_rep_priv *rpriv = priv->ppriv;
270
271 list_del(&nhe->neigh_list);
272
273 rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht,
274 &nhe->rhash_node,
275 mlx5e_neigh_ht_params);
276}
277
278static struct mlx5e_neigh_hash_entry *
279mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv,
280 struct mlx5e_neigh *m_neigh)
281{
282 struct mlx5e_rep_priv *rpriv = priv->ppriv;
283 struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
284
285 return rhashtable_lookup_fast(&neigh_update->neigh_ht, m_neigh,
286 mlx5e_neigh_ht_params);
287}
288
20a1ea67
OG
289static int mlx5e_rep_open(struct net_device *dev)
290{
291 struct mlx5e_priv *priv = netdev_priv(dev);
1d447a39
SM
292 struct mlx5e_rep_priv *rpriv = priv->ppriv;
293 struct mlx5_eswitch_rep *rep = rpriv->rep;
20a1ea67
OG
294 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
295 int err;
296
297 err = mlx5e_open(dev);
298 if (err)
299 return err;
300
301 err = mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_UP);
302 if (!err)
303 netif_carrier_on(dev);
304
305 return 0;
306}
307
308static int mlx5e_rep_close(struct net_device *dev)
309{
310 struct mlx5e_priv *priv = netdev_priv(dev);
1d447a39
SM
311 struct mlx5e_rep_priv *rpriv = priv->ppriv;
312 struct mlx5_eswitch_rep *rep = rpriv->rep;
20a1ea67
OG
313 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
314
315 (void)mlx5_eswitch_set_vport_state(esw, rep->vport, MLX5_ESW_VPORT_ADMIN_STATE_DOWN);
316
317 return mlx5e_close(dev);
318}
319
cb67b832
HHZ
320static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
321 char *buf, size_t len)
322{
323 struct mlx5e_priv *priv = netdev_priv(dev);
1d447a39
SM
324 struct mlx5e_rep_priv *rpriv = priv->ppriv;
325 struct mlx5_eswitch_rep *rep = rpriv->rep;
cb67b832
HHZ
326 int ret;
327
328 ret = snprintf(buf, len, "%d", rep->vport - 1);
329 if (ret >= len)
330 return -EOPNOTSUPP;
331
332 return 0;
333}
334
d957b4e3
OG
335static int mlx5e_rep_ndo_setup_tc(struct net_device *dev, u32 handle,
336 __be16 proto, struct tc_to_netdev *tc)
337{
338 struct mlx5e_priv *priv = netdev_priv(dev);
339
340 if (TC_H_MAJ(handle) != TC_H_MAJ(TC_H_INGRESS))
341 return -EOPNOTSUPP;
342
ebe06875
HHZ
343 if (tc->egress_dev) {
344 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
345 struct net_device *uplink_dev = mlx5_eswitch_get_uplink_netdev(esw);
346
347 return uplink_dev->netdev_ops->ndo_setup_tc(uplink_dev, handle,
348 proto, tc);
349 }
350
d957b4e3
OG
351 switch (tc->type) {
352 case TC_SETUP_CLSFLOWER:
353 switch (tc->cls_flower->command) {
354 case TC_CLSFLOWER_REPLACE:
355 return mlx5e_configure_flower(priv, proto, tc->cls_flower);
356 case TC_CLSFLOWER_DESTROY:
357 return mlx5e_delete_flower(priv, tc->cls_flower);
358 case TC_CLSFLOWER_STATS:
359 return mlx5e_stats_flower(priv, tc->cls_flower);
360 }
361 default:
362 return -EOPNOTSUPP;
363 }
364}
365
370bad0f
OG
366bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
367{
370bad0f 368 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1d447a39
SM
369 struct mlx5e_rep_priv *rpriv = priv->ppriv;
370 struct mlx5_eswitch_rep *rep;
371
372 if (!MLX5_CAP_GEN(priv->mdev, vport_group_manager))
373 return false;
370bad0f 374
1d447a39
SM
375 rep = rpriv->rep;
376 if (esw->mode == SRIOV_OFFLOADS &&
377 rep && rep->vport == FDB_UPLINK_VPORT)
370bad0f
OG
378 return true;
379
380 return false;
381}
382
20fd0c19 383static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
370bad0f 384{
1d447a39
SM
385 struct mlx5e_rep_priv *rpriv = priv->ppriv;
386 struct mlx5_eswitch_rep *rep = rpriv->rep;
370bad0f
OG
387
388 if (rep && rep->vport != FDB_UPLINK_VPORT)
389 return true;
390
391 return false;
392}
393
394bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
395{
396 struct mlx5e_priv *priv = netdev_priv(dev);
397
398 switch (attr_id) {
399 case IFLA_OFFLOAD_XSTATS_CPU_HIT:
400 if (mlx5e_is_vf_vport_rep(priv) || mlx5e_is_uplink_rep(priv))
401 return true;
402 }
403
404 return false;
405}
406
407static int
408mlx5e_get_sw_stats64(const struct net_device *dev,
409 struct rtnl_link_stats64 *stats)
410{
411 struct mlx5e_priv *priv = netdev_priv(dev);
412 struct mlx5e_sw_stats *sstats = &priv->stats.sw;
413
414 stats->rx_packets = sstats->rx_packets;
415 stats->rx_bytes = sstats->rx_bytes;
416 stats->tx_packets = sstats->tx_packets;
417 stats->tx_bytes = sstats->tx_bytes;
418
419 stats->tx_dropped = sstats->tx_queue_dropped;
420
421 return 0;
422}
423
424int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
425 void *sp)
426{
427 switch (attr_id) {
428 case IFLA_OFFLOAD_XSTATS_CPU_HIT:
429 return mlx5e_get_sw_stats64(dev, sp);
430 }
431
432 return -EINVAL;
433}
434
bc1f4470 435static void
370bad0f
OG
436mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
437{
438 struct mlx5e_priv *priv = netdev_priv(dev);
439
440 memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
370bad0f
OG
441}
442
cb67b832
HHZ
443static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
444 .switchdev_port_attr_get = mlx5e_attr_get,
445};
446
447static const struct net_device_ops mlx5e_netdev_ops_rep = {
20a1ea67
OG
448 .ndo_open = mlx5e_rep_open,
449 .ndo_stop = mlx5e_rep_close,
cb67b832
HHZ
450 .ndo_start_xmit = mlx5e_xmit,
451 .ndo_get_phys_port_name = mlx5e_rep_get_phys_port_name,
d957b4e3 452 .ndo_setup_tc = mlx5e_rep_ndo_setup_tc,
370bad0f
OG
453 .ndo_get_stats64 = mlx5e_rep_get_stats,
454 .ndo_has_offload_stats = mlx5e_has_offload_stats,
455 .ndo_get_offload_stats = mlx5e_get_offload_stats,
cb67b832
HHZ
456};
457
6a9764ef
SM
458static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
459 struct mlx5e_params *params)
cb67b832 460{
cb67b832
HHZ
461 u8 cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
462 MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
463 MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
464
6a9764ef
SM
465 params->log_sq_size = MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE;
466 params->rq_wq_type = MLX5_WQ_TYPE_LINKED_LIST;
467 params->log_rq_size = MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE;
cb67b832 468
6a9764ef
SM
469 params->rx_am_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
470 mlx5e_set_rx_cq_mode_params(params, cq_period_mode);
cb67b832 471
6a9764ef
SM
472 params->tx_max_inline = mlx5e_get_max_inline_cap(mdev);
473 params->num_tc = 1;
474 params->lro_wqe_sz = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
cb67b832
HHZ
475}
476
477static void mlx5e_build_rep_netdev(struct net_device *netdev)
478{
479 netdev->netdev_ops = &mlx5e_netdev_ops_rep;
480
481 netdev->watchdog_timeo = 15 * HZ;
482
483 netdev->ethtool_ops = &mlx5e_rep_ethtool_ops;
484
485#ifdef CONFIG_NET_SWITCHDEV
486 netdev->switchdev_ops = &mlx5e_rep_switchdev_ops;
487#endif
488
abd32772 489 netdev->features |= NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
d957b4e3 490 netdev->hw_features |= NETIF_F_HW_TC;
cb67b832
HHZ
491
492 eth_hw_addr_random(netdev);
493}
494
495static void mlx5e_init_rep(struct mlx5_core_dev *mdev,
496 struct net_device *netdev,
497 const struct mlx5e_profile *profile,
498 void *ppriv)
499{
6a9764ef
SM
500 struct mlx5e_priv *priv = netdev_priv(netdev);
501
502 priv->mdev = mdev;
503 priv->netdev = netdev;
504 priv->profile = profile;
505 priv->ppriv = ppriv;
506
507 mutex_init(&priv->state_lock);
508
509 INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
510
511 priv->channels.params.num_channels = profile->max_nch(mdev);
512 mlx5e_build_rep_params(mdev, &priv->channels.params);
cb67b832
HHZ
513 mlx5e_build_rep_netdev(netdev);
514}
515
516static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
517{
518 struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1d447a39
SM
519 struct mlx5e_rep_priv *rpriv = priv->ppriv;
520 struct mlx5_eswitch_rep *rep = rpriv->rep;
74491de9 521 struct mlx5_flow_handle *flow_rule;
cb67b832 522 int err;
cb67b832 523
2c3b5bee
SM
524 mlx5e_init_l2_addr(priv);
525
cb67b832 526 err = mlx5e_create_direct_rqts(priv);
8f493ffd 527 if (err)
cb67b832 528 return err;
cb67b832
HHZ
529
530 err = mlx5e_create_direct_tirs(priv);
8f493ffd 531 if (err)
cb67b832 532 goto err_destroy_direct_rqts;
cb67b832
HHZ
533
534 flow_rule = mlx5_eswitch_create_vport_rx_rule(esw,
535 rep->vport,
536 priv->direct_tir[0].tirn);
537 if (IS_ERR(flow_rule)) {
538 err = PTR_ERR(flow_rule);
539 goto err_destroy_direct_tirs;
540 }
541 rep->vport_rx_rule = flow_rule;
542
d957b4e3
OG
543 err = mlx5e_tc_init(priv);
544 if (err)
545 goto err_del_flow_rule;
546
cb67b832
HHZ
547 return 0;
548
d957b4e3 549err_del_flow_rule:
74491de9 550 mlx5_del_flow_rules(rep->vport_rx_rule);
cb67b832
HHZ
551err_destroy_direct_tirs:
552 mlx5e_destroy_direct_tirs(priv);
553err_destroy_direct_rqts:
8f493ffd 554 mlx5e_destroy_direct_rqts(priv);
cb67b832
HHZ
555 return err;
556}
557
558static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
559{
1d447a39
SM
560 struct mlx5e_rep_priv *rpriv = priv->ppriv;
561 struct mlx5_eswitch_rep *rep = rpriv->rep;
cb67b832 562
d957b4e3 563 mlx5e_tc_cleanup(priv);
74491de9 564 mlx5_del_flow_rules(rep->vport_rx_rule);
cb67b832 565 mlx5e_destroy_direct_tirs(priv);
8f493ffd 566 mlx5e_destroy_direct_rqts(priv);
cb67b832
HHZ
567}
568
569static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
570{
571 int err;
572
573 err = mlx5e_create_tises(priv);
574 if (err) {
575 mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
576 return err;
577 }
578 return 0;
579}
580
581static int mlx5e_get_rep_max_num_channels(struct mlx5_core_dev *mdev)
582{
583#define MLX5E_PORT_REPRESENTOR_NCH 1
584 return MLX5E_PORT_REPRESENTOR_NCH;
585}
586
587static struct mlx5e_profile mlx5e_rep_profile = {
588 .init = mlx5e_init_rep,
589 .init_rx = mlx5e_init_rep_rx,
590 .cleanup_rx = mlx5e_cleanup_rep_rx,
591 .init_tx = mlx5e_init_rep_tx,
592 .cleanup_tx = mlx5e_cleanup_nic_tx,
370bad0f 593 .update_stats = mlx5e_rep_update_stats,
cb67b832 594 .max_nch = mlx5e_get_rep_max_num_channels,
20fd0c19
SM
595 .rx_handlers.handle_rx_cqe = mlx5e_handle_rx_cqe_rep,
596 .rx_handlers.handle_rx_cqe_mpwqe = NULL /* Not supported */,
cb67b832
HHZ
597 .max_tc = 1,
598};
599
1d447a39
SM
600/* e-Switch vport representors */
601
602static int
603mlx5e_nic_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
604{
37b498ff
HHZ
605 struct mlx5e_priv *priv = netdev_priv(rep->netdev);
606 struct mlx5e_rep_priv *rpriv = priv->ppriv;
607
608 int err;
609
610 if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
611 err = mlx5e_add_sqs_fwd_rules(priv);
612 if (err)
613 return err;
614 }
615
616 err = mlx5e_rep_neigh_init(rpriv);
617 if (err)
618 goto err_remove_sqs;
1d447a39 619
1d447a39 620 return 0;
37b498ff
HHZ
621
622err_remove_sqs:
623 mlx5e_remove_sqs_fwd_rules(priv);
624 return err;
1d447a39
SM
625}
626
627static void
628mlx5e_nic_rep_unload(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
cb67b832 629{
37b498ff
HHZ
630 struct mlx5e_priv *priv = netdev_priv(rep->netdev);
631 struct mlx5e_rep_priv *rpriv = priv->ppriv;
1d447a39
SM
632
633 if (test_bit(MLX5E_STATE_OPENED, &priv->state))
634 mlx5e_remove_sqs_fwd_rules(priv);
635
636 /* clean (and re-init) existing uplink offloaded TC rules */
637 mlx5e_tc_cleanup(priv);
638 mlx5e_tc_init(priv);
37b498ff
HHZ
639
640 mlx5e_rep_neigh_cleanup(rpriv);
1d447a39
SM
641}
642
643static int
644mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
645{
646 struct mlx5e_rep_priv *rpriv;
26e59d80
MHY
647 struct net_device *netdev;
648 int err;
649
1d447a39
SM
650 rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
651 if (!rpriv)
652 return -ENOMEM;
653
654 netdev = mlx5e_create_netdev(esw->dev, &mlx5e_rep_profile, rpriv);
26e59d80
MHY
655 if (!netdev) {
656 pr_warn("Failed to create representor netdev for vport %d\n",
657 rep->vport);
1d447a39 658 kfree(rpriv);
cb67b832
HHZ
659 return -EINVAL;
660 }
26e59d80 661
726293f1 662 rep->netdev = netdev;
1d447a39 663 rpriv->rep = rep;
26e59d80 664
2c3b5bee 665 err = mlx5e_attach_netdev(netdev_priv(netdev));
26e59d80
MHY
666 if (err) {
667 pr_warn("Failed to attach representor netdev for vport %d\n",
668 rep->vport);
669 goto err_destroy_netdev;
670 }
671
37b498ff
HHZ
672 err = mlx5e_rep_neigh_init(rpriv);
673 if (err) {
674 pr_warn("Failed to initialized neighbours handling for vport %d\n",
675 rep->vport);
676 goto err_detach_netdev;
677 }
678
26e59d80
MHY
679 err = register_netdev(netdev);
680 if (err) {
681 pr_warn("Failed to register representor netdev for vport %d\n",
682 rep->vport);
37b498ff 683 goto err_neigh_cleanup;
26e59d80
MHY
684 }
685
cb67b832 686 return 0;
26e59d80 687
37b498ff
HHZ
688err_neigh_cleanup:
689 mlx5e_rep_neigh_cleanup(rpriv);
690
26e59d80 691err_detach_netdev:
2c3b5bee 692 mlx5e_detach_netdev(netdev_priv(netdev));
26e59d80
MHY
693
694err_destroy_netdev:
2c3b5bee 695 mlx5e_destroy_netdev(netdev_priv(netdev));
1d447a39 696 kfree(rpriv);
26e59d80
MHY
697 return err;
698
cb67b832
HHZ
699}
700
1d447a39
SM
701static void
702mlx5e_vport_rep_unload(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
cb67b832 703{
726293f1 704 struct net_device *netdev = rep->netdev;
1d447a39 705 struct mlx5e_priv *priv = netdev_priv(netdev);
37b498ff 706 struct mlx5e_rep_priv *rpriv = priv->ppriv;
1d447a39 707 void *ppriv = priv->ppriv;
cb67b832 708
37b498ff
HHZ
709 unregister_netdev(rep->netdev);
710
711 mlx5e_rep_neigh_cleanup(rpriv);
1d447a39
SM
712 mlx5e_detach_netdev(priv);
713 mlx5e_destroy_netdev(priv);
714 kfree(ppriv); /* mlx5e_rep_priv */
715}
716
717static void mlx5e_rep_register_vf_vports(struct mlx5e_priv *priv)
718{
719 struct mlx5_core_dev *mdev = priv->mdev;
720 struct mlx5_eswitch *esw = mdev->priv.eswitch;
721 int total_vfs = MLX5_TOTAL_VPORTS(mdev);
722 int vport;
723 u8 mac[ETH_ALEN];
724
725 mlx5_query_nic_vport_mac_address(mdev, 0, mac);
726
727 for (vport = 1; vport < total_vfs; vport++) {
728 struct mlx5_eswitch_rep rep;
729
730 rep.load = mlx5e_vport_rep_load;
731 rep.unload = mlx5e_vport_rep_unload;
732 rep.vport = vport;
733 ether_addr_copy(rep.hw_id, mac);
734 mlx5_eswitch_register_vport_rep(esw, vport, &rep);
735 }
736}
737
738static void mlx5e_rep_unregister_vf_vports(struct mlx5e_priv *priv)
739{
740 struct mlx5_core_dev *mdev = priv->mdev;
741 struct mlx5_eswitch *esw = mdev->priv.eswitch;
742 int total_vfs = MLX5_TOTAL_VPORTS(mdev);
743 int vport;
744
745 for (vport = 1; vport < total_vfs; vport++)
746 mlx5_eswitch_unregister_vport_rep(esw, vport);
747}
748
749void mlx5e_register_vport_reps(struct mlx5e_priv *priv)
750{
751 struct mlx5_core_dev *mdev = priv->mdev;
752 struct mlx5_eswitch *esw = mdev->priv.eswitch;
753 struct mlx5_eswitch_rep rep;
754
755 mlx5_query_nic_vport_mac_address(mdev, 0, rep.hw_id);
756 rep.load = mlx5e_nic_rep_load;
757 rep.unload = mlx5e_nic_rep_unload;
758 rep.vport = FDB_UPLINK_VPORT;
759 rep.netdev = priv->netdev;
760 mlx5_eswitch_register_vport_rep(esw, 0, &rep); /* UPLINK PF vport*/
761
762 mlx5e_rep_register_vf_vports(priv); /* VFs vports */
763}
764
765void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv)
766{
767 struct mlx5_core_dev *mdev = priv->mdev;
768 struct mlx5_eswitch *esw = mdev->priv.eswitch;
769
770 mlx5e_rep_unregister_vf_vports(priv); /* VFs vports */
771 mlx5_eswitch_unregister_vport_rep(esw, 0); /* UPLINK PF*/
cb67b832 772}