bcm63xx: ar-5315u: expose LEDs through controller
[openwrt/staging/mkresin.git] / target / linux / layerscape / patches-4.14 / 702-dpaa2-ethernet-support-layerscape.patch
index 44cedd12371d20b8c97584333356e5ac0dafe277..1656ddf3e8d316d271656063319a4c9a4e60715f 100644 (file)
@@ -1,33 +1,42 @@
-From 6ec4d0cf0b0e5e41abc91012db4ebff7d415a92b Mon Sep 17 00:00:00 2001
+From 90b3f1705785f0e30de6f41abc8764aae1391245 Mon Sep 17 00:00:00 2001
 From: Biwen Li <biwen.li@nxp.com>
-Date: Tue, 30 Oct 2018 18:26:13 +0800
-Subject: [PATCH 08/40] dpaa2-ethernet: support layerscape
-This is an integrated patch of dpaa2-ethernet for
- layerscape
+Date: Wed, 17 Apr 2019 18:58:28 +0800
+Subject: [PATCH] dpaa2-ethernet: support layerscape
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
 
+This is an integrated patch of dpaa2-ethernet for layerscape
+
+Signed-off-by: Biwen Li <biwen.li@nxp.com>
 Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
 Signed-off-by: Camelia Groza <camelia.groza@nxp.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 Signed-off-by: Guanhua Gao <guanhua.gao@nxp.com>
 Signed-off-by: Horia Geantă <horia.geanta@nxp.com>
+Signed-off-by: Ioana Ciornei <ioana.ciornei@nxp.com>
 Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
 Signed-off-by: Nipun Gupta <nipun.gupta@nxp.com>
+Signed-off-by: Valentin Catalin Neacsu <valentin-catalin.neacsu@nxp.com>
 Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
-Signed-off-by: Biwen Li <biwen.li@nxp.com>
 ---
  drivers/staging/fsl-dpaa2/Kconfig             |    7 +
- drivers/staging/fsl-dpaa2/ethernet/Makefile   |    2 +
- .../fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c      | 1240 +++++++++
+ drivers/staging/fsl-dpaa2/ethernet/Makefile   |    3 +
+ .../fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c      | 1187 ++++++++
  .../fsl-dpaa2/ethernet/dpaa2-eth-ceetm.h      |  183 ++
- .../fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c    |  357 +++
+ .../fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c    |  356 +++
  .../fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h    |   60 +
- .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c    | 2335 +++++++++++++----
- .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h    |  388 ++-
- .../fsl-dpaa2/ethernet/dpaa2-ethtool.c        |  625 ++++-
- drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h |  192 +-
- drivers/staging/fsl-dpaa2/ethernet/dpni.c     |  604 ++++-
- drivers/staging/fsl-dpaa2/ethernet/dpni.h     |  344 ++-
- 12 files changed, 5723 insertions(+), 614 deletions(-)
+ .../fsl-dpaa2/ethernet/dpaa2-eth-trace.h      |   29 +-
+ .../staging/fsl-dpaa2/ethernet/dpaa2-eth.c    | 2509 +++++++++++++----
+ .../staging/fsl-dpaa2/ethernet/dpaa2-eth.h    |  394 ++-
+ .../fsl-dpaa2/ethernet/dpaa2-ethtool.c        |  716 ++++-
+ drivers/staging/fsl-dpaa2/ethernet/dpkg.h     |  380 ++-
+ drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h |  255 +-
+ drivers/staging/fsl-dpaa2/ethernet/dpni.c     |  704 ++++-
+ drivers/staging/fsl-dpaa2/ethernet/dpni.h     |  401 ++-
+ drivers/staging/fsl-dpaa2/ethernet/net.h      |   30 +-
+ 15 files changed, 6315 insertions(+), 899 deletions(-)
  create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c
  create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.h
  create mode 100644 drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
@@ -51,7 +60,12 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        bool "Enable Rx error queue"
 --- a/drivers/staging/fsl-dpaa2/ethernet/Makefile
 +++ b/drivers/staging/fsl-dpaa2/ethernet/Makefile
-@@ -5,6 +5,8 @@
+@@ -1,3 +1,4 @@
++# SPDX-License-Identifier: GPL-2.0
+ #
+ # Makefile for the Freescale DPAA2 Ethernet controller
+ #
+@@ -5,6 +6,8 @@
  obj-$(CONFIG_FSL_DPAA2_ETH) += fsl-dpaa2-eth.o
  
  fsl-dpaa2-eth-objs    := dpaa2-eth.o dpaa2-ethtool.o dpni.o
@@ -62,10 +76,10 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  CFLAGS_dpaa2-eth.o := -I$(src)
 --- /dev/null
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-ceetm.c
-@@ -0,0 +1,1240 @@
+@@ -0,0 +1,1187 @@
 +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
 +/*
-+ * Copyright 2017 NXP
++ * Copyright 2017-2019 NXP
 + *
 + */
 +
@@ -197,7 +211,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                                         enum update_tx_prio type)
 +{
 +      struct dpaa2_ceetm_qdisc *sch = qdisc_priv(cl->parent);
-+      struct dpni_congestion_notification_cfg notif_cfg = {0};
 +      struct dpni_tx_schedule_cfg *sched_cfg;
 +      struct dpni_taildrop td = {0};
 +      u8 ch_id = 0, tc_id = 0;
@@ -209,18 +222,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +
 +      switch (type) {
 +      case DPAA2_ETH_ADD_CQ:
-+              /* Disable congestion notifications */
-+              notif_cfg.threshold_entry = 0;
-+              notif_cfg.threshold_exit = 0;
-+              err = dpni_set_congestion_notification(priv->mc_io, 0,
-+                                                     priv->mc_token,
-+                                                     DPNI_QUEUE_TX, tc_id,
-+                                                     &notif_cfg);
-+              if (err) {
-+                      netdev_err(priv->net_dev, "Error disabling congestion notifications %d\n",
-+                                 err);
-+                      return err;
-+              }
 +              /* Enable taildrop */
 +              td.enable = 1;
 +              td.units = DPNI_CONGESTION_UNIT_FRAMES;
@@ -245,24 +246,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                                 err);
 +                      return err;
 +              }
-+              /* Enable congestion notifications */
-+              notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES;
-+              notif_cfg.threshold_entry = DPAA2_ETH_TX_CONG_ENTRY_THRESH;
-+              notif_cfg.threshold_exit = DPAA2_ETH_TX_CONG_EXIT_THRESH;
-+              notif_cfg.message_ctx = (u64)priv;
-+              notif_cfg.message_iova = priv->cscn_dma;
-+              notif_cfg.notification_mode = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER |
-+                                            DPNI_CONG_OPT_WRITE_MEM_ON_EXIT |
-+                                            DPNI_CONG_OPT_COHERENT_WRITE;
-+              err = dpni_set_congestion_notification(priv->mc_io, 0,
-+                                                     priv->mc_token,
-+                                                     DPNI_QUEUE_TX, tc_id,
-+                                                     &notif_cfg);
-+              if (err) {
-+                      netdev_err(priv->net_dev, "Error enabling congestion notifications %d\n",
-+                                 err);
-+                      return err;
-+              }
 +              break;
 +      }
 +
@@ -564,15 +547,12 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      struct netdev_queue *dev_queue;
 +      unsigned int i, parent_id;
 +      struct Qdisc *qdisc;
-+      int err;
 +
 +      pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle);
 +
 +      /* Validate inputs */
 +      if (sch->parent != TC_H_ROOT) {
-+              pr_err("CEETM: a root ceetm qdisc can not be attached to a class\n");
-+              tcf_block_put(priv->block);
-+              qdisc_class_hash_destroy(&priv->clhash);
++              pr_err("CEETM: a root ceetm qdisc must be root\n");
 +              return -EINVAL;
 +      }
 +
@@ -589,10 +569,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      priv->root.qdiscs = kcalloc(dev->num_tx_queues,
 +                                  sizeof(priv->root.qdiscs[0]),
 +                                  GFP_KERNEL);
-+      if (!priv->root.qdiscs) {
-+              err = -ENOMEM;
-+              goto err_init_root;
-+      }
++      if (!priv->root.qdiscs)
++              return -ENOMEM;
 +
 +      for (i = 0; i < dev->num_tx_queues; i++) {
 +              dev_queue = netdev_get_tx_queue(dev, i);
@@ -601,10 +579,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +
 +              qdisc = qdisc_create_dflt(dev_queue, &pfifo_qdisc_ops,
 +                                        parent_id);
-+              if (!qdisc) {
-+                      err = -ENOMEM;
-+                      goto err_init_root;
-+              }
++              if (!qdisc)
++                      return -ENOMEM;
 +
 +              priv->root.qdiscs[i] = qdisc;
 +              qdisc->flags |= TCQ_F_ONETXQUEUE;
@@ -616,16 +592,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      if (!priv->root.qstats) {
 +              pr_err(KBUILD_BASENAME " : %s : alloc_percpu() failed\n",
 +                     __func__);
-+              err = -ENOMEM;
-+              goto err_init_root;
++              return -ENOMEM;
 +      }
 +
 +      dpaa2_eth_ceetm_enable(priv_eth);
 +      return 0;
-+
-+err_init_root:
-+      dpaa2_ceetm_destroy(sch);
-+      return err;
 +}
 +
 +/* Configure a prio ceetm qdisc */
@@ -636,21 +607,18 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      struct net_device *dev = qdisc_dev(sch);
 +      struct dpaa2_ceetm_class *parent_cl;
 +      struct Qdisc *parent_qdisc;
-+      int err;
 +
 +      pr_debug(KBUILD_BASENAME " : %s : qdisc %X\n", __func__, sch->handle);
 +
 +      if (sch->parent == TC_H_ROOT) {
 +              pr_err("CEETM: a prio ceetm qdisc can not be root\n");
-+              err = -EINVAL;
-+              goto err_init_prio;
++              return -EINVAL;
 +      }
 +
 +      parent_qdisc = qdisc_lookup(dev, TC_H_MAJ(sch->parent));
 +      if (strcmp(parent_qdisc->ops->id, dpaa2_ceetm_qdisc_ops.id)) {
 +              pr_err("CEETM: a ceetm qdisc can not be attached to other qdisc/class types\n");
-+              err = -EINVAL;
-+              goto err_init_prio;
++              return -EINVAL;
 +      }
 +
 +      /* Obtain the parent root ceetm_class */
@@ -658,20 +626,13 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +
 +      if (!parent_cl || parent_cl->type != CEETM_ROOT) {
 +              pr_err("CEETM: a prio ceetm qdiscs can be added only under a root ceetm class\n");
-+              err = -EINVAL;
-+              goto err_init_prio;
++              return -EINVAL;
 +      }
 +
 +      priv->prio.parent = parent_cl;
 +      parent_cl->child = sch;
 +
-+      err = dpaa2_ceetm_change_prio(sch, priv, qopt);
-+
-+      return 0;
-+
-+err_init_prio:
-+      dpaa2_ceetm_destroy(sch);
-+      return err;
++      return dpaa2_ceetm_change_prio(sch, priv, qopt);
 +}
 +
 +/* Configure a generic ceetm qdisc */
@@ -741,7 +702,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +              break;
 +      default:
 +              pr_err(KBUILD_BASENAME " : %s : invalid qdisc\n", __func__);
-+              dpaa2_ceetm_destroy(sch);
++              /* Note: dpaa2_ceetm_destroy() will be called by our caller */
 +              err = -EINVAL;
 +      }
 +
@@ -1491,7 +1452,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +#endif
 --- /dev/null
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
-@@ -0,0 +1,357 @@
+@@ -0,0 +1,356 @@
 +
 +/* Copyright 2015 Freescale Semiconductor Inc.
 + *
@@ -1605,9 +1566,9 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      int i, err;
 +
 +      seq_printf(file, "non-zero FQ stats for %s:\n", priv->net_dev->name);
-+      seq_printf(file, "%s%16s%16s%16s%16s%16s%16s\n",
++      seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
 +                 "VFQID", "CPU", "Traffic Class", "Type", "Frames",
-+                 "Pending frames", "Congestion");
++                 "Pending frames");
 +
 +      for (i = 0; i <  priv->num_fqs; i++) {
 +              fq = &priv->fq[i];
@@ -1619,14 +1580,13 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +              if (!fq->stats.frames && !fcnt)
 +                      continue;
 +
-+              seq_printf(file, "%5d%16d%16d%16s%16llu%16u%16llu\n",
++              seq_printf(file, "%5d%16d%16d%16s%16llu%16u\n",
 +                         fq->fqid,
 +                         fq->target_cpu,
 +                         fq->tc,
 +                         fq_type_to_str(fq),
 +                         fq->stats.frames,
-+                         fcnt,
-+                         fq->stats.congestion_entry);
++                         fcnt);
 +      }
 +
 +      return 0;
@@ -1912,9 +1872,80 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +#endif /* CONFIG_FSL_DPAA2_ETH_DEBUGFS */
 +
 +#endif /* DPAA2_ETH_DEBUGFS_H */
+--- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h
++++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h
+@@ -1,32 +1,5 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+ /* Copyright 2014-2015 Freescale Semiconductor Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- *     * Redistributions of source code must retain the above copyright
+- *     notice, this list of conditions and the following disclaimer.
+- *     * Redistributions in binary form must reproduce the above copyright
+- *     notice, this list of conditions and the following disclaimer in the
+- *     documentation and/or other materials provided with the distribution.
+- *     * Neither the name of Freescale Semiconductor nor the
+- *     names of its contributors may be used to endorse or promote products
+- *     derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
+ #undef TRACE_SYSTEM
 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
-@@ -38,9 +38,14 @@
+@@ -1,33 +1,6 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+ /* Copyright 2014-2016 Freescale Semiconductor Inc.
+  * Copyright 2016-2017 NXP
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- *     * Redistributions of source code must retain the above copyright
+- *     notice, this list of conditions and the following disclaimer.
+- *     * Redistributions in binary form must reproduce the above copyright
+- *     notice, this list of conditions and the following disclaimer in the
+- *     documentation and/or other materials provided with the distribution.
+- *     * Neither the name of Freescale Semiconductor nor the
+- *     names of its contributors may be used to endorse or promote products
+- *     derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
+ #include <linux/init.h>
+ #include <linux/module.h>
+@@ -38,9 +11,14 @@
  #include <linux/msi.h>
  #include <linux/kthread.h>
  #include <linux/iommu.h>
@@ -1930,7 +1961,16 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  /* CREATE_TRACE_POINTS only needs to be defined once. Other dpa files
   * using trace events only need to #include <trace/events/sched.h>
-@@ -104,13 +109,15 @@ static void free_rx_fd(struct dpaa2_eth_
+@@ -52,8 +30,6 @@ MODULE_LICENSE("Dual BSD/GPL");
+ MODULE_AUTHOR("Freescale Semiconductor, Inc");
+ MODULE_DESCRIPTION("Freescale DPAA2 Ethernet Driver");
+-const char dpaa2_eth_drv_version[] = "0.1";
+-
+ static void *dpaa2_iova_to_virt(struct iommu_domain *domain,
+                               dma_addr_t iova_addr)
+ {
+@@ -104,26 +80,27 @@ static void free_rx_fd(struct dpaa2_eth_
                /* We don't support any other format */
                return;
  
@@ -1943,28 +1983,47 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      for (i = 1; i < DPAA2_ETH_MAX_SG_ENTRIES; i++) {
                addr = dpaa2_sg_get_addr(&sgt[i]);
                sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, addr);
-               dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
+-              dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
 -                               DMA_FROM_DEVICE);
-+                               DMA_BIDIRECTIONAL);
++              dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
++                             DMA_BIDIRECTIONAL);
  
-               skb_free_frag(sg_vaddr);
+-              skb_free_frag(sg_vaddr);
++              free_pages((unsigned long)sg_vaddr, 0);
                if (dpaa2_sg_is_final(&sgt[i]))
