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