c9cc9747d21d187810c9f93efaf0937bb9c1ebe2
[sfrench/cifs-2.6.git] / drivers / net / ethernet / mellanox / mlx5 / core / en_rep.c
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>
36 #include <net/pkt_cls.h>
37 #include <net/act_api.h>
38 #include <net/netevent.h>
39 #include <net/arp.h>
40
41 #include "eswitch.h"
42 #include "en.h"
43 #include "en_rep.h"
44 #include "en_tc.h"
45 #include "fs_core.h"
46
47 #define MLX5E_REP_PARAMS_LOG_SQ_SIZE \
48         max(0x6, MLX5E_PARAMS_MINIMUM_LOG_SQ_SIZE)
49 #define MLX5E_REP_PARAMS_LOG_RQ_SIZE \
50         max(0x6, MLX5E_PARAMS_MINIMUM_LOG_RQ_SIZE)
51
52 static const char mlx5e_rep_driver_name[] = "mlx5e_rep";
53
54 static void mlx5e_rep_get_drvinfo(struct net_device *dev,
55                                   struct ethtool_drvinfo *drvinfo)
56 {
57         strlcpy(drvinfo->driver, mlx5e_rep_driver_name,
58                 sizeof(drvinfo->driver));
59         strlcpy(drvinfo->version, UTS_RELEASE, sizeof(drvinfo->version));
60 }
61
62 static const struct counter_desc sw_rep_stats_desc[] = {
63         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_packets) },
64         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_bytes) },
65         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_packets) },
66         { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_bytes) },
67 };
68
69 struct vport_stats {
70         u64 vport_rx_packets;
71         u64 vport_tx_packets;
72         u64 vport_rx_bytes;
73         u64 vport_tx_bytes;
74 };
75
76 static const struct counter_desc vport_rep_stats_desc[] = {
77         { MLX5E_DECLARE_STAT(struct vport_stats, vport_rx_packets) },
78         { MLX5E_DECLARE_STAT(struct vport_stats, vport_rx_bytes) },
79         { MLX5E_DECLARE_STAT(struct vport_stats, vport_tx_packets) },
80         { MLX5E_DECLARE_STAT(struct vport_stats, vport_tx_bytes) },
81 };
82
83 #define NUM_VPORT_REP_SW_COUNTERS ARRAY_SIZE(sw_rep_stats_desc)
84 #define NUM_VPORT_REP_HW_COUNTERS ARRAY_SIZE(vport_rep_stats_desc)
85
86 static void mlx5e_rep_get_strings(struct net_device *dev,
87                                   u32 stringset, uint8_t *data)
88 {
89         int i, j;
90
91         switch (stringset) {
92         case ETH_SS_STATS:
93                 for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++)
94                         strcpy(data + (i * ETH_GSTRING_LEN),
95                                sw_rep_stats_desc[i].format);
96                 for (j = 0; j < NUM_VPORT_REP_HW_COUNTERS; j++, i++)
97                         strcpy(data + (i * ETH_GSTRING_LEN),
98                                vport_rep_stats_desc[j].format);
99                 break;
100         }
101 }
102
103 static void mlx5e_rep_update_hw_counters(struct mlx5e_priv *priv)
104 {
105         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
106         struct mlx5e_rep_priv *rpriv = priv->ppriv;
107         struct mlx5_eswitch_rep *rep = rpriv->rep;
108         struct rtnl_link_stats64 *vport_stats;
109         struct ifla_vf_stats vf_stats;
110         int err;
111
112         err = mlx5_eswitch_get_vport_stats(esw, rep->vport, &vf_stats);
113         if (err) {
114                 pr_warn("vport %d error %d reading stats\n", rep->vport, err);
115                 return;
116         }
117
118         vport_stats = &priv->stats.vf_vport;
119         /* flip tx/rx as we are reporting the counters for the switch vport */
120         vport_stats->rx_packets = vf_stats.tx_packets;
121         vport_stats->rx_bytes   = vf_stats.tx_bytes;
122         vport_stats->tx_packets = vf_stats.rx_packets;
123         vport_stats->tx_bytes   = vf_stats.rx_bytes;
124 }
125
126 static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
127 {
128         struct mlx5e_sw_stats *s = &priv->stats.sw;
129         struct mlx5e_rq_stats *rq_stats;
130         struct mlx5e_sq_stats *sq_stats;
131         int i, j;
132
133         memset(s, 0, sizeof(*s));
134         for (i = 0; i < priv->channels.num; i++) {
135                 struct mlx5e_channel *c = priv->channels.c[i];
136
137                 rq_stats = c->rq.stats;
138
139                 s->rx_packets   += rq_stats->packets;
140                 s->rx_bytes     += rq_stats->bytes;
141
142                 for (j = 0; j < priv->channels.params.num_tc; j++) {
143                         sq_stats = c->sq[j].stats;
144
145                         s->tx_packets           += sq_stats->packets;
146                         s->tx_bytes             += sq_stats->bytes;
147                 }
148         }
149 }
150
151 static void mlx5e_rep_get_ethtool_stats(struct net_device *dev,
152                                         struct ethtool_stats *stats, u64 *data)
153 {
154         struct mlx5e_priv *priv = netdev_priv(dev);
155         int i, j;
156
157         if (!data)
158                 return;
159
160         mutex_lock(&priv->state_lock);
161         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
162                 mlx5e_rep_update_sw_counters(priv);
163         mlx5e_rep_update_hw_counters(priv);
164         mutex_unlock(&priv->state_lock);
165
166         for (i = 0; i < NUM_VPORT_REP_SW_COUNTERS; i++)
167                 data[i] = MLX5E_READ_CTR64_CPU(&priv->stats.sw,
168                                                sw_rep_stats_desc, i);
169
170         for (j = 0; j < NUM_VPORT_REP_HW_COUNTERS; j++, i++)
171                 data[i] = MLX5E_READ_CTR64_CPU(&priv->stats.vf_vport,
172                                                vport_rep_stats_desc, j);
173 }
174
175 static int mlx5e_rep_get_sset_count(struct net_device *dev, int sset)
176 {
177         switch (sset) {
178         case ETH_SS_STATS:
179                 return NUM_VPORT_REP_SW_COUNTERS + NUM_VPORT_REP_HW_COUNTERS;
180         default:
181                 return -EOPNOTSUPP;
182         }
183 }
184
185 static const struct ethtool_ops mlx5e_rep_ethtool_ops = {
186         .get_drvinfo       = mlx5e_rep_get_drvinfo,
187         .get_link          = ethtool_op_get_link,
188         .get_strings       = mlx5e_rep_get_strings,
189         .get_sset_count    = mlx5e_rep_get_sset_count,
190         .get_ethtool_stats = mlx5e_rep_get_ethtool_stats,
191 };
192
193 int mlx5e_attr_get(struct net_device *dev, struct switchdev_attr *attr)
194 {
195         struct mlx5e_priv *priv = netdev_priv(dev);
196         struct mlx5e_rep_priv *rpriv = priv->ppriv;
197         struct mlx5_eswitch_rep *rep = rpriv->rep;
198         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
199
200         if (esw->mode == SRIOV_NONE)
201                 return -EOPNOTSUPP;
202
203         switch (attr->id) {
204         case SWITCHDEV_ATTR_ID_PORT_PARENT_ID:
205                 attr->u.ppid.id_len = ETH_ALEN;
206                 ether_addr_copy(attr->u.ppid.id, rep->hw_id);
207                 break;
208         default:
209                 return -EOPNOTSUPP;
210         }
211
212         return 0;
213 }
214
215 static void mlx5e_sqs2vport_stop(struct mlx5_eswitch *esw,
216                                  struct mlx5_eswitch_rep *rep)
217 {
218         struct mlx5e_rep_sq *rep_sq, *tmp;
219         struct mlx5e_rep_priv *rpriv;
220
221         if (esw->mode != SRIOV_OFFLOADS)
222                 return;
223
224         rpriv = mlx5e_rep_to_rep_priv(rep);
225         list_for_each_entry_safe(rep_sq, tmp, &rpriv->vport_sqs_list, list) {
226                 mlx5_eswitch_del_send_to_vport_rule(rep_sq->send_to_vport_rule);
227                 list_del(&rep_sq->list);
228                 kfree(rep_sq);
229         }
230 }
231
232 static int mlx5e_sqs2vport_start(struct mlx5_eswitch *esw,
233                                  struct mlx5_eswitch_rep *rep,
234                                  u32 *sqns_array, int sqns_num)
235 {
236         struct mlx5_flow_handle *flow_rule;
237         struct mlx5e_rep_priv *rpriv;
238         struct mlx5e_rep_sq *rep_sq;
239         int err;
240         int i;
241
242         if (esw->mode != SRIOV_OFFLOADS)
243                 return 0;
244
245         rpriv = mlx5e_rep_to_rep_priv(rep);
246         for (i = 0; i < sqns_num; i++) {
247                 rep_sq = kzalloc(sizeof(*rep_sq), GFP_KERNEL);
248                 if (!rep_sq) {
249                         err = -ENOMEM;
250                         goto out_err;
251                 }
252
253                 /* Add re-inject rule to the PF/representor sqs */
254                 flow_rule = mlx5_eswitch_add_send_to_vport_rule(esw,
255                                                                 rep->vport,
256                                                                 sqns_array[i]);
257                 if (IS_ERR(flow_rule)) {
258                         err = PTR_ERR(flow_rule);
259                         kfree(rep_sq);
260                         goto out_err;
261                 }
262                 rep_sq->send_to_vport_rule = flow_rule;
263                 list_add(&rep_sq->list, &rpriv->vport_sqs_list);
264         }
265         return 0;
266
267 out_err:
268         mlx5e_sqs2vport_stop(esw, rep);
269         return err;
270 }
271
272 int mlx5e_add_sqs_fwd_rules(struct mlx5e_priv *priv)
273 {
274         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
275         struct mlx5e_rep_priv *rpriv = priv->ppriv;
276         struct mlx5_eswitch_rep *rep = rpriv->rep;
277         struct mlx5e_channel *c;
278         int n, tc, num_sqs = 0;
279         int err = -ENOMEM;
280         u32 *sqs;
281
282         sqs = kcalloc(priv->channels.num * priv->channels.params.num_tc, sizeof(*sqs), GFP_KERNEL);
283         if (!sqs)
284                 goto out;
285
286         for (n = 0; n < priv->channels.num; n++) {
287                 c = priv->channels.c[n];
288                 for (tc = 0; tc < c->num_tc; tc++)
289                         sqs[num_sqs++] = c->sq[tc].sqn;
290         }
291
292         err = mlx5e_sqs2vport_start(esw, rep, sqs, num_sqs);
293         kfree(sqs);
294
295 out:
296         if (err)
297                 netdev_warn(priv->netdev, "Failed to add SQs FWD rules %d\n", err);
298         return err;
299 }
300
301 void mlx5e_remove_sqs_fwd_rules(struct mlx5e_priv *priv)
302 {
303         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
304         struct mlx5e_rep_priv *rpriv = priv->ppriv;
305         struct mlx5_eswitch_rep *rep = rpriv->rep;
306
307         mlx5e_sqs2vport_stop(esw, rep);
308 }
309
310 static void mlx5e_rep_neigh_update_init_interval(struct mlx5e_rep_priv *rpriv)
311 {
312 #if IS_ENABLED(CONFIG_IPV6)
313         unsigned long ipv6_interval = NEIGH_VAR(&nd_tbl.parms,
314                                                 DELAY_PROBE_TIME);
315 #else
316         unsigned long ipv6_interval = ~0UL;
317 #endif
318         unsigned long ipv4_interval = NEIGH_VAR(&arp_tbl.parms,
319                                                 DELAY_PROBE_TIME);
320         struct net_device *netdev = rpriv->netdev;
321         struct mlx5e_priv *priv = netdev_priv(netdev);
322
323         rpriv->neigh_update.min_interval = min_t(unsigned long, ipv6_interval, ipv4_interval);
324         mlx5_fc_update_sampling_interval(priv->mdev, rpriv->neigh_update.min_interval);
325 }
326
327 void mlx5e_rep_queue_neigh_stats_work(struct mlx5e_priv *priv)
328 {
329         struct mlx5e_rep_priv *rpriv = priv->ppriv;
330         struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
331
332         mlx5_fc_queue_stats_work(priv->mdev,
333                                  &neigh_update->neigh_stats_work,
334                                  neigh_update->min_interval);
335 }
336
337 static void mlx5e_rep_neigh_stats_work(struct work_struct *work)
338 {
339         struct mlx5e_rep_priv *rpriv = container_of(work, struct mlx5e_rep_priv,
340                                                     neigh_update.neigh_stats_work.work);
341         struct net_device *netdev = rpriv->netdev;
342         struct mlx5e_priv *priv = netdev_priv(netdev);
343         struct mlx5e_neigh_hash_entry *nhe;
344
345         rtnl_lock();
346         if (!list_empty(&rpriv->neigh_update.neigh_list))
347                 mlx5e_rep_queue_neigh_stats_work(priv);
348
349         list_for_each_entry(nhe, &rpriv->neigh_update.neigh_list, neigh_list)
350                 mlx5e_tc_update_neigh_used_value(nhe);
351
352         rtnl_unlock();
353 }
354
355 static void mlx5e_rep_neigh_entry_hold(struct mlx5e_neigh_hash_entry *nhe)
356 {
357         refcount_inc(&nhe->refcnt);
358 }
359
360 static void mlx5e_rep_neigh_entry_release(struct mlx5e_neigh_hash_entry *nhe)
361 {
362         if (refcount_dec_and_test(&nhe->refcnt))
363                 kfree(nhe);
364 }
365
366 static void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
367                                    struct mlx5e_encap_entry *e,
368                                    bool neigh_connected,
369                                    unsigned char ha[ETH_ALEN])
370 {
371         struct ethhdr *eth = (struct ethhdr *)e->encap_header;
372
373         ASSERT_RTNL();
374
375         if ((!neigh_connected && (e->flags & MLX5_ENCAP_ENTRY_VALID)) ||
376             !ether_addr_equal(e->h_dest, ha))
377                 mlx5e_tc_encap_flows_del(priv, e);
378
379         if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
380                 ether_addr_copy(e->h_dest, ha);
381                 ether_addr_copy(eth->h_dest, ha);
382
383                 mlx5e_tc_encap_flows_add(priv, e);
384         }
385 }
386
387 static void mlx5e_rep_neigh_update(struct work_struct *work)
388 {
389         struct mlx5e_neigh_hash_entry *nhe =
390                 container_of(work, struct mlx5e_neigh_hash_entry, neigh_update_work);
391         struct neighbour *n = nhe->n;
392         struct mlx5e_encap_entry *e;
393         unsigned char ha[ETH_ALEN];
394         struct mlx5e_priv *priv;
395         bool neigh_connected;
396         bool encap_connected;
397         u8 nud_state, dead;
398
399         rtnl_lock();
400
401         /* If these parameters are changed after we release the lock,
402          * we'll receive another event letting us know about it.
403          * We use this lock to avoid inconsistency between the neigh validity
404          * and it's hw address.
405          */
406         read_lock_bh(&n->lock);
407         memcpy(ha, n->ha, ETH_ALEN);
408         nud_state = n->nud_state;
409         dead = n->dead;
410         read_unlock_bh(&n->lock);
411
412         neigh_connected = (nud_state & NUD_VALID) && !dead;
413
414         list_for_each_entry(e, &nhe->encap_list, encap_list) {
415                 encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID);
416                 priv = netdev_priv(e->out_dev);
417
418                 if (encap_connected != neigh_connected ||
419                     !ether_addr_equal(e->h_dest, ha))
420                         mlx5e_rep_update_flows(priv, e, neigh_connected, ha);
421         }
422         mlx5e_rep_neigh_entry_release(nhe);
423         rtnl_unlock();
424         neigh_release(n);
425 }
426
427 static struct mlx5e_neigh_hash_entry *
428 mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv,
429                              struct mlx5e_neigh *m_neigh);
430
431 static int mlx5e_rep_netevent_event(struct notifier_block *nb,
432                                     unsigned long event, void *ptr)
433 {
434         struct mlx5e_rep_priv *rpriv = container_of(nb, struct mlx5e_rep_priv,
435                                                     neigh_update.netevent_nb);
436         struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
437         struct net_device *netdev = rpriv->netdev;
438         struct mlx5e_priv *priv = netdev_priv(netdev);
439         struct mlx5e_neigh_hash_entry *nhe = NULL;
440         struct mlx5e_neigh m_neigh = {};
441         struct neigh_parms *p;
442         struct neighbour *n;
443         bool found = false;
444
445         switch (event) {
446         case NETEVENT_NEIGH_UPDATE:
447                 n = ptr;
448 #if IS_ENABLED(CONFIG_IPV6)
449                 if (n->tbl != &nd_tbl && n->tbl != &arp_tbl)
450 #else
451                 if (n->tbl != &arp_tbl)
452 #endif
453                         return NOTIFY_DONE;
454
455                 m_neigh.dev = n->dev;
456                 m_neigh.family = n->ops->family;
457                 memcpy(&m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
458
459                 /* We are in atomic context and can't take RTNL mutex, so use
460                  * spin_lock_bh to lookup the neigh table. bh is used since
461                  * netevent can be called from a softirq context.
462                  */
463                 spin_lock_bh(&neigh_update->encap_lock);
464                 nhe = mlx5e_rep_neigh_entry_lookup(priv, &m_neigh);
465                 if (!nhe) {
466                         spin_unlock_bh(&neigh_update->encap_lock);
467                         return NOTIFY_DONE;
468                 }
469
470                 /* This assignment is valid as long as the the neigh reference
471                  * is taken
472                  */
473                 nhe->n = n;
474
475                 /* Take a reference to ensure the neighbour and mlx5 encap
476                  * entry won't be destructed until we drop the reference in
477                  * delayed work.
478                  */
479                 neigh_hold(n);
480                 mlx5e_rep_neigh_entry_hold(nhe);
481
482                 if (!queue_work(priv->wq, &nhe->neigh_update_work)) {
483                         mlx5e_rep_neigh_entry_release(nhe);
484                         neigh_release(n);
485                 }
486                 spin_unlock_bh(&neigh_update->encap_lock);
487                 break;
488
489         case NETEVENT_DELAY_PROBE_TIME_UPDATE:
490                 p = ptr;
491
492                 /* We check the device is present since we don't care about
493                  * changes in the default table, we only care about changes
494                  * done per device delay prob time parameter.
495                  */
496 #if IS_ENABLED(CONFIG_IPV6)
497                 if (!p->dev || (p->tbl != &nd_tbl && p->tbl != &arp_tbl))
498 #else
499                 if (!p->dev || p->tbl != &arp_tbl)
500 #endif
501                         return NOTIFY_DONE;
502
503                 /* We are in atomic context and can't take RTNL mutex,
504                  * so use spin_lock_bh to walk the neigh list and look for
505                  * the relevant device. bh is used since netevent can be
506                  * called from a softirq context.
507                  */
508                 spin_lock_bh(&neigh_update->encap_lock);
509                 list_for_each_entry(nhe, &neigh_update->neigh_list, neigh_list) {
510                         if (p->dev == nhe->m_neigh.dev) {
511                                 found = true;
512                                 break;
513                         }
514                 }
515                 spin_unlock_bh(&neigh_update->encap_lock);
516                 if (!found)
517                         return NOTIFY_DONE;
518
519                 neigh_update->min_interval = min_t(unsigned long,
520                                                    NEIGH_VAR(p, DELAY_PROBE_TIME),
521                                                    neigh_update->min_interval);
522                 mlx5_fc_update_sampling_interval(priv->mdev,
523                                                  neigh_update->min_interval);
524                 break;
525         }
526         return NOTIFY_DONE;
527 }
528
529 static const struct rhashtable_params mlx5e_neigh_ht_params = {
530         .head_offset = offsetof(struct mlx5e_neigh_hash_entry, rhash_node),
531         .key_offset = offsetof(struct mlx5e_neigh_hash_entry, m_neigh),
532         .key_len = sizeof(struct mlx5e_neigh),
533         .automatic_shrinking = true,
534 };
535
536 static int mlx5e_rep_neigh_init(struct mlx5e_rep_priv *rpriv)
537 {
538         struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
539         int err;
540
541         err = rhashtable_init(&neigh_update->neigh_ht, &mlx5e_neigh_ht_params);
542         if (err)
543                 return err;
544
545         INIT_LIST_HEAD(&neigh_update->neigh_list);
546         spin_lock_init(&neigh_update->encap_lock);
547         INIT_DELAYED_WORK(&neigh_update->neigh_stats_work,
548                           mlx5e_rep_neigh_stats_work);
549         mlx5e_rep_neigh_update_init_interval(rpriv);
550
551         rpriv->neigh_update.netevent_nb.notifier_call = mlx5e_rep_netevent_event;
552         err = register_netevent_notifier(&rpriv->neigh_update.netevent_nb);
553         if (err)
554                 goto out_err;
555         return 0;
556
557 out_err:
558         rhashtable_destroy(&neigh_update->neigh_ht);
559         return err;
560 }
561
562 static void mlx5e_rep_neigh_cleanup(struct mlx5e_rep_priv *rpriv)
563 {
564         struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
565         struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
566
567         unregister_netevent_notifier(&neigh_update->netevent_nb);
568
569         flush_workqueue(priv->wq); /* flush neigh update works */
570
571         cancel_delayed_work_sync(&rpriv->neigh_update.neigh_stats_work);
572
573         rhashtable_destroy(&neigh_update->neigh_ht);
574 }
575
576 static int mlx5e_rep_neigh_entry_insert(struct mlx5e_priv *priv,
577                                         struct mlx5e_neigh_hash_entry *nhe)
578 {
579         struct mlx5e_rep_priv *rpriv = priv->ppriv;
580         int err;
581
582         err = rhashtable_insert_fast(&rpriv->neigh_update.neigh_ht,
583                                      &nhe->rhash_node,
584                                      mlx5e_neigh_ht_params);
585         if (err)
586                 return err;
587
588         list_add(&nhe->neigh_list, &rpriv->neigh_update.neigh_list);
589
590         return err;
591 }
592
593 static void mlx5e_rep_neigh_entry_remove(struct mlx5e_priv *priv,
594                                          struct mlx5e_neigh_hash_entry *nhe)
595 {
596         struct mlx5e_rep_priv *rpriv = priv->ppriv;
597
598         spin_lock_bh(&rpriv->neigh_update.encap_lock);
599
600         list_del(&nhe->neigh_list);
601
602         rhashtable_remove_fast(&rpriv->neigh_update.neigh_ht,
603                                &nhe->rhash_node,
604                                mlx5e_neigh_ht_params);
605         spin_unlock_bh(&rpriv->neigh_update.encap_lock);
606 }
607
608 /* This function must only be called under RTNL lock or under the
609  * representor's encap_lock in case RTNL mutex can't be held.
610  */
611 static struct mlx5e_neigh_hash_entry *
612 mlx5e_rep_neigh_entry_lookup(struct mlx5e_priv *priv,
613                              struct mlx5e_neigh *m_neigh)
614 {
615         struct mlx5e_rep_priv *rpriv = priv->ppriv;
616         struct mlx5e_neigh_update_table *neigh_update = &rpriv->neigh_update;
617
618         return rhashtable_lookup_fast(&neigh_update->neigh_ht, m_neigh,
619                                       mlx5e_neigh_ht_params);
620 }
621
622 static int mlx5e_rep_neigh_entry_create(struct mlx5e_priv *priv,
623                                         struct mlx5e_encap_entry *e,
624                                         struct mlx5e_neigh_hash_entry **nhe)
625 {
626         int err;
627
628         *nhe = kzalloc(sizeof(**nhe), GFP_KERNEL);
629         if (!*nhe)
630                 return -ENOMEM;
631
632         memcpy(&(*nhe)->m_neigh, &e->m_neigh, sizeof(e->m_neigh));
633         INIT_WORK(&(*nhe)->neigh_update_work, mlx5e_rep_neigh_update);
634         INIT_LIST_HEAD(&(*nhe)->encap_list);
635         refcount_set(&(*nhe)->refcnt, 1);
636
637         err = mlx5e_rep_neigh_entry_insert(priv, *nhe);
638         if (err)
639                 goto out_free;
640         return 0;
641
642 out_free:
643         kfree(*nhe);
644         return err;
645 }
646
647 static void mlx5e_rep_neigh_entry_destroy(struct mlx5e_priv *priv,
648                                           struct mlx5e_neigh_hash_entry *nhe)
649 {
650         /* The neigh hash entry must be removed from the hash table regardless
651          * of the reference count value, so it won't be found by the next
652          * neigh notification call. The neigh hash entry reference count is
653          * incremented only during creation and neigh notification calls and
654          * protects from freeing the nhe struct.
655          */
656         mlx5e_rep_neigh_entry_remove(priv, nhe);
657         mlx5e_rep_neigh_entry_release(nhe);
658 }
659
660 int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
661                                  struct mlx5e_encap_entry *e)
662 {
663         struct mlx5e_neigh_hash_entry *nhe;
664         int err;
665
666         nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh);
667         if (!nhe) {
668                 err = mlx5e_rep_neigh_entry_create(priv, e, &nhe);
669                 if (err)
670                         return err;
671         }
672         list_add(&e->encap_list, &nhe->encap_list);
673         return 0;
674 }
675
676 void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
677                                   struct mlx5e_encap_entry *e)
678 {
679         struct mlx5e_neigh_hash_entry *nhe;
680
681         list_del(&e->encap_list);
682         nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh);
683
684         if (list_empty(&nhe->encap_list))
685                 mlx5e_rep_neigh_entry_destroy(priv, nhe);
686 }
687
688 static int mlx5e_rep_open(struct net_device *dev)
689 {
690         struct mlx5e_priv *priv = netdev_priv(dev);
691         struct mlx5e_rep_priv *rpriv = priv->ppriv;
692         struct mlx5_eswitch_rep *rep = rpriv->rep;
693         int err;
694
695         mutex_lock(&priv->state_lock);
696         err = mlx5e_open_locked(dev);
697         if (err)
698                 goto unlock;
699
700         if (!mlx5_modify_vport_admin_state(priv->mdev,
701                                            MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
702                                            rep->vport, MLX5_VPORT_ADMIN_STATE_UP))
703                 netif_carrier_on(dev);
704
705 unlock:
706         mutex_unlock(&priv->state_lock);
707         return err;
708 }
709
710 static int mlx5e_rep_close(struct net_device *dev)
711 {
712         struct mlx5e_priv *priv = netdev_priv(dev);
713         struct mlx5e_rep_priv *rpriv = priv->ppriv;
714         struct mlx5_eswitch_rep *rep = rpriv->rep;
715         int ret;
716
717         mutex_lock(&priv->state_lock);
718         mlx5_modify_vport_admin_state(priv->mdev,
719                                       MLX5_VPORT_STATE_OP_MOD_ESW_VPORT,
720                                       rep->vport, MLX5_VPORT_ADMIN_STATE_DOWN);
721         ret = mlx5e_close_locked(dev);
722         mutex_unlock(&priv->state_lock);
723         return ret;
724 }
725
726 static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
727                                         char *buf, size_t len)
728 {
729         struct mlx5e_priv *priv = netdev_priv(dev);
730         struct mlx5e_rep_priv *rpriv = priv->ppriv;
731         struct mlx5_eswitch_rep *rep = rpriv->rep;
732         int ret;
733
734         ret = snprintf(buf, len, "%d", rep->vport - 1);
735         if (ret >= len)
736                 return -EOPNOTSUPP;
737
738         return 0;
739 }
740
741 static int
742 mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
743                               struct tc_cls_flower_offload *cls_flower, int flags)
744 {
745         switch (cls_flower->command) {
746         case TC_CLSFLOWER_REPLACE:
747                 return mlx5e_configure_flower(priv, cls_flower, flags);
748         case TC_CLSFLOWER_DESTROY:
749                 return mlx5e_delete_flower(priv, cls_flower, flags);
750         case TC_CLSFLOWER_STATS:
751                 return mlx5e_stats_flower(priv, cls_flower, flags);
752         default:
753                 return -EOPNOTSUPP;
754         }
755 }
756
757 static int mlx5e_rep_setup_tc_cb_egdev(enum tc_setup_type type, void *type_data,
758                                        void *cb_priv)
759 {
760         struct mlx5e_priv *priv = cb_priv;
761
762         if (!tc_cls_can_offload_and_chain0(priv->netdev, type_data))
763                 return -EOPNOTSUPP;
764
765         switch (type) {
766         case TC_SETUP_CLSFLOWER:
767                 return mlx5e_rep_setup_tc_cls_flower(priv, type_data, MLX5E_TC_EGRESS);
768         default:
769                 return -EOPNOTSUPP;
770         }
771 }
772
773 static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
774                                  void *cb_priv)
775 {
776         struct mlx5e_priv *priv = cb_priv;
777
778         if (!tc_cls_can_offload_and_chain0(priv->netdev, type_data))
779                 return -EOPNOTSUPP;
780
781         switch (type) {
782         case TC_SETUP_CLSFLOWER:
783                 return mlx5e_rep_setup_tc_cls_flower(priv, type_data, MLX5E_TC_INGRESS);
784         default:
785                 return -EOPNOTSUPP;
786         }
787 }
788
789 static int mlx5e_rep_setup_tc_block(struct net_device *dev,
790                                     struct tc_block_offload *f)
791 {
792         struct mlx5e_priv *priv = netdev_priv(dev);
793
794         if (f->binder_type != TCF_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
795                 return -EOPNOTSUPP;
796
797         switch (f->command) {
798         case TC_BLOCK_BIND:
799                 return tcf_block_cb_register(f->block, mlx5e_rep_setup_tc_cb,
800                                              priv, priv, f->extack);
801         case TC_BLOCK_UNBIND:
802                 tcf_block_cb_unregister(f->block, mlx5e_rep_setup_tc_cb, priv);
803                 return 0;
804         default:
805                 return -EOPNOTSUPP;
806         }
807 }
808
809 static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
810                               void *type_data)
811 {
812         switch (type) {
813         case TC_SETUP_BLOCK:
814                 return mlx5e_rep_setup_tc_block(dev, type_data);
815         default:
816                 return -EOPNOTSUPP;
817         }
818 }
819
820 bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
821 {
822         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
823         struct mlx5e_rep_priv *rpriv = priv->ppriv;
824         struct mlx5_eswitch_rep *rep;
825
826         if (!MLX5_ESWITCH_MANAGER(priv->mdev))
827                 return false;
828
829         rep = rpriv->rep;
830         if (esw->mode == SRIOV_OFFLOADS &&
831             rep && rep->vport == FDB_UPLINK_VPORT)
832                 return true;
833
834         return false;
835 }
836
837 static bool mlx5e_is_vf_vport_rep(struct mlx5e_priv *priv)
838 {
839         struct mlx5e_rep_priv *rpriv = priv->ppriv;
840         struct mlx5_eswitch_rep *rep;
841
842         if (!MLX5_ESWITCH_MANAGER(priv->mdev))
843                 return false;
844
845         rep = rpriv->rep;
846         if (rep && rep->vport != FDB_UPLINK_VPORT)
847                 return true;
848
849         return false;
850 }
851
852 bool mlx5e_has_offload_stats(const struct net_device *dev, int attr_id)
853 {
854         struct mlx5e_priv *priv = netdev_priv(dev);
855
856         switch (attr_id) {
857         case IFLA_OFFLOAD_XSTATS_CPU_HIT:
858                 if (mlx5e_is_vf_vport_rep(priv) || mlx5e_is_uplink_rep(priv))
859                         return true;
860         }
861
862         return false;
863 }
864
865 static int
866 mlx5e_get_sw_stats64(const struct net_device *dev,
867                      struct rtnl_link_stats64 *stats)
868 {
869         struct mlx5e_priv *priv = netdev_priv(dev);
870         struct mlx5e_sw_stats *sstats = &priv->stats.sw;
871
872         mlx5e_rep_update_sw_counters(priv);
873
874         stats->rx_packets = sstats->rx_packets;
875         stats->rx_bytes   = sstats->rx_bytes;
876         stats->tx_packets = sstats->tx_packets;
877         stats->tx_bytes   = sstats->tx_bytes;
878
879         stats->tx_dropped = sstats->tx_queue_dropped;
880
881         return 0;
882 }
883
884 int mlx5e_get_offload_stats(int attr_id, const struct net_device *dev,
885                             void *sp)
886 {
887         switch (attr_id) {
888         case IFLA_OFFLOAD_XSTATS_CPU_HIT:
889                 return mlx5e_get_sw_stats64(dev, sp);
890         }
891
892         return -EINVAL;
893 }
894
895 static void
896 mlx5e_rep_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
897 {
898         struct mlx5e_priv *priv = netdev_priv(dev);
899
900         /* update HW stats in background for next time */
901         queue_delayed_work(priv->wq, &priv->update_stats_work, 0);
902
903         memcpy(stats, &priv->stats.vf_vport, sizeof(*stats));
904 }
905
906 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
907         .switchdev_port_attr_get        = mlx5e_attr_get,
908 };
909
910 static int mlx5e_change_rep_mtu(struct net_device *netdev, int new_mtu)
911 {
912         return mlx5e_change_mtu(netdev, new_mtu, NULL);
913 }
914
915 static const struct net_device_ops mlx5e_netdev_ops_rep = {
916         .ndo_open                = mlx5e_rep_open,
917         .ndo_stop                = mlx5e_rep_close,
918         .ndo_start_xmit          = mlx5e_xmit,
919         .ndo_get_phys_port_name  = mlx5e_rep_get_phys_port_name,
920         .ndo_setup_tc            = mlx5e_rep_setup_tc,
921         .ndo_get_stats64         = mlx5e_rep_get_stats,
922         .ndo_has_offload_stats   = mlx5e_has_offload_stats,
923         .ndo_get_offload_stats   = mlx5e_get_offload_stats,
924         .ndo_change_mtu          = mlx5e_change_rep_mtu,
925 };
926
927 static void mlx5e_build_rep_params(struct mlx5_core_dev *mdev,
928                                    struct mlx5e_params *params, u16 mtu)
929 {
930         u8 cq_period_mode = MLX5_CAP_GEN(mdev, cq_period_start_from_cqe) ?
931                                          MLX5_CQ_PERIOD_MODE_START_FROM_CQE :
932                                          MLX5_CQ_PERIOD_MODE_START_FROM_EQE;
933
934         params->hard_mtu    = MLX5E_ETH_HARD_MTU;
935         params->sw_mtu      = mtu;
936         params->log_sq_size = MLX5E_REP_PARAMS_LOG_SQ_SIZE;
937         params->rq_wq_type  = MLX5_WQ_TYPE_CYCLIC;
938         params->log_rq_mtu_frames = MLX5E_REP_PARAMS_LOG_RQ_SIZE;
939
940         params->rx_dim_enabled = MLX5_CAP_GEN(mdev, cq_moderation);
941         mlx5e_set_rx_cq_mode_params(params, cq_period_mode);
942
943         params->num_tc                = 1;
944         params->lro_wqe_sz            = MLX5E_PARAMS_DEFAULT_LRO_WQE_SZ;
945
946         mlx5_query_min_inline(mdev, &params->tx_min_inline_mode);
947 }
948
949 static void mlx5e_build_rep_netdev(struct net_device *netdev)
950 {
951         struct mlx5e_priv *priv = netdev_priv(netdev);
952         struct mlx5_core_dev *mdev = priv->mdev;
953         u16 max_mtu;
954
955         netdev->netdev_ops = &mlx5e_netdev_ops_rep;
956
957         netdev->watchdog_timeo    = 15 * HZ;
958
959         netdev->ethtool_ops       = &mlx5e_rep_ethtool_ops;
960
961         netdev->switchdev_ops = &mlx5e_rep_switchdev_ops;
962
963         netdev->features         |= NETIF_F_VLAN_CHALLENGED | NETIF_F_HW_TC | NETIF_F_NETNS_LOCAL;
964         netdev->hw_features      |= NETIF_F_HW_TC;
965
966         eth_hw_addr_random(netdev);
967
968         netdev->min_mtu = ETH_MIN_MTU;
969         mlx5_query_port_max_mtu(mdev, &max_mtu, 1);
970         netdev->max_mtu = MLX5E_HW2SW_MTU(&priv->channels.params, max_mtu);
971 }
972
973 static void mlx5e_init_rep(struct mlx5_core_dev *mdev,
974                            struct net_device *netdev,
975                            const struct mlx5e_profile *profile,
976                            void *ppriv)
977 {
978         struct mlx5e_priv *priv = netdev_priv(netdev);
979
980         priv->mdev                         = mdev;
981         priv->netdev                       = netdev;
982         priv->profile                      = profile;
983         priv->ppriv                        = ppriv;
984
985         mutex_init(&priv->state_lock);
986
987         INIT_DELAYED_WORK(&priv->update_stats_work, mlx5e_update_stats_work);
988
989         priv->channels.params.num_channels = profile->max_nch(mdev);
990
991         mlx5e_build_rep_params(mdev, &priv->channels.params, netdev->mtu);
992         mlx5e_build_rep_netdev(netdev);
993
994         mlx5e_timestamp_init(priv);
995 }
996
997 static int mlx5e_init_rep_rx(struct mlx5e_priv *priv)
998 {
999         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
1000         struct mlx5e_rep_priv *rpriv = priv->ppriv;
1001         struct mlx5_eswitch_rep *rep = rpriv->rep;
1002         struct mlx5_flow_handle *flow_rule;
1003         int err;
1004
1005         mlx5e_init_l2_addr(priv);
1006
1007         err = mlx5e_create_direct_rqts(priv);
1008         if (err)
1009                 return err;
1010
1011         err = mlx5e_create_direct_tirs(priv);
1012         if (err)
1013                 goto err_destroy_direct_rqts;
1014
1015         flow_rule = mlx5_eswitch_create_vport_rx_rule(esw,
1016                                                       rep->vport,
1017                                                       priv->direct_tir[0].tirn);
1018         if (IS_ERR(flow_rule)) {
1019                 err = PTR_ERR(flow_rule);
1020                 goto err_destroy_direct_tirs;
1021         }
1022         rpriv->vport_rx_rule = flow_rule;
1023
1024         return 0;
1025
1026 err_destroy_direct_tirs:
1027         mlx5e_destroy_direct_tirs(priv);
1028 err_destroy_direct_rqts:
1029         mlx5e_destroy_direct_rqts(priv);
1030         return err;
1031 }
1032
1033 static void mlx5e_cleanup_rep_rx(struct mlx5e_priv *priv)
1034 {
1035         struct mlx5e_rep_priv *rpriv = priv->ppriv;
1036
1037         mlx5_del_flow_rules(rpriv->vport_rx_rule);
1038         mlx5e_destroy_direct_tirs(priv);
1039         mlx5e_destroy_direct_rqts(priv);
1040 }
1041
1042 static int mlx5e_init_rep_tx(struct mlx5e_priv *priv)
1043 {
1044         int err;
1045
1046         err = mlx5e_create_tises(priv);
1047         if (err) {
1048                 mlx5_core_warn(priv->mdev, "create tises failed, %d\n", err);
1049                 return err;
1050         }
1051         return 0;
1052 }
1053
1054 static int mlx5e_get_rep_max_num_channels(struct mlx5_core_dev *mdev)
1055 {
1056 #define MLX5E_PORT_REPRESENTOR_NCH 1
1057         return MLX5E_PORT_REPRESENTOR_NCH;
1058 }
1059
1060 static const struct mlx5e_profile mlx5e_rep_profile = {
1061         .init                   = mlx5e_init_rep,
1062         .init_rx                = mlx5e_init_rep_rx,
1063         .cleanup_rx             = mlx5e_cleanup_rep_rx,
1064         .init_tx                = mlx5e_init_rep_tx,
1065         .cleanup_tx             = mlx5e_cleanup_nic_tx,
1066         .update_stats           = mlx5e_rep_update_hw_counters,
1067         .max_nch                = mlx5e_get_rep_max_num_channels,
1068         .update_carrier         = NULL,
1069         .rx_handlers.handle_rx_cqe       = mlx5e_handle_rx_cqe_rep,
1070         .rx_handlers.handle_rx_cqe_mpwqe = NULL /* Not supported */,
1071         .max_tc                 = 1,
1072 };
1073
1074 /* e-Switch vport representors */
1075
1076 static int
1077 mlx5e_nic_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1078 {
1079         struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1080         struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
1081
1082         int err;
1083
1084         if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
1085                 err = mlx5e_add_sqs_fwd_rules(priv);
1086                 if (err)
1087                         return err;
1088         }
1089
1090         err = mlx5e_rep_neigh_init(rpriv);
1091         if (err)
1092                 goto err_remove_sqs;
1093
1094         /* init shared tc flow table */
1095         err = mlx5e_tc_esw_init(&rpriv->tc_ht);
1096         if (err)
1097                 goto  err_neigh_cleanup;
1098
1099         return 0;
1100
1101 err_neigh_cleanup:
1102         mlx5e_rep_neigh_cleanup(rpriv);
1103 err_remove_sqs:
1104         mlx5e_remove_sqs_fwd_rules(priv);
1105         return err;
1106 }
1107
1108 static void
1109 mlx5e_nic_rep_unload(struct mlx5_eswitch_rep *rep)
1110 {
1111         struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1112         struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
1113
1114         if (test_bit(MLX5E_STATE_OPENED, &priv->state))
1115                 mlx5e_remove_sqs_fwd_rules(priv);
1116
1117         /* clean uplink offloaded TC rules, delete shared tc flow table */
1118         mlx5e_tc_esw_cleanup(&rpriv->tc_ht);
1119
1120         mlx5e_rep_neigh_cleanup(rpriv);
1121 }
1122
1123 static int
1124 mlx5e_vport_rep_load(struct mlx5_core_dev *dev, struct mlx5_eswitch_rep *rep)
1125 {
1126         struct mlx5e_rep_priv *uplink_rpriv;
1127         struct mlx5e_rep_priv *rpriv;
1128         struct net_device *netdev;
1129         struct mlx5e_priv *upriv;
1130         int err;
1131
1132         rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
1133         if (!rpriv)
1134                 return -ENOMEM;
1135
1136         netdev = mlx5e_create_netdev(dev, &mlx5e_rep_profile, rpriv);
1137         if (!netdev) {
1138                 pr_warn("Failed to create representor netdev for vport %d\n",
1139                         rep->vport);
1140                 kfree(rpriv);
1141                 return -EINVAL;
1142         }
1143
1144         rpriv->netdev = netdev;
1145         rpriv->rep = rep;
1146         rep->rep_if[REP_ETH].priv = rpriv;
1147         INIT_LIST_HEAD(&rpriv->vport_sqs_list);
1148
1149         err = mlx5e_attach_netdev(netdev_priv(netdev));
1150         if (err) {
1151                 pr_warn("Failed to attach representor netdev for vport %d\n",
1152                         rep->vport);
1153                 goto err_destroy_netdev;
1154         }
1155
1156         err = mlx5e_rep_neigh_init(rpriv);
1157         if (err) {
1158                 pr_warn("Failed to initialized neighbours handling for vport %d\n",
1159                         rep->vport);
1160                 goto err_detach_netdev;
1161         }
1162
1163         uplink_rpriv = mlx5_eswitch_get_uplink_priv(dev->priv.eswitch, REP_ETH);
1164         upriv = netdev_priv(uplink_rpriv->netdev);
1165         err = tc_setup_cb_egdev_register(netdev, mlx5e_rep_setup_tc_cb_egdev,
1166                                          upriv);
1167         if (err)
1168                 goto err_neigh_cleanup;
1169
1170         err = register_netdev(netdev);
1171         if (err) {
1172                 pr_warn("Failed to register representor netdev for vport %d\n",
1173                         rep->vport);
1174                 goto err_egdev_cleanup;
1175         }
1176
1177         return 0;
1178
1179 err_egdev_cleanup:
1180         tc_setup_cb_egdev_unregister(netdev, mlx5e_rep_setup_tc_cb_egdev,
1181                                      upriv);
1182
1183 err_neigh_cleanup:
1184         mlx5e_rep_neigh_cleanup(rpriv);
1185
1186 err_detach_netdev:
1187         mlx5e_detach_netdev(netdev_priv(netdev));
1188
1189 err_destroy_netdev:
1190         mlx5e_destroy_netdev(netdev_priv(netdev));
1191         kfree(rpriv);
1192         return err;
1193 }
1194
1195 static void
1196 mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
1197 {
1198         struct mlx5e_rep_priv *rpriv = mlx5e_rep_to_rep_priv(rep);
1199         struct net_device *netdev = rpriv->netdev;
1200         struct mlx5e_priv *priv = netdev_priv(netdev);
1201         struct mlx5e_rep_priv *uplink_rpriv;
1202         void *ppriv = priv->ppriv;
1203         struct mlx5e_priv *upriv;
1204
1205         unregister_netdev(netdev);
1206         uplink_rpriv = mlx5_eswitch_get_uplink_priv(priv->mdev->priv.eswitch,
1207                                                     REP_ETH);
1208         upriv = netdev_priv(uplink_rpriv->netdev);
1209         tc_setup_cb_egdev_unregister(netdev, mlx5e_rep_setup_tc_cb_egdev,
1210                                      upriv);
1211         mlx5e_rep_neigh_cleanup(rpriv);
1212         mlx5e_detach_netdev(priv);
1213         mlx5e_destroy_netdev(priv);
1214         kfree(ppriv); /* mlx5e_rep_priv */
1215 }
1216
1217 static void *mlx5e_vport_rep_get_proto_dev(struct mlx5_eswitch_rep *rep)
1218 {
1219         struct mlx5e_rep_priv *rpriv;
1220
1221         rpriv = mlx5e_rep_to_rep_priv(rep);
1222
1223         return rpriv->netdev;
1224 }
1225
1226 static void mlx5e_rep_register_vf_vports(struct mlx5e_priv *priv)
1227 {
1228         struct mlx5_core_dev *mdev = priv->mdev;
1229         struct mlx5_eswitch *esw   = mdev->priv.eswitch;
1230         int total_vfs = MLX5_TOTAL_VPORTS(mdev);
1231         int vport;
1232
1233         for (vport = 1; vport < total_vfs; vport++) {
1234                 struct mlx5_eswitch_rep_if rep_if = {};
1235
1236                 rep_if.load = mlx5e_vport_rep_load;
1237                 rep_if.unload = mlx5e_vport_rep_unload;
1238                 rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
1239                 mlx5_eswitch_register_vport_rep(esw, vport, &rep_if, REP_ETH);
1240         }
1241 }
1242
1243 static void mlx5e_rep_unregister_vf_vports(struct mlx5e_priv *priv)
1244 {
1245         struct mlx5_core_dev *mdev = priv->mdev;
1246         struct mlx5_eswitch *esw = mdev->priv.eswitch;
1247         int total_vfs = MLX5_TOTAL_VPORTS(mdev);
1248         int vport;
1249
1250         for (vport = 1; vport < total_vfs; vport++)
1251                 mlx5_eswitch_unregister_vport_rep(esw, vport, REP_ETH);
1252 }
1253
1254 void mlx5e_register_vport_reps(struct mlx5e_priv *priv)
1255 {
1256         struct mlx5_core_dev *mdev = priv->mdev;
1257         struct mlx5_eswitch *esw   = mdev->priv.eswitch;
1258         struct mlx5_eswitch_rep_if rep_if;
1259         struct mlx5e_rep_priv *rpriv;
1260
1261         rpriv = priv->ppriv;
1262         rpriv->netdev = priv->netdev;
1263
1264         rep_if.load = mlx5e_nic_rep_load;
1265         rep_if.unload = mlx5e_nic_rep_unload;
1266         rep_if.get_proto_dev = mlx5e_vport_rep_get_proto_dev;
1267         rep_if.priv = rpriv;
1268         INIT_LIST_HEAD(&rpriv->vport_sqs_list);
1269         mlx5_eswitch_register_vport_rep(esw, 0, &rep_if, REP_ETH); /* UPLINK PF vport*/
1270
1271         mlx5e_rep_register_vf_vports(priv); /* VFs vports */
1272 }
1273
1274 void mlx5e_unregister_vport_reps(struct mlx5e_priv *priv)
1275 {
1276         struct mlx5_core_dev *mdev = priv->mdev;
1277         struct mlx5_eswitch *esw   = mdev->priv.eswitch;
1278
1279         mlx5e_rep_unregister_vf_vports(priv); /* VFs vports */
1280         mlx5_eswitch_unregister_vport_rep(esw, 0, REP_ETH); /* UPLINK PF*/
1281 }
1282
1283 void *mlx5e_alloc_nic_rep_priv(struct mlx5_core_dev *mdev)
1284 {
1285         struct mlx5_eswitch *esw = mdev->priv.eswitch;
1286         struct mlx5e_rep_priv *rpriv;
1287
1288         rpriv = kzalloc(sizeof(*rpriv), GFP_KERNEL);
1289         if (!rpriv)
1290                 return NULL;
1291
1292         rpriv->rep = &esw->offloads.vport_reps[0];
1293         return rpriv;
1294 }