-@@ -133,8 +140,7 @@ static struct sk_buff *build_linear_skb(
+                       break;
+       }
+ free_buf:
+-      skb_free_frag(vaddr);
++      free_pages((unsigned long)vaddr, 0);
+ }
+ /* Build a linear skb based on a single-buffer frame descriptor */
+-static struct sk_buff *build_linear_skb(struct dpaa2_eth_priv *priv,
+-                                      struct dpaa2_eth_channel *ch,
++static struct sk_buff *build_linear_skb(struct dpaa2_eth_channel *ch,
+                                       const struct dpaa2_fd *fd,
+                                       void *fd_vaddr)
+ {
+@@ -133,8 +110,7 @@ static struct sk_buff *build_linear_skb(
  
        ch->buf_count--;
  
 -      skb = build_skb(fd_vaddr, DPAA2_ETH_RX_BUF_SIZE +
 -                      SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
-+      skb = build_skb(fd_vaddr, DPAA2_ETH_SKB_SIZE);
++      skb = build_skb(fd_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE);
        if (unlikely(!skb))
                return NULL;
  
-@@ -170,15 +176,19 @@ static struct sk_buff *build_frag_skb(st
+@@ -169,16 +145,20 @@ static struct sk_buff *build_frag_skb(st
+               /* Get the address and length from the S/G entry */
                sg_addr = dpaa2_sg_get_addr(sge);
                sg_vaddr = dpaa2_iova_to_virt(priv->iommu_domain, sg_addr);
-               dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
+-              dma_unmap_single(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
 -                               DMA_FROM_DEVICE);
-+                               DMA_BIDIRECTIONAL);
++              dma_unmap_page(dev, sg_addr, DPAA2_ETH_RX_BUF_SIZE,
++                             DMA_BIDIRECTIONAL);
  
                sg_length = dpaa2_sg_get_len(sge);
  
@@ -1972,17 +2031,17 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                        /* We build the skb around the first data buffer */
 -                      skb = build_skb(sg_vaddr, DPAA2_ETH_RX_BUF_SIZE +
 -                              SKB_DATA_ALIGN(sizeof(struct skb_shared_info)));
-+                      skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE);
++                      skb = build_skb(sg_vaddr, DPAA2_ETH_RX_BUF_RAW_SIZE);
                        if (unlikely(!skb)) {
 +                              /* Free the first SG entry now, since we already
 +                               * unmapped it and obtained the virtual address
 +                               */
-+                              skb_free_frag(sg_vaddr);
++                              free_pages((unsigned long)sg_vaddr, 0);
 +
                                /* We still need to subtract the buffers used
                                 * by this FD from our software counter
                                 */
-@@ -213,17 +223,173 @@ static struct sk_buff *build_frag_skb(st
+@@ -213,17 +193,172 @@ static struct sk_buff *build_frag_skb(st
                        break;
        }
  
@@ -2021,9 +2080,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +
 +      fq = &priv->fq[queue_id];
 +      for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
-+              err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
-+                                                priv->tx_qdid, 0,
-+                                                fq->tx_qdbin, fd);
++              err = priv->enqueue(priv, fq, fd, 0);
 +              if (err != -EBUSY)
 +                      break;
 +      }
@@ -2039,6 +2096,9 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      return err;
 +}
 +
++/* Free buffers acquired from the buffer pool or which were meant to
++ * be released in the pool
++ */
 +static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
 +{
 +      struct device *dev = priv->net_dev->dev.parent;
@@ -2046,11 +2106,10 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      int i;
 +
 +      for (i = 0; i < count; i++) {
-+              /* Same logic as on regular Rx path */
 +              vaddr = dpaa2_iova_to_virt(priv->iommu_domain, buf_array[i]);
-+              dma_unmap_single(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
-+                               DMA_BIDIRECTIONAL);
-+              skb_free_frag(vaddr);
++              dma_unmap_page(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
++                             DMA_BIDIRECTIONAL);
++              free_pages((unsigned long)vaddr, 0);
 +      }
 +}
 +
@@ -2152,12 +2211,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                         struct dpaa2_eth_channel *ch,
                         const struct dpaa2_fd *fd,
 -                       struct napi_struct *napi)
-+                       struct napi_struct *napi,
-+                       u16 queue_id)
++                       struct dpaa2_eth_fq *fq)
  {
        dma_addr_t addr = dpaa2_fd_get_addr(fd);
        u8 fd_format = dpaa2_fd_get_format(fd);
-@@ -235,14 +401,16 @@ static void dpaa2_eth_rx(struct dpaa2_et
+@@ -235,14 +370,16 @@ static void dpaa2_eth_rx(struct dpaa2_et
        struct dpaa2_fas *fas;
        void *buf_data;
        u32 status = 0;
@@ -2176,23 +2234,25 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        prefetch(fas);
        buf_data = vaddr + dpaa2_fd_get_offset(fd);
        prefetch(buf_data);
-@@ -251,22 +419,41 @@ static void dpaa2_eth_rx(struct dpaa2_et
+@@ -251,22 +388,43 @@ static void dpaa2_eth_rx(struct dpaa2_et
        percpu_extras = this_cpu_ptr(priv->percpu_extras);
  
        if (fd_format == dpaa2_fd_single) {
+-              skb = build_linear_skb(priv, ch, fd, vaddr);
 +              xdp_act = dpaa2_eth_run_xdp(priv, ch, (struct dpaa2_fd *)fd,
-+                                          queue_id, vaddr);
++                                          fq->flowid, vaddr);
 +              if (xdp_act != XDP_PASS)
 +                      return;
 +
-+              dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
-+                               DMA_BIDIRECTIONAL);
-               skb = build_linear_skb(priv, ch, fd, vaddr);
++              dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
++                             DMA_BIDIRECTIONAL);
++              skb = build_linear_skb(ch, fd, vaddr);
        } else if (fd_format == dpaa2_fd_sg) {
-+              dma_unmap_single(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
++              dma_unmap_page(dev, addr, DPAA2_ETH_RX_BUF_SIZE,
 +                               DMA_BIDIRECTIONAL);
                skb = build_frag_skb(priv, ch, buf_data);
-               skb_free_frag(vaddr);
+-              skb_free_frag(vaddr);
++              free_pages((unsigned long)vaddr, 0);
                percpu_extras->rx_sg_frames++;
                percpu_extras->rx_sg_bytes += dpaa2_fd_get_len(fd);
        } else {
@@ -2210,30 +2270,29 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      /* Get the timestamp value */
 +      if (priv->ts_rx_en) {
 +              struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb);
-+              u64 *ns = dpaa2_get_ts(vaddr, false);
++              __le64 *ts = dpaa2_get_ts(vaddr, false);
++              u64 ns;
 +
-+              *ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ns);
 +              memset(shhwtstamps, 0, sizeof(*shhwtstamps));
-+              shhwtstamps->hwtstamp = ns_to_ktime(*ns);
++
++              ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ts);
++              shhwtstamps->hwtstamp = ns_to_ktime(ns);
 +      }
 +
        /* Check if we need to validate the L4 csum */
        if (likely(dpaa2_fd_get_frc(fd) & DPAA2_FD_FRC_FASV)) {
                status = le32_to_cpu(fas->status);
-@@ -275,6 +462,12 @@ static void dpaa2_eth_rx(struct dpaa2_et
+@@ -274,30 +432,80 @@ static void dpaa2_eth_rx(struct dpaa2_et
+       }
  
        skb->protocol = eth_type_trans(skb, priv->net_dev);
++      skb_record_rx_queue(skb, fq->flowid);
  
-+      /* Record Rx queue - this will be used when picking a Tx queue to
-+       * forward the frames. We're keeping flow affinity through the
-+       * network stack.
-+       */
-+      skb_record_rx_queue(skb, queue_id);
-+
        percpu_stats->rx_packets++;
        percpu_stats->rx_bytes += dpaa2_fd_get_len(fd);
  
-@@ -282,22 +475,74 @@ static void dpaa2_eth_rx(struct dpaa2_et
+-      napi_gro_receive(napi, skb);
++      napi_gro_receive(&ch->napi, skb);
  
        return;
  
@@ -2297,14 +2356,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * make sure we don't accidentally issue another volatile dequeue which would
   * overwrite (leak) frames already in the store.
   *
-+ * The number of frames is returned using the last 2 output arguments,
-+ * separately for Rx and Tx confirmations.
-+ *
   * Observance of NAPI budget is not our concern, leaving that to the caller.
   */
 -static int consume_frames(struct dpaa2_eth_channel *ch)
-+static bool consume_frames(struct dpaa2_eth_channel *ch, int *rx_cleaned,
-+                         int *tx_conf_cleaned)
++static int consume_frames(struct dpaa2_eth_channel *ch,
++                        struct dpaa2_eth_fq **src)
  {
        struct dpaa2_eth_priv *priv = ch->priv;
 -      struct dpaa2_eth_fq *fq;
@@ -2312,48 +2368,35 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpaa2_dq *dq;
        const struct dpaa2_fd *fd;
        int cleaned = 0;
-@@ -315,14 +560,60 @@ static int consume_frames(struct dpaa2_e
+@@ -315,16 +523,51 @@ static int consume_frames(struct dpaa2_e
                }
  
                fd = dpaa2_dq_fd(dq);
--              fq = (struct dpaa2_eth_fq *)(uintptr_t)dpaa2_dq_fqd_ctx(dq);
--              fq->stats.frames++;
 +              prefetch(fd);
++
+               fq = (struct dpaa2_eth_fq *)(uintptr_t)dpaa2_dq_fqd_ctx(dq);
+-              fq->stats.frames++;
  
 -              fq->consume(priv, ch, fd, &ch->napi);
-+              fq = (struct dpaa2_eth_fq *)(uintptr_t)dpaa2_dq_fqd_ctx(dq);
-+              fq->consume(priv, ch, fd, &ch->napi, fq->flowid);
++              fq->consume(priv, ch, fd, fq);
                cleaned++;
        } while (!is_last);
  
--      return cleaned;
 +      if (!cleaned)
-+              return false;
-+
-+      /* All frames brought in store by a volatile dequeue
-+       * come from the same queue
-+       */
-+      if (fq->type == DPAA2_TX_CONF_FQ) {
-+              *tx_conf_cleaned += cleaned;
-+      } else {
-+              *rx_cleaned += cleaned;
-+              /* If we processed XDP_REDIRECT frames, flush them now */
-+              /* FIXME: Since we don't actually do anything inside
-+               * ndo_xdp_flush, we call it here simply for compliance
-+               * reasons
-+               */
-+              if (ch->flush) {
-+                      xdp_do_flush_map();
-+                      ch->flush = false;
-+              }
-+      }
++              return 0;
 +
 +      fq->stats.frames += cleaned;
 +      ch->stats.frames += cleaned;
 +
-+      return true;
-+}
++      /* A dequeue operation only pulls frames from a single queue
++       * into the store. Return the frame queue as an out param.
++       */
++      if (src)
++              *src = fq;
 +
+       return cleaned;
+ }
 +/* Configure the egress frame annotation for timestamp update */
 +static void enable_tx_tstamp(struct dpaa2_fd *fd, void *buf_start)
 +{
@@ -2374,10 +2417,12 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      ctrl = DPAA2_FAEAD_A2V | DPAA2_FAEAD_UPDV | DPAA2_FAEAD_UPD;
 +      faead = dpaa2_get_faead(buf_start, true);
 +      faead->ctrl = cpu_to_le32(ctrl);
- }
++}
++
  /* Create a frame descriptor based on a fragmented skb */
-@@ -341,7 +632,6 @@ static int build_sg_fd(struct dpaa2_eth_
+ static int build_sg_fd(struct dpaa2_eth_priv *priv,
+                      struct sk_buff *skb,
+@@ -341,7 +584,6 @@ static int build_sg_fd(struct dpaa2_eth_
        int num_sg;
        int num_dma_bufs;
        struct dpaa2_eth_swa *swa;
@@ -2385,7 +2430,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* Create and map scatterlist.
         * We don't advertise NETIF_F_FRAGLIST, so skb_to_sgvec() will not have
-@@ -365,21 +655,14 @@ static int build_sg_fd(struct dpaa2_eth_
+@@ -365,21 +607,14 @@ static int build_sg_fd(struct dpaa2_eth_
  
        /* Prepare the HW SGT structure */
        sgt_buf_size = priv->tx_data_offset +
@@ -2410,7 +2455,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        sgt = (struct dpaa2_sg_entry *)(sgt_buf + priv->tx_data_offset);
  
-@@ -402,10 +685,11 @@ static int build_sg_fd(struct dpaa2_eth_
+@@ -402,10 +637,11 @@ static int build_sg_fd(struct dpaa2_eth_
         * all of them on Tx Conf.
         */
        swa = (struct dpaa2_eth_swa *)sgt_buf;
@@ -2426,7 +2471,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* Separately map the SGT buffer */
        addr = dma_map_single(dev, sgt_buf, sgt_buf_size, DMA_BIDIRECTIONAL);
-@@ -417,13 +701,15 @@ static int build_sg_fd(struct dpaa2_eth_
+@@ -417,13 +653,15 @@ static int build_sg_fd(struct dpaa2_eth_
        dpaa2_fd_set_format(fd, dpaa2_fd_sg);
        dpaa2_fd_set_addr(fd, addr);
        dpaa2_fd_set_len(fd, skb->len);
@@ -2445,7 +2490,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  sgt_buf_alloc_failed:
        dma_unmap_sg(dev, scl, num_sg, DMA_BIDIRECTIONAL);
  dma_map_sg_failed:
-@@ -437,29 +723,27 @@ static int build_single_fd(struct dpaa2_
+@@ -437,29 +675,27 @@ static int build_single_fd(struct dpaa2_
                           struct dpaa2_fd *fd)
  {
        struct device *dev = priv->net_dev->dev.parent;
@@ -2488,7 +2533,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        addr = dma_map_single(dev, buffer_start,
                              skb_tail_pointer(skb) - buffer_start,
-@@ -471,8 +755,10 @@ static int build_single_fd(struct dpaa2_
+@@ -471,8 +707,10 @@ static int build_single_fd(struct dpaa2_
        dpaa2_fd_set_offset(fd, (u16)(skb->data - buffer_start));
        dpaa2_fd_set_len(fd, skb->len);
        dpaa2_fd_set_format(fd, dpaa2_fd_single);
@@ -2501,15 +2546,17 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        return 0;
  }
-@@ -486,92 +772,128 @@ static int build_single_fd(struct dpaa2_
-  * Optionally, return the frame annotation status word (FAS), which needs
-  * to be checked if we're on the confirmation path.
+@@ -483,72 +721,75 @@ static int build_single_fd(struct dpaa2_
+  * back-pointed to is also freed.
+  * This can be called either from dpaa2_eth_tx_conf() or on the error path of
+  * dpaa2_eth_tx().
+- * Optionally, return the frame annotation status word (FAS), which needs
+- * to be checked if we're on the confirmation path.
   */
--static void free_tx_fd(const struct dpaa2_eth_priv *priv,
-+static void free_tx_fd(struct dpaa2_eth_priv *priv,
-                      const struct dpaa2_fd *fd,
+ static void free_tx_fd(const struct dpaa2_eth_priv *priv,
+-                     const struct dpaa2_fd *fd,
 -                     u32 *status)
-+                     bool in_napi)
++                     const struct dpaa2_fd *fd, bool in_napi)
  {
        struct device *dev = priv->net_dev->dev.parent;
        dma_addr_t fd_addr;
@@ -2594,13 +2641,13 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      /* Get the timestamp value */
 +      if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
 +              struct skb_shared_hwtstamps shhwtstamps;
-+              u64 *ns;
++              __le64 *ts = dpaa2_get_ts(buffer_start, true);
++              u64 ns;
 +
 +              memset(&shhwtstamps, 0, sizeof(shhwtstamps));
 +
-+              ns = dpaa2_get_ts(buffer_start, true);
-+              *ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ns);
-+              shhwtstamps.hwtstamp = ns_to_ktime(*ns);
++              ns = DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS * le64_to_cpup(ts);
++              shhwtstamps.hwtstamp = ns_to_ktime(ns);
 +              skb_tstamp_tx(skb, &shhwtstamps);
 +      }
  
@@ -2616,46 +2663,33 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  }
  
  static netdev_tx_t dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
- {
-       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-+      struct device *dev = net_dev->dev.parent;
-       struct dpaa2_fd fd;
+@@ -558,20 +799,41 @@ static netdev_tx_t dpaa2_eth_tx(struct s
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa2_eth_drv_stats *percpu_extras;
        struct dpaa2_eth_fq *fq;
++      struct netdev_queue *nq;
        u16 queue_mapping;
 -      int err, i;
 +      unsigned int needed_headroom;
++      u32 fd_len;
 +      u8 prio;
 +      int err, i, ch_id = 0;
 +
 +      queue_mapping = skb_get_queue_mapping(skb);
 +      prio = netdev_txq_to_tc(net_dev, queue_mapping);
-+
 +      /* Hardware interprets priority level 0 as being the highest,
 +       * so we need to do a reverse mapping to the netdev tc index
 +       */
 +      if (net_dev->num_tc)
 +              prio = net_dev->num_tc - prio - 1;
-+ 
++
 +      queue_mapping %= dpaa2_eth_queue_count(priv);
 +      fq = &priv->fq[queue_mapping];
-+
-+      /* If we're congested, stop this tx queue; transmission of
-+       * the current skb happens regardless of congestion state
-+       */
-+      dma_sync_single_for_cpu(dev, priv->cscn_dma,
-+                              DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
-+      if (unlikely(dpaa2_cscn_state_congested(priv->cscn_mem))) {
-+              netif_stop_subqueue(net_dev, queue_mapping);
-+              fq->stats.congestion_entry++;
-+      }
  
        percpu_stats = this_cpu_ptr(priv->percpu_stats);
        percpu_extras = this_cpu_ptr(priv->percpu_extras);
  
 -      if (unlikely(skb_headroom(skb) < DPAA2_ETH_NEEDED_HEADROOM(priv))) {
-+      /* For non-linear skb we don't need a minimum headroom */
 +      needed_headroom = dpaa2_eth_needed_headroom(priv, skb);
 +      if (skb_headroom(skb) < needed_headroom) {
                struct sk_buff *ns;
@@ -2667,43 +2701,56 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                        goto err_alloc_headroom;
                }
 +              percpu_extras->tx_reallocs++;
++
 +              if (skb->sk)
 +                      skb_set_owner_w(ns, skb->sk);
++
                dev_kfree_skb(skb);
                skb = ns;
        }
-@@ -605,13 +927,15 @@ static netdev_tx_t dpaa2_eth_tx(struct s
-       /* Tracing point */
-       trace_dpaa2_tx_fd(net_dev, &fd);
+@@ -602,17 +864,24 @@ static netdev_tx_t dpaa2_eth_tx(struct s
+               goto err_build_fd;
+       }
  
--      /* TxConf FQ selection primarily based on cpu affinity; this is
--       * non-migratable context, so it's safe to call smp_processor_id().
--       */
--      queue_mapping = smp_processor_id() % dpaa2_eth_queue_count(priv);
--      fq = &priv->fq[queue_mapping];
 +      if (dpaa2_eth_ceetm_is_enabled(priv)) {
 +              err = dpaa2_ceetm_classify(skb, net_dev->qdisc, &ch_id, &prio);
 +              if (err)
 +                      goto err_ceetm_classify;
 +      }
 +
+       /* Tracing point */
+       trace_dpaa2_tx_fd(net_dev, &fd);
+-      /* TxConf FQ selection primarily based on cpu affinity; this is
+-       * non-migratable context, so it's safe to call smp_processor_id().
++      fd_len = dpaa2_fd_get_len(&fd);
++      nq = netdev_get_tx_queue(net_dev, queue_mapping);
++      netdev_tx_sent_queue(nq, fd_len);
++
++      /* Everything that happens after this enqueues might race with
++       * the Tx confirmation callback for this frame
+        */
+-      queue_mapping = smp_processor_id() % dpaa2_eth_queue_count(priv);
+-      fq = &priv->fq[queue_mapping];
        for (i = 0; i < DPAA2_ETH_ENQUEUE_RETRIES; i++) {
 -              err = dpaa2_io_service_enqueue_qd(NULL, priv->tx_qdid, 0,
-+              err = dpaa2_io_service_enqueue_qd(fq->channel->dpio,
-+                                                priv->tx_qdid, prio,
-                                                 fq->tx_qdbin, &fd);
+-                                                fq->tx_qdbin, &fd);
++              err = priv->enqueue(priv, fq, &fd, 0);
                if (err != -EBUSY)
                        break;
-@@ -620,7 +944,7 @@ static netdev_tx_t dpaa2_eth_tx(struct s
+       }
+@@ -620,14 +889,17 @@ static netdev_tx_t dpaa2_eth_tx(struct s
        if (unlikely(err < 0)) {
                percpu_stats->tx_errors++;
                /* Clean up everything, including freeing the skb */
 -              free_tx_fd(priv, &fd, NULL);
 +              free_tx_fd(priv, &fd, false);
++              netdev_tx_completed_queue(nq, 1, fd_len);
        } else {
                percpu_stats->tx_packets++;
-               percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd);
-@@ -628,6 +952,8 @@ static netdev_tx_t dpaa2_eth_tx(struct s
+-              percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd);
++              percpu_stats->tx_bytes += fd_len;
+       }
  
        return NETDEV_TX_OK;
  
@@ -2712,29 +2759,36 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  err_build_fd:
  err_alloc_headroom:
        dev_kfree_skb(skb);
-@@ -639,13 +965,13 @@ err_alloc_headroom:
+@@ -637,48 +909,39 @@ err_alloc_headroom:
+ /* Tx confirmation frame processing routine */
  static void dpaa2_eth_tx_conf(struct dpaa2_eth_priv *priv,
-                             struct dpaa2_eth_channel *ch,
+-                            struct dpaa2_eth_channel *ch,
++                            struct dpaa2_eth_channel *ch __always_unused,
                              const struct dpaa2_fd *fd,
 -                            struct napi_struct *napi __always_unused)
-+                            struct napi_struct *napi __always_unused,
-+                            u16 queue_id)
++                            struct dpaa2_eth_fq *fq)
  {
-+      struct device *dev = priv->net_dev->dev.parent;
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa2_eth_drv_stats *percpu_extras;
 -      u32 status = 0;
++      u32 fd_len = dpaa2_fd_get_len(fd);
        u32 fd_errors;
 -      bool has_fas_errors = false;
  
        /* Tracing point */
        trace_dpaa2_tx_conf_fd(priv->net_dev, fd);
-@@ -654,31 +980,28 @@ static void dpaa2_eth_tx_conf(struct dpa
+       percpu_extras = this_cpu_ptr(priv->percpu_extras);
        percpu_extras->tx_conf_frames++;
-       percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
+-      percpu_extras->tx_conf_bytes += dpaa2_fd_get_len(fd);
++      percpu_extras->tx_conf_bytes += fd_len;
++
++      fq->dq_frames++;
++      fq->dq_bytes += fd_len;
  
--      /* Check frame errors in the FD field */
--      fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
+       /* Check frame errors in the FD field */
+       fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
 -      if (unlikely(fd_errors)) {
 -              /* We only check error bits in the FAS field if corresponding
 -               * FAERR bit is set in FD and the FAS field is marked as valid
@@ -2744,17 +2798,9 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -              if (net_ratelimit())
 -                      netdev_dbg(priv->net_dev, "TX frame FD error: 0x%08x\n",
 -                                 fd_errors);
-+      /* Check congestion state and wake all queues if necessary */
-+      if (unlikely(__netif_subqueue_stopped(priv->net_dev, queue_id))) {
-+              dma_sync_single_for_cpu(dev, priv->cscn_dma,
-+                                      DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
-+              if (!dpaa2_cscn_state_congested(priv->cscn_mem))
-+                      netif_tx_wake_all_queues(priv->net_dev);
-       }
+-      }
+-
 -      free_tx_fd(priv, fd, has_fas_errors ? &status : NULL);
-+      /* Check frame errors in the FD field */
-+      fd_errors = dpaa2_fd_get_ctrl(fd) & DPAA2_FD_TX_ERR_MASK;
 +      free_tx_fd(priv, fd, true);
  
        if (likely(!fd_errors))
@@ -2774,7 +2820,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  }
  
  static int set_rx_csum(struct dpaa2_eth_priv *priv, bool enable)
-@@ -728,26 +1051,27 @@ static int set_tx_csum(struct dpaa2_eth_
+@@ -728,26 +991,29 @@ static int set_tx_csum(struct dpaa2_eth_
  /* Perform a single release command to add buffers
   * to the specified buffer pool
   */
@@ -2784,7 +2830,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  {
        struct device *dev = priv->net_dev->dev.parent;
        u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
-       void *buf;
+-      void *buf;
++      struct page *page;
        dma_addr_t addr;
 -      int i;
 +      int i, err;
@@ -2794,25 +2841,30 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                 * alignment padding
                 */
 -              buf = napi_alloc_frag(DPAA2_ETH_BUF_RAW_SIZE);
-+              buf = napi_alloc_frag(dpaa2_eth_buf_raw_size(priv));
-               if (unlikely(!buf))
+-              if (unlikely(!buf))
++              /* allocate one page for each Rx buffer. WRIOP sees
++               * the entire page except for a tailroom reserved for
++               * skb shared info
++               */
++              page = dev_alloc_pages(0);
++              if (!page)
                        goto err_alloc;
  
 -              buf = PTR_ALIGN(buf, DPAA2_ETH_RX_BUF_ALIGN);
-+              buf = PTR_ALIGN(buf, priv->rx_buf_align);
-               addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE,
+-
+-              addr = dma_map_single(dev, buf, DPAA2_ETH_RX_BUF_SIZE,
 -                                    DMA_FROM_DEVICE);
-+                                    DMA_BIDIRECTIONAL);
++              addr = dma_map_page(dev, page, 0, DPAA2_ETH_RX_BUF_SIZE,
++                                  DMA_BIDIRECTIONAL);
                if (unlikely(dma_mapping_error(dev, addr)))
                        goto err_map;
  
-@@ -755,28 +1079,31 @@ static int add_bufs(struct dpaa2_eth_pri
+@@ -755,28 +1021,33 @@ static int add_bufs(struct dpaa2_eth_pri
  
                /* tracing point */
                trace_dpaa2_eth_buf_seed(priv->net_dev,
 -                                       buf, DPAA2_ETH_BUF_RAW_SIZE,
-+                                       buf, dpaa2_eth_buf_raw_size(priv),
++                                       page, DPAA2_ETH_RX_BUF_RAW_SIZE,
                                         addr, DPAA2_ETH_RX_BUF_SIZE,
                                         bpid);
        }
@@ -2833,8 +2885,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                                             buf_array, i)) == -EBUSY)
                cpu_relax();
 +
-+      /* If release command failed, clean up and bail out; not much
-+       * else we can do about it
++      /* If release command failed, clean up and bail out;
++       * not much else we can do about it
 +       */
 +      if (err) {
 +              free_bufs(priv, buf_array, i);
@@ -2844,13 +2896,16 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        return i;
  
  err_map:
-       skb_free_frag(buf);
+-      skb_free_frag(buf);
++      __free_pages(page, 0);
  err_alloc:
-+      /* If we managed to allocate at least some buffers, release them */
++      /* If we managed to allocate at least some buffers,
++       * release them to hardware
++       */
        if (i)
                goto release_bufs;
  
-@@ -796,9 +1123,10 @@ static int seed_pool(struct dpaa2_eth_pr
+@@ -796,9 +1067,10 @@ static int seed_pool(struct dpaa2_eth_pr
         */
        preempt_disable();
        for (j = 0; j < priv->num_channels; j++) {
@@ -2863,7 +2918,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                        priv->channel[j]->buf_count += new_count;
  
                        if (new_count < DPAA2_ETH_BUFS_PER_CMD) {
-@@ -818,10 +1146,8 @@ static int seed_pool(struct dpaa2_eth_pr
+@@ -818,10 +1090,8 @@ static int seed_pool(struct dpaa2_eth_pr
   */
  static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
  {
@@ -2875,7 +2930,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        do {
                ret = dpaa2_io_service_acquire(NULL, priv->bpid,
-@@ -830,27 +1156,16 @@ static void drain_bufs(struct dpaa2_eth_
+@@ -830,27 +1100,16 @@ static void drain_bufs(struct dpaa2_eth_
                        netdev_err(priv->net_dev, "dpaa2_io_service_acquire() failed\n");
                        return;
                }
@@ -2906,7 +2961,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  }
  
  /* Function is called from softirq context only, so we don't need to guard
-@@ -862,19 +1177,19 @@ static int refill_pool(struct dpaa2_eth_
+@@ -862,19 +1121,19 @@ static int refill_pool(struct dpaa2_eth_
  {
        int new_count;
  
@@ -2930,7 +2985,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                return -ENOMEM;
  
        return 0;
-@@ -887,7 +1202,8 @@ static int pull_channel(struct dpaa2_eth
+@@ -887,7 +1146,8 @@ static int pull_channel(struct dpaa2_eth
  
        /* Retry while portal is busy */
        do {
@@ -2940,22 +2995,16 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                dequeues++;
                cpu_relax();
        } while (err == -EBUSY);
-@@ -902,20 +1218,21 @@ static int pull_channel(struct dpaa2_eth
- /* NAPI poll routine
-  *
-  * Frames are dequeued from the QMan channel associated with this NAPI context.
-- * Rx, Tx confirmation and (if configured) Rx error frames all count
-- * towards the NAPI budget.
-+ * Rx and (if configured) Rx error frames count towards the NAPI budget. Tx
-+ * confirmation frames are limited by a threshold per NAPI poll cycle.
-  */
+@@ -908,14 +1168,17 @@ static int pull_channel(struct dpaa2_eth
  static int dpaa2_eth_poll(struct napi_struct *napi, int budget)
  {
        struct dpaa2_eth_channel *ch;
 -      int cleaned = 0, store_cleaned;
-+      int rx_cleaned = 0, tx_conf_cleaned = 0;
-+      bool store_cleaned;
        struct dpaa2_eth_priv *priv;
++      int rx_cleaned = 0, txconf_cleaned = 0;
++      struct dpaa2_eth_fq *fq, *txc_fq = NULL;
++      struct netdev_queue *nq;
++      int store_cleaned, work_done;
        int err;
  
        ch = container_of(napi, struct dpaa2_eth_channel, napi);
@@ -2966,25 +3015,45 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                err = pull_channel(ch);
                if (unlikely(err))
                        break;
-@@ -923,29 +1240,29 @@ static int dpaa2_eth_poll(struct napi_st
+@@ -923,29 +1186,56 @@ static int dpaa2_eth_poll(struct napi_st
                /* Refill pool if appropriate */
                refill_pool(priv, ch, priv->bpid);
  
 -              store_cleaned = consume_frames(ch);
 -              cleaned += store_cleaned;
-+              store_cleaned = consume_frames(ch, &rx_cleaned,
-+                                             &tx_conf_cleaned);
++              store_cleaned = consume_frames(ch, &fq);
++              if (!store_cleaned)
++                      break;
++              if (fq->type == DPAA2_RX_FQ) {
++                      rx_cleaned += store_cleaned;
++                      /* If these are XDP_REDIRECT frames, flush them now */
++                      /* TODO: Do we need this? */
++                      if (ch->flush) {
++                              xdp_do_flush_map();
++                              ch->flush = false;
++                      }
++              } else {
++                      txconf_cleaned += store_cleaned;
++                      /* We have a single Tx conf FQ on this channel */
++                      txc_fq = fq;
++              }
  
 -              /* If we have enough budget left for a full store,
 -               * try a new pull dequeue, otherwise we're done here
-+              /* If we've either consumed the budget with Rx frames,
-+               * or reached the Tx conf threshold, we're done.
++              /* If we either consumed the whole NAPI budget with Rx frames
++               * or we reached the Tx confirmations threshold, we're done.
                 */
 -              if (store_cleaned == 0 ||
 -                  cleaned > budget - DPAA2_ETH_STORE_SIZE)
 -                      break;
 -      }
--
++              if (rx_cleaned >= budget ||
++                  txconf_cleaned >= DPAA2_ETH_TXCONF_PER_NAPI) {
++                      work_done = budget;
++                      goto out;
++              }
++      } while (store_cleaned);
 -      if (cleaned < budget) {
 -              napi_complete_done(napi, cleaned);
 -              /* Re-enable data available notifications */
@@ -2993,29 +3062,69 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -                      cpu_relax();
 -              } while (err == -EBUSY);
 -      }
-+              if (rx_cleaned >= budget ||
-+                  tx_conf_cleaned >= TX_CONF_PER_NAPI_POLL)
-+                      return budget;
-+      } while (store_cleaned);
--      ch->stats.frames += cleaned;
-+      /* We didn't consume the entire budget, finish napi and
++      /* We didn't consume the entire budget, so finish napi and
 +       * re-enable data availability notifications
 +       */
-+      napi_complete(napi);
++      napi_complete_done(napi, rx_cleaned);
 +      do {
 +              err = dpaa2_io_service_rearm(ch->dpio, &ch->nctx);
 +              cpu_relax();
 +      } while (err == -EBUSY);
-+              WARN_ONCE(err, "CDAN notifications rearm failed on core %d",
-+                        ch->nctx.desired_cpu);
++      WARN_ONCE(err, "CDAN notifications rearm failed on core %d",
++                ch->nctx.desired_cpu);
+-      ch->stats.frames += cleaned;
++      work_done = max(rx_cleaned, 1);
  
 -      return cleaned;
-+      return max(rx_cleaned, 1);
++out:
++      if (txc_fq) {
++              nq = netdev_get_tx_queue(priv->net_dev, txc_fq->flowid);
++              netdev_tx_completed_queue(nq, txc_fq->dq_frames,
++                                        txc_fq->dq_bytes);
++              txc_fq->dq_frames = 0;
++              txc_fq->dq_bytes = 0;
++      }
++
++      return work_done;
  }
  
  static void enable_ch_napi(struct dpaa2_eth_priv *priv)
-@@ -1006,28 +1323,30 @@ static int dpaa2_eth_open(struct net_dev
+@@ -970,9 +1260,23 @@ static void disable_ch_napi(struct dpaa2
+       }
+ }
++static void update_tx_fqids(struct dpaa2_eth_priv *priv);
++
++static void update_pf(struct dpaa2_eth_priv *priv,
++                    struct dpni_link_state *state)
++{
++      bool pause_frames;
++
++      pause_frames = !!(state->options & DPNI_LINK_OPT_PAUSE);
++      if (priv->tx_pause_frames != pause_frames) {
++              priv->tx_pause_frames = pause_frames;
++              set_rx_taildrop(priv);
++      }
++}
++
+ static int link_state_update(struct dpaa2_eth_priv *priv)
+ {
+-      struct dpni_link_state state;
++      struct dpni_link_state state = {0};
+       int err;
+       err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
+@@ -988,6 +1292,8 @@ static int link_state_update(struct dpaa
+       priv->link_state = state;
+       if (state.up) {
++              update_tx_fqids(priv);
++              update_pf(priv, &state);
+               netif_carrier_on(priv->net_dev);
+               netif_tx_start_all_queues(priv->net_dev);
+       } else {
+@@ -1006,28 +1312,30 @@ static int dpaa2_eth_open(struct net_dev
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
        int err;
  
@@ -3057,7 +3166,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        err = dpni_enable(priv->mc_io, 0, priv->mc_token);
        if (err < 0) {
                netdev_err(net_dev, "dpni_enable() failed\n");
-@@ -1047,48 +1366,17 @@ static int dpaa2_eth_open(struct net_dev
+@@ -1047,48 +1355,17 @@ static int dpaa2_eth_open(struct net_dev
  
  link_state_err:
  enable_err:
@@ -3101,15 +3210,16 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  static int dpaa2_eth_stop(struct net_device *net_dev)
  {
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-       int dpni_enabled;
+-      int dpni_enabled;
 -      int retries = 10;
 -      u32 drained;
++      int dpni_enabled = 0;
 +      int retries = 10, i;
 +      int err = 0;
  
        netif_tx_stop_all_queues(net_dev);
        netif_carrier_off(net_dev);
-@@ -1105,56 +1393,24 @@ static int dpaa2_eth_stop(struct net_dev
+@@ -1105,56 +1382,24 @@ static int dpaa2_eth_stop(struct net_dev
        } while (dpni_enabled && --retries);
        if (!retries) {
                netdev_warn(net_dev, "Retry count exceeded disabling DPNI\n");
@@ -3176,7 +3286,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  }
  
  static int dpaa2_eth_set_addr(struct net_device *net_dev, void *addr)
-@@ -1200,25 +1456,6 @@ static void dpaa2_eth_get_stats(struct n
+@@ -1200,25 +1445,6 @@ static void dpaa2_eth_get_stats(struct n
        }
  }
  
@@ -3202,7 +3312,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  /* Copy mac unicast addresses from @net_dev to @priv.
   * Its sole purpose is to make dpaa2_eth_set_rx_mode() more readable.
   */
-@@ -1380,16 +1617,363 @@ static int dpaa2_eth_set_features(struct
+@@ -1380,16 +1606,430 @@ static int dpaa2_eth_set_features(struct
        return 0;
  }
  
@@ -3249,6 +3359,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +{
 +      struct device *dev = priv->net_dev->dev.parent;
 +      struct dpni_buffer_layout buf_layout = {0};
++      u16 rx_buf_align;
 +      int err;
 +
 +      /* We need to check for WRIOP version 1.0.0, but depending on the MC
@@ -3257,15 +3368,15 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +       */
 +      if (priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(0, 0, 0) ||
 +          priv->dpni_attrs.wriop_version == DPAA2_WRIOP_VERSION(1, 0, 0))
-+              priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1;
++              rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN_REV1;
 +      else
-+              priv->rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
++              rx_buf_align = DPAA2_ETH_RX_BUF_ALIGN;
 +
 +      /* tx buffer */
-+      buf_layout.pass_timestamp = true;
 +      buf_layout.private_data_size = DPAA2_ETH_SWA_SIZE;
-+      buf_layout.options = DPNI_BUF_LAYOUT_OPT_TIMESTAMP |
-+                           DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE;
++      buf_layout.pass_timestamp = true;
++      buf_layout.options = DPNI_BUF_LAYOUT_OPT_PRIVATE_DATA_SIZE |
++                           DPNI_BUF_LAYOUT_OPT_TIMESTAMP;
 +      err = dpni_set_buffer_layout(priv->mc_io, 0, priv->mc_token,
 +                                   DPNI_QUEUE_TX, &buf_layout);
 +      if (err) {
@@ -3299,9 +3410,9 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      /* rx buffer */
 +      buf_layout.pass_frame_status = true;
 +      buf_layout.pass_parser_result = true;
-+      buf_layout.data_align = priv->rx_buf_align;
-+      buf_layout.private_data_size = 0;
++      buf_layout.data_align = rx_buf_align;
 +      buf_layout.data_head_room = dpaa2_eth_rx_headroom(priv);
++      buf_layout.private_data_size = 0;
 +      /* If XDP program is attached, reserve extra space for
 +       * potential header expansions
 +       */
@@ -3322,6 +3433,73 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      return 0;
 +}
 +
++#define DPNI_ENQUEUE_FQID_VER_MAJOR   7
++#define DPNI_ENQUEUE_FQID_VER_MINOR   9
++
++static inline int dpaa2_eth_enqueue_qd(struct dpaa2_eth_priv *priv,
++                                     struct dpaa2_eth_fq *fq,
++                                     struct dpaa2_fd *fd, u8 prio)
++{
++      return dpaa2_io_service_enqueue_qd(fq->channel->dpio,
++                                         priv->tx_qdid, prio,
++                                         fq->tx_qdbin, fd);
++}
++
++static inline int dpaa2_eth_enqueue_fq(struct dpaa2_eth_priv *priv,
++                                     struct dpaa2_eth_fq *fq,
++                                     struct dpaa2_fd *fd,
++                                     u8 prio __always_unused)
++{
++      return dpaa2_io_service_enqueue_fq(fq->channel->dpio,
++                                         fq->tx_fqid, fd);
++}
++
++static void set_enqueue_mode(struct dpaa2_eth_priv *priv)
++{
++      if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_ENQUEUE_FQID_VER_MAJOR,
++                                 DPNI_ENQUEUE_FQID_VER_MINOR) < 0)
++              priv->enqueue = dpaa2_eth_enqueue_qd;
++      else
++              priv->enqueue = dpaa2_eth_enqueue_fq;
++}
++
++static void update_tx_fqids(struct dpaa2_eth_priv *priv)
++{
++      struct dpaa2_eth_fq *fq;
++      struct dpni_queue queue;
++      struct dpni_queue_id qid = {0};
++      int i, err;
++
++      /* We only use Tx FQIDs for FQID-based enqueue, so check
++       * if DPNI version supports it before updating FQIDs
++       */
++      if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_ENQUEUE_FQID_VER_MAJOR,
++                                 DPNI_ENQUEUE_FQID_VER_MINOR) < 0)
++              return;
++
++      for (i = 0; i < priv->num_fqs; i++) {
++              fq = &priv->fq[i];
++              if (fq->type != DPAA2_TX_CONF_FQ)
++                      continue;
++              err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
++                                   DPNI_QUEUE_TX, 0, fq->flowid,
++                                   &queue, &qid);
++              if (err)
++                      goto out_err;
++
++              fq->tx_fqid = qid.fqid;
++              if (fq->tx_fqid == 0)
++                      goto out_err;
++      }
++
++      return;
++
++out_err:
++      netdev_info(priv->net_dev,
++                  "Error reading Tx FQID, fallback to QDID-based enqueue");
++      priv->enqueue = dpaa2_eth_enqueue_qd;
++}
++
 +static int dpaa2_eth_set_xdp(struct net_device *net_dev, struct bpf_prog *prog)
 +{
 +      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
@@ -3471,7 +3649,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +       * so we do the actual frame enqueue in ndo_xdp_xmit
 +       */
 +}
-+
 +static int dpaa2_eth_update_xps(struct dpaa2_eth_priv *priv)
 +{
 +      struct net_device *net_dev = priv->net_dev;
@@ -3568,7 +3745,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  };
  
  static void cdan_cb(struct dpaa2_io_notification_ctx *ctx)
-@@ -1422,34 +2006,32 @@ static struct fsl_mc_device *setup_dpcon
+@@ -1422,34 +2062,32 @@ static struct fsl_mc_device *setup_dpcon
        err = dpcon_open(priv->mc_io, 0, dpcon->obj_desc.id, &dpcon->mc_handle);
        if (err) {
                dev_err(dev, "dpcon_open() failed\n");
@@ -3609,7 +3786,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        fsl_mc_object_free(dpcon);
  
        return NULL;
-@@ -1502,7 +2084,14 @@ err_setup:
+@@ -1502,7 +2140,14 @@ err_setup:
  static void free_channel(struct dpaa2_eth_priv *priv,
                         struct dpaa2_eth_channel *channel)
  {
@@ -3624,35 +3801,51 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        kfree(channel);
  }
  
-@@ -1546,7 +2135,8 @@ static int setup_dpio(struct dpaa2_eth_p
+@@ -1546,7 +2191,8 @@ static int setup_dpio(struct dpaa2_eth_p
                nctx->desired_cpu = i;
  
                /* Register the new context */
 -              err = dpaa2_io_service_register(NULL, nctx);
 +              channel->dpio = dpaa2_io_service_select(i);
-+              err = dpaa2_io_service_register(channel->dpio, nctx);
++              err = dpaa2_io_service_register(channel->dpio, nctx, dev);
                if (err) {
                        dev_dbg(dev, "No affine DPIO for cpu %d\n", i);
                        /* If no affine DPIO for this core, there's probably
-@@ -1586,7 +2176,7 @@ static int setup_dpio(struct dpaa2_eth_p
+@@ -1579,14 +2225,14 @@ static int setup_dpio(struct dpaa2_eth_p
+               /* Stop if we already have enough channels to accommodate all
+                * RX and TX conf queues
+                */
+-              if (priv->num_channels == dpaa2_eth_queue_count(priv))
++              if (priv->num_channels == priv->dpni_attrs.num_queues)
+                       break;
+       }
        return 0;
  
  err_set_cdan:
 -      dpaa2_io_service_deregister(NULL, nctx);
-+      dpaa2_io_service_deregister(channel->dpio, nctx);
++      dpaa2_io_service_deregister(channel->dpio, nctx, dev);
  err_service_reg:
        free_channel(priv, channel);
  err_alloc_ch:
-@@ -1609,7 +2199,7 @@ static void free_dpio(struct dpaa2_eth_p
+@@ -1603,13 +2249,14 @@ err_alloc_ch:
+ static void free_dpio(struct dpaa2_eth_priv *priv)
+ {
+-      int i;
++      struct device *dev = priv->net_dev->dev.parent;
+       struct dpaa2_eth_channel *ch;
++      int i;
        /* deregister CDAN notifications and free channels */
        for (i = 0; i < priv->num_channels; i++) {
                ch = priv->channel[i];
 -              dpaa2_io_service_deregister(NULL, &ch->nctx);
-+              dpaa2_io_service_deregister(ch->dpio, &ch->nctx);
++              dpaa2_io_service_deregister(ch->dpio, &ch->nctx, dev);
                free_channel(priv, ch);
        }
  }
-@@ -1636,8 +2226,7 @@ static void set_fq_affinity(struct dpaa2
+@@ -1636,8 +2283,7 @@ static void set_fq_affinity(struct dpaa2
  {
        struct device *dev = priv->net_dev->dev.parent;
        struct dpaa2_eth_fq *fq;
@@ -3662,7 +3855,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* For each FQ, pick one channel/CPU to deliver frames to.
         * This may well change at runtime, either through irqbalance or
-@@ -1649,6 +2238,7 @@ static void set_fq_affinity(struct dpaa2
+@@ -1649,6 +2295,7 @@ static void set_fq_affinity(struct dpaa2
                fq = &priv->fq[i];
                switch (fq->type) {
                case DPAA2_RX_FQ:
@@ -3670,15 +3863,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                        fq->target_cpu = rx_cpu;
                        rx_cpu = cpumask_next(rx_cpu, &priv->dpio_cpumask);
                        if (rx_cpu >= nr_cpu_ids)
-@@ -1656,6 +2246,7 @@ static void set_fq_affinity(struct dpaa2
-                       break;
-               case DPAA2_TX_CONF_FQ:
-                       fq->target_cpu = txc_cpu;
-+
-                       txc_cpu = cpumask_next(txc_cpu, &priv->dpio_cpumask);
-                       if (txc_cpu >= nr_cpu_ids)
-                               txc_cpu = cpumask_first(&priv->dpio_cpumask);
-@@ -1665,11 +2256,13 @@ static void set_fq_affinity(struct dpaa2
+@@ -1665,11 +2312,13 @@ static void set_fq_affinity(struct dpaa2
                }
                fq->channel = get_affine_channel(priv, fq->target_cpu);
        }
@@ -3693,7 +3878,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* We have one TxConf FQ per Tx flow.
         * The number of Tx and Rx queues is the same.
-@@ -1681,11 +2274,19 @@ static void setup_fqs(struct dpaa2_eth_p
+@@ -1681,11 +2330,19 @@ static void setup_fqs(struct dpaa2_eth_p
                priv->fq[priv->num_fqs++].flowid = (u16)i;
        }
  
@@ -3718,7 +3903,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* For each FQ, decide on which core to process incoming frames */
        set_fq_affinity(priv);
-@@ -1735,6 +2336,9 @@ static int setup_dpbp(struct dpaa2_eth_p
+@@ -1735,6 +2392,9 @@ static int setup_dpbp(struct dpaa2_eth_p
        }
        priv->bpid = dpbp_attrs.bpid;
  
@@ -3728,59 +3913,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        return 0;
  
  err_get_attr:
-@@ -1756,13 +2360,59 @@ static void free_dpbp(struct dpaa2_eth_p
-       fsl_mc_object_free(priv->dpbp_dev);
- }
-+static int setup_tx_congestion(struct dpaa2_eth_priv *priv)
-+{
-+      struct dpni_congestion_notification_cfg notif_cfg = {0};
-+      struct device *dev = priv->net_dev->dev.parent;
-+      int err;
-+
-+      priv->cscn_unaligned = kzalloc(DPAA2_CSCN_SIZE + DPAA2_CSCN_ALIGN,
-+                                     GFP_KERNEL);
-+
-+      if (!priv->cscn_unaligned)
-+              return -ENOMEM;
-+
-+      priv->cscn_mem = PTR_ALIGN(priv->cscn_unaligned, DPAA2_CSCN_ALIGN);
-+      priv->cscn_dma = dma_map_single(dev, priv->cscn_mem, DPAA2_CSCN_SIZE,
-+                                      DMA_FROM_DEVICE);
-+      if (dma_mapping_error(dev, priv->cscn_dma)) {
-+              dev_err(dev, "Error mapping CSCN memory area\n");
-+              err = -ENOMEM;
-+              goto err_dma_map;
-+      }
-+
-+      notif_cfg.units = DPNI_CONGESTION_UNIT_BYTES;
-+      notif_cfg.threshold_entry = DPAA2_ETH_TX_CONG_ENTRY_THRESH;
-+      notif_cfg.threshold_exit = DPAA2_ETH_TX_CONG_EXIT_THRESH;
-+      notif_cfg.message_ctx = (u64)priv;
-+      notif_cfg.message_iova = priv->cscn_dma;
-+      notif_cfg.notification_mode = DPNI_CONG_OPT_WRITE_MEM_ON_ENTER |
-+                                    DPNI_CONG_OPT_WRITE_MEM_ON_EXIT |
-+                                    DPNI_CONG_OPT_COHERENT_WRITE;
-+      err = dpni_set_congestion_notification(priv->mc_io, 0, priv->mc_token,
-+                                             DPNI_QUEUE_TX, 0, &notif_cfg);
-+      if (err) {
-+              dev_err(dev, "dpni_set_congestion_notification failed\n");
-+              goto err_set_cong;
-+      }
-+
-+      return 0;
-+
-+err_set_cong:
-+      dma_unmap_single(dev, priv->cscn_dma, DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
-+err_dma_map:
-+      kfree(priv->cscn_unaligned);
-+
-+      return err;
-+}
-+
- /* Configure the DPNI object this interface is associated with */
- static int setup_dpni(struct fsl_mc_device *ls_dev)
- {
+@@ -1762,7 +2422,7 @@ static int setup_dpni(struct fsl_mc_devi
        struct device *dev = &ls_dev->dev;
        struct dpaa2_eth_priv *priv;
        struct net_device *net_dev;
@@ -3789,7 +3922,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        int err;
  
        net_dev = dev_get_drvdata(dev);
-@@ -1772,7 +2422,22 @@ static int setup_dpni(struct fsl_mc_devi
+@@ -1772,7 +2432,22 @@ static int setup_dpni(struct fsl_mc_devi
        err = dpni_open(priv->mc_io, 0, ls_dev->obj_desc.id, &priv->mc_token);
        if (err) {
                dev_err(dev, "dpni_open() failed\n");
@@ -3813,7 +3946,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        }
  
        ls_dev->mc_io = priv->mc_io;
-@@ -1781,82 +2446,53 @@ static int setup_dpni(struct fsl_mc_devi
+@@ -1781,77 +2456,41 @@ static int setup_dpni(struct fsl_mc_devi
        err = dpni_reset(priv->mc_io, 0, priv->mc_token);
        if (err) {
                dev_err(dev, "dpni_reset() failed\n");
@@ -3858,10 +3991,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -              dev_err(dev, "dpni_set_buffer_layout(TX) failed\n");
 -              goto err_buf_layout;
 -      }
-+      /* Enable congestion notifications for Tx queues */
-+      err = setup_tx_congestion(priv);
-+      if (err)
-+              goto close;
++      set_enqueue_mode(priv);
  
 -      /* tx-confirm buffer */
 -      buf_layout.options = DPNI_BUF_LAYOUT_OPT_FRAME_STATUS;
@@ -3871,9 +4001,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -              dev_err(dev, "dpni_set_buffer_layout(TX_CONF) failed\n");
 -              goto err_buf_layout;
 -      }
-+      /* allocate classification rule space */
-+      priv->cls_rule = kzalloc(sizeof(*priv->cls_rule) *
-+                               dpaa2_eth_fs_count(priv), GFP_KERNEL);
++      priv->cls_rule = devm_kzalloc(dev, sizeof(struct dpaa2_eth_cls_rule) *
++                                    dpaa2_eth_fs_count(priv), GFP_KERNEL);
 +      if (!priv->cls_rule)
 +              goto close;
  
@@ -3890,7 +4019,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -              dev_err(dev, "dpni_get_tx_data_offset() failed\n");
 -              goto err_data_offset;
 +              dev_err(dev, "dpni_set_link_cfg() failed\n");
-+              goto cls_free;
++              goto close;
        }
  
 -      if ((priv->tx_data_offset % 64) != 0)
@@ -3906,8 +4035,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -err_buf_layout:
 -err_get_attr:
 -err_reset:
-+cls_free:
-+      kfree(priv->cls_rule);
 +close:
        dpni_close(priv->mc_io, 0, priv->mc_token);
 -err_open:
@@ -3915,25 +4042,15 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        return err;
  }
  
- static void free_dpni(struct dpaa2_eth_priv *priv)
- {
-+      struct device *dev = priv->net_dev->dev.parent;
-       int err;
-       err = dpni_reset(priv->mc_io, 0, priv->mc_token);
-@@ -1865,6 +2501,11 @@ static void free_dpni(struct dpaa2_eth_p
+@@ -1865,6 +2504,7 @@ static void free_dpni(struct dpaa2_eth_p
                            err);
  
        dpni_close(priv->mc_io, 0, priv->mc_token);
 +
-+      kfree(priv->cls_rule);
-+
-+      dma_unmap_single(dev, priv->cscn_dma, DPAA2_CSCN_SIZE, DMA_FROM_DEVICE);
-+      kfree(priv->cscn_unaligned);
  }
  
  static int setup_rx_flow(struct dpaa2_eth_priv *priv,
-@@ -1873,11 +2514,10 @@ static int setup_rx_flow(struct dpaa2_et
+@@ -1873,11 +2513,10 @@ static int setup_rx_flow(struct dpaa2_et
        struct device *dev = priv->net_dev->dev.parent;
        struct dpni_queue queue;
        struct dpni_queue_id qid;
@@ -3946,16 +4063,24 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        if (err) {
                dev_err(dev, "dpni_get_queue(RX) failed\n");
                return err;
-@@ -1890,7 +2530,7 @@ static int setup_rx_flow(struct dpaa2_et
+@@ -1889,24 +2528,136 @@ static int setup_rx_flow(struct dpaa2_et
+       queue.destination.type = DPNI_DEST_DPCON;
        queue.destination.priority = 1;
        queue.user_context = (u64)(uintptr_t)fq;
++      queue.flc.stash_control = 1;
++      queue.flc.value &= 0xFFFFFFFFFFFFFFC0;
++      /* 01 01 00 - data, annotation, flow context*/
++      queue.flc.value |= 0x14;
++
        err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
 -                           DPNI_QUEUE_RX, 0, fq->flowid,
+-                           DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST,
 +                           DPNI_QUEUE_RX, fq->tc, fq->flowid,
-                            DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST,
++                           DPNI_QUEUE_OPT_USER_CTX | DPNI_QUEUE_OPT_DEST |
++                           DPNI_QUEUE_OPT_FLC,
                             &queue);
        if (err) {
-@@ -1898,15 +2538,121 @@ static int setup_rx_flow(struct dpaa2_et
+               dev_err(dev, "dpni_set_queue(RX) failed\n");
                return err;
        }
  
@@ -4084,7 +4209,15 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        return 0;
  }
  
-@@ -1953,23 +2699,88 @@ static int setup_tx_flow(struct dpaa2_et
+@@ -1926,6 +2677,7 @@ static int setup_tx_flow(struct dpaa2_et
+       }
+       fq->tx_qdbin = qid.qdbin;
++      fq->tx_fqid = qid.fqid;
+       err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
+                            DPNI_QUEUE_TX_CONFIRM, 0, fq->flowid,
+@@ -1953,23 +2705,88 @@ static int setup_tx_flow(struct dpaa2_et
        return 0;
  }
  
@@ -4124,8 +4257,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +}
 +#endif
 +
-+/* default hash key fields */
-+static struct dpaa2_eth_dist_fields default_dist_fields[] = {
++/* Supported header fields for Rx hash distribution key */
++static const struct dpaa2_eth_dist_fields dist_fields[] = {
        {
 +              /* L2 header */
 +              .rxnfc_field = RXH_L2DA,
@@ -4175,7 +4308,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                .size = 1,
        }, {
                /* Using UDP ports, this is functionally equivalent to raw
-@@ -1978,90 +2789,182 @@ static const struct dpaa2_eth_hash_field
+@@ -1978,41 +2795,170 @@ static const struct dpaa2_eth_hash_field
                .rxnfc_field = RXH_L4_B_0_1,
                .cls_prot = NET_PROT_UDP,
                .cls_field = NH_FLD_UDP_PORT_SRC,
@@ -4191,157 +4324,188 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  };
  
 -/* Set RX hash options
-- * flags is a combination of RXH_ bits
-- */
--static int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
-+static int legacy_config_dist_key(struct dpaa2_eth_priv *priv,
-+                                dma_addr_t key_iova)
- {
--      struct device *dev = net_dev->dev.parent;
--      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
--      struct dpkg_profile_cfg cls_cfg;
++/* Configure the Rx hash key using the legacy API */
++static int config_legacy_hash_key(struct dpaa2_eth_priv *priv, dma_addr_t key)
++{
 +      struct device *dev = priv->net_dev->dev.parent;
-       struct dpni_rx_tc_dist_cfg dist_cfg;
--      u8 *dma_mem;
--      int i;
--      int err = 0;
-+      int i, err;
--      if (!dpaa2_eth_hash_enabled(priv)) {
--              dev_dbg(dev, "Hashing support is not enabled\n");
--              return 0;
-+      /* In legacy mode, we can't configure flow steering independently */
-+      if (!dpaa2_eth_hash_enabled(priv))
-+              return -EOPNOTSUPP;
++      struct dpni_rx_tc_dist_cfg dist_cfg;
++      int i, err = 0;
 +
 +      memset(&dist_cfg, 0, sizeof(dist_cfg));
 +
-+      dist_cfg.key_cfg_iova = key_iova;
++      dist_cfg.key_cfg_iova = key;
 +      dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
-+      if (dpaa2_eth_fs_enabled(priv)) {
-+              dist_cfg.dist_mode = DPNI_DIST_MODE_FS;
-+              dist_cfg.fs_cfg.miss_action = DPNI_FS_MISS_HASH;
-+      } else {
-+              dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
-       }
--      memset(&cls_cfg, 0, sizeof(cls_cfg));
++      dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
++
 +      for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
-+              err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, i,
-+                                        &dist_cfg);
++              err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token,
++                                        i, &dist_cfg);
 +              if (err) {
 +                      dev_err(dev, "dpni_set_rx_tc_dist failed\n");
-+                      return err;
++                      break;
 +              }
 +      }
 +
-+      return 0;
++      return err;
 +}
 +
-+static int config_hash_key(struct dpaa2_eth_priv *priv, dma_addr_t key_iova)
++/* Configure the Rx hash key using the new API */
++static int config_hash_key(struct dpaa2_eth_priv *priv, dma_addr_t key)
 +{
 +      struct device *dev = priv->net_dev->dev.parent;
 +      struct dpni_rx_dist_cfg dist_cfg;
-+      int i, err;
--      for (i = 0; i < ARRAY_SIZE(hash_fields); i++) {
--              struct dpkg_extract *key =
--                      &cls_cfg.extracts[cls_cfg.num_extracts];
-+      if (!dpaa2_eth_hash_enabled(priv))
-+              return -EOPNOTSUPP;
--              if (!(flags & hash_fields[i].rxnfc_field))
--                      continue;
++      int i, err = 0;
++
 +      memset(&dist_cfg, 0, sizeof(dist_cfg));
 +
-+      dist_cfg.key_cfg_iova = key_iova;
++      dist_cfg.key_cfg_iova = key;
 +      dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
-+      dist_cfg.enable = true;
++      dist_cfg.enable = 1;
 +
 +      for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
 +              dist_cfg.tc = i;
-+
-+              err = dpni_set_rx_hash_dist(priv->mc_io, 0,
-+                                          priv->mc_token, &dist_cfg);
++              err = dpni_set_rx_hash_dist(priv->mc_io, 0, priv->mc_token,
++                                          &dist_cfg);
 +              if (err) {
 +                      dev_err(dev, "dpni_set_rx_hash_dist failed\n");
-+                      return err;
++                      break;
 +              }
 +      }
 +
-+      return 0;
++      return err;
 +}
 +
-+static int config_fs_key(struct dpaa2_eth_priv *priv, dma_addr_t key_iova)
++/* Configure the Rx flow classification key */
++static int config_cls_key(struct dpaa2_eth_priv *priv, dma_addr_t key)
 +{
 +      struct device *dev = priv->net_dev->dev.parent;
 +      struct dpni_rx_dist_cfg dist_cfg;
-+      int i, err;
--              if (cls_cfg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
--                      dev_err(dev, "error adding key extraction rule, too many rules?\n");
--                      return -E2BIG;
-+      if (!dpaa2_eth_fs_enabled(priv))
-+              return -EOPNOTSUPP;
++      int i, err = 0;
 +
 +      memset(&dist_cfg, 0, sizeof(dist_cfg));
 +
-+      dist_cfg.key_cfg_iova = key_iova;
++      dist_cfg.key_cfg_iova = key;
 +      dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
-+      dist_cfg.enable = true;
++      dist_cfg.enable = 1;
 +
 +      for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
 +              dist_cfg.tc = i;
-+
-+              err = dpni_set_rx_fs_dist(priv->mc_io, 0,
-+                                        priv->mc_token, &dist_cfg);
++              err = dpni_set_rx_fs_dist(priv->mc_io, 0, priv->mc_token,
++                                        &dist_cfg);
 +              if (err) {
 +                      dev_err(dev, "dpni_set_rx_fs_dist failed\n");
-+                      return err;
-               }
++                      break;
++              }
 +      }
 +
-+      return 0;
++      return err;
 +}
-+int dpaa2_eth_set_dist_key(struct dpaa2_eth_priv *priv,
-+                         enum dpaa2_eth_rx_dist type, u32 key_fields)
-+{
-+      struct device *dev = priv->net_dev->dev.parent;
-+      struct dpkg_profile_cfg cls_cfg;
-+      struct dpkg_extract *key;
-+      u32 hash_fields = 0;
-+      dma_addr_t key_iova;
-+      u8 *key_mem;
-+      int i, err;
 +
-+      memset(&cls_cfg, 0, sizeof(cls_cfg));
++/* Size of the Rx flow classification key */
++int dpaa2_eth_cls_key_size(u64 fields)
++{
++      int i, size = 0;
 +
-+      for (i = 0; i < priv->num_dist_fields; i++) {
-+              if (!(key_fields & priv->dist_fields[i].id))
++      for (i = 0; i < ARRAY_SIZE(dist_fields); i++) {
++              if (!(fields & dist_fields[i].id))
 +                      continue;
++              size += dist_fields[i].size;
++      }
++
++      return size;
++}
++
++/* Offset of header field in Rx classification key */
++int dpaa2_eth_cls_fld_off(int prot, int field)
++{
++      int i, off = 0;
++
++      for (i = 0; i < ARRAY_SIZE(dist_fields); i++) {
++              if (dist_fields[i].cls_prot == prot &&
++                  dist_fields[i].cls_field == field)
++                      return off;
++              off += dist_fields[i].size;
++      }
++
++      WARN_ONCE(1, "Unsupported header field used for Rx flow cls\n");
++      return 0;
++}
++
++/* Prune unused fields from the classification rule.
++ * Used when masking is not supported
++ */
++void dpaa2_eth_cls_trim_rule(void *key_mem, u64 fields)
++{
++      int off = 0, new_off = 0;
++      int i, size;
++
++      for (i = 0; i < ARRAY_SIZE(dist_fields); i++) {
++              size = dist_fields[i].size;
++              if (dist_fields[i].id & fields) {
++                      memcpy(key_mem + new_off, key_mem + off, size);
++                      new_off += size;
++              }
++              off += size;
++      }
++}
 +
-+              key = &cls_cfg.extracts[cls_cfg.num_extracts];
++/* Set Rx distribution (hash or flow classification) key
+  * flags is a combination of RXH_ bits
+  */
+-static int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
++static int dpaa2_eth_set_dist_key(struct net_device *net_dev,
++                                enum dpaa2_eth_rx_dist type, u64 flags)
+ {
+       struct device *dev = net_dev->dev.parent;
+       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+       struct dpkg_profile_cfg cls_cfg;
+-      struct dpni_rx_tc_dist_cfg dist_cfg;
++      u32 rx_hash_fields = 0;
++      dma_addr_t key_iova;
+       u8 *dma_mem;
+       int i;
+       int err = 0;
+-      if (!dpaa2_eth_hash_enabled(priv)) {
+-              dev_dbg(dev, "Hashing support is not enabled\n");
+-              return 0;
+-      }
+-
+       memset(&cls_cfg, 0, sizeof(cls_cfg));
+-      for (i = 0; i < ARRAY_SIZE(hash_fields); i++) {
++      for (i = 0; i < ARRAY_SIZE(dist_fields); i++) {
+               struct dpkg_extract *key =
+                       &cls_cfg.extracts[cls_cfg.num_extracts];
+-              if (!(flags & hash_fields[i].rxnfc_field))
++              /* For both Rx hashing and classification keys
++               * we set only the selected fields.
++               */
++              if (!(flags & dist_fields[i].id))
+                       continue;
++              if (type == DPAA2_ETH_RX_DIST_HASH)
++                      rx_hash_fields |= dist_fields[i].rxnfc_field;
+               if (cls_cfg.num_extracts >= DPKG_MAX_NUM_OF_EXTRACTS) {
+                       dev_err(dev, "error adding key extraction rule, too many rules?\n");
+@@ -2020,12 +2966,10 @@ static int dpaa2_eth_set_hash(struct net
+               }
                key->type = DPKG_EXTRACT_FROM_HDR;
 -              key->extract.from_hdr.prot = hash_fields[i].cls_prot;
-+              key->extract.from_hdr.prot = priv->dist_fields[i].cls_prot;
++              key->extract.from_hdr.prot = dist_fields[i].cls_prot;
                key->extract.from_hdr.type = DPKG_FULL_FIELD;
 -              key->extract.from_hdr.field = hash_fields[i].cls_field;
-+              key->extract.from_hdr.field = priv->dist_fields[i].cls_field;
++              key->extract.from_hdr.field = dist_fields[i].cls_field;
                cls_cfg.num_extracts++;
+-
 -              priv->rx_hash_fields |= hash_fields[i].rxnfc_field;
-+              hash_fields |= priv->dist_fields[i].rxnfc_field;
        }
  
--      dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL);
--      if (!dma_mem)
-+      key_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL);
-+      if (!key_mem)
-               return -ENOMEM;
--      err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
-+      err = dpni_prepare_key_cfg(&cls_cfg, key_mem);
+       dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL);
+@@ -2035,36 +2979,96 @@ static int dpaa2_eth_set_hash(struct net
+       err = dpni_prepare_key_cfg(&cls_cfg, dma_mem);
        if (err) {
                dev_err(dev, "dpni_prepare_key_cfg error %d\n", err);
 -              goto err_prep_key;
@@ -4350,12 +4514,12 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
 -      memset(&dist_cfg, 0, sizeof(dist_cfg));
 -
--      /* Prepare for setting the rx dist */
+       /* Prepare for setting the rx dist */
 -      dist_cfg.key_cfg_iova = dma_map_single(dev, dma_mem,
 -                                             DPAA2_CLASSIFIER_DMA_SIZE,
 -                                             DMA_TO_DEVICE);
 -      if (dma_mapping_error(dev, dist_cfg.key_cfg_iova)) {
-+      key_iova = dma_map_single(dev, key_mem, DPAA2_CLASSIFIER_DMA_SIZE,
++      key_iova = dma_map_single(dev, dma_mem, DPAA2_CLASSIFIER_DMA_SIZE,
 +                                DMA_TO_DEVICE);
 +      if (dma_mapping_error(dev, key_iova)) {
                dev_err(dev, "DMA mapping failed\n");
@@ -4366,19 +4530,13 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
 -      dist_cfg.dist_size = dpaa2_eth_queue_count(priv);
 -      dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
-+      switch (type) {
-+      case DPAA2_ETH_RX_DIST_LEGACY:
-+              err = legacy_config_dist_key(priv, key_iova);
-+              break;
-+      case DPAA2_ETH_RX_DIST_HASH:
-+              err = config_hash_key(priv, key_iova);
-+              break;
-+      case DPAA2_ETH_RX_DIST_FS:
-+              err = config_fs_key(priv, key_iova);
-+              break;
-+      default:
-+              err = -EINVAL;
-+              break;
++      if (type == DPAA2_ETH_RX_DIST_HASH) {
++              if (dpaa2_eth_has_legacy_dist(priv))
++                      err = config_legacy_hash_key(priv, key_iova);
++              else
++                      err = config_hash_key(priv, key_iova);
++      } else {
++              err = config_cls_key(priv, key_iova);
 +      }
  
 -      err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
@@ -4388,24 +4546,79 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -              dev_err(dev, "dpni_set_rx_tc_dist() error %d\n", err);
 +      dma_unmap_single(dev, key_iova, DPAA2_CLASSIFIER_DMA_SIZE,
 +                       DMA_TO_DEVICE);
-+      if (err) {
-+              if (err != -EOPNOTSUPP)
-+                      dev_err(dev, "Distribution key config failed\n");
-+              goto free_key;
-+      }
++      if (!err && type == DPAA2_ETH_RX_DIST_HASH)
++              priv->rx_hash_fields = rx_hash_fields;
  
 -err_dma_map:
 -err_prep_key:
--      kfree(dma_mem);
-+      if (type != DPAA2_ETH_RX_DIST_FS)
-+              priv->rx_hash_fields = hash_fields;
-+
 +free_key:
-+      kfree(key_mem);
+       kfree(dma_mem);
        return err;
  }
  
-@@ -2080,6 +2983,7 @@ static int bind_dpni(struct dpaa2_eth_pr
++int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags)
++{
++      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
++      u64 key = 0;
++      int i;
++
++      if (!dpaa2_eth_hash_enabled(priv))
++              return -EOPNOTSUPP;
++
++      for (i = 0; i < ARRAY_SIZE(dist_fields); i++)
++              if (dist_fields[i].rxnfc_field & flags)
++                      key |= dist_fields[i].id;
++
++      return dpaa2_eth_set_dist_key(net_dev, DPAA2_ETH_RX_DIST_HASH, key);
++}
++
++int dpaa2_eth_set_cls(struct net_device *net_dev, u64 flags)
++{
++      return dpaa2_eth_set_dist_key(net_dev, DPAA2_ETH_RX_DIST_CLS, flags);
++}
++
++static int dpaa2_eth_set_default_cls(struct dpaa2_eth_priv *priv)
++{
++      struct device *dev = priv->net_dev->dev.parent;
++      int err;
++
++      /* Check if we actually support Rx flow classification */
++      if (dpaa2_eth_has_legacy_dist(priv)) {
++              dev_dbg(dev, "Rx cls not supported by current MC version\n");
++              return -EOPNOTSUPP;
++      }
++
++      if (!dpaa2_eth_fs_enabled(priv)) {
++              dev_dbg(dev, "Rx cls disabled in DPNI options\n");
++              return -EOPNOTSUPP;
++      }
++
++      if (!dpaa2_eth_hash_enabled(priv)) {
++              dev_dbg(dev, "Rx cls disabled for single queue DPNIs\n");
++              return -EOPNOTSUPP;
++      }
++
++      /* If there is no support for masking in the classification table,
++       * we don't set a default key, as it will depend on the rules
++       * added by the user at runtime.
++       */
++      if (!dpaa2_eth_fs_mask_enabled(priv))
++              goto out;
++
++      err = dpaa2_eth_set_cls(priv->net_dev, DPAA2_ETH_DIST_ALL);
++      if (err)
++              return err;
++
++out:
++      priv->rx_cls_enabled = 1;
++
++      return 0;
++}
++
+ /* Bind the DPNI to its needed objects and resources: buffer pool, DPIOs,
+  * frame queues and channels
+  */
+@@ -2080,6 +3084,7 @@ static int bind_dpni(struct dpaa2_eth_pr
        pools_params.num_dpbp = 1;
        pools_params.pools[0].dpbp_id = priv->dpbp_dev->obj_desc.id;
        pools_params.pools[0].backup_pool = 0;
@@ -4413,36 +4626,28 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        pools_params.pools[0].buffer_size = DPAA2_ETH_RX_BUF_SIZE;
        err = dpni_set_pools(priv->mc_io, 0, priv->mc_token, &pools_params);
        if (err) {
-@@ -2087,17 +2991,36 @@ static int bind_dpni(struct dpaa2_eth_pr
+@@ -2087,17 +3092,28 @@ static int bind_dpni(struct dpaa2_eth_pr
                return err;
        }
  
 -      /* have the interface implicitly distribute traffic based on supported
 -       * header fields
-+      /* Verify classification options and disable hashing and/or
-+       * flow steering support in case of invalid configuration values
++      /* have the interface implicitly distribute traffic based on
++       * the default hash key
         */
 -      err = dpaa2_eth_set_hash(net_dev, DPAA2_RXH_SUPPORTED);
 -      if (err)
 -              netdev_err(net_dev, "Failed to configure hashing\n");
-+      priv->dist_fields = default_dist_fields;
-+      priv->num_dist_fields = ARRAY_SIZE(default_dist_fields);
-+      check_cls_support(priv);
++      err = dpaa2_eth_set_hash(net_dev, DPAA2_RXH_DEFAULT);
++      if (err && err != -EOPNOTSUPP)
++              dev_err(dev, "Failed to configure hashing\n");
 +
-+      /* have the interface implicitly distribute traffic based on
-+       * a static hash key. Also configure flow steering key, if supported.
-+       * Errors here are not blocking, so just let the called function
-+       * print its error message and move along.
++      /* Configure the flow classification key; it includes all
++       * supported header fields and cannot be modified at runtime
 +       */
-+      if (dpaa2_eth_has_legacy_dist(priv)) {
-+              dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_LEGACY,
-+                                     DPAA2_ETH_DIST_ALL);
-+      } else {
-+              dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_HASH,
-+                                     DPAA2_ETH_DIST_DEFAULT_HASH);
-+              dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_FS,
-+                                     DPAA2_ETH_DIST_ALL);
-+      }
++      err = dpaa2_eth_set_default_cls(priv);
++      if (err && err != -EOPNOTSUPP)
++              dev_err(dev, "Failed to configure Rx classification key\n");
  
        /* Configure handling of error frames */
        err_cfg.errors = DPAA2_FAS_RX_ERR_MASK;
@@ -4455,7 +4660,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        err = dpni_set_errors_behavior(priv->mc_io, 0, priv->mc_token,
                                       &err_cfg);
        if (err) {
-@@ -2114,6 +3037,11 @@ static int bind_dpni(struct dpaa2_eth_pr
+@@ -2114,6 +3130,11 @@ static int bind_dpni(struct dpaa2_eth_pr
                case DPAA2_TX_CONF_FQ:
                        err = setup_tx_flow(priv, &priv->fq[i]);
                        break;
@@ -4467,7 +4672,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                default:
                        dev_err(dev, "Invalid FQ type %d\n", priv->fq[i].type);
                        return -EINVAL;
-@@ -2237,11 +3165,14 @@ static int netdev_init(struct net_device
+@@ -2237,11 +3258,14 @@ static int netdev_init(struct net_device
  {
        struct device *dev = net_dev->dev.parent;
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
@@ -4482,7 +4687,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        err = set_mac_addr(priv);
        if (err)
-@@ -2255,14 +3186,14 @@ static int netdev_init(struct net_device
+@@ -2255,14 +3279,14 @@ static int netdev_init(struct net_device
                return err;
        }
  
@@ -4493,10 +4698,10 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -
 -      /* Set MTU limits */
 -      net_dev->min_mtu = 68;
-+      /* Set MTU upper limit; lower limit is default (68B) */
++      /* Set MTU upper limit; lower limit is 68B (default value) */
        net_dev->max_mtu = DPAA2_ETH_MAX_MTU;
 +      err = dpni_set_max_frame_length(priv->mc_io, 0, priv->mc_token,
-+                                      (u16)DPAA2_ETH_MFL);
++                                      DPAA2_ETH_MFL);
 +      if (err) {
 +              dev_err(dev, "dpni_set_max_frame_length() failed\n");
 +              return err;
@@ -4504,7 +4709,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* Set actual number of queues in the net device */
        num_queues = dpaa2_eth_queue_count(priv);
-@@ -2277,12 +3208,23 @@ static int netdev_init(struct net_device
+@@ -2277,12 +3301,23 @@ static int netdev_init(struct net_device
                return err;
        }
  
@@ -4534,7 +4739,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        return 0;
  }
-@@ -2303,14 +3245,9 @@ static int poll_link_state(void *arg)
+@@ -2303,14 +3338,9 @@ static int poll_link_state(void *arg)
        return 0;
  }
  
@@ -4550,7 +4755,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct device *dev = (struct device *)arg;
        struct fsl_mc_device *dpni_dev = to_fsl_mc_device(dev);
        struct net_device *net_dev = dev_get_drvdata(dev);
-@@ -2320,18 +3257,12 @@ static irqreturn_t dpni_irq0_handler_thr
+@@ -2320,18 +3350,12 @@ static irqreturn_t dpni_irq0_handler_thr
                                  DPNI_IRQ_INDEX, &status);
        if (unlikely(err)) {
                netdev_err(net_dev, "Can't get irq status (err %d)\n", err);
@@ -4571,7 +4776,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        return IRQ_HANDLED;
  }
  
-@@ -2348,8 +3279,7 @@ static int setup_irqs(struct fsl_mc_devi
+@@ -2348,8 +3372,7 @@ static int setup_irqs(struct fsl_mc_devi
  
        irq = ls_dev->irqs[0];
        err = devm_request_threaded_irq(&ls_dev->dev, irq->msi_desc->irq,
@@ -4581,7 +4786,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                                        IRQF_NO_SUSPEND | IRQF_ONESHOT,
                                        dev_name(&ls_dev->dev), &ls_dev->dev);
        if (err < 0) {
-@@ -2405,6 +3335,393 @@ static void del_ch_napi(struct dpaa2_eth
+@@ -2405,6 +3428,393 @@ static void del_ch_napi(struct dpaa2_eth
        }
  }
  
@@ -4975,7 +5180,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
  {
        struct device *dev;
-@@ -2415,7 +3732,7 @@ static int dpaa2_eth_probe(struct fsl_mc
+@@ -2415,7 +3825,7 @@ static int dpaa2_eth_probe(struct fsl_mc
        dev = &dpni_dev->dev;
  
        /* Net device */
@@ -4984,7 +5189,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        if (!net_dev) {
                dev_err(dev, "alloc_etherdev_mq() failed\n");
                return -ENOMEM;
-@@ -2433,7 +3750,10 @@ static int dpaa2_eth_probe(struct fsl_mc
+@@ -2433,7 +3843,10 @@ static int dpaa2_eth_probe(struct fsl_mc
        err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
                                     &priv->mc_io);
        if (err) {
@@ -4996,7 +5201,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                goto err_portal_alloc;
        }
  
-@@ -2456,9 +3776,6 @@ static int dpaa2_eth_probe(struct fsl_mc
+@@ -2456,9 +3869,6 @@ static int dpaa2_eth_probe(struct fsl_mc
        if (err)
                goto err_bind;
  
@@ -5006,7 +5211,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        /* Percpu statistics */
        priv->percpu_stats = alloc_percpu(*priv->percpu_stats);
        if (!priv->percpu_stats) {
-@@ -2491,7 +3808,14 @@ static int dpaa2_eth_probe(struct fsl_mc
+@@ -2491,7 +3901,14 @@ static int dpaa2_eth_probe(struct fsl_mc
        if (err)
                goto err_alloc_rings;
  
@@ -5022,7 +5227,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        err = setup_irqs(dpni_dev);
        if (err) {
-@@ -2499,25 +3823,41 @@ static int dpaa2_eth_probe(struct fsl_mc
+@@ -2499,25 +3916,41 @@ static int dpaa2_eth_probe(struct fsl_mc
                priv->poll_thread = kthread_run(poll_link_state, priv,
                                                "%s_poll_link", net_dev->name);
                if (IS_ERR(priv->poll_thread)) {
@@ -5066,7 +5271,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        del_ch_napi(priv);
  err_bind:
        free_dpbp(priv);
-@@ -2544,8 +3884,15 @@ static int dpaa2_eth_remove(struct fsl_m
+@@ -2544,8 +3977,15 @@ static int dpaa2_eth_remove(struct fsl_m
        net_dev = dev_get_drvdata(dev);
        priv = netdev_priv(net_dev);
  
@@ -5083,7 +5288,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        if (priv->do_link_poll)
                kthread_stop(priv->poll_thread);
-@@ -2555,8 +3902,6 @@ static int dpaa2_eth_remove(struct fsl_m
+@@ -2555,17 +3995,16 @@ static int dpaa2_eth_remove(struct fsl_m
        free_rings(priv);
        free_percpu(priv->percpu_stats);
        free_percpu(priv->percpu_extras);
@@ -5092,8 +5297,10 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        free_dpbp(priv);
        free_dpio(priv);
        free_dpni(priv);
-@@ -2566,6 +3911,8 @@ static int dpaa2_eth_remove(struct fsl_m
-       dev_set_drvdata(dev, NULL);
+       fsl_mc_portal_free(priv->mc_io);
+-      dev_set_drvdata(dev, NULL);
        free_netdev(net_dev);
  
 +      dev_dbg(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
@@ -5101,7 +5308,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        return 0;
  }
  
-@@ -2588,4 +3935,34 @@ static struct fsl_mc_driver dpaa2_eth_dr
+@@ -2588,4 +4027,34 @@ static struct fsl_mc_driver dpaa2_eth_dr
        .match_id_table = dpaa2_eth_match_id_table
  };
  
@@ -5139,15 +5346,51 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +module_exit(dpaa2_eth_driver_exit);
 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
-@@ -33,6 +33,7 @@
+@@ -1,40 +1,15 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+ /* Copyright 2014-2016 Freescale Semiconductor Inc.
+  * Copyright 2016 NXP
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- *     * Redistributions of source code must retain the above copyright
+- *     notice, this list of conditions and the following disclaimer.
+- *     * Redistributions in binary form must reproduce the above copyright
+- *     notice, this list of conditions and the following disclaimer in the
+- *     documentation and/or other materials provided with the distribution.
+- *     * Neither the name of Freescale Semiconductor nor the
+- *     names of its contributors may be used to endorse or promote products
+- *     derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+  */
  #ifndef __DPAA2_ETH_H
  #define __DPAA2_ETH_H
  
 +#include <linux/dcbnl.h>
  #include <linux/netdevice.h>
  #include <linux/if_vlan.h>
++#include <linux/filter.h>
  
-@@ -44,9 +45,17 @@
+ #include "../../fsl-mc/include/dpaa2-io.h"
+ #include "../../fsl-mc/include/dpaa2-fd.h"
+@@ -44,6 +19,9 @@
  #include "dpni-cmd.h"
  
  #include "dpaa2-eth-trace.h"
@@ -5157,59 +5400,61 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  #define DPAA2_ETH_STORE_SIZE          16
  
-+/* We set a max threshold for how many Tx confirmations we should process
-+ * on a NAPI poll call, they take less processing time.
-+ */
-+#define TX_CONF_PER_NAPI_POLL         256
-+
- /* Maximum number of scatter-gather entries in an ingress frame,
-  * considering the maximum receive frame size is 64K
-  */
-@@ -60,6 +69,14 @@
+@@ -60,43 +38,59 @@
  /* Convert L3 MTU to L2 MFL */
  #define DPAA2_ETH_L2_MAX_FRM(mtu)     ((mtu) + VLAN_ETH_HLEN)
  
+-/* Set the taildrop threshold (in bytes) to allow the enqueue of several jumbo
+- * frames in the Rx queues (length of the current frame is not
+- * taken into account when making the taildrop decision)
+- */
+-#define DPAA2_ETH_TAILDROP_THRESH     (64 * 1024)
+-
+-/* Buffer quota per queue. Must be large enough such that for minimum sized
+- * frames taildrop kicks in before the bpool gets depleted, so we compute
+- * how many 64B frames fit inside the taildrop threshold and add a margin
+- * to accommodate the buffer refill delay.
+- */
+-#define DPAA2_ETH_MAX_FRAMES_PER_QUEUE        (DPAA2_ETH_TAILDROP_THRESH / 64)
+-#define DPAA2_ETH_NUM_BUFS            (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
+-#define DPAA2_ETH_REFILL_THRESH               DPAA2_ETH_MAX_FRAMES_PER_QUEUE
 +/* Maximum burst size value for Tx shaping */
 +#define DPAA2_ETH_MAX_BURST_SIZE      0xF7FF
+ /* Maximum number of buffers that can be acquired/released through a single
+  * QBMan command
+  */
+ #define DPAA2_ETH_BUFS_PER_CMD                7
+-/* Hardware requires alignment for ingress/egress buffer addresses
+- * and ingress buffer lengths.
++/* Set the taildrop threshold to 1MB to allow the enqueue of a sufficiently
++ * large number of jumbo frames in the Rx queues (length of the current frame
++ * is not taken into account when making the taildrop decision)
++ */
++#define DPAA2_ETH_TAILDROP_THRESH     (1024 * 1024)
 +
-+/* Maximum number of buffers that can be acquired/released through a single
-+ * QBMan command
++/* Maximum number of Tx confirmation frames to be processed
++ * in a single NAPI call
 + */
-+#define DPAA2_ETH_BUFS_PER_CMD                7
++#define DPAA2_ETH_TXCONF_PER_NAPI     256
 +
- /* Set the taildrop threshold (in bytes) to allow the enqueue of several jumbo
-  * frames in the Rx queues (length of the current frame is not
-  * taken into account when making the taildrop decision)
-@@ -72,31 +89,32 @@
-  * to accommodate the buffer refill delay.
++/* Buffer quota per channel.
++ * We want to keep in check number of ingress frames in flight: for small
++ * sized frames, buffer pool depletion will kick in first; for large sizes,
++ * Rx FQ taildrop threshold will ensure only a reasonable number of frames
++ * will be pending at any given time.
   */
- #define DPAA2_ETH_MAX_FRAMES_PER_QUEUE        (DPAA2_ETH_TAILDROP_THRESH / 64)
--#define DPAA2_ETH_NUM_BUFS            (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
--#define DPAA2_ETH_REFILL_THRESH               DPAA2_ETH_MAX_FRAMES_PER_QUEUE
-+#define DPAA2_ETH_NUM_BUFS_PER_CH     (DPAA2_ETH_MAX_FRAMES_PER_QUEUE + 256)
+-#define DPAA2_ETH_RX_BUF_SIZE         2048
++#define DPAA2_ETH_NUM_BUFS_PER_CH     1024
 +#define DPAA2_ETH_REFILL_THRESH(priv) \
 +      ((priv)->max_bufs_per_ch - DPAA2_ETH_BUFS_PER_CMD)
--/* Maximum number of buffers that can be acquired/released through a single
-- * QBMan command
-- */
--#define DPAA2_ETH_BUFS_PER_CMD                7
++
 +/* Global buffer quota in case flow control is enabled */
 +#define DPAA2_ETH_NUM_BUFS_FC         256
 +
 +/* Hardware requires alignment for ingress/egress buffer addresses */
-+#define DPAA2_ETH_TX_BUF_ALIGN                64
--/* Hardware requires alignment for ingress/egress buffer addresses
-- * and ingress buffer lengths.
-+/* Due to a limitation in WRIOP 1.0.0, the RX buffer data must be aligned
-+ * to 256B. For newer revisions, the requirement is only for 64B alignment
-  */
-+#define DPAA2_ETH_RX_BUF_ALIGN_REV1   256
-+#define DPAA2_ETH_RX_BUF_ALIGN                64
-+
- #define DPAA2_ETH_RX_BUF_SIZE         2048
--#define DPAA2_ETH_TX_BUF_ALIGN                64
+ #define DPAA2_ETH_TX_BUF_ALIGN                64
 -#define DPAA2_ETH_RX_BUF_ALIGN                256
 -#define DPAA2_ETH_NEEDED_HEADROOM(p_priv) \
 -      ((p_priv)->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN)
@@ -5222,19 +5467,29 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 -      (DPAA2_ETH_RX_BUF_SIZE + \
 -      SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + \
 -      DPAA2_ETH_RX_BUF_ALIGN)
-+#define DPAA2_ETH_SKB_SIZE \
-+      (DPAA2_ETH_RX_BUF_SIZE + SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
 +
-+/* PTP nominal frequency 1GHz */
-+#define DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS 1
++#define DPAA2_ETH_RX_BUF_RAW_SIZE     PAGE_SIZE
++#define DPAA2_ETH_RX_BUF_TAILROOM \
++      SKB_DATA_ALIGN(sizeof(struct skb_shared_info))
++#define DPAA2_ETH_RX_BUF_SIZE \
++      (DPAA2_ETH_RX_BUF_RAW_SIZE - DPAA2_ETH_RX_BUF_TAILROOM)
 +
 +/* Hardware annotation area in RX/TX buffers */
 +#define DPAA2_ETH_RX_HWA_SIZE         64
 +#define DPAA2_ETH_TX_HWA_SIZE         128
++
++/* PTP nominal frequency 1GHz */
++#define DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS 1
++
++/* Due to a limitation in WRIOP 1.0.0, the RX buffer data must be aligned
++ * to 256B. For newer revisions, the requirement is only for 64B alignment
++ */
++#define DPAA2_ETH_RX_BUF_ALIGN_REV1   256
++#define DPAA2_ETH_RX_BUF_ALIGN                64
  
  /* We are accommodating a skb backpointer and some S/G info
   * in the frame's software annotation. The hardware
-@@ -104,12 +122,32 @@
+@@ -104,12 +98,32 @@
   */
  #define DPAA2_ETH_SWA_SIZE            64
  
@@ -5271,11 +5526,10 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  };
  
  /* Annotation valid bits in FD FRC */
-@@ -120,23 +158,14 @@ struct dpaa2_eth_swa {
- #define DPAA2_FD_FRC_FASWOV           0x0800
+@@ -121,22 +135,14 @@ struct dpaa2_eth_swa {
  #define DPAA2_FD_FRC_FAICFDV          0x0400
  
--/* Error bits in FD CTRL */
+ /* Error bits in FD CTRL */
 -#define DPAA2_FD_CTRL_UFD             0x00000004
 -#define DPAA2_FD_CTRL_SBE             0x00000008
 -#define DPAA2_FD_CTRL_FSE             0x00000020
@@ -5294,13 +5548,14 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                                       FD_CTRL_FAERR)
  
  /* Annotation bits in FD CTRL */
- #define DPAA2_FD_CTRL_ASAL            0x00020000      /* ASAL = 128 */
+-#define DPAA2_FD_CTRL_ASAL            0x00020000      /* ASAL = 128 */
 -#define DPAA2_FD_CTRL_PTA             0x00800000
 -#define DPAA2_FD_CTRL_PTV1            0x00400000
++#define DPAA2_FD_CTRL_ASAL            0x00020000      /* ASAL = 128B */
  
  /* Frame annotation status */
  struct dpaa2_fas {
-@@ -144,7 +173,7 @@ struct dpaa2_fas {
+@@ -144,7 +150,7 @@ struct dpaa2_fas {
        u8 ppid;
        __le16 ifpid;
        __le32 status;
@@ -5309,7 +5564,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  /* Frame annotation status word is located in the first 8 bytes
   * of the buffer's hardware annoatation area
-@@ -152,11 +181,45 @@ struct dpaa2_fas {
+@@ -152,11 +158,45 @@ struct dpaa2_fas {
  #define DPAA2_FAS_OFFSET              0
  #define DPAA2_FAS_SIZE                        (sizeof(struct dpaa2_fas))
  
@@ -5347,7 +5602,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      return dpaa2_get_hwa(buf_addr, swa) + DPAA2_FAS_OFFSET;
 +}
 +
-+static inline u64 *dpaa2_get_ts(void *buf_addr, bool swa)
++static inline __le64 *dpaa2_get_ts(void *buf_addr, bool swa)
 +{
 +      return dpaa2_get_hwa(buf_addr, swa) + DPAA2_TS_OFFSET;
 +}
@@ -5359,7 +5614,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  /* Error and status bits in the frame annotation status word */
  /* Debug frame, otherwise supposed to be discarded */
-@@ -203,11 +266,6 @@ struct dpaa2_fas {
+@@ -203,11 +243,6 @@ struct dpaa2_fas {
                                         DPAA2_FAS_BLE          | \
                                         DPAA2_FAS_L3CE         | \
                                         DPAA2_FAS_L4CE)
@@ -5371,22 +5626,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  /* Time in milliseconds between link state updates */
  #define DPAA2_ETH_LINK_STATE_REFRESH  1000
-@@ -218,6 +276,14 @@ struct dpaa2_fas {
-  */
- #define DPAA2_ETH_ENQUEUE_RETRIES     10
-+/* Tx congestion entry & exit thresholds, in number of bytes.
-+ * We allow a maximum of 512KB worth of frames pending processing on the Tx
-+ * queues of an interface
-+ */
-+#define DPAA2_ETH_TX_CONG_ENTRY_THRESH  (512 * 1024)
-+#define DPAA2_ETH_TX_CONG_EXIT_THRESH \
-+      (DPAA2_ETH_TX_CONG_ENTRY_THRESH * 9 / 10)
-+
- /* Driver statistics, other than those in struct rtnl_link_stats64.
-  * These are usually collected per-CPU and aggregated by ethtool.
-  */
-@@ -226,6 +292,7 @@ struct dpaa2_eth_drv_stats {
+@@ -226,6 +261,7 @@ struct dpaa2_eth_drv_stats {
        __u64   tx_conf_bytes;
        __u64   tx_sg_frames;
        __u64   tx_sg_bytes;
@@ -5394,16 +5634,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        __u64   rx_sg_frames;
        __u64   rx_sg_bytes;
        /* Enqueues retried due to portal busy */
-@@ -236,6 +303,8 @@ struct dpaa2_eth_drv_stats {
- struct dpaa2_eth_fq_stats {
-       /* Number of frames received on this queue */
-       __u64 frames;
-+      /* Number of times this queue entered congestion */
-+      __u64 congestion_entry;
- };
- /* Per-channel statistics */
-@@ -250,17 +319,23 @@ struct dpaa2_eth_ch_stats {
+@@ -250,17 +286,23 @@ struct dpaa2_eth_ch_stats {
        __u64 pull_err;
  };
  
@@ -5431,25 +5662,31 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  };
  
  struct dpaa2_eth_priv;
-@@ -269,6 +344,7 @@ struct dpaa2_eth_fq {
+@@ -268,15 +310,19 @@ struct dpaa2_eth_priv;
+ struct dpaa2_eth_fq {
        u32 fqid;
        u32 tx_qdbin;
++      u32 tx_fqid;
        u16 flowid;
 +      u8 tc;
        int target_cpu;
++      u32 dq_frames;
++      u32 dq_bytes;
        struct dpaa2_eth_channel *channel;
        enum dpaa2_eth_fq_type type;
-@@ -276,7 +352,8 @@ struct dpaa2_eth_fq {
-       void (*consume)(struct dpaa2_eth_priv *,
-                       struct dpaa2_eth_channel *,
-                       const struct dpaa2_fd *,
+-      void (*consume)(struct dpaa2_eth_priv *,
+-                      struct dpaa2_eth_channel *,
+-                      const struct dpaa2_fd *,
 -                      struct napi_struct *);
-+                      struct napi_struct *,
-+                      u16 queue_id);
++      void (*consume)(struct dpaa2_eth_priv *priv,
++                      struct dpaa2_eth_channel *ch,
++                      const struct dpaa2_fd *fd,
++                      struct dpaa2_eth_fq *fq);
        struct dpaa2_eth_fq_stats stats;
  };
  
-@@ -285,24 +362,53 @@ struct dpaa2_eth_channel {
+@@ -285,19 +331,29 @@ struct dpaa2_eth_channel {
        struct fsl_mc_device *dpcon;
        int dpcon_id;
        int ch_id;
@@ -5464,11 +5701,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      u64 rel_buf_array[DPAA2_ETH_BUFS_PER_CMD];
 +      u8 rel_buf_cnt;
 +      bool flush;
-+};
-+
-+struct dpaa2_eth_cls_rule {
-+      struct ethtool_rx_flow_spec fs;
-+      bool in_use;
  };
  
 -struct dpaa2_eth_hash_fields {
@@ -5476,77 +5708,56 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        u64 rxnfc_field;
        enum net_prot cls_prot;
        int cls_field;
-+      int offset;
        int size;
-+      u32 id;
++      u64 id;
++};
++
++struct dpaa2_eth_cls_rule {
++      struct ethtool_rx_flow_spec fs;
++      u8 in_use;
  };
  
  /* Driver private data */
- struct dpaa2_eth_priv {
-       struct net_device *net_dev;
-+      /* Standard statistics */
-+      struct rtnl_link_stats64 __percpu *percpu_stats;
-+      /* Extra stats, in addition to the ones known by the kernel */
-+      struct dpaa2_eth_drv_stats __percpu *percpu_extras;
-+      bool ts_tx_en; /* Tx timestamping enabled */
-+      bool ts_rx_en; /* Rx timestamping enabled */
-+      u16 tx_data_offset;
-+      u16 bpid;
-+      u16 tx_qdid;
-+      u16 rx_buf_align;
-+      struct iommu_domain *iommu_domain;
-+      int max_bufs_per_ch;
-+      int refill_thresh;
-+      bool has_xdp_prog;
-+
-+      void *cscn_mem; /* Tx congestion notifications are written here */
-+      void *cscn_unaligned;
-+      dma_addr_t cscn_dma;
+@@ -306,17 +362,29 @@ struct dpaa2_eth_priv {
  
        u8 num_fqs;
        struct dpaa2_eth_fq fq[DPAA2_ETH_MAX_QUEUES];
-@@ -311,51 +417,193 @@ struct dpaa2_eth_priv {
++      int (*enqueue)(struct dpaa2_eth_priv *priv,
++                     struct dpaa2_eth_fq *fq,
++                     struct dpaa2_fd *fd, u8 prio);
+       u8 num_channels;
        struct dpaa2_eth_channel *channel[DPAA2_ETH_MAX_DPCONS];
++      int max_bufs_per_ch;
++      int refill_thresh;
++
++      bool has_xdp_prog;
  
        struct dpni_attr dpni_attrs;
--      u16 tx_data_offset;
--
 +      u16 dpni_ver_major;
 +      u16 dpni_ver_minor;
+       u16 tx_data_offset;
        struct fsl_mc_device *dpbp_dev;
--      u16 bpid;
--      struct iommu_domain *iommu_domain;
+       u16 bpid;
+       struct iommu_domain *iommu_domain;
  
--      u16 tx_qdid;
++      bool ts_tx_en; /* Tx timestamping enabled */
++      bool ts_rx_en; /* Rx timestamping enabled */
++
+       u16 tx_qdid;
        struct fsl_mc_io *mc_io;
        /* Cores which have an affine DPIO/DPCON.
-        * This is the cpu set on which Rx and Tx conf frames are processed
-        */
-       struct cpumask dpio_cpumask;
--      /* Standard statistics */
--      struct rtnl_link_stats64 __percpu *percpu_stats;
--      /* Extra stats, in addition to the ones known by the kernel */
--      struct dpaa2_eth_drv_stats __percpu *percpu_extras;
--
-       u16 mc_token;
-       struct dpni_link_state link_state;
-       bool do_link_poll;
-       struct task_struct *poll_thread;
+@@ -337,13 +405,30 @@ struct dpaa2_eth_priv {
  
-+      /* Rx distribution (hash and flow steering) header fields
-+       * supported by the driver
-+       */
-+      struct dpaa2_eth_dist_fields *dist_fields;
-+      u8 num_dist_fields;
        /* enabled ethtool hashing bits */
        u64 rx_hash_fields;
++      u64 rx_cls_fields;
++      struct dpaa2_eth_cls_rule *cls_rule;
++      u8 rx_cls_enabled;
 +#ifdef CONFIG_FSL_DPAA2_ETH_DEBUGFS
 +      struct dpaa2_debugfs dbg;
 +#endif
-+      /* array of classification rules */
-+      struct dpaa2_eth_cls_rule *cls_rule;
 +      struct dpni_tx_shaping_cfg shaping_cfg;
 +
 +      u8 dcbx_mode;
@@ -5555,55 +5766,26 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      bool tx_pause_frames;
 +
 +      bool ceetm_en;
-+};
-+
-+enum dpaa2_eth_rx_dist {
-+      DPAA2_ETH_RX_DIST_HASH,
-+      DPAA2_ETH_RX_DIST_FS,
-+      DPAA2_ETH_RX_DIST_LEGACY
  };
  
 -/* default Rx hash options, set during probing */
--#define DPAA2_RXH_SUPPORTED   (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO \
--                              | RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 \
--                              | RXH_L4_B_2_3)
-+/* Supported Rx distribution field ids */
-+#define DPAA2_ETH_DIST_ETHSRC         BIT(0)
-+#define DPAA2_ETH_DIST_ETHDST         BIT(1)
-+#define DPAA2_ETH_DIST_ETHTYPE                BIT(2)
-+#define DPAA2_ETH_DIST_VLAN           BIT(3)
-+#define DPAA2_ETH_DIST_IPSRC          BIT(4)
-+#define DPAA2_ETH_DIST_IPDST          BIT(5)
-+#define DPAA2_ETH_DIST_IPPROTO                BIT(6)
-+#define DPAA2_ETH_DIST_L4SRC          BIT(7)
-+#define DPAA2_ETH_DIST_L4DST          BIT(8)
-+#define DPAA2_ETH_DIST_ALL            (~0U)
-+
-+/* Default Rx hash key */
-+#define DPAA2_ETH_DIST_DEFAULT_HASH \
-+      (DPAA2_ETH_DIST_IPPROTO | \
-+       DPAA2_ETH_DIST_IPSRC | DPAA2_ETH_DIST_IPDST | \
-+       DPAA2_ETH_DIST_L4SRC | DPAA2_ETH_DIST_L4DST)
+ #define DPAA2_RXH_SUPPORTED   (RXH_L2DA | RXH_VLAN | RXH_L3_PROTO \
+                               | RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 \
+                               | RXH_L4_B_2_3)
  
++/* default Rx hash options, set during probing */
++#define DPAA2_RXH_DEFAULT     (RXH_L3_PROTO | RXH_IP_SRC | RXH_IP_DST | \
++                               RXH_L4_B_0_1 | RXH_L4_B_2_3)
++
  #define dpaa2_eth_hash_enabled(priv)  \
        ((priv)->dpni_attrs.num_queues > 1)
  
-+#define dpaa2_eth_fs_enabled(priv)    \
-+      (!((priv)->dpni_attrs.options & DPNI_OPT_NO_FS))
-+
-+#define dpaa2_eth_fs_mask_enabled(priv)       \
-+      ((priv)->dpni_attrs.options & DPNI_OPT_HAS_KEY_MASKING)
-+
-+#define dpaa2_eth_fs_count(priv)      \
-+      ((priv)->dpni_attrs.fs_entries)
-+
- /* Required by struct dpni_rx_tc_dist_cfg::key_cfg_iova */
- #define DPAA2_CLASSIFIER_DMA_SIZE 256
+@@ -352,10 +437,127 @@ struct dpaa2_eth_priv {
  
  extern const struct ethtool_ops dpaa2_ethtool_ops;
  extern const char dpaa2_eth_drv_version[];
--static int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
++extern int dpaa2_phc_index;
++
 +static inline int dpaa2_eth_cmp_dpni_ver(struct dpaa2_eth_priv *priv,
 +                                       u16 ver_major, u16 ver_minor)
 +{
@@ -5612,27 +5794,51 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      return priv->dpni_ver_major - ver_major;
 +}
 +
-+#define DPNI_DIST_KEY_VER_MAJOR                       7
-+#define DPNI_DIST_KEY_VER_MINOR                       5
++/* Minimum firmware version that supports a more flexible API
++ * for configuring the Rx flow hash key
++ */
++#define DPNI_RX_DIST_KEY_VER_MAJOR    7
++#define DPNI_RX_DIST_KEY_VER_MINOR    5
 +
-+static inline bool dpaa2_eth_has_legacy_dist(struct dpaa2_eth_priv *priv)
-+{
-+      return (dpaa2_eth_cmp_dpni_ver(priv, DPNI_DIST_KEY_VER_MAJOR,
-+                                     DPNI_DIST_KEY_VER_MINOR) < 0);
-+}
++#define dpaa2_eth_has_legacy_dist(priv)                                       \
++      (dpaa2_eth_cmp_dpni_ver((priv), DPNI_RX_DIST_KEY_VER_MAJOR,     \
++                              DPNI_RX_DIST_KEY_VER_MINOR) < 0)
 +
-+/* Hardware only sees DPAA2_ETH_RX_BUF_SIZE, but the skb built around
-+ * the buffer also needs space for its shared info struct, and we need
-+ * to allocate enough to accommodate hardware alignment restrictions
-+ */
-+static inline unsigned int dpaa2_eth_buf_raw_size(struct dpaa2_eth_priv *priv)
-+{
-+      return DPAA2_ETH_SKB_SIZE + priv->rx_buf_align;
-+}
++#define dpaa2_eth_fs_enabled(priv)    \
++      (!((priv)->dpni_attrs.options & DPNI_OPT_NO_FS))
++
++#define dpaa2_eth_fs_mask_enabled(priv)       \
++      ((priv)->dpni_attrs.options & DPNI_OPT_HAS_KEY_MASKING)
++
++#define dpaa2_eth_fs_count(priv)      \
++      ((priv)->dpni_attrs.fs_entries)
++
++#define dpaa2_eth_queue_count(priv)   \
++      ((priv)->num_channels)
 +
-+/* Total headroom needed by the hardware in Tx frame buffers */
-+static inline unsigned int
-+dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv, struct sk_buff *skb)
++#define dpaa2_eth_tc_count(priv)      \
++      ((priv)->dpni_attrs.num_tcs)
++
++enum dpaa2_eth_rx_dist {
++      DPAA2_ETH_RX_DIST_HASH,
++      DPAA2_ETH_RX_DIST_CLS
++};
++
++/* Unique IDs for the supported Rx classification header fields */
++#define DPAA2_ETH_DIST_ETHDST         BIT(0)
++#define DPAA2_ETH_DIST_ETHSRC         BIT(1)
++#define DPAA2_ETH_DIST_ETHTYPE                BIT(2)
++#define DPAA2_ETH_DIST_VLAN           BIT(3)
++#define DPAA2_ETH_DIST_IPSRC          BIT(4)
++#define DPAA2_ETH_DIST_IPDST          BIT(5)
++#define DPAA2_ETH_DIST_IPPROTO                BIT(6)
++#define DPAA2_ETH_DIST_L4SRC          BIT(7)
++#define DPAA2_ETH_DIST_L4DST          BIT(8)
++#define DPAA2_ETH_DIST_ALL            (~0U)
++
++static inline
++unsigned int dpaa2_eth_needed_headroom(struct dpaa2_eth_priv *priv,
++                                     struct sk_buff *skb)
 +{
 +      unsigned int headroom = DPAA2_ETH_SWA_SIZE;
 +
@@ -5641,7 +5847,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +       */
 +      if (!skb)
 +              return headroom;
-+
+-static int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
 +      /* For non-linear skbs we have no headroom requirement, as we build a
 +       * SG frame with a newly allocated SGT buffer
 +       */
@@ -5656,24 +5863,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +}
 +
 +/* Extra headroom space requested to hardware, in order to make sure there's
-+ * no realloc'ing in forwarding scenarios. We need to reserve enough space
-+ * such that we can accommodate the maximum required Tx offset and alignment
-+ * in the ingress frame buffer
++ * no realloc'ing in forwarding scenarios
 + */
 +static inline unsigned int dpaa2_eth_rx_headroom(struct dpaa2_eth_priv *priv)
 +{
-+      return priv->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN -
-+             DPAA2_ETH_RX_HWA_SIZE;
-+}
-+
-+static inline int dpaa2_eth_queue_count(struct dpaa2_eth_priv *priv)
- {
-       return priv->dpni_attrs.num_queues;
- }
-+static inline int dpaa2_eth_tc_count(struct dpaa2_eth_priv *priv)
-+{
-+      return priv->dpni_attrs.num_tcs;
++      return priv->tx_data_offset - DPAA2_ETH_RX_HWA_SIZE;
 +}
 +
 +static inline bool dpaa2_eth_is_pfc_enabled(struct dpaa2_eth_priv *priv,
@@ -5702,28 +5896,74 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +}
 +
 +static inline int dpaa2_eth_ch_count(struct dpaa2_eth_priv *priv)
-+{
+ {
+-      return priv->dpni_attrs.num_queues;
 +      return 1;
-+}
-+
-+void check_cls_support(struct dpaa2_eth_priv *priv);
+ }
++int dpaa2_eth_set_hash(struct net_device *net_dev, u64 flags);
++int dpaa2_eth_set_cls(struct net_device *net_dev, u64 key);
++int dpaa2_eth_cls_key_size(u64 key);
++int dpaa2_eth_cls_fld_off(int prot, int field);
++void dpaa2_eth_cls_trim_rule(void *key_mem, u64 fields);
 +
 +int set_rx_taildrop(struct dpaa2_eth_priv *priv);
-+
-+int dpaa2_eth_set_dist_key(struct dpaa2_eth_priv *priv,
-+                         enum dpaa2_eth_rx_dist type, u32 key_fields);
 +
  #endif        /* __DPAA2_H */
 --- a/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
-@@ -1,5 +1,5 @@
+@@ -1,35 +1,10 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
  /* Copyright 2014-2016 Freescale Semiconductor Inc.
 - * Copyright 2016 NXP
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- *     * Redistributions of source code must retain the above copyright
+- *     notice, this list of conditions and the following disclaimer.
+- *     * Redistributions in binary form must reproduce the above copyright
+- *     notice, this list of conditions and the following disclaimer in the
+- *     documentation and/or other materials provided with the distribution.
+- *     * Neither the name of Freescale Semiconductor nor the
+- *     names of its contributors may be used to endorse or promote products
+- *     derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+- * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 + * Copyright 2016-2017 NXP
-  *
-  * Redistribution and use in source and binary forms, with or without
-  * modification, are permitted provided that the following conditions are met:
-@@ -62,6 +62,7 @@ static char dpaa2_ethtool_extras[][ETH_G
+  */
++#include <linux/net_tstamp.h>
++
+ #include "dpni.h"     /* DPNI_LINK_OPT_* */
+ #include "dpaa2-eth.h"
+@@ -52,6 +27,10 @@ static char dpaa2_ethtool_stats[][ETH_GS
+       "[hw] rx nobuffer discards",
+       "[hw] tx discarded frames",
+       "[hw] tx confirmed frames",
++      "[hw] tx dequeued bytes",
++      "[hw] tx dequeued frames",
++      "[hw] tx rejected bytes",
++      "[hw] tx rejected frames",
+ };
+ #define DPAA2_ETH_NUM_STATS   ARRAY_SIZE(dpaa2_ethtool_stats)
+@@ -62,6 +41,7 @@ static char dpaa2_ethtool_extras[][ETH_G
        "[drv] tx conf bytes",
        "[drv] tx sg frames",
        "[drv] tx sg bytes",
@@ -5731,31 +5971,28 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        "[drv] rx sg frames",
        "[drv] rx sg bytes",
        "[drv] enqueue portal busy",
-@@ -69,6 +70,15 @@ static char dpaa2_ethtool_extras[][ETH_G
+@@ -69,6 +49,12 @@ static char dpaa2_ethtool_extras[][ETH_G
        "[drv] dequeue portal busy",
        "[drv] channel pull errors",
        "[drv] cdan",
-+      "[drv] tx congestion state",
-+#ifdef CONFIG_FSL_QBMAN_DEBUG
 +      /* FQ stats */
 +      "rx pending frames",
 +      "rx pending bytes",
 +      "tx conf pending frames",
 +      "tx conf pending bytes",
 +      "buffer count"
-+#endif
  };
  
  #define DPAA2_ETH_NUM_EXTRA_STATS     ARRAY_SIZE(dpaa2_ethtool_extras)
-@@ -76,10 +86,15 @@ static char dpaa2_ethtool_extras[][ETH_G
+@@ -76,14 +62,55 @@ static char dpaa2_ethtool_extras[][ETH_G
  static void dpaa2_eth_get_drvinfo(struct net_device *net_dev,
                                  struct ethtool_drvinfo *drvinfo)
  {
 +      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 +
        strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
-       strlcpy(drvinfo->version, dpaa2_eth_drv_version,
-               sizeof(drvinfo->version));
+-      strlcpy(drvinfo->version, dpaa2_eth_drv_version,
+-              sizeof(drvinfo->version));
 -      strlcpy(drvinfo->fw_version, "N/A", sizeof(drvinfo->fw_version));
 +
 +      snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
@@ -5764,7 +6001,86 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        strlcpy(drvinfo->bus_info, dev_name(net_dev->dev.parent->parent),
                sizeof(drvinfo->bus_info));
  }
-@@ -113,25 +128,37 @@ out:
++#define DPNI_LINK_AUTONEG_VER_MAJOR           7
++#define DPNI_LINK_AUTONEG_VER_MINOR           8
++
++struct dpaa2_eth_link_mode_map {
++      u64 dpni_lm;
++      u64 ethtool_lm;
++};
++
++static const struct dpaa2_eth_link_mode_map dpaa2_eth_lm_map[] = {
++      {DPNI_ADVERTISED_10BASET_FULL, ETHTOOL_LINK_MODE_10baseT_Full_BIT},
++      {DPNI_ADVERTISED_100BASET_FULL, ETHTOOL_LINK_MODE_100baseT_Full_BIT},
++      {DPNI_ADVERTISED_1000BASET_FULL, ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
++      {DPNI_ADVERTISED_10000BASET_FULL, ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
++      {DPNI_ADVERTISED_2500BASEX_FULL, ETHTOOL_LINK_MODE_2500baseX_Full_BIT},
++      {DPNI_ADVERTISED_AUTONEG, ETHTOOL_LINK_MODE_Autoneg_BIT},
++};
++
++static void link_mode_dpni2ethtool(u64 dpni_lm, unsigned long *ethtool_lm)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(dpaa2_eth_lm_map); i++) {
++              if (dpni_lm & dpaa2_eth_lm_map[i].dpni_lm)
++                      __set_bit(dpaa2_eth_lm_map[i].ethtool_lm, ethtool_lm);
++      }
++}
++
++static void link_mode_ethtool2dpni(const unsigned long *ethtool_lm,
++                                 u64 *dpni_lm)
++{
++      int i;
++
++      for (i = 0; i < ARRAY_SIZE(dpaa2_eth_lm_map); i++) {
++              if (test_bit(dpaa2_eth_lm_map[i].ethtool_lm, ethtool_lm))
++                      *dpni_lm |= dpaa2_eth_lm_map[i].dpni_lm;
++      }
++}
++
+ static int
+ dpaa2_eth_get_link_ksettings(struct net_device *net_dev,
+                            struct ethtool_link_ksettings *link_settings)
+@@ -92,17 +119,27 @@ dpaa2_eth_get_link_ksettings(struct net_
+       int err = 0;
+       struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
+-      err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
+-      if (err) {
+-              netdev_err(net_dev, "ERROR %d getting link state\n", err);
+-              goto out;
++      if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_LINK_AUTONEG_VER_MAJOR,
++                                 DPNI_LINK_AUTONEG_VER_MINOR) < 0) {
++              err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token,
++                                        &state);
++              if (err) {
++                      netdev_err(net_dev, "dpni_get_link_state failed\n");
++                      goto out;
++              }
++      } else {
++              err = dpni_get_link_state_v2(priv->mc_io, 0, priv->mc_token,
++                                           &state);
++              if (err) {
++                      netdev_err(net_dev, "dpni_get_link_state_v2 failed\n");
++                      goto out;
++              }
++              link_mode_dpni2ethtool(state.supported,
++                                     link_settings->link_modes.supported);
++              link_mode_dpni2ethtool(state.advertising,
++                                     link_settings->link_modes.advertising);
+       }
+-      /* At the moment, we have no way of interrogating the DPMAC
+-       * from the DPNI side - and for that matter there may exist
+-       * no DPMAC at all. So for now we just don't report anything
+-       * beyond the DPNI attributes.
+-       */
+       if (state.options & DPNI_LINK_OPT_AUTONEG)
+               link_settings->base.autoneg = AUTONEG_ENABLE;
+       if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX))
+@@ -113,25 +150,37 @@ out:
        return err;
  }
  
@@ -5811,10 +6127,21 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        cfg.rate = link_settings->base.speed;
        if (link_settings->base.autoneg == AUTONEG_ENABLE)
                cfg.options |= DPNI_LINK_OPT_AUTONEG;
-@@ -149,6 +176,81 @@ dpaa2_eth_set_link_ksettings(struct net_
-                */
-               netdev_dbg(net_dev, "ERROR %d setting link cfg\n", err);
+@@ -142,13 +191,92 @@ dpaa2_eth_set_link_ksettings(struct net_
+       else
+               cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX;
  
++      if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_LINK_AUTONEG_VER_MAJOR,
++                                 DPNI_LINK_AUTONEG_VER_MINOR)) {
++              err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
++      } else {
++              link_mode_ethtool2dpni(link_settings->link_modes.advertising,
++                                     &cfg.advertising);
++              dpni_set_link_cfg_v2(priv->mc_io, 0, priv->mc_token, &cfg);
++      }
++      if (err)
++              netdev_err(net_dev, "dpni_set_link_cfg failed");
++
 +out:
 +      return err;
 +}
@@ -5874,7 +6201,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      else
 +              cfg.options &= ~DPNI_LINK_OPT_ASYM_PAUSE;
 +
-+      err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
+       err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
 +      if (err) {
 +              netdev_dbg(net_dev, "Error setting link\n");
 +              goto out;
@@ -5886,44 +6213,55 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +
 +      priv->tx_pause_frames = pause->tx_pause;
 +      err = set_rx_taildrop(priv);
-+      if (err)
+       if (err)
+-              /* ethtool will be loud enough if we return an error; no point
+-               * in putting our own error message on the console by default
+-               */
+-              netdev_dbg(net_dev, "ERROR %d setting link cfg\n", err);
 +              netdev_dbg(net_dev, "Error configuring taildrop\n");
-+
 +out:
        return err;
  }
  
-@@ -192,6 +294,13 @@ static void dpaa2_eth_get_ethtool_stats(
+@@ -192,6 +320,10 @@ static void dpaa2_eth_get_ethtool_stats(
        int j, k, err;
        int num_cnt;
        union dpni_statistics dpni_stats;
-+
-+#ifdef CONFIG_FSL_QBMAN_DEBUG
 +      u32 fcnt, bcnt;
 +      u32 fcnt_rx_total = 0, fcnt_tx_total = 0;
 +      u32 bcnt_rx_total = 0, bcnt_tx_total = 0;
 +      u32 buf_cnt;
-+#endif
        u64 cdan = 0;
        u64 portal_busy = 0, pull_err = 0;
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-@@ -204,7 +313,7 @@ static void dpaa2_eth_get_ethtool_stats(
+@@ -202,9 +334,9 @@ static void dpaa2_eth_get_ethtool_stats(
+              sizeof(u64) * (DPAA2_ETH_NUM_STATS + DPAA2_ETH_NUM_EXTRA_STATS));
        /* Print standard counters, from DPNI statistics */
-       for (j = 0; j <= 2; j++) {
+-      for (j = 0; j <= 2; j++) {
++      for (j = 0; j <= 3; j++) {
                err = dpni_get_statistics(priv->mc_io, 0, priv->mc_token,
 -                                        j, &dpni_stats);
 +                                        j, 0, &dpni_stats);
                if (err != 0)
                        netdev_warn(net_dev, "dpni_get_stats(%d) failed\n", j);
                switch (j) {
-@@ -240,12 +349,474 @@ static void dpaa2_eth_get_ethtool_stats(
+@@ -217,6 +349,9 @@ static void dpaa2_eth_get_ethtool_stats(
+               case 2:
+                       num_cnt = sizeof(dpni_stats.page_2) / sizeof(u64);
+                       break;
++              case 3:
++                      num_cnt = sizeof(dpni_stats.page_3) / sizeof(u64);
++                      break;
+               }
+               for (k = 0; k < num_cnt; k++)
+                       *(data + i++) = dpni_stats.raw.counter[k];
+@@ -240,12 +375,410 @@ static void dpaa2_eth_get_ethtool_stats(
        *(data + i++) = portal_busy;
        *(data + i++) = pull_err;
        *(data + i++) = cdan;
 +
-+      *(data + i++) = dpaa2_cscn_state_congested(priv->cscn_mem);
-+
-+#ifdef CONFIG_FSL_QBMAN_DEBUG
 +      for (j = 0; j < priv->num_fqs; j++) {
 +              /* Print FQ instantaneous counts */
 +              err = dpaa2_io_query_fq_count(NULL, priv->fq[j].fqid,
@@ -5953,279 +6291,221 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +              return;
 +      }
 +      *(data + i++) = buf_cnt;
-+#endif
 +}
 +
-+static int cls_key_off(struct dpaa2_eth_priv *priv, int prot, int field)
++static int prep_eth_rule(struct ethhdr *eth_value, struct ethhdr *eth_mask,
++                       void *key, void *mask, u64 *fields)
 +{
-+      int i, off = 0;
++      int off;
 +
-+      for (i = 0; i < priv->num_dist_fields; i++) {
-+              if (priv->dist_fields[i].cls_prot == prot &&
-+                  priv->dist_fields[i].cls_field == field)
-+                      return off;
-+              off += priv->dist_fields[i].size;
++      if (eth_mask->h_proto) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
++              *(__be16 *)(key + off) = eth_value->h_proto;
++              *(__be16 *)(mask + off) = eth_mask->h_proto;
++              *fields |= DPAA2_ETH_DIST_ETHTYPE;
 +      }
 +
-+      return -1;
-+}
-+
-+static u8 cls_key_size(struct dpaa2_eth_priv *priv)
-+{
-+      u8 i, size = 0;
-+
-+      for (i = 0; i < priv->num_dist_fields; i++)
-+              size += priv->dist_fields[i].size;
-+
-+      return size;
-+}
-+
-+void check_cls_support(struct dpaa2_eth_priv *priv)
-+{
-+      u8 key_size = cls_key_size(priv);
-+      struct device *dev = priv->net_dev->dev.parent;
-+
-+      if (dpaa2_eth_hash_enabled(priv)) {
-+              if (priv->dpni_attrs.fs_key_size < key_size) {
-+                      dev_info(dev, "max_dist_key_size = %d, expected %d. Hashing and steering are disabled\n",
-+                               priv->dpni_attrs.fs_key_size,
-+                               key_size);
-+                      goto disable_fs;
-+              }
-+              if (priv->num_dist_fields > DPKG_MAX_NUM_OF_EXTRACTS) {
-+                      dev_info(dev, "Too many key fields (max = %d). Hashing and steering are disabled\n",
-+                               DPKG_MAX_NUM_OF_EXTRACTS);
-+                      goto disable_fs;
-+              }
++      if (!is_zero_ether_addr(eth_mask->h_source)) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_SA);
++              ether_addr_copy(key + off, eth_value->h_source);
++              ether_addr_copy(mask + off, eth_mask->h_source);
++              *fields |= DPAA2_ETH_DIST_ETHSRC;
 +      }
 +
-+      if (dpaa2_eth_fs_enabled(priv)) {
-+              if (!dpaa2_eth_hash_enabled(priv)) {
-+                      dev_info(dev, "Insufficient queues. Steering is disabled\n");
-+                      goto disable_fs;
-+              }
-+
-+              if (!dpaa2_eth_fs_mask_enabled(priv)) {
-+                      dev_info(dev, "Key masks not supported. Steering is disabled\n");
-+                      goto disable_fs;
-+              }
++      if (!is_zero_ether_addr(eth_mask->h_dest)) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_DA);
++              ether_addr_copy(key + off, eth_value->h_dest);
++              ether_addr_copy(mask + off, eth_mask->h_dest);
++              *fields |= DPAA2_ETH_DIST_ETHDST;
 +      }
 +
-+      return;
-+
-+disable_fs:
-+      priv->dpni_attrs.options |= DPNI_OPT_NO_FS;
-+      priv->dpni_attrs.options &= ~DPNI_OPT_HAS_KEY_MASKING;
++      return 0;
 +}
 +
-+static int prep_l4_rule(struct dpaa2_eth_priv *priv,
-+                      struct ethtool_tcpip4_spec *l4_value,
-+                      struct ethtool_tcpip4_spec *l4_mask,
-+                      void *key, void *mask, u8 l4_proto)
++static int prep_user_ip_rule(struct ethtool_usrip4_spec *uip_value,
++                           struct ethtool_usrip4_spec *uip_mask,
++                           void *key, void *mask, u64 *fields)
 +{
-+      int offset;
++      int off;
++      u32 tmp_value, tmp_mask;
 +
-+      if (l4_mask->tos) {
-+              netdev_err(priv->net_dev, "ToS is not supported for IPv4 L4\n");
++      if (uip_mask->tos || uip_mask->ip_ver)
 +              return -EOPNOTSUPP;
-+      }
-+
-+      if (l4_mask->ip4src) {
-+              offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_SRC);
-+              *(u32 *)(key + offset) = l4_value->ip4src;
-+              *(u32 *)(mask + offset) = l4_mask->ip4src;
-+      }
 +
-+      if (l4_mask->ip4dst) {
-+              offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_DST);
-+              *(u32 *)(key + offset) = l4_value->ip4dst;
-+              *(u32 *)(mask + offset) = l4_mask->ip4dst;
++      if (uip_mask->ip4src) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_SRC);
++              *(__be32 *)(key + off) = uip_value->ip4src;
++              *(__be32 *)(mask + off) = uip_mask->ip4src;
++              *fields |= DPAA2_ETH_DIST_IPSRC;
 +      }
 +
-+      if (l4_mask->psrc) {
-+              offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
-+              *(u32 *)(key + offset) = l4_value->psrc;
-+              *(u32 *)(mask + offset) = l4_mask->psrc;
++      if (uip_mask->ip4dst) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_DST);
++              *(__be32 *)(key + off) = uip_value->ip4dst;
++              *(__be32 *)(mask + off) = uip_mask->ip4dst;
++              *fields |= DPAA2_ETH_DIST_IPDST;
 +      }
 +
-+      if (l4_mask->pdst) {
-+              offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
-+              *(u32 *)(key + offset) = l4_value->pdst;
-+              *(u32 *)(mask + offset) = l4_mask->pdst;
++      if (uip_mask->proto) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_PROTO);
++              *(u8 *)(key + off) = uip_value->proto;
++              *(u8 *)(mask + off) = uip_mask->proto;
++              *fields |= DPAA2_ETH_DIST_IPPROTO;
 +      }
 +
-+      /* Only apply the rule for the user-specified L4 protocol
-+       * and if ethertype matches IPv4
-+       */
-+      offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_TYPE);
-+      *(u16 *)(key + offset) = htons(ETH_P_IP);
-+      *(u16 *)(mask + offset) = 0xFFFF;
-+
-+      offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_PROTO);
-+      *(u8 *)(key + offset) = l4_proto;
-+      *(u8 *)(mask + offset) = 0xFF;
-+
-+      /* TODO: check IP version */
-+
-+      return 0;
-+}
-+
-+static int prep_eth_rule(struct dpaa2_eth_priv *priv,
-+                       struct ethhdr *eth_value, struct ethhdr *eth_mask,
-+                       void *key, void *mask)
-+{
-+      int offset;
++      if (uip_mask->l4_4_bytes) {
++              tmp_value = be32_to_cpu(uip_value->l4_4_bytes);
++              tmp_mask = be32_to_cpu(uip_mask->l4_4_bytes);
 +
-+      if (eth_mask->h_proto) {
-+              netdev_err(priv->net_dev, "Ethertype is not supported!\n");
-+              return -EOPNOTSUPP;
-+      }
++              off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
++              *(__be16 *)(key + off) = htons(tmp_value >> 16);
++              *(__be16 *)(mask + off) = htons(tmp_mask >> 16);
++              *fields |= DPAA2_ETH_DIST_L4SRC;
 +
-+      if (!is_zero_ether_addr(eth_mask->h_source)) {
-+              offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_SA);
-+              ether_addr_copy(key + offset, eth_value->h_source);
-+              ether_addr_copy(mask + offset, eth_mask->h_source);
++              off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
++              *(__be16 *)(key + off) = htons(tmp_value & 0xFFFF);
++              *(__be16 *)(mask + off) = htons(tmp_mask & 0xFFFF);
++              *fields |= DPAA2_ETH_DIST_L4DST;
 +      }
 +
-+      if (!is_zero_ether_addr(eth_mask->h_dest)) {
-+              offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_DA);
-+              ether_addr_copy(key + offset, eth_value->h_dest);
-+              ether_addr_copy(mask + offset, eth_mask->h_dest);
-+      }
++      /* Only apply the rule for IPv4 frames */
++      off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
++      *(__be16 *)(key + off) = htons(ETH_P_IP);
++      *(__be16 *)(mask + off) = htons(0xFFFF);
++      *fields |= DPAA2_ETH_DIST_ETHTYPE;
 +
 +      return 0;
 +}
 +
-+static int prep_user_ip_rule(struct dpaa2_eth_priv *priv,
-+                           struct ethtool_usrip4_spec *uip_value,
-+                           struct ethtool_usrip4_spec *uip_mask,
-+                           void *key, void *mask)
++static int prep_l4_rule(struct ethtool_tcpip4_spec *l4_value,
++                      struct ethtool_tcpip4_spec *l4_mask,
++                      void *key, void *mask, u8 l4_proto, u64 *fields)
 +{
-+      int offset;
++      int off;
 +
-+      if (uip_mask->tos)
++      if (l4_mask->tos)
 +              return -EOPNOTSUPP;
-+
-+      if (uip_mask->ip4src) {
-+              offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_SRC);
-+              *(u32 *)(key + offset) = uip_value->ip4src;
-+              *(u32 *)(mask + offset) = uip_mask->ip4src;
++      if (l4_mask->ip4src) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_SRC);
++              *(__be32 *)(key + off) = l4_value->ip4src;
++              *(__be32 *)(mask + off) = l4_mask->ip4src;
++              *fields |= DPAA2_ETH_DIST_IPSRC;
 +      }
 +
-+      if (uip_mask->ip4dst) {
-+              offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_DST);
-+              *(u32 *)(key + offset) = uip_value->ip4dst;
-+              *(u32 *)(mask + offset) = uip_mask->ip4dst;
++      if (l4_mask->ip4dst) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_DST);
++              *(__be32 *)(key + off) = l4_value->ip4dst;
++              *(__be32 *)(mask + off) = l4_mask->ip4dst;
++              *fields |= DPAA2_ETH_DIST_IPDST;
 +      }
 +
-+      if (uip_mask->proto) {
-+              offset = cls_key_off(priv, NET_PROT_IP, NH_FLD_IP_PROTO);
-+              *(u32 *)(key + offset) = uip_value->proto;
-+              *(u32 *)(mask + offset) = uip_mask->proto;
++      if (l4_mask->psrc) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
++              *(__be16 *)(key + off) = l4_value->psrc;
++              *(__be16 *)(mask + off) = l4_mask->psrc;
++              *fields |= DPAA2_ETH_DIST_L4SRC;
 +      }
-+      if (uip_mask->l4_4_bytes) {
-+              offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_SRC);
-+              *(u16 *)(key + offset) = uip_value->l4_4_bytes << 16;
-+              *(u16 *)(mask + offset) = uip_mask->l4_4_bytes << 16;
 +
-+              offset = cls_key_off(priv, NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
-+              *(u16 *)(key + offset) = uip_value->l4_4_bytes & 0xFFFF;
-+              *(u16 *)(mask + offset) = uip_mask->l4_4_bytes & 0xFFFF;
++      if (l4_mask->pdst) {
++              off = dpaa2_eth_cls_fld_off(NET_PROT_UDP, NH_FLD_UDP_PORT_DST);
++              *(__be16 *)(key + off) = l4_value->pdst;
++              *(__be16 *)(mask + off) = l4_mask->pdst;
++              *fields |= DPAA2_ETH_DIST_L4DST;
 +      }
 +
-+      /* Ethertype must be IP */
-+      offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_TYPE);
-+      *(u16 *)(key + offset) = htons(ETH_P_IP);
-+      *(u16 *)(mask + offset) = 0xFFFF;
++      /* Only apply the rule for the user-specified L4 protocol
++       * and if ethertype matches IPv4
++       */
++      off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_TYPE);
++      *(__be16 *)(key + off) = htons(ETH_P_IP);
++      *(__be16 *)(mask + off) = htons(0xFFFF);
++      *fields |= DPAA2_ETH_DIST_ETHTYPE;
++
++      off = dpaa2_eth_cls_fld_off(NET_PROT_IP, NH_FLD_IP_PROTO);
++      *(u8 *)(key + off) = l4_proto;
++      *(u8 *)(mask + off) = 0xFF;
++      *fields |= DPAA2_ETH_DIST_IPPROTO;
 +
 +      return 0;
 +}
 +
-+static int prep_ext_rule(struct dpaa2_eth_priv *priv,
-+                       struct ethtool_flow_ext *ext_value,
++static int prep_ext_rule(struct ethtool_flow_ext *ext_value,
 +                       struct ethtool_flow_ext *ext_mask,
-+                       void *key, void *mask)
++                       void *key, void *mask, u64 *fields)
 +{
-+      int offset;
++      int off;
 +
 +      if (ext_mask->vlan_etype)
 +              return -EOPNOTSUPP;
 +
 +      if (ext_mask->vlan_tci) {
-+              offset = cls_key_off(priv, NET_PROT_VLAN, NH_FLD_VLAN_TCI);
-+              *(u16 *)(key + offset) = ext_value->vlan_tci;
-+              *(u16 *)(mask + offset) = ext_mask->vlan_tci;
++              off = dpaa2_eth_cls_fld_off(NET_PROT_VLAN, NH_FLD_VLAN_TCI);
++              *(__be16 *)(key + off) = ext_value->vlan_tci;
++              *(__be16 *)(mask + off) = ext_mask->vlan_tci;
++              *fields |= DPAA2_ETH_DIST_VLAN;
 +      }
 +
 +      return 0;
 +}
 +
-+static int prep_mac_ext_rule(struct dpaa2_eth_priv *priv,
-+                           struct ethtool_flow_ext *ext_value,
++static int prep_mac_ext_rule(struct ethtool_flow_ext *ext_value,
 +                           struct ethtool_flow_ext *ext_mask,
-+                           void *key, void *mask)
++                           void *key, void *mask, u64 *fields)
 +{
-+      int offset;
++      int off;
 +
 +      if (!is_zero_ether_addr(ext_mask->h_dest)) {
-+              offset = cls_key_off(priv, NET_PROT_ETH, NH_FLD_ETH_DA);
-+              ether_addr_copy(key + offset, ext_value->h_dest);
-+              ether_addr_copy(mask + offset, ext_mask->h_dest);
++              off = dpaa2_eth_cls_fld_off(NET_PROT_ETH, NH_FLD_ETH_DA);
++              ether_addr_copy(key + off, ext_value->h_dest);
++              ether_addr_copy(mask + off, ext_mask->h_dest);
++              *fields |= DPAA2_ETH_DIST_ETHDST;
 +      }
 +
 +      return 0;
 +}
 +
-+static int prep_cls_rule(struct net_device *net_dev,
-+                       struct ethtool_rx_flow_spec *fs,
-+                       void *key)
++static int prep_cls_rule(struct ethtool_rx_flow_spec *fs, void *key, void *mask,
++                       u64 *fields)
 +{
-+      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-+      const u8 key_size = cls_key_size(priv);
-+      void *msk = key + key_size;
 +      int err;
 +
-+      memset(key, 0, key_size * 2);
-+
-+      switch (fs->flow_type & 0xff) {
++      switch (fs->flow_type & 0xFF) {
++      case ETHER_FLOW:
++              err = prep_eth_rule(&fs->h_u.ether_spec, &fs->m_u.ether_spec,
++                                  key, mask, fields);
++              break;
++      case IP_USER_FLOW:
++              err = prep_user_ip_rule(&fs->h_u.usr_ip4_spec,
++                                  &fs->m_u.usr_ip4_spec, key, mask, fields);
++              break;
 +      case TCP_V4_FLOW:
-+              err = prep_l4_rule(priv, &fs->h_u.tcp_ip4_spec,
-+                                 &fs->m_u.tcp_ip4_spec, key, msk,
-+                                 IPPROTO_TCP);
++              err = prep_l4_rule(&fs->h_u.tcp_ip4_spec, &fs->m_u.tcp_ip4_spec,
++                                 key, mask, IPPROTO_TCP, fields);
 +              break;
 +      case UDP_V4_FLOW:
-+              err = prep_l4_rule(priv, &fs->h_u.udp_ip4_spec,
-+                                 &fs->m_u.udp_ip4_spec, key, msk,
-+                                 IPPROTO_UDP);
++              err = prep_l4_rule(&fs->h_u.udp_ip4_spec, &fs->m_u.udp_ip4_spec,
++                                 key, mask, IPPROTO_UDP, fields);
 +              break;
 +      case SCTP_V4_FLOW:
-+              err = prep_l4_rule(priv, &fs->h_u.sctp_ip4_spec,
-+                                 &fs->m_u.sctp_ip4_spec, key, msk,
-+                                 IPPROTO_SCTP);
-+              break;
-+      case ETHER_FLOW:
-+              err = prep_eth_rule(priv, &fs->h_u.ether_spec,
-+                                  &fs->m_u.ether_spec, key, msk);
-+              break;
-+      case IP_USER_FLOW:
-+              err = prep_user_ip_rule(priv, &fs->h_u.usr_ip4_spec,
-+                                      &fs->m_u.usr_ip4_spec, key, msk);
++              err = prep_l4_rule(&fs->h_u.sctp_ip4_spec, &fs->m_u.sctp_ip4_spec,
++                                 key, mask, IPPROTO_SCTP, fields);
 +              break;
 +      default:
-+              /* TODO: AH, ESP */
 +              return -EOPNOTSUPP;
 +      }
++
 +      if (err)
 +              return err;
 +
 +      if (fs->flow_type & FLOW_EXT) {
-+              err = prep_ext_rule(priv, &fs->h_ext, &fs->m_ext, key, msk);
++              err = prep_ext_rule(&fs->h_ext, &fs->m_ext, key, mask, fields);
 +              if (err)
 +                      return err;
 +      }
 +
 +      if (fs->flow_type & FLOW_MAC_EXT) {
-+              err = prep_mac_ext_rule(priv, &fs->h_ext, &fs->m_ext, key, msk);
++              err = prep_mac_ext_rule(&fs->h_ext, &fs->m_ext, key, mask,
++                                      fields);
 +              if (err)
 +                      return err;
 +      }
@@ -6233,185 +6513,179 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +      return 0;
 +}
 +
-+static int del_cls(struct net_device *net_dev, int location);
-+
-+static int do_cls(struct net_device *net_dev,
-+                struct ethtool_rx_flow_spec *fs,
-+                bool add)
++static int do_cls_rule(struct net_device *net_dev,
++                     struct ethtool_rx_flow_spec *fs,
++                     bool add)
 +{
 +      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
 +      struct device *dev = net_dev->dev.parent;
-+      const int rule_cnt = dpaa2_eth_fs_count(priv);
-+      struct dpni_rule_cfg rule_cfg;
++      struct dpni_rule_cfg rule_cfg = { 0 };
 +      struct dpni_fs_action_cfg fs_act = { 0 };
-+      void *dma_mem;
-+      int err = 0, tc;
-+
-+      if (!dpaa2_eth_fs_enabled(priv)) {
-+              netdev_err(net_dev, "dev does not support steering!\n");
-+              /* dev doesn't support steering */
-+              return -EOPNOTSUPP;
-+      }
++      dma_addr_t key_iova;
++      u64 fields = 0;
++      void *key_buf;
++      int i, err = 0;
 +
-+      if ((fs->ring_cookie != RX_CLS_FLOW_DISC &&
-+           fs->ring_cookie >= dpaa2_eth_queue_count(priv)) ||
-+           fs->location >= rule_cnt)
++      if (fs->ring_cookie != RX_CLS_FLOW_DISC &&
++          fs->ring_cookie >= dpaa2_eth_queue_count(priv))
 +              return -EINVAL;
 +
-+      /* When adding a new rule, check if location if available
-+       * and if not, free the existing table entry before inserting
-+       * the new one
-+       */
-+      if (add && (priv->cls_rule[fs->location].in_use == true))
-+              del_cls(net_dev, fs->location);
-+
-+      memset(&rule_cfg, 0, sizeof(rule_cfg));
-+      rule_cfg.key_size = cls_key_size(priv);
++      rule_cfg.key_size = dpaa2_eth_cls_key_size(DPAA2_ETH_DIST_ALL);
 +
 +      /* allocate twice the key size, for the actual key and for mask */
-+      dma_mem = kzalloc(rule_cfg.key_size * 2, GFP_DMA | GFP_KERNEL);
-+      if (!dma_mem)
++      key_buf = kzalloc(rule_cfg.key_size * 2, GFP_KERNEL);
++      if (!key_buf)
 +              return -ENOMEM;
 +
-+      err = prep_cls_rule(net_dev, fs, dma_mem);
++      /* Fill the key and mask memory areas */
++      err = prep_cls_rule(fs, key_buf, key_buf + rule_cfg.key_size, &fields);
 +      if (err)
-+              goto err_free_mem;
++              goto free_mem;
++
++      if (!dpaa2_eth_fs_mask_enabled(priv)) {
++              /* Masking allows us to configure a maximal key during init and
++               * use it for all flow steering rules. Without it, we include
++               * in the key only the fields actually used, so we need to
++               * extract the others from the final key buffer.
++               *
++               * Program the FS key if needed, or return error if previously
++               * set key can't be used for the current rule. User needs to
++               * delete existing rules in this case to allow for the new one.
++               */
++              if (!priv->rx_cls_fields) {
++                      err = dpaa2_eth_set_cls(net_dev, fields);
++                      if (err)
++                              goto free_mem;
++
++                      priv->rx_cls_fields = fields;
++              } else if (priv->rx_cls_fields != fields) {
++                      netdev_err(net_dev, "No support for multiple FS keys, need to delete existing rules\n");
++                      err = -EOPNOTSUPP;
++                      goto free_mem;
++              }
 +
-+      rule_cfg.key_iova = dma_map_single(dev, dma_mem,
-+                                         rule_cfg.key_size * 2,
-+                                         DMA_TO_DEVICE);
++              dpaa2_eth_cls_trim_rule(key_buf, fields);
++              rule_cfg.key_size = dpaa2_eth_cls_key_size(fields);
++      }
 +
-+      rule_cfg.mask_iova = rule_cfg.key_iova + rule_cfg.key_size;
++      key_iova = dma_map_single(dev, key_buf, rule_cfg.key_size * 2,
++                                DMA_TO_DEVICE);
++      if (dma_mapping_error(dev, key_iova)) {
++              err = -ENOMEM;
++              goto free_mem;
++      }
 +
-+      if (fs->ring_cookie == RX_CLS_FLOW_DISC)
-+              fs_act.options |= DPNI_FS_OPT_DISCARD;
-+      else
-+              fs_act.flow_id = fs->ring_cookie;
++      rule_cfg.key_iova = key_iova;
++      if (dpaa2_eth_fs_mask_enabled(priv))
++              rule_cfg.mask_iova = key_iova + rule_cfg.key_size;
 +
-+      for (tc = 0; tc < dpaa2_eth_tc_count(priv); tc++) {
++      if (add) {
++              if (fs->ring_cookie == RX_CLS_FLOW_DISC)
++                      fs_act.options |= DPNI_FS_OPT_DISCARD;
++              else
++                      fs_act.flow_id = fs->ring_cookie;
++      }
++      for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
 +              if (add)
 +                      err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token,
-+                                              tc, fs->location, &rule_cfg,
++                                              i, fs->location, &rule_cfg,
 +                                              &fs_act);
 +              else
 +                      err = dpni_remove_fs_entry(priv->mc_io, 0,
-+                                                 priv->mc_token, tc,
++                                                 priv->mc_token, i,
 +                                                 &rule_cfg);
-+
 +              if (err)
 +                      break;
 +      }
 +
-+      dma_unmap_single(dev, rule_cfg.key_iova,
-+                       rule_cfg.key_size * 2, DMA_TO_DEVICE);
-+
-+      if (err)
-+              netdev_err(net_dev, "dpaa2_add/remove_cls() error %d\n", err);
++      dma_unmap_single(dev, key_iova, rule_cfg.key_size * 2, DMA_TO_DEVICE);
 +
-+err_free_mem:
-+      kfree(dma_mem);
++free_mem:
++      kfree(key_buf);
 +
 +      return err;
 +}
 +
-+static int add_cls(struct net_device *net_dev,
-+                 struct ethtool_rx_flow_spec *fs)
++static int num_rules(struct dpaa2_eth_priv *priv)
 +{
-+      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-+      int err;
-+
-+      err = do_cls(net_dev, fs, true);
-+      if (err)
-+              return err;
++      int i, rules = 0;
 +
-+      priv->cls_rule[fs->location].in_use = true;
-+      priv->cls_rule[fs->location].fs = *fs;
++      for (i = 0; i < dpaa2_eth_fs_count(priv); i++)
++              if (priv->cls_rule[i].in_use)
++                      rules++;
 +
-+      return 0;
++      return rules;
 +}
 +
-+static int del_cls(struct net_device *net_dev, int location)
++static int update_cls_rule(struct net_device *net_dev,
++                         struct ethtool_rx_flow_spec *new_fs,
++                         int location)
 +{
 +      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-+      int err;
++      struct dpaa2_eth_cls_rule *rule;
++      int err = -EINVAL;
 +
-+      err = do_cls(net_dev, &priv->cls_rule[location].fs, false);
-+      if (err)
-+              return err;
++      if (!priv->rx_cls_enabled)
++              return -EOPNOTSUPP;
 +
-+      priv->cls_rule[location].in_use = false;
++      if (location >= dpaa2_eth_fs_count(priv))
++              return -EINVAL;
 +
-+      return 0;
-+}
++      rule = &priv->cls_rule[location];
 +
-+static int set_hash(struct net_device *net_dev, u64 data)
-+{
-+      struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-+      u32 key = 0;
-+      int i;
++      /* If a rule is present at the specified location, delete it. */
++      if (rule->in_use) {
++              err = do_cls_rule(net_dev, &rule->fs, false);
++              if (err)
++                      return err;
 +
-+      if (data & RXH_DISCARD)
-+              return -EOPNOTSUPP;
++              rule->in_use = 0;
 +
-+      for (i = 0; i < priv->num_dist_fields; i++)
-+              if (priv->dist_fields[i].rxnfc_field & data)
-+                      key |= priv->dist_fields[i].id;
++              if (!dpaa2_eth_fs_mask_enabled(priv) && !num_rules(priv))
++                      priv->rx_cls_fields = 0;
++      }
 +
-+      return dpaa2_eth_set_dist_key(priv, DPAA2_ETH_RX_DIST_HASH, key);
-+}
++      /* If no new entry to add, return here */
++      if (!new_fs)
++              return err;
 +
-+static int dpaa2_eth_set_rxnfc(struct net_device *net_dev,
-+                             struct ethtool_rxnfc *rxnfc)
-+{
-+      int err = 0;
++      err = do_cls_rule(net_dev, new_fs, true);
++      if (err)
++              return err;
 +
-+      switch (rxnfc->cmd) {
-+      case ETHTOOL_SRXCLSRLINS:
-+              err = add_cls(net_dev, &rxnfc->fs);
-+              break;
-+      case ETHTOOL_SRXCLSRLDEL:
-+              err = del_cls(net_dev, rxnfc->fs.location);
-+              break;
-+      case ETHTOOL_SRXFH:
-+              err = set_hash(net_dev, rxnfc->data);
-+              break;
-+      default:
-+              err = -EOPNOTSUPP;
-+      }
++      rule->in_use = 1;
++      rule->fs = *new_fs;
 +
-+      return err;
++      return 0;
  }
  
  static int dpaa2_eth_get_rxnfc(struct net_device *net_dev,
                               struct ethtool_rxnfc *rxnfc, u32 *rule_locs)
  {
        struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
-+      const int rule_cnt = dpaa2_eth_fs_count(priv);
-+      int i, j;
++      int rule_cnt = dpaa2_eth_fs_count(priv);
++      int i, j = 0;
  
        switch (rxnfc->cmd) {
        case ETHTOOL_GRXFH:
-@@ -258,6 +829,33 @@ static int dpaa2_eth_get_rxnfc(struct ne
+@@ -258,6 +791,29 @@ static int dpaa2_eth_get_rxnfc(struct ne
        case ETHTOOL_GRXRINGS:
                rxnfc->data = dpaa2_eth_queue_count(priv);
                break;
-+
 +      case ETHTOOL_GRXCLSRLCNT:
-+              for (i = 0, rxnfc->rule_cnt = 0; i < rule_cnt; i++)
-+                      if (priv->cls_rule[i].in_use)
-+                              rxnfc->rule_cnt++;
++              rxnfc->rule_cnt = 0;
++              rxnfc->rule_cnt = num_rules(priv);
 +              rxnfc->data = rule_cnt;
 +              break;
-+
 +      case ETHTOOL_GRXCLSRULE:
++              if (rxnfc->fs.location >= rule_cnt)
++                      return -EINVAL;
 +              if (!priv->cls_rule[rxnfc->fs.location].in_use)
 +                      return -EINVAL;
-+
 +              rxnfc->fs = priv->cls_rule[rxnfc->fs.location].fs;
 +              break;
-+
 +      case ETHTOOL_GRXCLSRLALL:
-+              for (i = 0, j = 0; i < rule_cnt; i++) {
++              for (i = 0; i < rule_cnt; i++) {
 +                      if (!priv->cls_rule[i].in_use)
 +                              continue;
 +                      if (j == rxnfc->rule_cnt)
@@ -6421,11 +6695,59 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +              rxnfc->rule_cnt = j;
 +              rxnfc->data = rule_cnt;
 +              break;
+       default:
+               return -EOPNOTSUPP;
+       }
+@@ -265,13 +821,61 @@ static int dpaa2_eth_get_rxnfc(struct ne
+       return 0;
+ }
++int dpaa2_phc_index = -1;
++EXPORT_SYMBOL(dpaa2_phc_index);
++
++static int dpaa2_eth_get_ts_info(struct net_device *dev,
++                               struct ethtool_ts_info *info)
++{
++      info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
++                              SOF_TIMESTAMPING_RX_HARDWARE |
++                              SOF_TIMESTAMPING_RAW_HARDWARE;
++
++      info->phc_index = dpaa2_phc_index;
++
++      info->tx_types = (1 << HWTSTAMP_TX_OFF) |
++                       (1 << HWTSTAMP_TX_ON);
++
++      info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
++                         (1 << HWTSTAMP_FILTER_ALL);
++      return 0;
++}
++
++static int dpaa2_eth_set_rxnfc(struct net_device *net_dev,
++                             struct ethtool_rxnfc *rxnfc)
++{
++      int err = 0;
++
++      switch (rxnfc->cmd) {
++      case ETHTOOL_SRXFH:
++              if ((rxnfc->data & DPAA2_RXH_SUPPORTED) != rxnfc->data)
++                      return -EOPNOTSUPP;
++              err = dpaa2_eth_set_hash(net_dev, rxnfc->data);
++              break;
++      case ETHTOOL_SRXCLSRLINS:
++              err = update_cls_rule(net_dev, &rxnfc->fs, rxnfc->fs.location);
++              break;
++      case ETHTOOL_SRXCLSRLDEL:
++              err = update_cls_rule(net_dev, NULL, rxnfc->fs.location);
++              break;
++      default:
++              err = -EOPNOTSUPP;
++      }
 +
-       default:
-               return -EOPNOTSUPP;
-       }
-@@ -270,8 +868,11 @@ const struct ethtool_ops dpaa2_ethtool_o
++      return err;
++}
++
+ const struct ethtool_ops dpaa2_ethtool_ops = {
+       .get_drvinfo = dpaa2_eth_get_drvinfo,
        .get_link = ethtool_op_get_link,
        .get_link_ksettings = dpaa2_eth_get_link_ksettings,
        .set_link_ksettings = dpaa2_eth_set_link_ksettings,
@@ -6436,10 +6758,446 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        .get_strings = dpaa2_eth_get_strings,
        .get_rxnfc = dpaa2_eth_get_rxnfc,
 +      .set_rxnfc = dpaa2_eth_set_rxnfc,
++      .get_ts_info = dpaa2_eth_get_ts_info,
+ };
+--- a/drivers/staging/fsl-dpaa2/ethernet/dpkg.h
++++ b/drivers/staging/fsl-dpaa2/ethernet/dpkg.h
+@@ -1,39 +1,10 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+ /* Copyright 2013-2015 Freescale Semiconductor Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- * * Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * * Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * * Neither the name of the above-listed copyright holders nor the
+- * names of any contributors may be used to endorse or promote products
+- * derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGE.
+  */
+ #ifndef __FSL_DPKG_H_
+ #define __FSL_DPKG_H_
+ #include <linux/types.h>
+-#include "net.h"
+ /* Data Path Key Generator API
+  * Contains initialization APIs and runtime APIs for the Key Generator
+@@ -86,6 +57,355 @@ struct dpkg_mask {
+       u8 offset;
  };
++/* Protocol fields */
++
++/* Ethernet fields */
++#define NH_FLD_ETH_DA                         BIT(0)
++#define NH_FLD_ETH_SA                         BIT(1)
++#define NH_FLD_ETH_LENGTH                     BIT(2)
++#define NH_FLD_ETH_TYPE                               BIT(3)
++#define NH_FLD_ETH_FINAL_CKSUM                        BIT(4)
++#define NH_FLD_ETH_PADDING                    BIT(5)
++#define NH_FLD_ETH_ALL_FIELDS                 (BIT(6) - 1)
++
++/* VLAN fields */
++#define NH_FLD_VLAN_VPRI                      BIT(0)
++#define NH_FLD_VLAN_CFI                               BIT(1)
++#define NH_FLD_VLAN_VID                               BIT(2)
++#define NH_FLD_VLAN_LENGTH                    BIT(3)
++#define NH_FLD_VLAN_TYPE                      BIT(4)
++#define NH_FLD_VLAN_ALL_FIELDS                        (BIT(5) - 1)
++
++#define NH_FLD_VLAN_TCI                               (NH_FLD_VLAN_VPRI | \
++                                               NH_FLD_VLAN_CFI | \
++                                               NH_FLD_VLAN_VID)
++
++/* IP (generic) fields */
++#define NH_FLD_IP_VER                         BIT(0)
++#define NH_FLD_IP_DSCP                                BIT(2)
++#define NH_FLD_IP_ECN                         BIT(3)
++#define NH_FLD_IP_PROTO                               BIT(4)
++#define NH_FLD_IP_SRC                         BIT(5)
++#define NH_FLD_IP_DST                         BIT(6)
++#define NH_FLD_IP_TOS_TC                      BIT(7)
++#define NH_FLD_IP_ID                          BIT(8)
++#define NH_FLD_IP_ALL_FIELDS                  (BIT(9) - 1)
++
++/* IPV4 fields */
++#define NH_FLD_IPV4_VER                               BIT(0)
++#define NH_FLD_IPV4_HDR_LEN                   BIT(1)
++#define NH_FLD_IPV4_TOS                               BIT(2)
++#define NH_FLD_IPV4_TOTAL_LEN                 BIT(3)
++#define NH_FLD_IPV4_ID                                BIT(4)
++#define NH_FLD_IPV4_FLAG_D                    BIT(5)
++#define NH_FLD_IPV4_FLAG_M                    BIT(6)
++#define NH_FLD_IPV4_OFFSET                    BIT(7)
++#define NH_FLD_IPV4_TTL                               BIT(8)
++#define NH_FLD_IPV4_PROTO                     BIT(9)
++#define NH_FLD_IPV4_CKSUM                     BIT(10)
++#define NH_FLD_IPV4_SRC_IP                    BIT(11)
++#define NH_FLD_IPV4_DST_IP                    BIT(12)
++#define NH_FLD_IPV4_OPTS                      BIT(13)
++#define NH_FLD_IPV4_OPTS_COUNT                        BIT(14)
++#define NH_FLD_IPV4_ALL_FIELDS                        (BIT(15) - 1)
++
++/* IPV6 fields */
++#define NH_FLD_IPV6_VER                               BIT(0)
++#define NH_FLD_IPV6_TC                                BIT(1)
++#define NH_FLD_IPV6_SRC_IP                    BIT(2)
++#define NH_FLD_IPV6_DST_IP                    BIT(3)
++#define NH_FLD_IPV6_NEXT_HDR                  BIT(4)
++#define NH_FLD_IPV6_FL                                BIT(5)
++#define NH_FLD_IPV6_HOP_LIMIT                 BIT(6)
++#define NH_FLD_IPV6_ID                                BIT(7)
++#define NH_FLD_IPV6_ALL_FIELDS                        (BIT(8) - 1)
++
++/* ICMP fields */
++#define NH_FLD_ICMP_TYPE                      BIT(0)
++#define NH_FLD_ICMP_CODE                      BIT(1)
++#define NH_FLD_ICMP_CKSUM                     BIT(2)
++#define NH_FLD_ICMP_ID                                BIT(3)
++#define NH_FLD_ICMP_SQ_NUM                    BIT(4)
++#define NH_FLD_ICMP_ALL_FIELDS                        (BIT(5) - 1)
++
++/* IGMP fields */
++#define NH_FLD_IGMP_VERSION                   BIT(0)
++#define NH_FLD_IGMP_TYPE                      BIT(1)
++#define NH_FLD_IGMP_CKSUM                     BIT(2)
++#define NH_FLD_IGMP_DATA                      BIT(3)
++#define NH_FLD_IGMP_ALL_FIELDS                        (BIT(4) - 1)
++
++/* TCP fields */
++#define NH_FLD_TCP_PORT_SRC                   BIT(0)
++#define NH_FLD_TCP_PORT_DST                   BIT(1)
++#define NH_FLD_TCP_SEQ                                BIT(2)
++#define NH_FLD_TCP_ACK                                BIT(3)
++#define NH_FLD_TCP_OFFSET                     BIT(4)
++#define NH_FLD_TCP_FLAGS                      BIT(5)
++#define NH_FLD_TCP_WINDOW                     BIT(6)
++#define NH_FLD_TCP_CKSUM                      BIT(7)
++#define NH_FLD_TCP_URGPTR                     BIT(8)
++#define NH_FLD_TCP_OPTS                               BIT(9)
++#define NH_FLD_TCP_OPTS_COUNT                 BIT(10)
++#define NH_FLD_TCP_ALL_FIELDS                 (BIT(11) - 1)
++
++/* UDP fields */
++#define NH_FLD_UDP_PORT_SRC                   BIT(0)
++#define NH_FLD_UDP_PORT_DST                   BIT(1)
++#define NH_FLD_UDP_LEN                                BIT(2)
++#define NH_FLD_UDP_CKSUM                      BIT(3)
++#define NH_FLD_UDP_ALL_FIELDS                 (BIT(4) - 1)
++
++/* UDP-lite fields */
++#define NH_FLD_UDP_LITE_PORT_SRC              BIT(0)
++#define NH_FLD_UDP_LITE_PORT_DST              BIT(1)
++#define NH_FLD_UDP_LITE_ALL_FIELDS            (BIT(2) - 1)
++
++/* UDP-encap-ESP fields */
++#define NH_FLD_UDP_ENC_ESP_PORT_SRC           BIT(0)
++#define NH_FLD_UDP_ENC_ESP_PORT_DST           BIT(1)
++#define NH_FLD_UDP_ENC_ESP_LEN                        BIT(2)
++#define NH_FLD_UDP_ENC_ESP_CKSUM              BIT(3)
++#define NH_FLD_UDP_ENC_ESP_SPI                        BIT(4)
++#define NH_FLD_UDP_ENC_ESP_SEQUENCE_NUM               BIT(5)
++#define NH_FLD_UDP_ENC_ESP_ALL_FIELDS         (BIT(6) - 1)
++
++/* SCTP fields */
++#define NH_FLD_SCTP_PORT_SRC                  BIT(0)
++#define NH_FLD_SCTP_PORT_DST                  BIT(1)
++#define NH_FLD_SCTP_VER_TAG                   BIT(2)
++#define NH_FLD_SCTP_CKSUM                     BIT(3)
++#define NH_FLD_SCTP_ALL_FIELDS                        (BIT(4) - 1)
++
++/* DCCP fields */
++#define NH_FLD_DCCP_PORT_SRC                  BIT(0)
++#define NH_FLD_DCCP_PORT_DST                  BIT(1)
++#define NH_FLD_DCCP_ALL_FIELDS                        (BIT(2) - 1)
++
++/* IPHC fields */
++#define NH_FLD_IPHC_CID                               BIT(0)
++#define NH_FLD_IPHC_CID_TYPE                  BIT(1)
++#define NH_FLD_IPHC_HCINDEX                   BIT(2)
++#define NH_FLD_IPHC_GEN                               BIT(3)
++#define NH_FLD_IPHC_D_BIT                     BIT(4)
++#define NH_FLD_IPHC_ALL_FIELDS                        (BIT(5) - 1)
++
++/* SCTP fields */
++#define NH_FLD_SCTP_CHUNK_DATA_TYPE           BIT(0)
++#define NH_FLD_SCTP_CHUNK_DATA_FLAGS          BIT(1)
++#define NH_FLD_SCTP_CHUNK_DATA_LENGTH         BIT(2)
++#define NH_FLD_SCTP_CHUNK_DATA_TSN            BIT(3)
++#define NH_FLD_SCTP_CHUNK_DATA_STREAM_ID      BIT(4)
++#define NH_FLD_SCTP_CHUNK_DATA_STREAM_SQN     BIT(5)
++#define NH_FLD_SCTP_CHUNK_DATA_PAYLOAD_PID    BIT(6)
++#define NH_FLD_SCTP_CHUNK_DATA_UNORDERED      BIT(7)
++#define NH_FLD_SCTP_CHUNK_DATA_BEGGINING      BIT(8)
++#define NH_FLD_SCTP_CHUNK_DATA_END            BIT(9)
++#define NH_FLD_SCTP_CHUNK_DATA_ALL_FIELDS     (BIT(10) - 1)
++
++/* L2TPV2 fields */
++#define NH_FLD_L2TPV2_TYPE_BIT                        BIT(0)
++#define NH_FLD_L2TPV2_LENGTH_BIT              BIT(1)
++#define NH_FLD_L2TPV2_SEQUENCE_BIT            BIT(2)
++#define NH_FLD_L2TPV2_OFFSET_BIT              BIT(3)
++#define NH_FLD_L2TPV2_PRIORITY_BIT            BIT(4)
++#define NH_FLD_L2TPV2_VERSION                 BIT(5)
++#define NH_FLD_L2TPV2_LEN                     BIT(6)
++#define NH_FLD_L2TPV2_TUNNEL_ID                       BIT(7)
++#define NH_FLD_L2TPV2_SESSION_ID              BIT(8)
++#define NH_FLD_L2TPV2_NS                      BIT(9)
++#define NH_FLD_L2TPV2_NR                      BIT(10)
++#define NH_FLD_L2TPV2_OFFSET_SIZE             BIT(11)
++#define NH_FLD_L2TPV2_FIRST_BYTE              BIT(12)
++#define NH_FLD_L2TPV2_ALL_FIELDS              (BIT(13) - 1)
++
++/* L2TPV3 fields */
++#define NH_FLD_L2TPV3_CTRL_TYPE_BIT           BIT(0)
++#define NH_FLD_L2TPV3_CTRL_LENGTH_BIT         BIT(1)
++#define NH_FLD_L2TPV3_CTRL_SEQUENCE_BIT               BIT(2)
++#define NH_FLD_L2TPV3_CTRL_VERSION            BIT(3)
++#define NH_FLD_L2TPV3_CTRL_LENGTH             BIT(4)
++#define NH_FLD_L2TPV3_CTRL_CONTROL            BIT(5)
++#define NH_FLD_L2TPV3_CTRL_SENT                       BIT(6)
++#define NH_FLD_L2TPV3_CTRL_RECV                       BIT(7)
++#define NH_FLD_L2TPV3_CTRL_FIRST_BYTE         BIT(8)
++#define NH_FLD_L2TPV3_CTRL_ALL_FIELDS         (BIT(9) - 1)
++
++#define NH_FLD_L2TPV3_SESS_TYPE_BIT           BIT(0)
++#define NH_FLD_L2TPV3_SESS_VERSION            BIT(1)
++#define NH_FLD_L2TPV3_SESS_ID                 BIT(2)
++#define NH_FLD_L2TPV3_SESS_COOKIE             BIT(3)
++#define NH_FLD_L2TPV3_SESS_ALL_FIELDS         (BIT(4) - 1)
++
++/* PPP fields */
++#define NH_FLD_PPP_PID                                BIT(0)
++#define NH_FLD_PPP_COMPRESSED                 BIT(1)
++#define NH_FLD_PPP_ALL_FIELDS                 (BIT(2) - 1)
++
++/* PPPoE fields */
++#define NH_FLD_PPPOE_VER                      BIT(0)
++#define NH_FLD_PPPOE_TYPE                     BIT(1)
++#define NH_FLD_PPPOE_CODE                     BIT(2)
++#define NH_FLD_PPPOE_SID                      BIT(3)
++#define NH_FLD_PPPOE_LEN                      BIT(4)
++#define NH_FLD_PPPOE_SESSION                  BIT(5)
++#define NH_FLD_PPPOE_PID                      BIT(6)
++#define NH_FLD_PPPOE_ALL_FIELDS                       (BIT(7) - 1)
++
++/* PPP-Mux fields */
++#define NH_FLD_PPPMUX_PID                     BIT(0)
++#define NH_FLD_PPPMUX_CKSUM                   BIT(1)
++#define NH_FLD_PPPMUX_COMPRESSED              BIT(2)
++#define NH_FLD_PPPMUX_ALL_FIELDS              (BIT(3) - 1)
++
++/* PPP-Mux sub-frame fields */
++#define NH_FLD_PPPMUX_SUBFRM_PFF              BIT(0)
++#define NH_FLD_PPPMUX_SUBFRM_LXT              BIT(1)
++#define NH_FLD_PPPMUX_SUBFRM_LEN              BIT(2)
++#define NH_FLD_PPPMUX_SUBFRM_PID              BIT(3)
++#define NH_FLD_PPPMUX_SUBFRM_USE_PID          BIT(4)
++#define NH_FLD_PPPMUX_SUBFRM_ALL_FIELDS               (BIT(5) - 1)
++
++/* LLC fields */
++#define NH_FLD_LLC_DSAP                               BIT(0)
++#define NH_FLD_LLC_SSAP                               BIT(1)
++#define NH_FLD_LLC_CTRL                               BIT(2)
++#define NH_FLD_LLC_ALL_FIELDS                 (BIT(3) - 1)
++
++/* NLPID fields */
++#define NH_FLD_NLPID_NLPID                    BIT(0)
++#define NH_FLD_NLPID_ALL_FIELDS                       (BIT(1) - 1)
++
++/* SNAP fields */
++#define NH_FLD_SNAP_OUI                               BIT(0)
++#define NH_FLD_SNAP_PID                               BIT(1)
++#define NH_FLD_SNAP_ALL_FIELDS                        (BIT(2) - 1)
++
++/* LLC SNAP fields */
++#define NH_FLD_LLC_SNAP_TYPE                  BIT(0)
++#define NH_FLD_LLC_SNAP_ALL_FIELDS            (BIT(1) - 1)
++
++/* ARP fields */
++#define NH_FLD_ARP_HTYPE                      BIT(0)
++#define NH_FLD_ARP_PTYPE                      BIT(1)
++#define NH_FLD_ARP_HLEN                               BIT(2)
++#define NH_FLD_ARP_PLEN                               BIT(3)
++#define NH_FLD_ARP_OPER                               BIT(4)
++#define NH_FLD_ARP_SHA                                BIT(5)
++#define NH_FLD_ARP_SPA                                BIT(6)
++#define NH_FLD_ARP_THA                                BIT(7)
++#define NH_FLD_ARP_TPA                                BIT(8)
++#define NH_FLD_ARP_ALL_FIELDS                 (BIT(9) - 1)
++
++/* RFC2684 fields */
++#define NH_FLD_RFC2684_LLC                    BIT(0)
++#define NH_FLD_RFC2684_NLPID                  BIT(1)
++#define NH_FLD_RFC2684_OUI                    BIT(2)
++#define NH_FLD_RFC2684_PID                    BIT(3)
++#define NH_FLD_RFC2684_VPN_OUI                        BIT(4)
++#define NH_FLD_RFC2684_VPN_IDX                        BIT(5)
++#define NH_FLD_RFC2684_ALL_FIELDS             (BIT(6) - 1)
++
++/* User defined fields */
++#define NH_FLD_USER_DEFINED_SRCPORT           BIT(0)
++#define NH_FLD_USER_DEFINED_PCDID             BIT(1)
++#define NH_FLD_USER_DEFINED_ALL_FIELDS                (BIT(2) - 1)
++
++/* Payload fields */
++#define NH_FLD_PAYLOAD_BUFFER                 BIT(0)
++#define NH_FLD_PAYLOAD_SIZE                   BIT(1)
++#define NH_FLD_MAX_FRM_SIZE                   BIT(2)
++#define NH_FLD_MIN_FRM_SIZE                   BIT(3)
++#define NH_FLD_PAYLOAD_TYPE                   BIT(4)
++#define NH_FLD_FRAME_SIZE                     BIT(5)
++#define NH_FLD_PAYLOAD_ALL_FIELDS             (BIT(6) - 1)
++
++/* GRE fields */
++#define NH_FLD_GRE_TYPE                               BIT(0)
++#define NH_FLD_GRE_ALL_FIELDS                 (BIT(1) - 1)
++
++/* MINENCAP fields */
++#define NH_FLD_MINENCAP_SRC_IP                        BIT(0)
++#define NH_FLD_MINENCAP_DST_IP                        BIT(1)
++#define NH_FLD_MINENCAP_TYPE                  BIT(2)
++#define NH_FLD_MINENCAP_ALL_FIELDS            (BIT(3) - 1)
++
++/* IPSEC AH fields */
++#define NH_FLD_IPSEC_AH_SPI                   BIT(0)
++#define NH_FLD_IPSEC_AH_NH                    BIT(1)
++#define NH_FLD_IPSEC_AH_ALL_FIELDS            (BIT(2) - 1)
++
++/* IPSEC ESP fields */
++#define NH_FLD_IPSEC_ESP_SPI                  BIT(0)
++#define NH_FLD_IPSEC_ESP_SEQUENCE_NUM         BIT(1)
++#define NH_FLD_IPSEC_ESP_ALL_FIELDS           (BIT(2) - 1)
++
++/* MPLS fields */
++#define NH_FLD_MPLS_LABEL_STACK                       BIT(0)
++#define NH_FLD_MPLS_LABEL_STACK_ALL_FIELDS    (BIT(1) - 1)
++
++/* MACSEC fields */
++#define NH_FLD_MACSEC_SECTAG                  BIT(0)
++#define NH_FLD_MACSEC_ALL_FIELDS              (BIT(1) - 1)
++
++/* GTP fields */
++#define NH_FLD_GTP_TEID                               BIT(0)
++
++/* Supported protocols */
++enum net_prot {
++      NET_PROT_NONE = 0,
++      NET_PROT_PAYLOAD,
++      NET_PROT_ETH,
++      NET_PROT_VLAN,
++      NET_PROT_IPV4,
++      NET_PROT_IPV6,
++      NET_PROT_IP,
++      NET_PROT_TCP,
++      NET_PROT_UDP,
++      NET_PROT_UDP_LITE,
++      NET_PROT_IPHC,
++      NET_PROT_SCTP,
++      NET_PROT_SCTP_CHUNK_DATA,
++      NET_PROT_PPPOE,
++      NET_PROT_PPP,
++      NET_PROT_PPPMUX,
++      NET_PROT_PPPMUX_SUBFRM,
++      NET_PROT_L2TPV2,
++      NET_PROT_L2TPV3_CTRL,
++      NET_PROT_L2TPV3_SESS,
++      NET_PROT_LLC,
++      NET_PROT_LLC_SNAP,
++      NET_PROT_NLPID,
++      NET_PROT_SNAP,
++      NET_PROT_MPLS,
++      NET_PROT_IPSEC_AH,
++      NET_PROT_IPSEC_ESP,
++      NET_PROT_UDP_ENC_ESP, /* RFC 3948 */
++      NET_PROT_MACSEC,
++      NET_PROT_GRE,
++      NET_PROT_MINENCAP,
++      NET_PROT_DCCP,
++      NET_PROT_ICMP,
++      NET_PROT_IGMP,
++      NET_PROT_ARP,
++      NET_PROT_CAPWAP_DATA,
++      NET_PROT_CAPWAP_CTRL,
++      NET_PROT_RFC2684,
++      NET_PROT_ICMPV6,
++      NET_PROT_FCOE,
++      NET_PROT_FIP,
++      NET_PROT_ISCSI,
++      NET_PROT_GTP,
++      NET_PROT_USER_DEFINED_L2,
++      NET_PROT_USER_DEFINED_L3,
++      NET_PROT_USER_DEFINED_L4,
++      NET_PROT_USER_DEFINED_L5,
++      NET_PROT_USER_DEFINED_SHIM1,
++      NET_PROT_USER_DEFINED_SHIM2,
++
++      NET_PROT_DUMMY_LAST
++};
++
+ /**
+  * struct dpkg_extract - A structure for defining a single extraction
+  * @type: Determines how the union below is interpreted:
 --- a/drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
-@@ -39,9 +39,11 @@
+@@ -1,34 +1,6 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+ /* Copyright 2013-2016 Freescale Semiconductor Inc.
+  * Copyright 2016 NXP
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- * * Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * * Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * * Neither the name of the above-listed copyright holders nor the
+- * names of any contributors may be used to endorse or promote products
+- * derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGE.
+  */
+ #ifndef _FSL_DPNI_CMD_H
+ #define _FSL_DPNI_CMD_H
+@@ -39,9 +11,11 @@
  #define DPNI_VER_MAJOR                                7
  #define DPNI_VER_MINOR                                0
  #define DPNI_CMD_BASE_VERSION                 1
@@ -6451,7 +7209,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  #define DPNI_CMDID_OPEN                                       DPNI_CMD(0x801)
  #define DPNI_CMDID_CLOSE                              DPNI_CMD(0x800)
-@@ -64,7 +66,7 @@
+@@ -64,16 +38,18 @@
  #define DPNI_CMDID_GET_IRQ_STATUS                     DPNI_CMD(0x016)
  #define DPNI_CMDID_CLEAR_IRQ_STATUS                   DPNI_CMD(0x017)
  
@@ -6460,16 +7218,19 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  #define DPNI_CMDID_SET_ERRORS_BEHAVIOR                        DPNI_CMD(0x20B)
  
  #define DPNI_CMDID_GET_QDID                           DPNI_CMD(0x210)
-@@ -73,7 +75,7 @@
+ #define DPNI_CMDID_GET_TX_DATA_OFFSET                 DPNI_CMD(0x212)
+ #define DPNI_CMDID_GET_LINK_STATE                     DPNI_CMD(0x215)
++#define DPNI_CMDID_GET_LINK_STATE_V2                  DPNI_CMD_V2(0x215)
  #define DPNI_CMDID_SET_MAX_FRAME_LENGTH                       DPNI_CMD(0x216)
  #define DPNI_CMDID_GET_MAX_FRAME_LENGTH                       DPNI_CMD(0x217)
  #define DPNI_CMDID_SET_LINK_CFG                               DPNI_CMD(0x21A)
 -#define DPNI_CMDID_SET_TX_SHAPING                     DPNI_CMD(0x21B)
++#define DPNI_CMDID_SET_LINK_CFG_V2                    DPNI_CMD_V2(0x21A)
 +#define DPNI_CMDID_SET_TX_SHAPING                     DPNI_CMD_V2(0x21B)
  
  #define DPNI_CMDID_SET_MCAST_PROMISC                  DPNI_CMD(0x220)
  #define DPNI_CMDID_GET_MCAST_PROMISC                  DPNI_CMD(0x221)
-@@ -87,11 +89,16 @@
+@@ -87,11 +63,16 @@
  
  #define DPNI_CMDID_SET_RX_TC_DIST                     DPNI_CMD(0x235)
  
@@ -6487,7 +7248,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  #define DPNI_CMDID_GET_QUEUE                          DPNI_CMD(0x25F)
  #define DPNI_CMDID_SET_QUEUE                          DPNI_CMD(0x260)
  #define DPNI_CMDID_GET_TAILDROP                               DPNI_CMD(0x261)
-@@ -110,6 +117,9 @@
+@@ -110,6 +91,9 @@
  #define DPNI_CMDID_GET_OFFLOAD                                DPNI_CMD(0x26B)
  #define DPNI_CMDID_SET_OFFLOAD                                DPNI_CMD(0x26C)
  
@@ -6497,7 +7258,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  /* Macros for accessing command fields smaller than 1byte */
  #define DPNI_MASK(field)      \
        GENMASK(DPNI_##field##_SHIFT + DPNI_##field##_SIZE - 1, \
-@@ -126,13 +136,14 @@ struct dpni_cmd_open {
+@@ -126,13 +110,14 @@ struct dpni_cmd_open {
  
  #define DPNI_BACKUP_POOL(val, order)  (((val) & 0x1) << (order))
  struct dpni_cmd_set_pools {
@@ -6516,7 +7277,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        __le16 buffer_size[DPNI_MAX_DPBP];
  };
  
-@@ -303,6 +314,7 @@ struct dpni_rsp_get_tx_data_offset {
+@@ -303,6 +288,7 @@ struct dpni_rsp_get_tx_data_offset {
  
  struct dpni_cmd_get_statistics {
        u8 page_number;
@@ -6524,10 +7285,50 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  };
  
  struct dpni_rsp_get_statistics {
-@@ -335,6 +347,22 @@ struct dpni_rsp_get_link_state {
+@@ -319,8 +305,22 @@ struct dpni_cmd_set_link_cfg {
+       __le64 options;
+ };
++struct dpni_cmd_set_link_cfg_v2 {
++      /* cmd word 0 */
++      __le64 pad0;
++      /* cmd word 1 */
++      __le32 rate;
++      __le32 pad1;
++      /* cmd word 2 */
++      __le64 options;
++      /* cmd word 3 */
++      __le64 advertising;
++};
++
+ #define DPNI_LINK_STATE_SHIFT         0
+ #define DPNI_LINK_STATE_SIZE          1
++#define DPNI_STATE_VALID_SHIFT                1
++#define DPNI_STATE_VALID_SIZE         1
+ struct dpni_rsp_get_link_state {
+       /* response word 0 */
+@@ -335,6 +335,39 @@ struct dpni_rsp_get_link_state {
        __le64 options;
  };
  
++struct dpni_rsp_get_link_state_v2 {
++      /* response word 0 */
++      __le32 pad0;
++      /* from LSB: up:1, valid:1 */
++      u8 flags;
++      u8 pad1[3];
++      /* response word 1 */
++      __le32 rate;
++      __le32 pad2;
++      /* response word 2 */
++      __le64 options;
++      /* cmd word 3 */
++      __le64 supported;
++      /* cmd word 4 */
++      __le64 advertising;
++};
++
 +#define DPNI_COUPLED_SHIFT    0
 +#define DPNI_COUPLED_SIZE     1
 +
@@ -6547,7 +7348,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  struct dpni_cmd_set_max_frame_length {
        __le16 max_frame_length;
  };
-@@ -394,6 +422,24 @@ struct dpni_cmd_clear_mac_filters {
+@@ -394,6 +427,24 @@ struct dpni_cmd_clear_mac_filters {
        u8 flags;
  };
  
@@ -6572,7 +7373,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  #define DPNI_DIST_MODE_SHIFT          0
  #define DPNI_DIST_MODE_SIZE           4
  #define DPNI_MISS_ACTION_SHIFT                4
-@@ -503,6 +549,63 @@ struct dpni_cmd_set_queue {
+@@ -503,6 +554,63 @@ struct dpni_cmd_set_queue {
        __le64 user_context;
  };
  
@@ -6636,7 +7437,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  struct dpni_cmd_set_taildrop {
        /* cmd word 0 */
        u8 congestion_point;
-@@ -538,4 +641,79 @@ struct dpni_rsp_get_taildrop {
+@@ -538,4 +646,79 @@ struct dpni_rsp_get_taildrop {
        __le32 threshold;
  };
  
@@ -6718,7 +7519,43 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  #endif /* _FSL_DPNI_CMD_H */
 --- a/drivers/staging/fsl-dpaa2/ethernet/dpni.c
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
-@@ -122,7 +122,7 @@ int dpni_open(struct fsl_mc_io *mc_io,
+@@ -1,34 +1,6 @@
++// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+ /* Copyright 2013-2016 Freescale Semiconductor Inc.
+  * Copyright 2016 NXP
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- * * Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * * Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * * Neither the name of the above-listed copyright holders nor the
+- * names of any contributors may be used to endorse or promote products
+- * derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGE.
+  */
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+@@ -122,7 +94,7 @@ int dpni_open(struct fsl_mc_io *mc_io,
              int dpni_id,
              u16 *token)
  {
@@ -6727,7 +7564,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_open *cmd_params;
  
        int err;
-@@ -160,7 +160,7 @@ int dpni_close(struct fsl_mc_io *mc_io,
+@@ -160,7 +132,7 @@ int dpni_close(struct fsl_mc_io *mc_io,
               u32 cmd_flags,
               u16 token)
  {
@@ -6736,7 +7573,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* prepare command */
        cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE,
-@@ -188,7 +188,7 @@ int dpni_set_pools(struct fsl_mc_io *mc_
+@@ -188,7 +160,7 @@ int dpni_set_pools(struct fsl_mc_io *mc_
                   u16 token,
                   const struct dpni_pools_cfg *cfg)
  {
@@ -6745,7 +7582,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_pools *cmd_params;
        int i;
  
-@@ -199,7 +199,10 @@ int dpni_set_pools(struct fsl_mc_io *mc_
+@@ -199,7 +171,10 @@ int dpni_set_pools(struct fsl_mc_io *mc_
        cmd_params = (struct dpni_cmd_set_pools *)cmd.params;
        cmd_params->num_dpbp = cfg->num_dpbp;
        for (i = 0; i < DPNI_MAX_DPBP; i++) {
@@ -6757,7 +7594,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
                cmd_params->buffer_size[i] =
                        cpu_to_le16(cfg->pools[i].buffer_size);
                cmd_params->backup_pool_mask |=
-@@ -222,7 +225,7 @@ int dpni_enable(struct fsl_mc_io *mc_io,
+@@ -222,7 +197,7 @@ int dpni_enable(struct fsl_mc_io *mc_io,
                u32 cmd_flags,
                u16 token)
  {
@@ -6766,7 +7603,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* prepare command */
        cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE,
-@@ -245,7 +248,7 @@ int dpni_disable(struct fsl_mc_io *mc_io
+@@ -245,7 +220,7 @@ int dpni_disable(struct fsl_mc_io *mc_io
                 u32 cmd_flags,
                 u16 token)
  {
@@ -6775,7 +7612,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* prepare command */
        cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE,
-@@ -270,7 +273,7 @@ int dpni_is_enabled(struct fsl_mc_io *mc
+@@ -270,7 +245,7 @@ int dpni_is_enabled(struct fsl_mc_io *mc
                    u16 token,
                    int *en)
  {
@@ -6784,7 +7621,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_is_enabled *rsp_params;
        int err;
  
-@@ -303,7 +306,7 @@ int dpni_reset(struct fsl_mc_io *mc_io,
+@@ -303,7 +278,7 @@ int dpni_reset(struct fsl_mc_io *mc_io,
               u32 cmd_flags,
               u16 token)
  {
@@ -6793,7 +7630,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* prepare command */
        cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET,
-@@ -335,7 +338,7 @@ int dpni_set_irq_enable(struct fsl_mc_io
+@@ -335,7 +310,7 @@ int dpni_set_irq_enable(struct fsl_mc_io
                        u8 irq_index,
                        u8 en)
  {
@@ -6802,7 +7639,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_irq_enable *cmd_params;
  
        /* prepare command */
-@@ -366,7 +369,7 @@ int dpni_get_irq_enable(struct fsl_mc_io
+@@ -366,7 +341,7 @@ int dpni_get_irq_enable(struct fsl_mc_io
                        u8 irq_index,
                        u8 *en)
  {
@@ -6811,7 +7648,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_irq_enable *cmd_params;
        struct dpni_rsp_get_irq_enable *rsp_params;
  
-@@ -413,7 +416,7 @@ int dpni_set_irq_mask(struct fsl_mc_io *
+@@ -413,7 +388,7 @@ int dpni_set_irq_mask(struct fsl_mc_io *
                      u8 irq_index,
                      u32 mask)
  {
@@ -6820,7 +7657,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_irq_mask *cmd_params;
  
        /* prepare command */
-@@ -447,7 +450,7 @@ int dpni_get_irq_mask(struct fsl_mc_io *
+@@ -447,7 +422,7 @@ int dpni_get_irq_mask(struct fsl_mc_io *
                      u8 irq_index,
                      u32 *mask)
  {
@@ -6829,7 +7666,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_irq_mask *cmd_params;
        struct dpni_rsp_get_irq_mask *rsp_params;
        int err;
-@@ -489,7 +492,7 @@ int dpni_get_irq_status(struct fsl_mc_io
+@@ -489,7 +464,7 @@ int dpni_get_irq_status(struct fsl_mc_io
                        u8 irq_index,
                        u32 *status)
  {
@@ -6838,7 +7675,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_irq_status *cmd_params;
        struct dpni_rsp_get_irq_status *rsp_params;
        int err;
-@@ -532,7 +535,7 @@ int dpni_clear_irq_status(struct fsl_mc_
+@@ -532,7 +507,7 @@ int dpni_clear_irq_status(struct fsl_mc_
                          u8 irq_index,
                          u32 status)
  {
@@ -6847,7 +7684,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_clear_irq_status *cmd_params;
  
        /* prepare command */
-@@ -561,7 +564,7 @@ int dpni_get_attributes(struct fsl_mc_io
+@@ -561,7 +536,7 @@ int dpni_get_attributes(struct fsl_mc_io
                        u16 token,
                        struct dpni_attr *attr)
  {
@@ -6856,7 +7693,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_attr *rsp_params;
  
        int err;
-@@ -609,7 +612,7 @@ int dpni_set_errors_behavior(struct fsl_
+@@ -609,7 +584,7 @@ int dpni_set_errors_behavior(struct fsl_
                             u16 token,
                             struct dpni_error_cfg *cfg)
  {
@@ -6865,7 +7702,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_errors_behavior *cmd_params;
  
        /* prepare command */
-@@ -641,7 +644,7 @@ int dpni_get_buffer_layout(struct fsl_mc
+@@ -641,7 +616,7 @@ int dpni_get_buffer_layout(struct fsl_mc
                           enum dpni_queue_type qtype,
                           struct dpni_buffer_layout *layout)
  {
@@ -6874,7 +7711,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_buffer_layout *cmd_params;
        struct dpni_rsp_get_buffer_layout *rsp_params;
        int err;
-@@ -689,7 +692,7 @@ int dpni_set_buffer_layout(struct fsl_mc
+@@ -689,7 +664,7 @@ int dpni_set_buffer_layout(struct fsl_mc
                           enum dpni_queue_type qtype,
                           const struct dpni_buffer_layout *layout)
  {
@@ -6883,7 +7720,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_buffer_layout *cmd_params;
  
        /* prepare command */
-@@ -731,7 +734,7 @@ int dpni_set_offload(struct fsl_mc_io *m
+@@ -731,7 +706,7 @@ int dpni_set_offload(struct fsl_mc_io *m
                     enum dpni_offload type,
                     u32 config)
  {
@@ -6892,7 +7729,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_offload *cmd_params;
  
        cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_OFFLOAD,
-@@ -750,7 +753,7 @@ int dpni_get_offload(struct fsl_mc_io *m
+@@ -750,7 +725,7 @@ int dpni_get_offload(struct fsl_mc_io *m
                     enum dpni_offload type,
                     u32 *config)
  {
@@ -6901,7 +7738,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_offload *cmd_params;
        struct dpni_rsp_get_offload *rsp_params;
        int err;
-@@ -792,7 +795,7 @@ int dpni_get_qdid(struct fsl_mc_io *mc_i
+@@ -792,7 +767,7 @@ int dpni_get_qdid(struct fsl_mc_io *mc_i
                  enum dpni_queue_type qtype,
                  u16 *qdid)
  {
@@ -6910,7 +7747,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_qdid *cmd_params;
        struct dpni_rsp_get_qdid *rsp_params;
        int err;
-@@ -830,7 +833,7 @@ int dpni_get_tx_data_offset(struct fsl_m
+@@ -830,7 +805,7 @@ int dpni_get_tx_data_offset(struct fsl_m
                            u16 token,
                            u16 *data_offset)
  {
@@ -6919,7 +7756,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_tx_data_offset *rsp_params;
        int err;
  
-@@ -865,7 +868,7 @@ int dpni_set_link_cfg(struct fsl_mc_io *
+@@ -865,7 +840,7 @@ int dpni_set_link_cfg(struct fsl_mc_io *
                      u16 token,
                      const struct dpni_link_cfg *cfg)
  {
@@ -6928,7 +7765,44 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_link_cfg *cmd_params;
  
        /* prepare command */
-@@ -894,7 +897,7 @@ int dpni_get_link_state(struct fsl_mc_io
+@@ -881,6 +856,36 @@ int dpni_set_link_cfg(struct fsl_mc_io *
+ }
+ /**
++ * dpni_set_link_cfg_v2() - set the link configuration.
++ * @mc_io:      Pointer to MC portal's I/O object
++ * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:      Token of DPNI object
++ * @cfg:        Link configuration
++ *
++ * Return:      '0' on Success; Error code otherwise.
++ */
++int dpni_set_link_cfg_v2(struct fsl_mc_io *mc_io,
++                       u32 cmd_flags,
++                       u16 token,
++                       const struct dpni_link_cfg *cfg)
++{
++      struct fsl_mc_command cmd = { 0 };
++      struct dpni_cmd_set_link_cfg_v2 *cmd_params;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG_V2,
++                                        cmd_flags,
++                                        token);
++      cmd_params = (struct dpni_cmd_set_link_cfg_v2 *)cmd.params;
++      cmd_params->rate = cpu_to_le32(cfg->rate);
++      cmd_params->options = cpu_to_le64(cfg->options);
++      cmd_params->advertising = cpu_to_le64(cfg->advertising);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++/**
+  * dpni_get_link_state() - Return the link state (either up or down)
+  * @mc_io:    Pointer to MC portal's I/O object
+  * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
+@@ -894,7 +899,7 @@ int dpni_get_link_state(struct fsl_mc_io
                        u16 token,
                        struct dpni_link_state *state)
  {
@@ -6937,10 +7811,50 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_link_state *rsp_params;
        int err;
  
-@@ -918,6 +921,44 @@ int dpni_get_link_state(struct fsl_mc_io
+@@ -918,6 +923,84 @@ int dpni_get_link_state(struct fsl_mc_io
  }
  
  /**
++ * dpni_get_link_state_v2() - Return the link state (either up or down)
++ * @mc_io:      Pointer to MC portal's I/O object
++ * @cmd_flags:  Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:      Token of DPNI object
++ * @state:      Returned link state;
++ *
++ * Return:      '0' on Success; Error code otherwise.
++ */
++int dpni_get_link_state_v2(struct fsl_mc_io *mc_io,
++                         u32 cmd_flags,
++                         u16 token,
++                         struct dpni_link_state *state)
++{
++      struct fsl_mc_command cmd = { 0 };
++      struct dpni_rsp_get_link_state_v2 *rsp_params;
++      int err;
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE_V2,
++                                        cmd_flags,
++                                        token);
++
++      /* send command to mc*/
++      err = mc_send_command(mc_io, &cmd);
++      if (err)
++              return err;
++
++      /* retrieve response parameters */
++      rsp_params = (struct dpni_rsp_get_link_state_v2 *)cmd.params;
++      state->up = dpni_get_field(rsp_params->flags, LINK_STATE);
++      state->state_valid = dpni_get_field(rsp_params->flags, STATE_VALID);
++      state->rate = le32_to_cpu(rsp_params->rate);
++      state->options = le64_to_cpu(rsp_params->options);
++      state->supported = le64_to_cpu(rsp_params->supported);
++      state->advertising = le64_to_cpu(rsp_params->advertising);
++
++      return 0;
++}
++
++/**
 + * dpni_set_tx_shaping() - Set the transmit shaping
 + * @mc_io:            Pointer to MC portal's I/O object
 + * @cmd_flags:                Command flags; one or more of 'MC_CMD_FLAG_'
@@ -6982,7 +7896,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * dpni_set_max_frame_length() - Set the maximum received frame length.
   * @mc_io:    Pointer to MC portal's I/O object
   * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
-@@ -933,7 +974,7 @@ int dpni_set_max_frame_length(struct fsl
+@@ -933,7 +1016,7 @@ int dpni_set_max_frame_length(struct fsl
                              u16 token,
                              u16 max_frame_length)
  {
@@ -6991,7 +7905,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_max_frame_length *cmd_params;
  
        /* prepare command */
-@@ -963,7 +1004,7 @@ int dpni_get_max_frame_length(struct fsl
+@@ -963,7 +1046,7 @@ int dpni_get_max_frame_length(struct fsl
                              u16 token,
                              u16 *max_frame_length)
  {
@@ -7000,7 +7914,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_max_frame_length *rsp_params;
        int err;
  
-@@ -998,7 +1039,7 @@ int dpni_set_multicast_promisc(struct fs
+@@ -998,7 +1081,7 @@ int dpni_set_multicast_promisc(struct fs
                               u16 token,
                               int en)
  {
@@ -7009,7 +7923,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_multicast_promisc *cmd_params;
  
        /* prepare command */
-@@ -1026,7 +1067,7 @@ int dpni_get_multicast_promisc(struct fs
+@@ -1026,7 +1109,7 @@ int dpni_get_multicast_promisc(struct fs
                               u16 token,
                               int *en)
  {
@@ -7018,7 +7932,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_multicast_promisc *rsp_params;
        int err;
  
-@@ -1061,7 +1102,7 @@ int dpni_set_unicast_promisc(struct fsl_
+@@ -1061,7 +1144,7 @@ int dpni_set_unicast_promisc(struct fsl_
                             u16 token,
                             int en)
  {
@@ -7027,7 +7941,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_unicast_promisc *cmd_params;
  
        /* prepare command */
-@@ -1089,7 +1130,7 @@ int dpni_get_unicast_promisc(struct fsl_
+@@ -1089,7 +1172,7 @@ int dpni_get_unicast_promisc(struct fsl_
                             u16 token,
                             int *en)
  {
@@ -7036,7 +7950,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_unicast_promisc *rsp_params;
        int err;
  
-@@ -1124,7 +1165,7 @@ int dpni_set_primary_mac_addr(struct fsl
+@@ -1124,7 +1207,7 @@ int dpni_set_primary_mac_addr(struct fsl
                              u16 token,
                              const u8 mac_addr[6])
  {
@@ -7045,7 +7959,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_primary_mac_addr *cmd_params;
        int i;
  
-@@ -1154,7 +1195,7 @@ int dpni_get_primary_mac_addr(struct fsl
+@@ -1154,7 +1237,7 @@ int dpni_get_primary_mac_addr(struct fsl
                              u16 token,
                              u8 mac_addr[6])
  {
@@ -7054,7 +7968,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_primary_mac_addr *rsp_params;
        int i, err;
  
-@@ -1193,7 +1234,7 @@ int dpni_get_port_mac_addr(struct fsl_mc
+@@ -1193,7 +1276,7 @@ int dpni_get_port_mac_addr(struct fsl_mc
                           u16 token,
                           u8 mac_addr[6])
  {
@@ -7063,7 +7977,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_rsp_get_port_mac_addr *rsp_params;
        int i, err;
  
-@@ -1229,7 +1270,7 @@ int dpni_add_mac_addr(struct fsl_mc_io *
+@@ -1229,7 +1312,7 @@ int dpni_add_mac_addr(struct fsl_mc_io *
                      u16 token,
                      const u8 mac_addr[6])
  {
@@ -7072,7 +7986,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_add_mac_addr *cmd_params;
        int i;
  
-@@ -1259,7 +1300,7 @@ int dpni_remove_mac_addr(struct fsl_mc_i
+@@ -1259,7 +1342,7 @@ int dpni_remove_mac_addr(struct fsl_mc_i
                         u16 token,
                         const u8 mac_addr[6])
  {
@@ -7081,7 +7995,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_remove_mac_addr *cmd_params;
        int i;
  
-@@ -1293,7 +1334,7 @@ int dpni_clear_mac_filters(struct fsl_mc
+@@ -1293,7 +1376,7 @@ int dpni_clear_mac_filters(struct fsl_mc
                           int unicast,
                           int multicast)
  {
@@ -7090,7 +8004,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_clear_mac_filters *cmd_params;
  
        /* prepare command */
-@@ -1309,6 +1350,55 @@ int dpni_clear_mac_filters(struct fsl_mc
+@@ -1309,6 +1392,55 @@ int dpni_clear_mac_filters(struct fsl_mc
  }
  
  /**
@@ -7146,7 +8060,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * dpni_set_rx_tc_dist() - Set Rx traffic class distribution configuration
   * @mc_io:    Pointer to MC portal's I/O object
   * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
-@@ -1327,7 +1417,7 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io
+@@ -1327,7 +1459,7 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io
                        u8 tc_id,
                        const struct dpni_rx_tc_dist_cfg *cfg)
  {
@@ -7155,7 +8069,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_rx_tc_dist *cmd_params;
  
        /* prepare command */
-@@ -1346,6 +1436,293 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io
+@@ -1346,6 +1478,215 @@ int dpni_set_rx_tc_dist(struct fsl_mc_io
        return mc_send_command(mc_io, &cmd);
  }
  
@@ -7266,84 +8180,6 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +}
 +
 +/**
-+ * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class
-+ *                    (to select a flow ID)
-+ * @mc_io:    Pointer to MC portal's I/O object
-+ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
-+ * @token:    Token of DPNI object
-+ * @tc_id:    Traffic class selection (0-7)
-+ * @index:    Location in the QoS table where to insert the entry.
-+ *            Only relevant if MASKING is enabled for QoS
-+ *            classification on this DPNI, it is ignored for exact match.
-+ * @cfg:      Flow steering rule to add
-+ * @action:   Action to be taken as result of a classification hit
-+ *
-+ * Return:    '0' on Success; Error code otherwise.
-+ */
-+int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
-+                    u32 cmd_flags,
-+                    u16 token,
-+                    u8 tc_id,
-+                    u16 index,
-+                    const struct dpni_rule_cfg *cfg,
-+                    const struct dpni_fs_action_cfg *action)
-+{
-+      struct dpni_cmd_add_fs_entry *cmd_params;
-+      struct fsl_mc_command cmd = { 0 };
-+
-+      /* prepare command */
-+      cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT,
-+                                        cmd_flags,
-+                                        token);
-+      cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params;
-+      cmd_params->tc_id = tc_id;
-+      cmd_params->key_size = cfg->key_size;
-+      cmd_params->index = cpu_to_le16(index);
-+      cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
-+      cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
-+      cmd_params->options = cpu_to_le16(action->options);
-+      cmd_params->flow_id = cpu_to_le16(action->flow_id);
-+      cmd_params->flc = cpu_to_le64(action->flc);
-+
-+      /* send command to mc*/
-+      return mc_send_command(mc_io, &cmd);
-+}
-+
-+/**
-+ * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific
-+ *                        traffic class
-+ * @mc_io:    Pointer to MC portal's I/O object
-+ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
-+ * @token:    Token of DPNI object
-+ * @tc_id:    Traffic class selection (0-7)
-+ * @cfg:      Flow steering rule to remove
-+ *
-+ * Return:    '0' on Success; Error code otherwise.
-+ */
-+int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
-+                       u32 cmd_flags,
-+                       u16 token,
-+                       u8 tc_id,
-+                       const struct dpni_rule_cfg *cfg)
-+{
-+      struct dpni_cmd_remove_fs_entry *cmd_params;
-+      struct fsl_mc_command cmd = { 0 };
-+
-+      /* prepare command */
-+      cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT,
-+                                        cmd_flags,
-+                                        token);
-+      cmd_params = (struct dpni_cmd_remove_fs_entry *)cmd.params;
-+      cmd_params->tc_id = tc_id;
-+      cmd_params->key_size = cfg->key_size;
-+      cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
-+      cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
-+
-+      /* send command to mc*/
-+      return mc_send_command(mc_io, &cmd);
-+}
-+
-+/**
 + * dpni_set_congestion_notification() - Set traffic class congestion
 + *                                    notification configuration
 + * @mc_io:    Pointer to MC portal's I/O object
@@ -7449,7 +8285,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  /**
   * dpni_set_queue() - Set queue parameters
   * @mc_io:    Pointer to MC portal's I/O object
-@@ -1371,7 +1748,7 @@ int dpni_set_queue(struct fsl_mc_io *mc_
+@@ -1371,7 +1712,7 @@ int dpni_set_queue(struct fsl_mc_io *mc_
                   u8 options,
                   const struct dpni_queue *queue)
  {
@@ -7458,7 +8294,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_queue *cmd_params;
  
        /* prepare command */
-@@ -1419,7 +1796,7 @@ int dpni_get_queue(struct fsl_mc_io *mc_
+@@ -1419,7 +1760,7 @@ int dpni_get_queue(struct fsl_mc_io *mc_
                   struct dpni_queue *queue,
                   struct dpni_queue_id *qid)
  {
@@ -7467,7 +8303,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_queue *cmd_params;
        struct dpni_rsp_get_queue *rsp_params;
        int err;
-@@ -1463,6 +1840,8 @@ int dpni_get_queue(struct fsl_mc_io *mc_
+@@ -1463,6 +1804,8 @@ int dpni_get_queue(struct fsl_mc_io *mc_
   * @token:    Token of DPNI object
   * @page:     Selects the statistics page to retrieve, see
   *            DPNI_GET_STATISTICS output. Pages are numbered 0 to 2.
@@ -7476,7 +8312,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * @stat:     Structure containing the statistics
   *
   * Return:    '0' on Success; Error code otherwise.
-@@ -1471,9 +1850,10 @@ int dpni_get_statistics(struct fsl_mc_io
+@@ -1471,9 +1814,10 @@ int dpni_get_statistics(struct fsl_mc_io
                        u32 cmd_flags,
                        u16 token,
                        u8 page,
@@ -7488,7 +8324,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_statistics *cmd_params;
        struct dpni_rsp_get_statistics *rsp_params;
        int i, err;
-@@ -1484,6 +1864,7 @@ int dpni_get_statistics(struct fsl_mc_io
+@@ -1484,6 +1828,7 @@ int dpni_get_statistics(struct fsl_mc_io
                                          token);
        cmd_params = (struct dpni_cmd_get_statistics *)cmd.params;
        cmd_params->page_number = page;
@@ -7496,7 +8332,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
        /* send command to mc */
        err = mc_send_command(mc_io, &cmd);
-@@ -1499,6 +1880,29 @@ int dpni_get_statistics(struct fsl_mc_io
+@@ -1499,6 +1844,29 @@ int dpni_get_statistics(struct fsl_mc_io
  }
  
  /**
@@ -7526,7 +8362,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * dpni_set_taildrop() - Set taildrop per queue or TC
   * @mc_io:    Pointer to MC portal's I/O object
   * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
-@@ -1506,7 +1910,10 @@ int dpni_get_statistics(struct fsl_mc_io
+@@ -1506,7 +1874,10 @@ int dpni_get_statistics(struct fsl_mc_io
   * @cg_point: Congestion point
   * @q_type:   Queue type on which the taildrop is configured.
   *            Only Rx queues are supported for now
@@ -7538,7 +8374,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * @q_index:  Index of the queue if the DPNI supports multiple queues for
   *            traffic distribution. Ignored if CONGESTION_POINT is not 0.
   * @taildrop: Taildrop structure
-@@ -1522,7 +1929,7 @@ int dpni_set_taildrop(struct fsl_mc_io *
+@@ -1522,7 +1893,7 @@ int dpni_set_taildrop(struct fsl_mc_io *
                      u8 index,
                      struct dpni_taildrop *taildrop)
  {
@@ -7547,7 +8383,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_set_taildrop *cmd_params;
  
        /* prepare command */
-@@ -1550,7 +1957,10 @@ int dpni_set_taildrop(struct fsl_mc_io *
+@@ -1550,7 +1921,10 @@ int dpni_set_taildrop(struct fsl_mc_io *
   * @cg_point: Congestion point
   * @q_type:   Queue type on which the taildrop is configured.
   *            Only Rx queues are supported for now
@@ -7559,7 +8395,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * @q_index:  Index of the queue if the DPNI supports multiple queues for
   *            traffic distribution. Ignored if CONGESTION_POINT is not 0.
   * @taildrop: Taildrop structure
-@@ -1566,7 +1976,7 @@ int dpni_get_taildrop(struct fsl_mc_io *
+@@ -1566,7 +1940,7 @@ int dpni_get_taildrop(struct fsl_mc_io *
                      u8 index,
                      struct dpni_taildrop *taildrop)
  {
@@ -7568,7 +8404,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        struct dpni_cmd_get_taildrop *cmd_params;
        struct dpni_rsp_get_taildrop *rsp_params;
        int err;
-@@ -1594,3 +2004,109 @@ int dpni_get_taildrop(struct fsl_mc_io *
+@@ -1594,3 +1968,187 @@ int dpni_get_taildrop(struct fsl_mc_io *
  
        return 0;
  }
@@ -7636,11 +8472,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                                        cmd_flags,
 +                                        token);
 +      cmd_params = (struct dpni_cmd_set_rx_fs_dist *)cmd.params;
-+      cmd_params->dist_size = le16_to_cpu(cfg->dist_size);
++      cmd_params->dist_size = cpu_to_le16(cfg->dist_size);
 +      dpni_set_field(cmd_params->enable, RX_FS_DIST_ENABLE, cfg->enable);
 +      cmd_params->tc = cfg->tc;
-+      cmd_params->miss_flow_id = le16_to_cpu(cfg->fs_miss_flow_id);
-+      cmd_params->key_cfg_iova = le64_to_cpu(cfg->key_cfg_iova);
++      cmd_params->miss_flow_id = cpu_to_le16(cfg->fs_miss_flow_id);
++      cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
 +
 +      /* send command to mc*/
 +      return mc_send_command(mc_io, &cmd);
@@ -7670,17 +8506,131 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                                        cmd_flags,
 +                                        token);
 +      cmd_params = (struct dpni_cmd_set_rx_hash_dist *)cmd.params;
-+      cmd_params->dist_size = le16_to_cpu(cfg->dist_size);
++      cmd_params->dist_size = cpu_to_le16(cfg->dist_size);
 +      dpni_set_field(cmd_params->enable, RX_FS_DIST_ENABLE, cfg->enable);
 +      cmd_params->tc = cfg->tc;
-+      cmd_params->key_cfg_iova = le64_to_cpu(cfg->key_cfg_iova);
++      cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++/**
++ * dpni_add_fs_entry() - Add Flow Steering entry for a specific traffic class
++ *                    (to select a flow ID)
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPNI object
++ * @tc_id:    Traffic class selection (0-7)
++ * @index:    Location in the QoS table where to insert the entry.
++ *            Only relevant if MASKING is enabled for QoS
++ *            classification on this DPNI, it is ignored for exact match.
++ * @cfg:      Flow steering rule to add
++ * @action:   Action to be taken as result of a classification hit
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpni_add_fs_entry(struct fsl_mc_io *mc_io,
++                    u32 cmd_flags,
++                    u16 token,
++                    u8 tc_id,
++                    u16 index,
++                    const struct dpni_rule_cfg *cfg,
++                    const struct dpni_fs_action_cfg *action)
++{
++      struct dpni_cmd_add_fs_entry *cmd_params;
++      struct fsl_mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_FS_ENT,
++                                        cmd_flags,
++                                        token);
++      cmd_params = (struct dpni_cmd_add_fs_entry *)cmd.params;
++      cmd_params->tc_id = tc_id;
++      cmd_params->key_size = cfg->key_size;
++      cmd_params->index = cpu_to_le16(index);
++      cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
++      cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
++      cmd_params->options = cpu_to_le16(action->options);
++      cmd_params->flow_id = cpu_to_le16(action->flow_id);
++      cmd_params->flc = cpu_to_le64(action->flc);
++
++      /* send command to mc*/
++      return mc_send_command(mc_io, &cmd);
++}
++
++/**
++ * dpni_remove_fs_entry() - Remove Flow Steering entry from a specific
++ *                        traffic class
++ * @mc_io:    Pointer to MC portal's I/O object
++ * @cmd_flags:        Command flags; one or more of 'MC_CMD_FLAG_'
++ * @token:    Token of DPNI object
++ * @tc_id:    Traffic class selection (0-7)
++ * @cfg:      Flow steering rule to remove
++ *
++ * Return:    '0' on Success; Error code otherwise.
++ */
++int dpni_remove_fs_entry(struct fsl_mc_io *mc_io,
++                       u32 cmd_flags,
++                       u16 token,
++                       u8 tc_id,
++                       const struct dpni_rule_cfg *cfg)
++{
++      struct dpni_cmd_remove_fs_entry *cmd_params;
++      struct fsl_mc_command cmd = { 0 };
++
++      /* prepare command */
++      cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_FS_ENT,
++                                        cmd_flags,
++                                        token);
++      cmd_params = (struct dpni_cmd_remove_fs_entry *)cmd.params;
++      cmd_params->tc_id = tc_id;
++      cmd_params->key_size = cfg->key_size;
++      cmd_params->key_iova = cpu_to_le64(cfg->key_iova);
++      cmd_params->mask_iova = cpu_to_le64(cfg->mask_iova);
 +
 +      /* send command to mc*/
 +      return mc_send_command(mc_io, &cmd);
 +}
 --- a/drivers/staging/fsl-dpaa2/ethernet/dpni.h
 +++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.h
-@@ -52,6 +52,14 @@ struct fsl_mc_io;
+@@ -1,34 +1,6 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+ /* Copyright 2013-2016 Freescale Semiconductor Inc.
+  * Copyright 2016 NXP
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- * * Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * * Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * * Neither the name of the above-listed copyright holders nor the
+- * names of any contributors may be used to endorse or promote products
+- * derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGE.
+  */
+ #ifndef __FSL_DPNI_H
+ #define __FSL_DPNI_H
+@@ -52,6 +24,14 @@ struct fsl_mc_io;
   * Maximum number of buffer pools per DPNI
   */
  #define DPNI_MAX_DPBP                         8
@@ -7695,7 +8645,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  
  /**
   * All traffic classes considered; see dpni_set_queue()
-@@ -123,13 +131,15 @@ struct dpni_pools_cfg {
+@@ -123,13 +103,15 @@ struct dpni_pools_cfg {
        /**
         * struct pools - Buffer pools parameters
         * @dpbp_id: DPBP object ID
@@ -7713,7 +8663,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
        } pools[DPNI_MAX_DPBP];
  };
  
-@@ -476,6 +486,24 @@ union dpni_statistics {
+@@ -476,6 +458,24 @@ union dpni_statistics {
                u64 egress_confirmed_frames;
        } page_2;
        /**
@@ -7738,7 +8688,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
         * struct raw - raw statistics structure
         */
        struct {
-@@ -487,8 +515,13 @@ int dpni_get_statistics(struct fsl_mc_io
+@@ -487,8 +487,13 @@ int dpni_get_statistics(struct fsl_mc_io
                        u32                     cmd_flags,
                        u16                     token,
                        u8                      page,
@@ -7752,7 +8702,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  /**
   * Enable auto-negotiation
   */
-@@ -505,6 +538,10 @@ int dpni_get_statistics(struct fsl_mc_io
+@@ -505,6 +510,23 @@ int dpni_get_statistics(struct fsl_mc_io
   * Enable a-symmetric pause frames
   */
  #define DPNI_LINK_OPT_ASYM_PAUSE      0x0000000000000008ULL
@@ -7760,13 +8710,62 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 + * Enable priority flow control pause frames
 + */
 +#define DPNI_LINK_OPT_PFC_PAUSE               0x0000000000000010ULL
++/**
++ * Advertised link speeds
++ */
++#define DPNI_ADVERTISED_10BASET_FULL           0x0000000000000001ULL
++#define DPNI_ADVERTISED_100BASET_FULL          0x0000000000000002ULL
++#define DPNI_ADVERTISED_1000BASET_FULL         0x0000000000000004ULL
++#define DPNI_ADVERTISED_10000BASET_FULL        0x0000000000000010ULL
++#define DPNI_ADVERTISED_2500BASEX_FULL         0x0000000000000020ULL
++
++/**
++ * Advertise auto-negotiation enabled
++ */
++#define DPNI_ADVERTISED_AUTONEG                0x0000000000000008ULL
  
  /**
   * struct - Structure representing DPNI link configuration
-@@ -538,6 +575,23 @@ int dpni_get_link_state(struct fsl_mc_io
+@@ -514,6 +536,7 @@ int dpni_get_statistics(struct fsl_mc_io
+ struct dpni_link_cfg {
+       u32 rate;
+       u64 options;
++      u64 advertising;
+ };
+ int dpni_set_link_cfg(struct fsl_mc_io                        *mc_io,
+@@ -521,6 +544,11 @@ int dpni_set_link_cfg(struct fsl_mc_io
+                     u16                               token,
+                     const struct dpni_link_cfg        *cfg);
++int dpni_set_link_cfg_v2(struct fsl_mc_io             *mc_io,
++                       u32                            cmd_flags,
++                       u16                            token,
++                       const struct dpni_link_cfg     *cfg);
++
+ /**
+  * struct dpni_link_state - Structure representing DPNI link state
+  * @rate: Rate
+@@ -530,7 +558,10 @@ int dpni_set_link_cfg(struct fsl_mc_io
+ struct dpni_link_state {
+       u32     rate;
+       u64     options;
++      u64     supported;
++      u64     advertising;
+       int     up;
++      int     state_valid;
+ };
+ int dpni_get_link_state(struct fsl_mc_io      *mc_io,
+@@ -538,6 +569,28 @@ int dpni_get_link_state(struct fsl_mc_io
                        u16                     token,
                        struct dpni_link_state  *state);
  
++int dpni_get_link_state_v2(struct fsl_mc_io   *mc_io,
++                         u32                  cmd_flags,
++                         u16                  token,
++                         struct dpni_link_state       *state);
++
 +/**
 + * struct dpni_tx_shaping - Structure representing DPNI tx shaping configuration
 + * @rate_limit: rate in Mbps
@@ -7787,7 +8786,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
  int dpni_set_max_frame_length(struct fsl_mc_io        *mc_io,
                              u32               cmd_flags,
                              u16               token,
-@@ -639,6 +693,70 @@ int dpni_prepare_key_cfg(const struct dp
+@@ -639,6 +692,70 @@ int dpni_prepare_key_cfg(const struct dp
                         u8 *key_cfg_buf);
  
  /**
@@ -7858,7 +8857,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * struct dpni_rx_tc_dist_cfg - Rx traffic class distribution configuration
   * @dist_size: Set the distribution size;
   *    supported values: 1,2,3,4,6,7,8,12,14,16,24,28,32,48,56,64,96,
-@@ -784,6 +902,108 @@ enum dpni_congestion_point {
+@@ -784,6 +901,108 @@ enum dpni_congestion_point {
  };
  
  /**
@@ -7967,7 +8966,7 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
   * struct dpni_taildrop - Structure representing the taildrop
   * @enable:   Indicates whether the taildrop is active or not.
   * @units:    Indicates the unit of THRESHOLD. Queue taildrop only supports
-@@ -829,4 +1049,124 @@ struct dpni_rule_cfg {
+@@ -829,4 +1048,124 @@ struct dpni_rule_cfg {
        u8      key_size;
  };
  
@@ -8092,3 +9091,40 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com>
 +                        const struct dpni_rx_dist_cfg *cfg);
 +
  #endif /* __FSL_DPNI_H */
+--- a/drivers/staging/fsl-dpaa2/ethernet/net.h
++++ b/drivers/staging/fsl-dpaa2/ethernet/net.h
+@@ -1,33 +1,5 @@
++/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+ /* Copyright 2013-2015 Freescale Semiconductor Inc.
+- *
+- * Redistribution and use in source and binary forms, with or without
+- * modification, are permitted provided that the following conditions are met:
+- * * Redistributions of source code must retain the above copyright
+- * notice, this list of conditions and the following disclaimer.
+- * * Redistributions in binary form must reproduce the above copyright
+- * notice, this list of conditions and the following disclaimer in the
+- * documentation and/or other materials provided with the distribution.
+- * * Neither the name of the above-listed copyright holders nor the
+- * names of any contributors may be used to endorse or promote products
+- * derived from this software without specific prior written permission.
+- *
+- *
+- * ALTERNATIVELY, this software may be distributed under the terms of the
+- * GNU General Public License ("GPL") as published by the Free Software
+- * Foundation, either version 2 of that License or (at your option) any
+- * later version.
+- *
+- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
+- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+- * POSSIBILITY OF SUCH DAMAGE.
+  */
+ #ifndef __FSL_NET_H
+ #define __FSL_NET_H