aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch
diff options
context:
space:
mode:
authorYangbo Lu <yangbo.lu@nxp.com>2018-02-06 12:39:05 +0800
committerJohn Crispin <john@phrozen.org>2018-02-13 10:01:49 +0100
commit1a28100e68f4863ebc68625d5c6123ef0e5de8db (patch)
tree904bf6eec64dd2235c89e02bdc4033253512fbd1 /target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch
parent3a0fa1e7b860c600256f102d07356964821e7d7e (diff)
downloadupstream-1a28100e68f4863ebc68625d5c6123ef0e5de8db.tar.gz
upstream-1a28100e68f4863ebc68625d5c6123ef0e5de8db.tar.bz2
upstream-1a28100e68f4863ebc68625d5c6123ef0e5de8db.zip
layerscape: update patches-4.9 to LSDK1712
Patches changes - Updated patches-4.9 to NXP LSDK1712 linux-4.9. - Merged changes of patch 303 into integrated patch 201. - Split changes of patch 706 into dpaa part and dpaa2 part, and merged these changes into integrated patches 701 and 705. - Removed patch 819 since ehci-fsl driver could be compiled now. - Refreshed these patches. Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
Diffstat (limited to 'target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch')
-rw-r--r--target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch991
1 files changed, 830 insertions, 161 deletions
diff --git a/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch b/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch
index 51abc03254..c0f5819be9 100644
--- a/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch
+++ b/target/linux/layerscape/patches-4.9/705-dpaa2-support-layerscape.patch
@@ -1,15 +1,16 @@
-From 3a302437605308079db398b67000a77a4fe92da8 Mon Sep 17 00:00:00 2001
+From 72b1e89ab8edb5e883e812d07d0751fe2b140548 Mon Sep 17 00:00:00 2001
From: Yangbo Lu <yangbo.lu@nxp.com>
-Date: Mon, 25 Sep 2017 12:07:58 +0800
-Subject: [PATCH] dpaa2: support layerscape
+Date: Wed, 17 Jan 2018 15:12:58 +0800
+Subject: [PATCH 11/30] dpaa2: support layerscape
-This is a integrated patch for layerscape dpaa2 support.
+This is an integrated patch for layerscape dpaa2 support.
Signed-off-by: Bogdan Purcareata <bogdan.purcareata@nxp.com>
Signed-off-by: Ioana Radulescu <ruxandra.radulescu@nxp.com>
Signed-off-by: Razvan Stefanescu <razvan.stefanescu@nxp.com>
Signed-off-by: costi <constantin.tudor@freescale.com>
Signed-off-by: Catalin Horghidan <catalin.horghidan@nxp.com>
+Signed-off-by: Mathew McBride <matt@traverse.com.au>
Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
---
drivers/soc/fsl/ls2-console/Kconfig | 4 +
@@ -17,41 +18,41 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
drivers/soc/fsl/ls2-console/ls2-console.c | 284 ++
drivers/staging/fsl-dpaa2/ethernet/Makefile | 11 +
drivers/staging/fsl-dpaa2/ethernet/README | 186 ++
- .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c | 350 +++
+ .../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c | 352 ++
.../staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.h | 60 +
- .../staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h | 184 ++
- drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 3155 ++++++++++++++++++++
- drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 460 +++
- drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c | 856 ++++++
- drivers/staging/fsl-dpaa2/ethernet/dpkg.h | 176 ++
- drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h | 600 ++++
- drivers/staging/fsl-dpaa2/ethernet/dpni.c | 1770 +++++++++++
- drivers/staging/fsl-dpaa2/ethernet/dpni.h | 989 ++++++
+ .../staging/fsl-dpaa2/ethernet/dpaa2-eth-trace.h | 184 +
+ drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c | 3516 ++++++++++++++++++++
+ drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h | 499 +++
+ drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c | 864 +++++
+ drivers/staging/fsl-dpaa2/ethernet/dpkg.h | 176 +
+ drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h | 658 ++++
+ drivers/staging/fsl-dpaa2/ethernet/dpni.c | 1903 +++++++++++
+ drivers/staging/fsl-dpaa2/ethernet/dpni.h | 1053 ++++++
drivers/staging/fsl-dpaa2/ethernet/net.h | 480 +++
drivers/staging/fsl-dpaa2/ethsw/Kconfig | 6 +
drivers/staging/fsl-dpaa2/ethsw/Makefile | 10 +
- drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 851 ++++++
- drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 2762 +++++++++++++++++
- drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 1269 ++++++++
- drivers/staging/fsl-dpaa2/ethsw/switch.c | 1857 ++++++++++++
+ drivers/staging/fsl-dpaa2/ethsw/dpsw-cmd.h | 851 +++++
+ drivers/staging/fsl-dpaa2/ethsw/dpsw.c | 2762 +++++++++++++++
+ drivers/staging/fsl-dpaa2/ethsw/dpsw.h | 1269 +++++++
+ drivers/staging/fsl-dpaa2/ethsw/switch.c | 1857 +++++++++++
drivers/staging/fsl-dpaa2/evb/Kconfig | 7 +
drivers/staging/fsl-dpaa2/evb/Makefile | 10 +
drivers/staging/fsl-dpaa2/evb/dpdmux-cmd.h | 279 ++
drivers/staging/fsl-dpaa2/evb/dpdmux.c | 1112 +++++++
drivers/staging/fsl-dpaa2/evb/dpdmux.h | 453 +++
- drivers/staging/fsl-dpaa2/evb/evb.c | 1350 +++++++++
+ drivers/staging/fsl-dpaa2/evb/evb.c | 1350 ++++++++
drivers/staging/fsl-dpaa2/mac/Kconfig | 23 +
drivers/staging/fsl-dpaa2/mac/Makefile | 10 +
- drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 ++
+ drivers/staging/fsl-dpaa2/mac/dpmac-cmd.h | 172 +
drivers/staging/fsl-dpaa2/mac/dpmac.c | 620 ++++
- drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 +++
- drivers/staging/fsl-dpaa2/mac/mac.c | 666 +++++
+ drivers/staging/fsl-dpaa2/mac/dpmac.h | 342 ++
+ drivers/staging/fsl-dpaa2/mac/mac.c | 669 ++++
drivers/staging/fsl-dpaa2/rtc/Makefile | 10 +
drivers/staging/fsl-dpaa2/rtc/dprtc-cmd.h | 160 +
drivers/staging/fsl-dpaa2/rtc/dprtc.c | 746 +++++
- drivers/staging/fsl-dpaa2/rtc/dprtc.h | 172 ++
+ drivers/staging/fsl-dpaa2/rtc/dprtc.h | 172 +
drivers/staging/fsl-dpaa2/rtc/rtc.c | 243 ++
- 39 files changed, 22696 insertions(+)
+ 39 files changed, 23364 insertions(+)
create mode 100644 drivers/soc/fsl/ls2-console/Kconfig
create mode 100644 drivers/soc/fsl/ls2-console/Makefile
create mode 100644 drivers/soc/fsl/ls2-console/ls2-console.c
@@ -595,7 +596,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+non-standard driver stats can be consulted through ethtool -S option.
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth-debugfs.c
-@@ -0,0 +1,350 @@
+@@ -0,0 +1,352 @@
+
+/* Copyright 2015 Freescale Semiconductor Inc.
+ *
@@ -708,9 +709,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ int i, err;
+
+ seq_printf(file, "FQ stats for %s:\n", priv->net_dev->name);
-+ seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
-+ "VFQID", "CPU", "Type", "Frames", "Pending frames",
-+ "Congestion");
++ seq_printf(file, "%s%16s%16s%16s%16s%16s%16s\n",
++ "VFQID", "CPU", "Traffic Class", "Type", "Frames",
++ "Pending frames", "Congestion");
+
+ for (i = 0; i < priv->num_fqs; i++) {
+ fq = &priv->fq[i];
@@ -718,9 +719,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ if (err)
+ fcnt = 0;
+
-+ seq_printf(file, "%5d%16d%16s%16llu%16u%16llu\n",
++ seq_printf(file, "%5d%16d%16d%16s%16llu%16u%16llu\n",
+ fq->fqid,
+ fq->target_cpu,
++ fq->tc,
+ fq_type_to_str(fq),
+ fq->stats.frames,
+ fcnt,
@@ -756,19 +758,20 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ int i;
+
+ seq_printf(file, "Channel stats for %s:\n", priv->net_dev->name);
-+ seq_printf(file, "%s%16s%16s%16s%16s%16s\n",
++ seq_printf(file, "%s%16s%16s%16s%16s%16s%16s\n",
+ "CHID", "CPU", "Deq busy", "Frames", "CDANs",
-+ "Avg frm/CDAN");
++ "Avg frm/CDAN", "Buf count");
+
+ for (i = 0; i < priv->num_channels; i++) {
+ ch = priv->channel[i];
-+ seq_printf(file, "%4d%16d%16llu%16llu%16llu%16llu\n",
++ seq_printf(file, "%4d%16d%16llu%16llu%16llu%16llu%16d\n",
+ ch->ch_id,
+ ch->nctx.desired_cpu,
+ ch->stats.dequeue_portal_busy,
+ ch->stats.frames,
+ ch->stats.cdan,
-+ ch->stats.frames / ch->stats.cdan);
++ ch->stats.frames / ch->stats.cdan,
++ ch->buf_count);
+ }
+
+ return 0;
@@ -1198,7 +1201,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#include <trace/define_trace.h>
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.c
-@@ -0,0 +1,3155 @@
+@@ -0,0 +1,3516 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
@@ -1338,6 +1341,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u16 fd_offset = dpaa2_fd_get_offset(fd);
+ u32 fd_length = dpaa2_fd_get_len(fd);
+
++ ch->buf_count--;
++
+ skb = build_skb(fd_vaddr, DPAA2_ETH_SKB_SIZE);
+ if (unlikely(!skb))
+ return NULL;
@@ -1345,8 +1350,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ skb_reserve(skb, fd_offset);
+ skb_put(skb, fd_length);
+
-+ ch->buf_count--;
-+
+ return skb;
+}
+
@@ -1384,7 +1387,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ /* We build the skb around the first data buffer */
+ skb = build_skb(sg_vaddr, DPAA2_ETH_SKB_SIZE);
+ if (unlikely(!skb))
-+ return NULL;
++ goto err_build;
+
+ sg_offset = dpaa2_sg_get_offset(sge);
+ skb_reserve(skb, sg_offset);
@@ -1415,6 +1418,32 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ ch->buf_count -= i + 2;
+
+ return skb;
++
++err_build:
++ /* We still need to subtract the buffers used by this FD from our
++ * software counter
++ */
++ for (i = 0; i < DPAA2_ETH_MAX_SG_ENTRIES; i++)
++ if (dpaa2_sg_is_final(&sgt[i]))
++ break;
++ ch->buf_count -= i + 2;
++
++ return NULL;
++}
++
++static void free_bufs(struct dpaa2_eth_priv *priv, u64 *buf_array, int count)
++{
++ struct device *dev = priv->net_dev->dev.parent;
++ void *vaddr;
++ int i;
++
++ for (i = 0; i < count; i++) {
++ /* Same logic as on regular Rx path */
++ vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain, buf_array[i]);
++ dma_unmap_single(dev, buf_array[i], DPAA2_ETH_RX_BUF_SIZE,
++ DMA_FROM_DEVICE);
++ put_page(virt_to_head_page(vaddr));
++ }
+}
+
+/* Main Rx frame processing routine */
@@ -1722,7 +1751,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ dpaa2_fd_set_addr(fd, addr);
+ dpaa2_fd_set_len(fd, skb->len);
+
-+ fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA | FD_CTRL_PTV1;
++ fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA;
+
+ if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+ enable_tx_tstamp(fd, sgt_buf);
@@ -1779,7 +1808,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ dpaa2_fd_set_len(fd, skb->len);
+ dpaa2_fd_set_format(fd, dpaa2_fd_single);
+
-+ fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA | FD_CTRL_PTV1;
++ fd->simple.ctrl = DPAA2_FD_CTRL_ASAL | FD_CTRL_PTA;
+
+ if (priv->ts_tx_en && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)
+ enable_tx_tstamp(fd, buffer_start);
@@ -1798,7 +1827,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ */
+static void free_tx_fd(const struct dpaa2_eth_priv *priv,
+ const struct dpaa2_fd *fd,
-+ u32 *status)
++ u32 *status, bool in_napi)
+{
+ struct device *dev = priv->net_dev->dev.parent;
+ dma_addr_t fd_addr;
@@ -1877,7 +1906,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ kfree(skbh);
+
+ /* Move on with skb release */
-+ dev_kfree_skb(skb);
++ napi_consume_skb(skb, in_napi);
+}
+
+static int dpaa2_eth_tx(struct sk_buff *skb, struct net_device *net_dev)
@@ -1961,7 +1990,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ 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, NULL, false);
+ } else {
+ percpu_stats->tx_packets++;
+ percpu_stats->tx_bytes += dpaa2_fd_get_len(&fd);
@@ -2014,7 +2043,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ fd->simple.ctrl & DPAA2_FD_TX_ERR_MASK);
+ }
+
-+ free_tx_fd(priv, fd, check_fas_errors ? &status : NULL);
++ free_tx_fd(priv, fd, check_fas_errors ? &status : NULL, true);
+
+ /* if there are no errors, we're done */
+ if (likely(!errors))
@@ -2084,7 +2113,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
+ void *buf;
+ dma_addr_t addr;
-+ int i;
++ int i, err;
+
+ for (i = 0; i < DPAA2_ETH_BUFS_PER_CMD; i++) {
+ /* Allocate buffer visible to WRIOP + skb shared info +
@@ -2111,22 +2140,25 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ }
+
+release_bufs:
-+ /* In case the portal is busy, retry until successful.
-+ * The buffer release function would only fail if the QBMan portal
-+ * was busy, which implies portal contention (i.e. more CPUs than
-+ * portals, i.e. GPPs w/o affine DPIOs). For all practical purposes,
-+ * there is little we can realistically do, short of giving up -
-+ * in which case we'd risk depleting the buffer pool and never again
-+ * receiving the Rx interrupt which would kick-start the refill logic.
-+ * So just keep retrying, at the risk of being moved to ksoftirqd.
-+ */
-+ while (dpaa2_io_service_release(NULL, bpid, buf_array, i))
++ /* In case the portal is busy, retry until successful */
++ while ((err = dpaa2_io_service_release(NULL, bpid,
++ buf_array, i)) == -EBUSY)
+ cpu_relax();
++
++ /* If release command failed, clean up and bail out; not much
++ * else we can do about it
++ */
++ if (unlikely(err)) {
++ free_bufs(priv, buf_array, i);
++ return 0;
++ }
++
+ return i;
+
+err_map:
+ put_page(virt_to_head_page(buf));
+err_alloc:
++ /* If we managed to allocate at least some buffers, release them */
+ if (i)
+ goto release_bufs;
+
@@ -2169,10 +2201,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ */
+static void drain_bufs(struct dpaa2_eth_priv *priv, int count)
+{
-+ struct device *dev = priv->net_dev->dev.parent;
+ u64 buf_array[DPAA2_ETH_BUFS_PER_CMD];
-+ void *vaddr;
-+ int ret, i;
++ int ret;
+
+ do {
+ ret = dpaa2_io_service_acquire(NULL, priv->bpid,
@@ -2181,15 +2211,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ netdev_err(priv->net_dev, "dpaa2_io_service_acquire() failed\n");
+ return;
+ }
-+ for (i = 0; i < ret; i++) {
-+ /* Same logic as on regular Rx path */
-+ vaddr = dpaa2_eth_iova_to_virt(priv->iommu_domain,
-+ buf_array[i]);
-+ dma_unmap_single(dev, buf_array[i],
-+ DPAA2_ETH_RX_BUF_SIZE,
-+ DMA_FROM_DEVICE);
-+ put_page(virt_to_head_page(vaddr));
-+ }
++ free_bufs(priv, buf_array, ret);
+ } while (ret);
+}
+
@@ -2497,7 +2519,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+/** Fill in counters maintained by the GPP driver. These may be different from
+ * the hardware counters obtained by ethtool.
+ */
-+static void dpaa2_eth_get_stats(struct net_device *net_dev,
++static struct rtnl_link_stats64 *dpaa2_eth_get_stats(struct net_device *net_dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
@@ -2513,6 +2535,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ for (j = 0; j < num; j++)
+ netstats[j] += cpustats[j];
+ }
++ return stats;
+}
+
+static int dpaa2_eth_change_mtu(struct net_device *net_dev, int mtu)
@@ -3039,7 +3062,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+
+static void setup_fqs(struct dpaa2_eth_priv *priv)
+{
-+ int i;
++ int i, j;
+
+ /* We have one TxConf FQ per Tx flow. Tx queues MUST be at the
+ * beginning of the queue array.
@@ -3052,11 +3075,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ priv->fq[priv->num_fqs++].flowid = (u16)i;
+ }
+
-+ for (i = 0; i < dpaa2_eth_queue_count(priv); i++) {
-+ priv->fq[priv->num_fqs].type = DPAA2_RX_FQ;
-+ priv->fq[priv->num_fqs].consume = dpaa2_eth_rx;
-+ priv->fq[priv->num_fqs++].flowid = (u16)i;
-+ }
++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++)
++ for (j = 0; j < dpaa2_eth_queue_count(priv); j++) {
++ priv->fq[priv->num_fqs].type = DPAA2_RX_FQ;
++ priv->fq[priv->num_fqs].consume = dpaa2_eth_rx;
++ priv->fq[priv->num_fqs].tc = (u8)i;
++ priv->fq[priv->num_fqs++].flowid = (u16)j;
++ }
+
+#ifdef CONFIG_FSL_DPAA2_ETH_USE_ERR_QUEUE
+ /* We have exactly one Rx error queue per DPNI */
@@ -3299,9 +3324,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ dev_warn(dev, "Tx data offset (%d) not a multiple of 64B",
+ priv->tx_data_offset);
+
-+ /* Accommodate software annotation space (SWA) */
-+ priv->tx_data_offset += DPAA2_ETH_SWA_SIZE;
-+
+ /* Enable congestion notifications for Tx queues */
+ err = setup_tx_congestion(priv);
+ if (err)
@@ -3357,39 +3379,111 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ kfree(priv->cscn_unaligned);
+}
+
-+int setup_fqs_taildrop(struct dpaa2_eth_priv *priv,
-+ bool enable)
++static int set_queue_taildrop(struct dpaa2_eth_priv *priv,
++ struct dpni_taildrop *td)
+{
+ struct device *dev = priv->net_dev->dev.parent;
-+ struct dpni_taildrop td;
-+ int err = 0, i;
++ int err, i;
+
-+ td.enable = enable;
-+ td.threshold = DPAA2_ETH_TAILDROP_THRESH;
-+
-+ if (enable) {
-+ priv->num_bufs = DPAA2_ETH_NUM_BUFS_TD;
-+ priv->refill_thresh = DPAA2_ETH_REFILL_THRESH_TD;
-+ } else {
-+ priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC /
-+ priv->num_channels;
-+ priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD;
-+ }
+
+ for (i = 0; i < priv->num_fqs; i++) {
+ if (priv->fq[i].type != DPAA2_RX_FQ)
+ continue;
+
+ err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token,
-+ DPNI_CP_QUEUE, DPNI_QUEUE_RX, 0,
-+ priv->fq[i].flowid, &td);
++ DPNI_CP_QUEUE, DPNI_QUEUE_RX,
++ priv->fq[i].tc, priv->fq[i].flowid,
++ td);
+ if (err) {
+ dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err);
-+ break;
++ return err;
+ }
+ }
+
-+ return err;
++ return 0;
++}
++
++static int set_group_taildrop(struct dpaa2_eth_priv *priv,
++ struct dpni_taildrop *td)
++{
++ struct device *dev = priv->net_dev->dev.parent;
++ struct dpni_taildrop disable_td, *tc_td;
++ int i, err;
++
++ memset(&disable_td, 0, sizeof(struct dpni_taildrop));
++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
++ if (td->enable && dpaa2_eth_is_pfc_enabled(priv, i))
++ /* Do not set taildrop thresholds for PFC-enabled
++ * traffic classes. We will enable congestion
++ * notifications for them.
++ */
++ tc_td = &disable_td;
++ else
++ tc_td = td;
++
++ err = dpni_set_taildrop(priv->mc_io, 0, priv->mc_token,
++ DPNI_CP_GROUP, DPNI_QUEUE_RX,
++ i, 0, tc_td);
++ if (err) {
++ dev_err(dev, "dpni_set_taildrop() failed (%d)\n", err);
++ return err;
++ }
++ }
++ return 0;
++}
++
++/* Enable/disable Rx FQ taildrop
++ *
++ * Rx FQ taildrop is mutually exclusive with flow control and it only gets
++ * disabled when FC is active. Depending on FC status, we need to compute
++ * the maximum number of buffers in the pool differently, so use the
++ * opportunity to update max number of buffers as well.
++ */
++int set_rx_taildrop(struct dpaa2_eth_priv *priv)
++{
++ enum dpaa2_eth_td_cfg cfg = dpaa2_eth_get_td_type(priv);
++ struct dpni_taildrop td_queue, td_group;
++ int err = 0;
++
++ switch (cfg) {
++ case DPAA2_ETH_TD_NONE:
++ memset(&td_queue, 0, sizeof(struct dpni_taildrop));
++ memset(&td_group, 0, sizeof(struct dpni_taildrop));
++ priv->num_bufs = DPAA2_ETH_NUM_BUFS_FC /
++ priv->num_channels;
++ break;
++ case DPAA2_ETH_TD_QUEUE:
++ memset(&td_group, 0, sizeof(struct dpni_taildrop));
++ td_queue.enable = 1;
++ td_queue.units = DPNI_CONGESTION_UNIT_BYTES;
++ td_queue.threshold = DPAA2_ETH_TAILDROP_THRESH /
++ dpaa2_eth_tc_count(priv);
++ priv->num_bufs = DPAA2_ETH_NUM_BUFS_TD;
++ break;
++ case DPAA2_ETH_TD_GROUP:
++ memset(&td_queue, 0, sizeof(struct dpni_taildrop));
++ td_group.enable = 1;
++ td_group.units = DPNI_CONGESTION_UNIT_FRAMES;
++ td_group.threshold = NAPI_POLL_WEIGHT *
++ dpaa2_eth_queue_count(priv);
++ priv->num_bufs = NAPI_POLL_WEIGHT *
++ dpaa2_eth_tc_count(priv);
++ break;
++ default:
++ break;
++ }
++
++ err = set_queue_taildrop(priv, &td_queue);
++ if (err)
++ return err;
++
++ err = set_group_taildrop(priv, &td_group);
++ if (err)
++ return err;
++
++ priv->refill_thresh = priv->num_bufs - DPAA2_ETH_BUFS_PER_CMD;
++
++ return 0;
+}
+
+static int setup_rx_flow(struct dpaa2_eth_priv *priv,
@@ -3402,7 +3496,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ int err;
+
+ err = dpni_get_queue(priv->mc_io, 0, priv->mc_token,
-+ DPNI_QUEUE_RX, 0, fq->flowid, &q, &qid);
++ DPNI_QUEUE_RX, fq->tc, fq->flowid, &q, &qid);
+ if (err) {
+ dev_err(dev, "dpni_get_queue() failed (%d)\n", err);
+ return err;
@@ -3415,7 +3509,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ q.destination.priority = 1;
+ q.user_context = (u64)fq;
+ err = dpni_set_queue(priv->mc_io, 0, priv->mc_token,
-+ DPNI_QUEUE_RX, 0, fq->flowid, q_opt, &q);
++ DPNI_QUEUE_RX, fq->tc, fq->flowid, q_opt, &q);
+ if (err) {
+ dev_err(dev, "dpni_set_queue() failed (%d)\n", err);
+ return err;
@@ -3612,7 +3706,13 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ dist_cfg.dist_mode = DPNI_DIST_MODE_HASH;
+ }
+
-+ err = dpni_set_rx_tc_dist(priv->mc_io, 0, priv->mc_token, 0, &dist_cfg);
++ 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);
++ if (err)
++ break;
++ }
++
+ dma_unmap_single(dev, dist_cfg.key_cfg_iova,
+ DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE);
+ if (err)
@@ -3639,6 +3739,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ pools_params.num_dpbp = 1;
+ pools_params.pools[0].dpbp_id = priv->dpbp_dev->obj_desc.id;
+ pools_params.pools[0].backup_pool = 0;
++ pools_params.pools[0].priority_mask = 0xff;
+ 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) {
@@ -4124,6 +4225,264 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ device_remove_file(dev, &dpaa2_eth_attrs[i]);
+}
+
++#ifdef CONFIG_FSL_DPAA2_ETH_DCB
++static int dpaa2_eth_dcbnl_ieee_getpfc(struct net_device *net_dev,
++ struct ieee_pfc *pfc)
++{
++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
++ struct dpni_congestion_notification_cfg notification_cfg;
++ struct dpni_link_state state;
++ int err, i;
++
++ pfc->pfc_cap = dpaa2_eth_tc_count(priv);
++
++ err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
++ if (err) {
++ netdev_err(net_dev, "ERROR %d getting link state", err);
++ return err;
++ }
++
++ if (!(state.options & DPNI_LINK_OPT_PFC_PAUSE))
++ return 0;
++
++ priv->pfc.pfc_en = 0;
++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
++ err = dpni_get_congestion_notification(priv->mc_io, 0,
++ priv->mc_token,
++ DPNI_QUEUE_RX,
++ i, &notification_cfg);
++ if (err) {
++ netdev_err(net_dev, "Error %d getting congestion notif",
++ err);
++ return err;
++ }
++
++ if (notification_cfg.threshold_entry)
++ priv->pfc.pfc_en |= 1 << i;
++ }
++
++ pfc->pfc_en = priv->pfc.pfc_en;
++ pfc->mbc = priv->pfc.mbc;
++ pfc->delay = priv->pfc.delay;
++
++ return 0;
++}
++
++/* Configure ingress classification based on VLAN PCP */
++static int set_vlan_qos(struct dpaa2_eth_priv *priv)
++{
++ struct device *dev = priv->net_dev->dev.parent;
++ struct dpkg_profile_cfg kg_cfg = {0};
++ struct dpni_qos_tbl_cfg qos_cfg = {0};
++ struct dpni_rule_cfg key_params;
++ u8 *params_iova;
++ __be16 key, mask = cpu_to_be16(VLAN_PRIO_MASK);
++ int err = 0, i, j = 0;
++
++ if (priv->vlan_clsf_set)
++ return 0;
++
++ params_iova = kzalloc(DPAA2_CLASSIFIER_DMA_SIZE, GFP_KERNEL);
++ if (!params_iova)
++ return -ENOMEM;
++
++ kg_cfg.num_extracts = 1;
++ kg_cfg.extracts[0].type = DPKG_EXTRACT_FROM_HDR;
++ kg_cfg.extracts[0].extract.from_hdr.prot = NET_PROT_VLAN;
++ kg_cfg.extracts[0].extract.from_hdr.type = DPKG_FULL_FIELD;
++ kg_cfg.extracts[0].extract.from_hdr.field = NH_FLD_VLAN_TCI;
++
++ err = dpni_prepare_key_cfg(&kg_cfg, params_iova);
++ if (err) {
++ dev_err(dev, "dpkg_prepare_key_cfg failed: %d\n", err);
++ goto out_free;
++ }
++
++ /* Set QoS table */
++ qos_cfg.default_tc = 0;
++ qos_cfg.discard_on_miss = 0;
++ qos_cfg.key_cfg_iova = dma_map_single(dev, params_iova,
++ DPAA2_CLASSIFIER_DMA_SIZE,
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(dev, qos_cfg.key_cfg_iova)) {
++ dev_err(dev, "%s: DMA mapping failed\n", __func__);
++ err = -ENOMEM;
++ goto out_free;
++ }
++ err = dpni_set_qos_table(priv->mc_io, 0, priv->mc_token, &qos_cfg);
++ dma_unmap_single(dev, qos_cfg.key_cfg_iova,
++ DPAA2_CLASSIFIER_DMA_SIZE, DMA_TO_DEVICE);
++
++ if (err) {
++ dev_err(dev, "dpni_set_qos_table failed: %d\n", err);
++ goto out_free;
++ }
++
++ key_params.key_size = sizeof(key);
++
++ if (dpaa2_eth_fs_mask_enabled(priv)) {
++ key_params.mask_iova = dma_map_single(dev, &mask, sizeof(mask),
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(dev, key_params.mask_iova)) {
++ dev_err(dev, "DMA mapping failed %s\n", __func__);
++ err = -ENOMEM;
++ goto out_free;
++ }
++ } else {
++ key_params.mask_iova = 0;
++ }
++
++ key_params.key_iova = dma_map_single(dev, &key, sizeof(key),
++ DMA_TO_DEVICE);
++ if (dma_mapping_error(dev, key_params.key_iova)) {
++ dev_err(dev, "%s: DMA mapping failed\n", __func__);
++ err = -ENOMEM;
++ goto out_unmap_mask;
++ }
++
++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
++ key = cpu_to_be16(i << VLAN_PRIO_SHIFT);
++ dma_sync_single_for_device(dev, key_params.key_iova,
++ sizeof(key), DMA_TO_DEVICE);
++
++ err = dpni_add_qos_entry(priv->mc_io, 0, priv->mc_token,
++ &key_params, i, j++);
++ if (err) {
++ dev_err(dev, "dpni_add_qos_entry failed: %d\n", err);
++ goto out_unmap;
++ }
++ }
++
++ priv->vlan_clsf_set = true;
++
++out_unmap:
++ dma_unmap_single(dev, key_params.key_iova, sizeof(key), DMA_TO_DEVICE);
++out_unmap_mask:
++ if (key_params.mask_iova)
++ dma_unmap_single(dev, key_params.mask_iova, sizeof(mask),
++ DMA_TO_DEVICE);
++out_free:
++ kfree(params_iova);
++ return err;
++}
++
++static int dpaa2_eth_dcbnl_ieee_setpfc(struct net_device *net_dev,
++ struct ieee_pfc *pfc)
++{
++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
++ struct dpni_congestion_notification_cfg notification_cfg = {0};
++ struct dpni_link_state state = {0};
++ struct dpni_link_cfg cfg = {0};
++ int err = 0, i;
++
++ if (priv->pfc.pfc_en == pfc->pfc_en)
++ /* Same enabled mask, nothing to be done */
++ return 0;
++
++ err = set_vlan_qos(priv);
++ if (err)
++ return err;
++
++ err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state);
++ if (err) {
++ netdev_err(net_dev, "ERROR %d getting link state", err);
++ return err;
++ }
++
++ cfg.rate = state.rate;
++ cfg.options = state.options;
++ if (pfc->pfc_en)
++ cfg.options |= DPNI_LINK_OPT_PFC_PAUSE;
++ else
++ cfg.options &= ~DPNI_LINK_OPT_PFC_PAUSE;
++
++ err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg);
++ if (err) {
++ netdev_err(net_dev, "ERROR %d setting link cfg", err);
++ return err;
++ }
++
++ memcpy(&priv->pfc, pfc, sizeof(priv->pfc));
++
++ err = set_rx_taildrop(priv);
++ if (err)
++ return err;
++
++ /* configure congestion notifications */
++ notification_cfg.notification_mode = DPNI_CONG_OPT_FLOW_CONTROL;
++ notification_cfg.units = DPNI_CONGESTION_UNIT_FRAMES;
++ notification_cfg.message_iova = 0ULL;
++ notification_cfg.message_ctx = 0ULL;
++
++ for (i = 0; i < dpaa2_eth_tc_count(priv); i++) {
++ if (dpaa2_eth_is_pfc_enabled(priv, i)) {
++ notification_cfg.threshold_entry = NAPI_POLL_WEIGHT;
++ notification_cfg.threshold_exit = NAPI_POLL_WEIGHT / 2;
++ } else {
++ notification_cfg.threshold_entry = 0;
++ notification_cfg.threshold_exit = 0;
++ }
++
++ err = dpni_set_congestion_notification(priv->mc_io, 0,
++ priv->mc_token,
++ DPNI_QUEUE_RX,
++ i, &notification_cfg);
++ if (err) {
++ netdev_err(net_dev, "Error %d setting congestion notif",
++ err);
++ return err;
++ }
++ }
++
++ return 0;
++}
++
++static u8 dpaa2_eth_dcbnl_getdcbx(struct net_device *net_dev)
++{
++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
++
++ return priv->dcbx_mode;
++}
++
++static u8 dpaa2_eth_dcbnl_setdcbx(struct net_device *net_dev, u8 mode)
++{
++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
++
++ priv->dcbx_mode = mode;
++ return 0;
++}
++
++static u8 dpaa2_eth_dcbnl_getcap(struct net_device *net_dev, int capid, u8 *cap)
++{
++ struct dpaa2_eth_priv *priv = netdev_priv(net_dev);
++
++ switch (capid) {
++ case DCB_CAP_ATTR_PFC:
++ *cap = true;
++ break;
++ case DCB_CAP_ATTR_PFC_TCS:
++ *cap = 1 << dpaa2_eth_tc_count(priv);
++ break;
++ case DCB_CAP_ATTR_DCBX:
++ *cap = priv->dcbx_mode;
++ break;
++ default:
++ *cap = false;
++ break;
++ }
++
++ return 0;
++}
++
++const struct dcbnl_rtnl_ops dpaa2_eth_dcbnl_ops = {
++ .ieee_getpfc = dpaa2_eth_dcbnl_ieee_getpfc,
++ .ieee_setpfc = dpaa2_eth_dcbnl_ieee_setpfc,
++ .getdcbx = dpaa2_eth_dcbnl_getdcbx,
++ .setdcbx = dpaa2_eth_dcbnl_setdcbx,
++ .getcap = dpaa2_eth_dcbnl_getcap,
++};
++#endif
++
+static int dpaa2_eth_probe(struct fsl_mc_device *dpni_dev)
+{
+ struct device *dev;
@@ -4152,7 +4511,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ err = fsl_mc_portal_allocate(dpni_dev, FSL_MC_IO_ATOMIC_CONTEXT_PORTAL,
+ &priv->mc_io);
+ if (err) {
-+ dev_err(dev, "MC portal allocation failed\n");
++ dev_dbg(dev, "MC portal allocation failed\n");
++ err = -EPROBE_DEFER;
+ goto err_portal_alloc;
+ }
+
@@ -4178,10 +4538,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ if (err)
+ goto err_bind;
+
-+ /* Add a NAPI context for each channel */
-+ add_ch_napi(priv);
-+ enable_ch_napi(priv);
-+
+ /* Percpu statistics */
+ priv->percpu_stats = alloc_percpu(*priv->percpu_stats);
+ if (!priv->percpu_stats) {
@@ -4224,6 +4580,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ goto err_alloc_rings;
+
+ net_dev->ethtool_ops = &dpaa2_ethtool_ops;
++#ifdef CONFIG_FSL_DPAA2_ETH_DCB
++ net_dev->dcbnl_ops = &dpaa2_eth_dcbnl_ops;
++ priv->dcbx_mode = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
++#endif
++
++ /* Add a NAPI context for each channel */
++ add_ch_napi(priv);
++ enable_ch_napi(priv);
+
+ err = setup_irqs(dpni_dev);
+ if (err) {
@@ -4287,6 +4651,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#endif
+ dpaa2_eth_sysfs_remove(&net_dev->dev);
+
++ disable_ch_napi(priv);
++ del_ch_napi(priv);
++
+ unregister_netdev(net_dev);
+ dev_info(net_dev->dev.parent, "Removed interface %s\n", net_dev->name);
+
@@ -4298,9 +4665,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ free_rings(priv);
+ free_percpu(priv->percpu_stats);
+ free_percpu(priv->percpu_extras);
-+
-+ disable_ch_napi(priv);
-+ del_ch_napi(priv);
+ free_dpbp(priv);
+ free_dpio(priv);
+ free_dpni(priv);
@@ -4356,7 +4720,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+module_exit(dpaa2_eth_driver_exit);
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-eth.h
-@@ -0,0 +1,460 @@
+@@ -0,0 +1,499 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
@@ -4392,6 +4756,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#define __DPAA2_ETH_H
+
+#include <linux/atomic.h>
++#include <linux/dcbnl.h>
+#include <linux/netdevice.h>
+#include <linux/if_vlan.h>
+#include "../../fsl-mc/include/dpaa2-io.h"
@@ -4455,7 +4820,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#define DPAA2_ETH_RX_BUF_ALIGN 64
+#define DPAA2_ETH_RX_BUF_ALIGN_V1 256
+#define DPAA2_ETH_NEEDED_HEADROOM(p_priv) \
-+ ((p_priv)->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN)
++ ((p_priv)->tx_data_offset + DPAA2_ETH_TX_BUF_ALIGN - HH_DATA_MOD)
+
+/* rx_extra_head prevents reallocations in L3 processing. */
+#define DPAA2_ETH_SKB_SIZE \
@@ -4473,17 +4838,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+/* PTP nominal frequency 1GHz */
+#define DPAA2_PTP_NOMINAL_FREQ_PERIOD_NS 1
+
-+/* Leave enough extra space in the headroom to make sure the skb is
-+ * not realloc'd in forwarding scenarios.
-+ */
-+#define DPAA2_ETH_RX_HEAD_ROOM 192
-+
+/* We are accommodating a skb backpointer and some S/G info
+ * in the frame's software annotation. The hardware
+ * options are either 0 or 64, so we choose the latter.
+ */
+#define DPAA2_ETH_SWA_SIZE 64
+
++/* Extra headroom space requested to hardware, in order to make sure there's
++ * no realloc'ing in forwarding scenarios
++ */
++#define DPAA2_ETH_RX_HEAD_ROOM \
++ (DPAA2_ETH_TX_HWA_SIZE - DPAA2_ETH_RX_HWA_SIZE + \
++ DPAA2_ETH_TX_BUF_ALIGN)
++
+/* Must keep this struct smaller than DPAA2_ETH_SWA_SIZE */
+struct dpaa2_eth_swa {
+ struct sk_buff *skb;
@@ -4660,16 +5027,17 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ __u64 pull_err;
+};
+
++#define DPAA2_ETH_MAX_DPCONS NR_CPUS
++#define DPAA2_ETH_MAX_TCS 8
++
+/* Maximum number of queues associated with a DPNI */
-+#define DPAA2_ETH_MAX_RX_QUEUES 16
-+#define DPAA2_ETH_MAX_TX_QUEUES NR_CPUS
++#define DPAA2_ETH_MAX_RX_QUEUES (DPNI_MAX_DIST_SIZE * DPAA2_ETH_MAX_TCS)
++#define DPAA2_ETH_MAX_TX_QUEUES DPNI_MAX_SENDERS
+#define DPAA2_ETH_MAX_RX_ERR_QUEUES 1
+#define DPAA2_ETH_MAX_QUEUES (DPAA2_ETH_MAX_RX_QUEUES + \
+ DPAA2_ETH_MAX_TX_QUEUES + \
+ DPAA2_ETH_MAX_RX_ERR_QUEUES)
+
-+#define DPAA2_ETH_MAX_DPCONS NR_CPUS
-+
+enum dpaa2_eth_fq_type {
+ DPAA2_RX_FQ = 0,
+ DPAA2_TX_CONF_FQ,
@@ -4682,6 +5050,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u32 fqid;
+ u32 tx_qdbin;
+ u16 flowid;
++ u8 tc;
+ int target_cpu;
+ struct dpaa2_eth_channel *channel;
+ enum dpaa2_eth_fq_type type;
@@ -4788,6 +5157,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ struct dpaa2_eth_cls_rule *cls_rule;
+
+ struct dpni_tx_shaping_cfg shaping_cfg;
++
++ u8 dcbx_mode;
++ struct ieee_pfc pfc;
++ bool vlan_clsf_set;
+};
+
+#define dpaa2_eth_hash_enabled(priv) \
@@ -4813,13 +5186,43 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ return priv->dpni_attrs.num_queues;
+}
+
++static inline int dpaa2_eth_tc_count(struct dpaa2_eth_priv *priv)
++{
++ return priv->dpni_attrs.num_tcs;
++}
++
++static inline bool dpaa2_eth_is_pfc_enabled(struct dpaa2_eth_priv *priv,
++ int traffic_class)
++{
++ return priv->pfc.pfc_en & (1 << traffic_class);
++}
++
++enum dpaa2_eth_td_cfg {
++ DPAA2_ETH_TD_NONE,
++ DPAA2_ETH_TD_QUEUE,
++ DPAA2_ETH_TD_GROUP
++};
++
++static inline enum dpaa2_eth_td_cfg
++dpaa2_eth_get_td_type(struct dpaa2_eth_priv *priv)
++{
++ bool pfc_enabled = !!(priv->pfc.pfc_en);
++
++ if (pfc_enabled)
++ return DPAA2_ETH_TD_GROUP;
++ else if (priv->tx_pause_frames)
++ return DPAA2_ETH_TD_NONE;
++ else
++ return DPAA2_ETH_TD_QUEUE;
++}
++
+void check_cls_support(struct dpaa2_eth_priv *priv);
+
-+int setup_fqs_taildrop(struct dpaa2_eth_priv *priv, bool enable);
++int set_rx_taildrop(struct dpaa2_eth_priv *priv);
+#endif /* __DPAA2_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpaa2-ethtool.c
-@@ -0,0 +1,856 @@
+@@ -0,0 +1,864 @@
+/* Copyright 2014-2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
@@ -5052,7 +5455,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ if (current_tx_pause == pause->tx_pause)
+ goto out;
+
-+ err = setup_fqs_taildrop(priv, !pause->tx_pause);
++ priv->tx_pause_frames = pause->tx_pause;
++ err = set_rx_taildrop(priv);
+ if (err)
+ netdev_dbg(net_dev, "ERROR %d configuring taildrop", err);
+
@@ -5498,7 +5902,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ struct dpni_rule_cfg rule_cfg;
+ struct dpni_fs_action_cfg fs_act = { 0 };
+ void *dma_mem;
-+ int err = 0;
++ int err = 0, tc;
+
+ if (!dpaa2_eth_fs_enabled(priv)) {
+ netdev_err(net_dev, "dev does not support steering!\n");
@@ -5541,12 +5945,19 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ else
+ fs_act.flow_id = fs->ring_cookie;
+
-+ if (add)
-+ err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token,
-+ 0, fs->location, &rule_cfg, &fs_act);
-+ else
-+ err = dpni_remove_fs_entry(priv->mc_io, 0, priv->mc_token,
-+ 0, &rule_cfg);
++ for (tc = 0; tc < dpaa2_eth_tc_count(priv); tc++) {
++ if (add)
++ err = dpni_add_fs_entry(priv->mc_io, 0, priv->mc_token,
++ tc, fs->location, &rule_cfg,
++ &fs_act);
++ else
++ err = dpni_remove_fs_entry(priv->mc_io, 0,
++ priv->mc_token, tc,
++ &rule_cfg);
++
++ if (err)
++ break;
++ }
+
+ dma_unmap_single(dev, rule_cfg.key_iova,
+ rule_cfg.key_size * 2, DMA_TO_DEVICE);
@@ -5857,7 +6268,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#endif /* __FSL_DPKG_H_ */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni-cmd.h
-@@ -0,0 +1,600 @@
+@@ -0,0 +1,658 @@
+/* Copyright 2013-2016 Freescale Semiconductor Inc.
+ * Copyright 2016 NXP
+ *
@@ -5897,9 +6308,11 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#define DPNI_VER_MAJOR 7
+#define DPNI_VER_MINOR 0
+#define DPNI_CMD_BASE_VERSION 1
++#define DPNI_CMD_2ND_VERSION 2
+#define DPNI_CMD_ID_OFFSET 4
+
+#define DPNI_CMD(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_BASE_VERSION)
++#define DPNI_CMD_V2(id) (((id) << DPNI_CMD_ID_OFFSET) | DPNI_CMD_2ND_VERSION)
+
+#define DPNI_CMDID_OPEN DPNI_CMD(0x801)
+#define DPNI_CMDID_CLOSE DPNI_CMD(0x800)
@@ -5922,7 +6335,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#define DPNI_CMDID_GET_IRQ_STATUS DPNI_CMD(0x016)
+#define DPNI_CMDID_CLEAR_IRQ_STATUS DPNI_CMD(0x017)
+
-+#define DPNI_CMDID_SET_POOLS DPNI_CMD(0x200)
++#define DPNI_CMDID_SET_POOLS DPNI_CMD_V2(0x200)
+#define DPNI_CMDID_SET_ERRORS_BEHAVIOR DPNI_CMD(0x20B)
+
+#define DPNI_CMDID_GET_QDID DPNI_CMD(0x210)
@@ -5945,6 +6358,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+
+#define DPNI_CMDID_SET_RX_TC_DIST DPNI_CMD(0x235)
+
++#define DPNI_CMDID_SET_QOS_TBL DPNI_CMD(0x240)
++#define DPNI_CMDID_ADD_QOS_ENT DPNI_CMD(0x241)
+#define DPNI_CMDID_ADD_FS_ENT DPNI_CMD(0x244)
+#define DPNI_CMDID_REMOVE_FS_ENT DPNI_CMD(0x245)
+#define DPNI_CMDID_CLR_FS_ENT DPNI_CMD(0x246)
@@ -5985,13 +6400,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+
+#define DPNI_BACKUP_POOL(val, order) (((val) & 0x1) << (order))
+struct dpni_cmd_set_pools {
-+ /* cmd word 0 */
+ u8 num_dpbp;
+ u8 backup_pool_mask;
+ __le16 pad;
-+ /* cmd word 0..4 */
-+ __le32 dpbp_id[DPNI_MAX_DPBP];
-+ /* cmd word 4..6 */
++ struct {
++ __le16 dpbp_id;
++ u8 priority_mask;
++ u8 pad;
++ } pool[DPNI_MAX_DPBP];
+ __le16 buffer_size[DPNI_MAX_DPBP];
+};
+
@@ -6370,6 +6786,36 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ __le64 user_context;
+};
+
++#define DPNI_DISCARD_ON_MISS_SHIFT 0
++#define DPNI_DISCARD_ON_MISS_SIZE 1
++
++struct dpni_cmd_set_qos_table {
++ u32 pad;
++ u8 default_tc;
++ /* only the LSB */
++ u8 discard_on_miss;
++ u16 pad1[21];
++ u64 key_cfg_iova;
++};
++
++struct dpni_cmd_add_qos_entry {
++ u16 pad;
++ u8 tc_id;
++ u8 key_size;
++ u16 index;
++ u16 pad2;
++ u64 key_iova;
++ u64 mask_iova;
++};
++
++struct dpni_cmd_remove_qos_entry {
++ u8 pad1[3];
++ u8 key_size;
++ u32 pad2;
++ u64 key_iova;
++ u64 mask_iova;
++};
++
+struct dpni_cmd_add_fs_entry {
+ /* cmd word 0 */
+ u16 options;
@@ -6457,10 +6903,33 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u32 threshold_exit;
+};
+
++struct dpni_cmd_get_congestion_notification {
++ /* cmd word 0 */
++ u8 qtype;
++ u8 tc;
++};
++
++struct dpni_rsp_get_congestion_notification {
++ /* cmd word 0 */
++ u64 pad;
++ /* cmd word 1 */
++ u32 dest_id;
++ u16 notification_mode;
++ u8 dest_priority;
++ /* from LSB: dest_type: 4 units:2 */
++ u8 type_units;
++ /* cmd word 2 */
++ u64 message_iova;
++ /* cmd word 3 */
++ u64 message_ctx;
++ /* cmd word 4 */
++ u32 threshold_entry;
++ u32 threshold_exit;
++};
+#endif /* _FSL_DPNI_CMD_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.c
-@@ -0,0 +1,1770 @@
+@@ -0,0 +1,1903 @@
+/* Copyright 2013-2016 Freescale Semiconductor Inc.
+ * Copyright 2016 NXP
+ *
@@ -6661,7 +7130,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ cmd_params = (struct dpni_cmd_set_pools *)cmd.params;
+ cmd_params->num_dpbp = cfg->num_dpbp;
+ for (i = 0; i < DPNI_MAX_DPBP; i++) {
-+ cmd_params->dpbp_id[i] = cpu_to_le32(cfg->pools[i].dpbp_id);
++ cmd_params->pool[i].dpbp_id =
++ cpu_to_le16(cfg->pools[i].dpbp_id);
++ cmd_params->pool[i].priority_mask =
++ cfg->pools[i].priority_mask;
+ cmd_params->buffer_size[i] =
+ cpu_to_le16(cfg->pools[i].buffer_size);
+ cmd_params->backup_pool_mask |=
@@ -7837,6 +8309,82 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ return mc_send_command(mc_io, &cmd);
+}
+
++/*
++ * dpni_set_qos_table() - Set QoS mapping table
++ * @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: QoS table configuration
++ *
++ * This function and all QoS-related functions require that
++ *'max_tcs > 1' was set at DPNI creation.
++ *
++ * warning: Before calling this function, call dpkg_prepare_key_cfg() to
++ * prepare the key_cfg_iova parameter
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpni_set_qos_table(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ const struct dpni_qos_tbl_cfg *cfg)
++{
++ struct dpni_cmd_set_qos_table *cmd_params;
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_QOS_TBL,
++ cmd_flags,
++ token);
++ cmd_params = (struct dpni_cmd_set_qos_table *)cmd.params;
++ cmd_params->default_tc = cfg->default_tc;
++ cmd_params->key_cfg_iova = cpu_to_le64(cfg->key_cfg_iova);
++ dpni_set_field(cmd_params->discard_on_miss,
++ ENABLE,
++ cfg->discard_on_miss);
++
++ /* send command to mc*/
++ return mc_send_command(mc_io, &cmd);
++}
++
++/**
++ * dpni_add_qos_entry() - Add QoS mapping entry (to select a 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
++ * @cfg: QoS rule to add
++ * @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.
++ *
++ * Return: '0' on Success; Error code otherwise.
++ */
++int dpni_add_qos_entry(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ const struct dpni_rule_cfg *cfg,
++ u8 tc_id,
++ u16 index)
++{
++ struct dpni_cmd_add_qos_entry *cmd_params;
++ struct mc_command cmd = { 0 };
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_QOS_ENT,
++ cmd_flags,
++ token);
++ cmd_params = (struct dpni_cmd_add_qos_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);
++
++ /* 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)
@@ -7961,6 +8509,60 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+}
+
+/**
++ * dpni_get_congestion_notification() - Get traffic class congestion
++ * notification 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
++ * @qtype: Type of queue - Rx, Tx and Tx confirm types are supported
++ * @tc_id: Traffic class selection (0-7)
++ * @cfg: congestion notification configuration
++ *
++ * Return: '0' on Success; error code otherwise.
++ */
++int dpni_get_congestion_notification(
++ struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ enum dpni_queue_type qtype,
++ u8 tc_id,
++ struct dpni_congestion_notification_cfg *cfg)
++{
++ struct dpni_rsp_get_congestion_notification *rsp_params;
++ struct dpni_cmd_get_congestion_notification *cmd_params;
++ struct mc_command cmd = { 0 };
++ int err;
++
++ /* prepare command */
++ cmd.header = mc_encode_cmd_header(
++ DPNI_CMDID_GET_CONGESTION_NOTIFICATION,
++ cmd_flags,
++ token);
++ cmd_params = (struct dpni_cmd_get_congestion_notification *)cmd.params;
++ cmd_params->qtype = qtype;
++ cmd_params->tc = tc_id;
++
++ /* send command to mc*/
++ err = mc_send_command(mc_io, &cmd);
++ if (err)
++ return err;
++
++ rsp_params = (struct dpni_rsp_get_congestion_notification *)cmd.params;
++ cfg->units = dpni_get_field(rsp_params->type_units, CONG_UNITS);
++ cfg->threshold_entry = le32_to_cpu(rsp_params->threshold_entry);
++ cfg->threshold_exit = le32_to_cpu(rsp_params->threshold_exit);
++ cfg->message_ctx = le64_to_cpu(rsp_params->message_ctx);
++ cfg->message_iova = le64_to_cpu(rsp_params->message_iova);
++ cfg->notification_mode = le16_to_cpu(rsp_params->notification_mode);
++ cfg->dest_cfg.dest_id = le32_to_cpu(rsp_params->dest_id);
++ cfg->dest_cfg.priority = rsp_params->dest_priority;
++ cfg->dest_cfg.dest_type = dpni_get_field(rsp_params->type_units,
++ DEST_TYPE);
++
++ return 0;
++}
++
++/**
+ * dpni_set_queue() - Set queue parameters
+ * @mc_io: Pointer to MC portal's I/O object
+ * @cmd_flags: Command flags; one or more of 'MC_CMD_FLAG_'
@@ -8233,7 +8835,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+}
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/ethernet/dpni.h
-@@ -0,0 +1,989 @@
+@@ -0,0 +1,1053 @@
+/* Copyright 2013-2016 Freescale Semiconductor Inc.
+ * Copyright 2016 NXP
+ *
@@ -8288,6 +8890,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ * Maximum number of buffer pools per DPNI
+ */
+#define DPNI_MAX_DPBP 8
++/**
++ * Maximum number of senders
++ */
++#define DPNI_MAX_SENDERS 8
++/**
++ * Maximum distribution size
++ */
++#define DPNI_MAX_DIST_SIZE 8
+
+/**
+ * All traffic classes considered; see dpni_set_queue()
@@ -8359,13 +8969,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ /**
+ * struct pools - Buffer pools parameters
+ * @dpbp_id: DPBP object ID
++ * @priority_mask: priorities served by DPBP
+ * @buffer_size: Buffer size
+ * @backup_pool: Backup pool
+ */
+ struct {
-+ int dpbp_id;
++ u16 dpbp_id;
++ u8 priority_mask;
+ u16 buffer_size;
-+ int backup_pool;
++ u8 backup_pool;
+ } pools[DPNI_MAX_DPBP];
+};
+
@@ -8745,6 +9357,10 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ * Enable a-symmetric pause frames
+ */
+#define DPNI_LINK_OPT_ASYM_PAUSE 0x0000000000000008ULL
++/**
++ * Enable priority flow control pause frames
++ */
++#define DPNI_LINK_OPT_PFC_PAUSE 0x0000000000000010ULL
+
+/**
+ * struct - Structure representing DPNI link configuration
@@ -8894,6 +9510,26 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u8 *key_cfg_buf);
+
+/**
++ * struct dpni_qos_tbl_cfg - Structure representing QOS table configuration
++ * @key_cfg_iova: I/O virtual address of 256 bytes DMA-able memory filled with
++ * key extractions to be used as the QoS criteria by calling
++ * dpkg_prepare_key_cfg()
++ * @discard_on_miss: Set to '1' to discard frames in case of no match (miss);
++ * '0' to use the 'default_tc' in such cases
++ * @default_tc: Used in case of no-match and 'discard_on_miss'= 0
++ */
++struct dpni_qos_tbl_cfg {
++ u64 key_cfg_iova;
++ int discard_on_miss;
++ u8 default_tc;
++};
++
++int dpni_set_qos_table(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ const struct dpni_qos_tbl_cfg *cfg);
++
++/**
+ * 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,
@@ -9086,6 +9722,12 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ * sw-portal's DQRR, the DQRI interrupt is asserted immediately (if enabled)
+ */
+#define DPNI_CONG_OPT_INTR_COALESCING_DISABLED 0x00000020
++/**
++ * This congestion will trigger flow control or priority flow control.
++ * This will have effect only if flow control is enabled with
++ * dpni_set_link_cfg().
++ */
++#define DPNI_CONG_OPT_FLOW_CONTROL 0x00000040
+
+/**
+ * struct dpni_congestion_notification_cfg - congestion notification
@@ -9119,6 +9761,14 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u8 tc_id,
+ const struct dpni_congestion_notification_cfg *cfg);
+
++int dpni_get_congestion_notification(
++ struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ enum dpni_queue_type qtype,
++ u8 tc_id,
++ struct dpni_congestion_notification_cfg *cfg);
++
+/**
+ * struct dpni_taildrop - Structure representing the taildrop
+ * @enable: Indicates whether the taildrop is active or not.
@@ -9165,6 +9815,22 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ u8 key_size;
+};
+
++int dpni_add_qos_entry(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ const struct dpni_rule_cfg *cfg,
++ u8 tc_id,
++ u16 index);
++
++int dpni_remove_qos_entry(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token,
++ const struct dpni_rule_cfg *cfg);
++
++int dpni_clear_qos_table(struct fsl_mc_io *mc_io,
++ u32 cmd_flags,
++ u16 token);
++
+/**
+ * Discard matching traffic. If set, this takes precedence over any other
+ * configuration and matching traffic is always discarded.
@@ -15718,7 +16384,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ return 0;
+}
+
-+void ethsw_port_get_stats(struct net_device *netdev,
++struct rtnl_link_stats64 *ethsw_port_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *storage)
+{
+ struct ethsw_port_priv *port_priv = netdev_priv(netdev);
@@ -15778,7 +16444,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ if (err)
+ goto error;
+
-+ return;
++ return storage;
+
+error:
+ netdev_err(netdev, "dpsw_if_get_counter err %d\n", err);
@@ -19125,7 +19791,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ return 0;
+}
+
-+void evb_port_get_stats(struct net_device *netdev,
++struct rtnl_link_stats64 *evb_port_get_stats(struct net_device *netdev,
+ struct rtnl_link_stats64 *storage)
+{
+ struct evb_port_priv *port_priv = netdev_priv(netdev);
@@ -19202,7 +19868,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ if (unlikely(err))
+ goto error;
+
-+ return;
++ return storage;
+
+error:
+ netdev_err(netdev, "dpdmux_if_get_counter err %d\n", err);
@@ -20892,7 +21558,7 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+#endif /* __FSL_DPMAC_H */
--- /dev/null
+++ b/drivers/staging/fsl-dpaa2/mac/mac.c
-@@ -0,0 +1,666 @@
+@@ -0,0 +1,669 @@
+/* Copyright 2015 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
@@ -21014,15 +21680,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ dev_err(&priv->mc_dev->dev, "dpmac_set_link_state: %d\n", err);
+}
+
-+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
-+static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
-+ struct net_device *dev)
-+{
-+ /* we don't support I/O for now, drop the frame */
-+ dev_kfree_skb_any(skb);
-+ return NETDEV_TX_OK;
-+}
-+
+static int dpaa2_mac_open(struct net_device *netdev)
+{
+ /* start PHY state machine */
@@ -21047,6 +21704,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ return 0;
+}
+
++#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
++static netdev_tx_t dpaa2_mac_drop_frame(struct sk_buff *skb,
++ struct net_device *dev)
++{
++ /* we don't support I/O for now, drop the frame */
++ dev_kfree_skb_any(skb);
++ return NETDEV_TX_OK;
++}
++
+static int dpaa2_mac_get_settings(struct net_device *netdev,
+ struct ethtool_cmd *cmd)
+{
@@ -21207,9 +21873,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+}
+
+static const struct net_device_ops dpaa2_mac_ndo_ops = {
-+ .ndo_start_xmit = &dpaa2_mac_drop_frame,
+ .ndo_open = &dpaa2_mac_open,
+ .ndo_stop = &dpaa2_mac_stop,
++ .ndo_start_xmit = &dpaa2_mac_drop_frame,
+ .ndo_get_stats64 = &dpaa2_mac_get_stats,
+};
+
@@ -21437,10 +22103,9 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ }
+#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
+
-+ /* probe the PHY as a fixed-link if the link type declared in DPC
-+ * explicitly mandates this
++ /* probe the PHY as a fixed-link if there's a phy-handle defined
++ * in the device tree
+ */
-+
+ phy_node = of_parse_phandle(dpmac_node, "phy-handle", 0);
+ if (!phy_node) {
+ goto probe_fixed_link;
@@ -21492,12 +22157,8 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ dev_info(dev, "Registered fixed PHY.\n");
+ }
+
-+ /* start PHY state machine */
-+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+ dpaa2_mac_open(netdev);
-+#else /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
-+ phy_start(netdev->phydev);
-+#endif /* CONFIG_FSL_DPAA2_MAC_NETDEVS */
++
+ return 0;
+
+err_defer:
@@ -21521,6 +22182,15 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+{
+ struct device *dev = &mc_dev->dev;
+ struct dpaa2_mac_priv *priv = dev_get_drvdata(dev);
++ struct net_device *netdev = priv->netdev;
++
++ dpaa2_mac_stop(netdev);
++
++ if (phy_is_pseudo_fixed_link(netdev->phydev))
++ fixed_phy_unregister(netdev->phydev);
++ else
++ phy_disconnect(netdev->phydev);
++ netdev->phydev = NULL;
+
+#ifdef CONFIG_FSL_DPAA2_MAC_NETDEVS
+ unregister_netdev(priv->netdev);
@@ -21531,7 +22201,6 @@ Signed-off-by: Yangbo Lu <yangbo.lu@nxp.com>
+ free_netdev(priv->netdev);
+
+ dev_set_drvdata(dev, NULL);
-+ kfree(priv);
+
+ return 0;
+}