diff options
Diffstat (limited to 'target/linux/layerscape/patches-4.14/702-dpaa2-ethernet-support-layerscape.patch')
-rw-r--r-- | target/linux/layerscape/patches-4.14/702-dpaa2-ethernet-support-layerscape.patch | 3605 |
1 files changed, 2329 insertions, 1276 deletions
diff --git a/target/linux/layerscape/patches-4.14/702-dpaa2-ethernet-support-layerscape.patch b/target/linux/layerscape/patches-4.14/702-dpaa2-ethernet-support-layerscape.patch index 44cedd1237..9ccacba3ae 100644 --- a/target/linux/layerscape/patches-4.14/702-dpaa2-ethernet-support-layerscape.patch +++ b/target/linux/layerscape/patches-4.14/702-dpaa2-ethernet-support-layerscape.patch @@ -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, -+ ¬if_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, -+ ¬if_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,51 +1355,20 @@ static int dpaa2_eth_open(struct net_dev link_state_err: enable_err: @@ -3072,7 +3181,8 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com> - */ -static u32 drain_channel(struct dpaa2_eth_priv *priv, - struct dpaa2_eth_channel *ch) --{ ++static int dpaa2_eth_stop(struct net_device *net_dev) + { - u32 drained = 0, total = 0; - - do { @@ -3083,7 +3193,11 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com> - - return total; -} -- ++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev); ++ int dpni_enabled = 0; ++ int retries = 10, i; ++ int err = 0; + -static u32 drain_ingress_frames(struct dpaa2_eth_priv *priv) -{ - struct dpaa2_eth_channel *ch; @@ -3098,18 +3212,21 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com> - return drained; -} - - static int dpaa2_eth_stop(struct net_device *net_dev) - { - struct dpaa2_eth_priv *priv = netdev_priv(net_dev); - int dpni_enabled; +-static int dpaa2_eth_stop(struct net_device *net_dev) +-{ +- struct dpaa2_eth_priv *priv = netdev_priv(net_dev); +- int dpni_enabled; - int retries = 10; - u32 drained; -+ 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 +- +- netif_tx_stop_all_queues(net_dev); +- netif_carrier_off(net_dev); ++ netif_tx_stop_all_queues(net_dev); ++ netif_carrier_off(net_dev); + + /* Loop while dpni_disable() attempts to drain the egress FQs + * and confirm them back to us. +@@ -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 +3293,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 +3319,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 +3366,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 +3375,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 +3417,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 +3440,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 +3656,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 +3752,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 +3793,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 +3808,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 +3862,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 +3870,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 +3885,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 +3910,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 +3920,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, ¬if_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 +3929,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 +3953,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 +3998,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 +4008,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 +4026,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 +4042,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 +4049,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 +4070,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 +4216,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 +4264,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 +4315,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,161 +4331,265 @@ 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; + -+ key = &cls_cfg.extracts[cls_cfg.num_extracts]; ++ 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; ++ } ++} ++ ++/* 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,49 +2966,107 @@ 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++; ++ } ++ ++ dma_mem = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL); ++ if (!dma_mem) ++ return -ENOMEM; ++ ++ err = dpni_prepare_key_cfg(&cls_cfg, dma_mem); ++ if (err) { ++ dev_err(dev, "dpni_prepare_key_cfg error %d\n", err); ++ goto free_key; ++ } ++ ++ /* Prepare for setting the rx dist */ ++ 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"); ++ err = -ENOMEM; ++ goto free_key; ++ } ++ ++ 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); ++ } ++ ++ dma_unmap_single(dev, key_iova, DPAA2_CLASSIFIER_DMA_SIZE, ++ DMA_TO_DEVICE); ++ if (!err && type == DPAA2_ETH_RX_DIST_HASH) ++ priv->rx_hash_fields = rx_hash_fields; ++ ++free_key: ++ kfree(dma_mem); ++ return err; ++} ++ ++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; - priv->rx_hash_fields |= hash_fields[i].rxnfc_field; -+ hash_fields |= priv->dist_fields[i].rxnfc_field; ++ /* 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; } - 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; - +- return -ENOMEM; +- - err = dpni_prepare_key_cfg(&cls_cfg, dma_mem); -+ err = dpni_prepare_key_cfg(&cls_cfg, key_mem); - if (err) { - dev_err(dev, "dpni_prepare_key_cfg error %d\n", err); +- if (err) { +- dev_err(dev, "dpni_prepare_key_cfg error %d\n", err); - goto err_prep_key; -+ goto free_key; ++ if (!dpaa2_eth_fs_enabled(priv)) { ++ dev_dbg(dev, "Rx cls disabled in DPNI options\n"); ++ return -EOPNOTSUPP; } - memset(&dist_cfg, 0, sizeof(dist_cfg)); @@ -4355,57 +4599,43 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com> - 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, -+ DMA_TO_DEVICE); -+ if (dma_mapping_error(dev, key_iova)) { - dev_err(dev, "DMA mapping failed\n"); - err = -ENOMEM; +- dev_err(dev, "DMA mapping failed\n"); +- err = -ENOMEM; - goto err_dma_map; -+ goto free_key; ++ if (!dpaa2_eth_hash_enabled(priv)) { ++ dev_dbg(dev, "Rx cls disabled for single queue DPNIs\n"); ++ return -EOPNOTSUPP; } - 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 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 = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg); - dma_unmap_single(dev, dist_cfg.key_cfg_iova, - DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE); -- if (err) ++ err = dpaa2_eth_set_cls(priv->net_dev, DPAA2_ETH_DIST_ALL); + if (err) - 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; -+ } ++ return err; -err_dma_map: -err_prep_key: - kfree(dma_mem); -+ if (type != DPAA2_ETH_RX_DIST_FS) -+ priv->rx_hash_fields = hash_fields; +- return err; ++out: ++ priv->rx_cls_enabled = 1; + -+free_key: -+ kfree(key_mem); - return err; ++ return 0; } -@@ -2080,6 +2983,7 @@ static int bind_dpni(struct dpaa2_eth_pr + /* Bind the DPNI to its needed objects and resources: buffer pool, DPIOs, +@@ -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 +4643,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 +4677,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 +4689,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 +4704,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 +4715,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 +4726,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 +4756,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 +4772,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 +4793,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 +4803,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 +5197,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 +5206,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 +5218,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 +5228,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 +5244,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 +5288,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 +5305,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 +5314,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 +5325,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 +5363,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 +5417,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 +5484,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 +5543,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 +5565,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 +5581,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 +5619,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 +5631,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 +5643,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 +5651,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 +5679,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 +5718,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 +5725,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 +5783,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 +5811,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) ++ ++#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) + -+/* 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) ++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 +5864,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 +5880,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 +5913,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 +5988,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 +6018,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 +6144,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 +6218,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 +6230,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 +6308,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 +6530,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; ++ int i, rules = 0; + -+ err = do_cls(net_dev, fs, true); -+ if (err) -+ return err; ++ for (i = 0; i < dpaa2_eth_fs_count(priv); i++) ++ if (priv->cls_rule[i].in_use) ++ rules++; + -+ priv->cls_rule[fs->location].in_use = true; -+ priv->cls_rule[fs->location].fs = *fs; -+ -+ 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 +6712,59 @@ Signed-off-by: Biwen Li <biwen.li@nxp.com> + rxnfc->rule_cnt = j; + rxnfc->data = rule_cnt; + break; -+ default: return -EOPNOTSUPP; } -@@ -270,8 +868,11 @@ const struct ethtool_ops dpaa2_ethtool_o +@@ -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; ++ } ++ ++ 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 +6775,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 +7226,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 +7235,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 +7265,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 +7275,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 +7294,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 +7302,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 +7365,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 +7390,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 +7454,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 +7536,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 +7581,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 +7590,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 +7599,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 +7611,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 +7620,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 +7629,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 +7638,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 +7647,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 +7656,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 +7665,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 +7674,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 +7683,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 +7692,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 +7701,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 +7710,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 +7719,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 +7728,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 +7737,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 +7746,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 +7755,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 +7764,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 +7773,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 +7782,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 +7828,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 +7913,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 +7922,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 +7931,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 +7940,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 +7949,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 +7958,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 +7967,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 +7976,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 +7985,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 +7994,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 +8003,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 +8012,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 +8021,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 +8077,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 +8086,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 +8197,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 +8302,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 +8311,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 +8320,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 +8329,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 +8341,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 +8349,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 +8379,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 +8391,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 +8400,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 +8412,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 +8421,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 +8489,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 +8523,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 +8662,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 +8680,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 +8705,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 +8719,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 +8727,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 +8803,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 +8874,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 +8983,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 +9108,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 |