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