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