Merge branch 'mhi-net-immutable' of https://git.kernel.org/pub/scm/linux/kernel/git...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlx5 / core / en / rep / tc.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2020 Mellanox Technologies. */
3
4 #include <net/dst_metadata.h>
5 #include <linux/netdevice.h>
6 #include <linux/list.h>
7 #include <linux/rculist.h>
8 #include <linux/rtnetlink.h>
9 #include <linux/workqueue.h>
10 #include <linux/spinlock.h>
11 #include "tc.h"
12 #include "neigh.h"
13 #include "en_rep.h"
14 #include "eswitch.h"
15 #include "lib/fs_chains.h"
16 #include "en/tc_ct.h"
17 #include "en/mapping.h"
18 #include "en/tc_tun.h"
19 #include "lib/port_tun.h"
20
21 struct mlx5e_rep_indr_block_priv {
22         struct net_device *netdev;
23         struct mlx5e_rep_priv *rpriv;
24
25         struct list_head list;
26 };
27
28 int mlx5e_rep_encap_entry_attach(struct mlx5e_priv *priv,
29                                  struct mlx5e_encap_entry *e)
30 {
31         struct mlx5e_rep_priv *rpriv = priv->ppriv;
32         struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
33         struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy;
34         struct mlx5e_neigh_hash_entry *nhe;
35         int err;
36
37         err = mlx5_tun_entropy_refcount_inc(tun_entropy, e->reformat_type);
38         if (err)
39                 return err;
40
41         mutex_lock(&rpriv->neigh_update.encap_lock);
42         nhe = mlx5e_rep_neigh_entry_lookup(priv, &e->m_neigh);
43         if (!nhe) {
44                 err = mlx5e_rep_neigh_entry_create(priv, e, &nhe);
45                 if (err) {
46                         mutex_unlock(&rpriv->neigh_update.encap_lock);
47                         mlx5_tun_entropy_refcount_dec(tun_entropy,
48                                                       e->reformat_type);
49                         return err;
50                 }
51         }
52
53         e->nhe = nhe;
54         spin_lock(&nhe->encap_list_lock);
55         list_add_rcu(&e->encap_list, &nhe->encap_list);
56         spin_unlock(&nhe->encap_list_lock);
57
58         mutex_unlock(&rpriv->neigh_update.encap_lock);
59
60         return 0;
61 }
62
63 void mlx5e_rep_encap_entry_detach(struct mlx5e_priv *priv,
64                                   struct mlx5e_encap_entry *e)
65 {
66         struct mlx5e_rep_priv *rpriv = priv->ppriv;
67         struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
68         struct mlx5_tun_entropy *tun_entropy = &uplink_priv->tun_entropy;
69
70         if (!e->nhe)
71                 return;
72
73         spin_lock(&e->nhe->encap_list_lock);
74         list_del_rcu(&e->encap_list);
75         spin_unlock(&e->nhe->encap_list_lock);
76
77         mlx5e_rep_neigh_entry_release(e->nhe);
78         e->nhe = NULL;
79         mlx5_tun_entropy_refcount_dec(tun_entropy, e->reformat_type);
80 }
81
82 void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
83                             struct mlx5e_encap_entry *e,
84                             bool neigh_connected,
85                             unsigned char ha[ETH_ALEN])
86 {
87         struct ethhdr *eth = (struct ethhdr *)e->encap_header;
88         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
89         bool encap_connected;
90         LIST_HEAD(flow_list);
91
92         ASSERT_RTNL();
93
94         /* wait for encap to be fully initialized */
95         wait_for_completion(&e->res_ready);
96
97         mutex_lock(&esw->offloads.encap_tbl_lock);
98         encap_connected = !!(e->flags & MLX5_ENCAP_ENTRY_VALID);
99         if (e->compl_result < 0 || (encap_connected == neigh_connected &&
100                                     ether_addr_equal(e->h_dest, ha)))
101                 goto unlock;
102
103         mlx5e_take_all_encap_flows(e, &flow_list);
104
105         if ((e->flags & MLX5_ENCAP_ENTRY_VALID) &&
106             (!neigh_connected || !ether_addr_equal(e->h_dest, ha)))
107                 mlx5e_tc_encap_flows_del(priv, e, &flow_list);
108
109         if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
110                 struct net_device *route_dev;
111
112                 ether_addr_copy(e->h_dest, ha);
113                 ether_addr_copy(eth->h_dest, ha);
114                 /* Update the encap source mac, in case that we delete
115                  * the flows when encap source mac changed.
116                  */
117                 route_dev = __dev_get_by_index(dev_net(priv->netdev), e->route_dev_ifindex);
118                 if (route_dev)
119                         ether_addr_copy(eth->h_source, route_dev->dev_addr);
120
121                 mlx5e_tc_encap_flows_add(priv, e, &flow_list);
122         }
123 unlock:
124         mutex_unlock(&esw->offloads.encap_tbl_lock);
125         mlx5e_put_encap_flow_list(priv, &flow_list);
126 }
127
128 static int
129 mlx5e_rep_setup_tc_cls_flower(struct mlx5e_priv *priv,
130                               struct flow_cls_offload *cls_flower, int flags)
131 {
132         switch (cls_flower->command) {
133         case FLOW_CLS_REPLACE:
134                 return mlx5e_configure_flower(priv->netdev, priv, cls_flower,
135                                               flags);
136         case FLOW_CLS_DESTROY:
137                 return mlx5e_delete_flower(priv->netdev, priv, cls_flower,
138                                            flags);
139         case FLOW_CLS_STATS:
140                 return mlx5e_stats_flower(priv->netdev, priv, cls_flower,
141                                           flags);
142         default:
143                 return -EOPNOTSUPP;
144         }
145 }
146
147 static
148 int mlx5e_rep_setup_tc_cls_matchall(struct mlx5e_priv *priv,
149                                     struct tc_cls_matchall_offload *ma)
150 {
151         switch (ma->command) {
152         case TC_CLSMATCHALL_REPLACE:
153                 return mlx5e_tc_configure_matchall(priv, ma);
154         case TC_CLSMATCHALL_DESTROY:
155                 return mlx5e_tc_delete_matchall(priv, ma);
156         case TC_CLSMATCHALL_STATS:
157                 mlx5e_tc_stats_matchall(priv, ma);
158                 return 0;
159         default:
160                 return -EOPNOTSUPP;
161         }
162 }
163
164 static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
165                                  void *cb_priv)
166 {
167         unsigned long flags = MLX5_TC_FLAG(INGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD);
168         struct mlx5e_priv *priv = cb_priv;
169
170         switch (type) {
171         case TC_SETUP_CLSFLOWER:
172                 return mlx5e_rep_setup_tc_cls_flower(priv, type_data, flags);
173         case TC_SETUP_CLSMATCHALL:
174                 return mlx5e_rep_setup_tc_cls_matchall(priv, type_data);
175         default:
176                 return -EOPNOTSUPP;
177         }
178 }
179
180 static int mlx5e_rep_setup_ft_cb(enum tc_setup_type type, void *type_data,
181                                  void *cb_priv)
182 {
183         struct flow_cls_offload tmp, *f = type_data;
184         struct mlx5e_priv *priv = cb_priv;
185         struct mlx5_eswitch *esw;
186         unsigned long flags;
187         int err;
188
189         flags = MLX5_TC_FLAG(INGRESS) |
190                 MLX5_TC_FLAG(ESW_OFFLOAD) |
191                 MLX5_TC_FLAG(FT_OFFLOAD);
192         esw = priv->mdev->priv.eswitch;
193
194         switch (type) {
195         case TC_SETUP_CLSFLOWER:
196                 memcpy(&tmp, f, sizeof(*f));
197
198                 if (!mlx5_chains_prios_supported(esw_chains(esw)))
199                         return -EOPNOTSUPP;
200
201                 /* Re-use tc offload path by moving the ft flow to the
202                  * reserved ft chain.
203                  *
204                  * FT offload can use prio range [0, INT_MAX], so we normalize
205                  * it to range [1, mlx5_esw_chains_get_prio_range(esw)]
206                  * as with tc, where prio 0 isn't supported.
207                  *
208                  * We only support chain 0 of FT offload.
209                  */
210                 if (tmp.common.prio >= mlx5_chains_get_prio_range(esw_chains(esw)))
211                         return -EOPNOTSUPP;
212                 if (tmp.common.chain_index != 0)
213                         return -EOPNOTSUPP;
214
215                 tmp.common.chain_index = mlx5_chains_get_nf_ft_chain(esw_chains(esw));
216                 tmp.common.prio++;
217                 err = mlx5e_rep_setup_tc_cls_flower(priv, &tmp, flags);
218                 memcpy(&f->stats, &tmp.stats, sizeof(f->stats));
219                 return err;
220         default:
221                 return -EOPNOTSUPP;
222         }
223 }
224
225 static LIST_HEAD(mlx5e_rep_block_tc_cb_list);
226 static LIST_HEAD(mlx5e_rep_block_ft_cb_list);
227 int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
228                        void *type_data)
229 {
230         struct mlx5e_priv *priv = netdev_priv(dev);
231         struct flow_block_offload *f = type_data;
232
233         f->unlocked_driver_cb = true;
234
235         switch (type) {
236         case TC_SETUP_BLOCK:
237                 return flow_block_cb_setup_simple(type_data,
238                                                   &mlx5e_rep_block_tc_cb_list,
239                                                   mlx5e_rep_setup_tc_cb,
240                                                   priv, priv, true);
241         case TC_SETUP_FT:
242                 return flow_block_cb_setup_simple(type_data,
243                                                   &mlx5e_rep_block_ft_cb_list,
244                                                   mlx5e_rep_setup_ft_cb,
245                                                   priv, priv, true);
246         default:
247                 return -EOPNOTSUPP;
248         }
249 }
250
251 int mlx5e_rep_tc_init(struct mlx5e_rep_priv *rpriv)
252 {
253         struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
254         int err;
255
256         mutex_init(&uplink_priv->unready_flows_lock);
257         INIT_LIST_HEAD(&uplink_priv->unready_flows);
258
259         /* init shared tc flow table */
260         err = mlx5e_tc_esw_init(&uplink_priv->tc_ht);
261         return err;
262 }
263
264 void mlx5e_rep_tc_cleanup(struct mlx5e_rep_priv *rpriv)
265 {
266         /* delete shared tc flow table */
267         mlx5e_tc_esw_cleanup(&rpriv->uplink_priv.tc_ht);
268         mutex_destroy(&rpriv->uplink_priv.unready_flows_lock);
269 }
270
271 void mlx5e_rep_tc_enable(struct mlx5e_priv *priv)
272 {
273         struct mlx5e_rep_priv *rpriv = priv->ppriv;
274
275         INIT_WORK(&rpriv->uplink_priv.reoffload_flows_work,
276                   mlx5e_tc_reoffload_flows_work);
277 }
278
279 void mlx5e_rep_tc_disable(struct mlx5e_priv *priv)
280 {
281         struct mlx5e_rep_priv *rpriv = priv->ppriv;
282
283         cancel_work_sync(&rpriv->uplink_priv.reoffload_flows_work);
284 }
285
286 int mlx5e_rep_tc_event_port_affinity(struct mlx5e_priv *priv)
287 {
288         struct mlx5e_rep_priv *rpriv = priv->ppriv;
289
290         queue_work(priv->wq, &rpriv->uplink_priv.reoffload_flows_work);
291
292         return NOTIFY_OK;
293 }
294
295 static struct mlx5e_rep_indr_block_priv *
296 mlx5e_rep_indr_block_priv_lookup(struct mlx5e_rep_priv *rpriv,
297                                  struct net_device *netdev)
298 {
299         struct mlx5e_rep_indr_block_priv *cb_priv;
300
301         /* All callback list access should be protected by RTNL. */
302         ASSERT_RTNL();
303
304         list_for_each_entry(cb_priv,
305                             &rpriv->uplink_priv.tc_indr_block_priv_list,
306                             list)
307                 if (cb_priv->netdev == netdev)
308                         return cb_priv;
309
310         return NULL;
311 }
312
313 static int
314 mlx5e_rep_indr_offload(struct net_device *netdev,
315                        struct flow_cls_offload *flower,
316                        struct mlx5e_rep_indr_block_priv *indr_priv,
317                        unsigned long flags)
318 {
319         struct mlx5e_priv *priv = netdev_priv(indr_priv->rpriv->netdev);
320         int err = 0;
321
322         switch (flower->command) {
323         case FLOW_CLS_REPLACE:
324                 err = mlx5e_configure_flower(netdev, priv, flower, flags);
325                 break;
326         case FLOW_CLS_DESTROY:
327                 err = mlx5e_delete_flower(netdev, priv, flower, flags);
328                 break;
329         case FLOW_CLS_STATS:
330                 err = mlx5e_stats_flower(netdev, priv, flower, flags);
331                 break;
332         default:
333                 err = -EOPNOTSUPP;
334         }
335
336         return err;
337 }
338
339 static int mlx5e_rep_indr_setup_tc_cb(enum tc_setup_type type,
340                                       void *type_data, void *indr_priv)
341 {
342         unsigned long flags = MLX5_TC_FLAG(EGRESS) | MLX5_TC_FLAG(ESW_OFFLOAD);
343         struct mlx5e_rep_indr_block_priv *priv = indr_priv;
344
345         switch (type) {
346         case TC_SETUP_CLSFLOWER:
347                 return mlx5e_rep_indr_offload(priv->netdev, type_data, priv,
348                                               flags);
349         default:
350                 return -EOPNOTSUPP;
351         }
352 }
353
354 static int mlx5e_rep_indr_setup_ft_cb(enum tc_setup_type type,
355                                       void *type_data, void *indr_priv)
356 {
357         struct mlx5e_rep_indr_block_priv *priv = indr_priv;
358         struct flow_cls_offload *f = type_data;
359         struct flow_cls_offload tmp;
360         struct mlx5e_priv *mpriv;
361         struct mlx5_eswitch *esw;
362         unsigned long flags;
363         int err;
364
365         mpriv = netdev_priv(priv->rpriv->netdev);
366         esw = mpriv->mdev->priv.eswitch;
367
368         flags = MLX5_TC_FLAG(EGRESS) |
369                 MLX5_TC_FLAG(ESW_OFFLOAD) |
370                 MLX5_TC_FLAG(FT_OFFLOAD);
371
372         switch (type) {
373         case TC_SETUP_CLSFLOWER:
374                 memcpy(&tmp, f, sizeof(*f));
375
376                 /* Re-use tc offload path by moving the ft flow to the
377                  * reserved ft chain.
378                  *
379                  * FT offload can use prio range [0, INT_MAX], so we normalize
380                  * it to range [1, mlx5_esw_chains_get_prio_range(esw)]
381                  * as with tc, where prio 0 isn't supported.
382                  *
383                  * We only support chain 0 of FT offload.
384                  */
385                 if (!mlx5_chains_prios_supported(esw_chains(esw)) ||
386                     tmp.common.prio >= mlx5_chains_get_prio_range(esw_chains(esw)) ||
387                     tmp.common.chain_index)
388                         return -EOPNOTSUPP;
389
390                 tmp.common.chain_index = mlx5_chains_get_nf_ft_chain(esw_chains(esw));
391                 tmp.common.prio++;
392                 err = mlx5e_rep_indr_offload(priv->netdev, &tmp, priv, flags);
393                 memcpy(&f->stats, &tmp.stats, sizeof(f->stats));
394                 return err;
395         default:
396                 return -EOPNOTSUPP;
397         }
398 }
399
400 static void mlx5e_rep_indr_block_unbind(void *cb_priv)
401 {
402         struct mlx5e_rep_indr_block_priv *indr_priv = cb_priv;
403
404         list_del(&indr_priv->list);
405         kfree(indr_priv);
406 }
407
408 static LIST_HEAD(mlx5e_block_cb_list);
409
410 static int
411 mlx5e_rep_indr_setup_block(struct net_device *netdev, struct Qdisc *sch,
412                            struct mlx5e_rep_priv *rpriv,
413                            struct flow_block_offload *f,
414                            flow_setup_cb_t *setup_cb,
415                            void *data,
416                            void (*cleanup)(struct flow_block_cb *block_cb))
417 {
418         struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
419         struct mlx5e_rep_indr_block_priv *indr_priv;
420         struct flow_block_cb *block_cb;
421
422         if (!mlx5e_tc_tun_device_to_offload(priv, netdev) &&
423             !(is_vlan_dev(netdev) && vlan_dev_real_dev(netdev) == rpriv->netdev))
424                 return -EOPNOTSUPP;
425
426         if (f->binder_type != FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
427                 return -EOPNOTSUPP;
428
429         f->unlocked_driver_cb = true;
430         f->driver_block_list = &mlx5e_block_cb_list;
431
432         switch (f->command) {
433         case FLOW_BLOCK_BIND:
434                 indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
435                 if (indr_priv)
436                         return -EEXIST;
437
438                 indr_priv = kmalloc(sizeof(*indr_priv), GFP_KERNEL);
439                 if (!indr_priv)
440                         return -ENOMEM;
441
442                 indr_priv->netdev = netdev;
443                 indr_priv->rpriv = rpriv;
444                 list_add(&indr_priv->list,
445                          &rpriv->uplink_priv.tc_indr_block_priv_list);
446
447                 block_cb = flow_indr_block_cb_alloc(setup_cb, indr_priv, indr_priv,
448                                                     mlx5e_rep_indr_block_unbind,
449                                                     f, netdev, sch, data, rpriv,
450                                                     cleanup);
451                 if (IS_ERR(block_cb)) {
452                         list_del(&indr_priv->list);
453                         kfree(indr_priv);
454                         return PTR_ERR(block_cb);
455                 }
456                 flow_block_cb_add(block_cb, f);
457                 list_add_tail(&block_cb->driver_list, &mlx5e_block_cb_list);
458
459                 return 0;
460         case FLOW_BLOCK_UNBIND:
461                 indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
462                 if (!indr_priv)
463                         return -ENOENT;
464
465                 block_cb = flow_block_cb_lookup(f->block, setup_cb, indr_priv);
466                 if (!block_cb)
467                         return -ENOENT;
468
469                 flow_indr_block_cb_remove(block_cb, f);
470                 list_del(&block_cb->driver_list);
471                 return 0;
472         default:
473                 return -EOPNOTSUPP;
474         }
475         return 0;
476 }
477
478 static
479 int mlx5e_rep_indr_setup_cb(struct net_device *netdev, struct Qdisc *sch, void *cb_priv,
480                             enum tc_setup_type type, void *type_data,
481                             void *data,
482                             void (*cleanup)(struct flow_block_cb *block_cb))
483 {
484         switch (type) {
485         case TC_SETUP_BLOCK:
486                 return mlx5e_rep_indr_setup_block(netdev, sch, cb_priv, type_data,
487                                                   mlx5e_rep_indr_setup_tc_cb,
488                                                   data, cleanup);
489         case TC_SETUP_FT:
490                 return mlx5e_rep_indr_setup_block(netdev, sch, cb_priv, type_data,
491                                                   mlx5e_rep_indr_setup_ft_cb,
492                                                   data, cleanup);
493         default:
494                 return -EOPNOTSUPP;
495         }
496 }
497
498 int mlx5e_rep_tc_netdevice_event_register(struct mlx5e_rep_priv *rpriv)
499 {
500         struct mlx5_rep_uplink_priv *uplink_priv = &rpriv->uplink_priv;
501
502         /* init indirect block notifications */
503         INIT_LIST_HEAD(&uplink_priv->tc_indr_block_priv_list);
504
505         return flow_indr_dev_register(mlx5e_rep_indr_setup_cb, rpriv);
506 }
507
508 void mlx5e_rep_tc_netdevice_event_unregister(struct mlx5e_rep_priv *rpriv)
509 {
510         flow_indr_dev_unregister(mlx5e_rep_indr_setup_cb, rpriv,
511                                  mlx5e_rep_indr_block_unbind);
512 }
513
514 #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
515 static bool mlx5e_restore_tunnel(struct mlx5e_priv *priv, struct sk_buff *skb,
516                                  struct mlx5e_tc_update_priv *tc_priv,
517                                  u32 tunnel_id)
518 {
519         struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
520         struct tunnel_match_enc_opts enc_opts = {};
521         struct mlx5_rep_uplink_priv *uplink_priv;
522         struct mlx5e_rep_priv *uplink_rpriv;
523         struct metadata_dst *tun_dst;
524         struct tunnel_match_key key;
525         u32 tun_id, enc_opts_id;
526         struct net_device *dev;
527         int err;
528
529         enc_opts_id = tunnel_id & ENC_OPTS_BITS_MASK;
530         tun_id = tunnel_id >> ENC_OPTS_BITS;
531
532         if (!tun_id)
533                 return true;
534
535         uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
536         uplink_priv = &uplink_rpriv->uplink_priv;
537
538         err = mapping_find(uplink_priv->tunnel_mapping, tun_id, &key);
539         if (err) {
540                 WARN_ON_ONCE(true);
541                 netdev_dbg(priv->netdev,
542                            "Couldn't find tunnel for tun_id: %d, err: %d\n",
543                            tun_id, err);
544                 return false;
545         }
546
547         if (enc_opts_id) {
548                 err = mapping_find(uplink_priv->tunnel_enc_opts_mapping,
549                                    enc_opts_id, &enc_opts);
550                 if (err) {
551                         netdev_dbg(priv->netdev,
552                                    "Couldn't find tunnel (opts) for tun_id: %d, err: %d\n",
553                                    enc_opts_id, err);
554                         return false;
555                 }
556         }
557
558         if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV4_ADDRS) {
559                 tun_dst = __ip_tun_set_dst(key.enc_ipv4.src, key.enc_ipv4.dst,
560                                            key.enc_ip.tos, key.enc_ip.ttl,
561                                            key.enc_tp.dst, TUNNEL_KEY,
562                                            key32_to_tunnel_id(key.enc_key_id.keyid),
563                                            enc_opts.key.len);
564         } else if (key.enc_control.addr_type == FLOW_DISSECTOR_KEY_IPV6_ADDRS) {
565                 tun_dst = __ipv6_tun_set_dst(&key.enc_ipv6.src, &key.enc_ipv6.dst,
566                                              key.enc_ip.tos, key.enc_ip.ttl,
567                                              key.enc_tp.dst, 0, TUNNEL_KEY,
568                                              key32_to_tunnel_id(key.enc_key_id.keyid),
569                                              enc_opts.key.len);
570         } else {
571                 netdev_dbg(priv->netdev,
572                            "Couldn't restore tunnel, unsupported addr_type: %d\n",
573                            key.enc_control.addr_type);
574                 return false;
575         }
576
577         if (!tun_dst) {
578                 netdev_dbg(priv->netdev, "Couldn't restore tunnel, no tun_dst\n");
579                 return false;
580         }
581
582         tun_dst->u.tun_info.key.tp_src = key.enc_tp.src;
583
584         if (enc_opts.key.len)
585                 ip_tunnel_info_opts_set(&tun_dst->u.tun_info,
586                                         enc_opts.key.data,
587                                         enc_opts.key.len,
588                                         enc_opts.key.dst_opt_type);
589
590         skb_dst_set(skb, (struct dst_entry *)tun_dst);
591         dev = dev_get_by_index(&init_net, key.filter_ifindex);
592         if (!dev) {
593                 netdev_dbg(priv->netdev,
594                            "Couldn't find tunnel device with ifindex: %d\n",
595                            key.filter_ifindex);
596                 return false;
597         }
598
599         /* Set tun_dev so we do dev_put() after datapath */
600         tc_priv->tun_dev = dev;
601
602         skb->dev = dev;
603
604         return true;
605 }
606 #endif /* CONFIG_NET_TC_SKB_EXT */
607
608 bool mlx5e_rep_tc_update_skb(struct mlx5_cqe64 *cqe,
609                              struct sk_buff *skb,
610                              struct mlx5e_tc_update_priv *tc_priv)
611 {
612 #if IS_ENABLED(CONFIG_NET_TC_SKB_EXT)
613         u32 chain = 0, reg_c0, reg_c1, tunnel_id, zone_restore_id;
614         struct mlx5_rep_uplink_priv *uplink_priv;
615         struct mlx5e_rep_priv *uplink_rpriv;
616         struct tc_skb_ext *tc_skb_ext;
617         struct mlx5_eswitch *esw;
618         struct mlx5e_priv *priv;
619         int err;
620
621         reg_c0 = (be32_to_cpu(cqe->sop_drop_qpn) & MLX5E_TC_FLOW_ID_MASK);
622         if (reg_c0 == MLX5_FS_DEFAULT_FLOW_TAG)
623                 reg_c0 = 0;
624         reg_c1 = be32_to_cpu(cqe->ft_metadata);
625
626         if (!reg_c0)
627                 return true;
628
629         /* If reg_c0 is not equal to the default flow tag then skb->mark
630          * is not supported and must be reset back to 0.
631          */
632         skb->mark = 0;
633
634         priv = netdev_priv(skb->dev);
635         esw = priv->mdev->priv.eswitch;
636
637         err = mlx5_get_chain_for_tag(esw_chains(esw), reg_c0, &chain);
638         if (err) {
639                 netdev_dbg(priv->netdev,
640                            "Couldn't find chain for chain tag: %d, err: %d\n",
641                            reg_c0, err);
642                 return false;
643         }
644
645         if (chain) {
646                 tc_skb_ext = skb_ext_add(skb, TC_SKB_EXT);
647                 if (!tc_skb_ext) {
648                         WARN_ON(1);
649                         return false;
650                 }
651
652                 tc_skb_ext->chain = chain;
653
654                 zone_restore_id = reg_c1 & ZONE_RESTORE_MAX;
655
656                 uplink_rpriv = mlx5_eswitch_get_uplink_priv(esw, REP_ETH);
657                 uplink_priv = &uplink_rpriv->uplink_priv;
658                 if (!mlx5e_tc_ct_restore_flow(uplink_priv->ct_priv, skb,
659                                               zone_restore_id))
660                         return false;
661         }
662
663         tunnel_id = reg_c1 >> REG_MAPPING_SHIFT(TUNNEL_TO_REG);
664         return mlx5e_restore_tunnel(priv, skb, tc_priv, tunnel_id);
665 #endif /* CONFIG_NET_TC_SKB_EXT */
666
667         return true;
668 }
669
670 void mlx5_rep_tc_post_napi_receive(struct mlx5e_tc_update_priv *tc_priv)
671 {
672         if (tc_priv->tun_dev)
673                 dev_put(tc_priv->tun_dev);
674 }