[Arm-dev] [PATCH v2 07/11] Integrate upstream patches for X-Gene Enet driver
Duc Dang
dhdang at apm.com
Fri Nov 11 19:02:36 UTC 2016
Signed-off-by: Duc Dang <dhdang at apm.com>
---
...net-xgene-fix-error-handling-during-reset.patch | 72 +++++
...-net-xgene-fix-backward-compatibility-fix.patch | 47 ++++
...t-apm-xgene-use-phydev-from-struct-net_de.patch | 150 +++++++++++
...014-drivers-net-xgene-Fix-MSS-programming.patch | 297 +++++++++++++++++++++
...net-xgene-fix-Use-GPIO-to-get-link-status.patch | 91 +++++++
...-xgene-fix-Disable-coalescing-on-v1-hardw.patch | 61 +++++
...-xgene-fix-Coalescing-values-for-v2-hardw.patch | 67 +++++
SPECS/kernel-aarch64.spec | 15 ++
8 files changed, 800 insertions(+)
create mode 100644 SOURCES/1011-net-xgene-fix-error-handling-during-reset.patch
create mode 100644 SOURCES/1012-net-xgene-fix-backward-compatibility-fix.patch
create mode 100644 SOURCES/1013-net-ethernet-apm-xgene-use-phydev-from-struct-net_de.patch
create mode 100644 SOURCES/1014-drivers-net-xgene-Fix-MSS-programming.patch
create mode 100644 SOURCES/1015-drivers-net-xgene-fix-Use-GPIO-to-get-link-status.patch
create mode 100644 SOURCES/1016-drivers-net-xgene-fix-Disable-coalescing-on-v1-hardw.patch
create mode 100644 SOURCES/1017-drivers-net-xgene-fix-Coalescing-values-for-v2-hardw.patch
diff --git a/SOURCES/1011-net-xgene-fix-error-handling-during-reset.patch b/SOURCES/1011-net-xgene-fix-error-handling-during-reset.patch
new file mode 100644
index 0000000..e10b74f
--- /dev/null
+++ b/SOURCES/1011-net-xgene-fix-error-handling-during-reset.patch
@@ -0,0 +1,72 @@
+From 98ccf422fa923fe6d9288980faef4c1257387282 Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Fri, 26 Aug 2016 17:25:46 +0200
+Subject: [PATCH 1011/1018] net/xgene: fix error handling during reset
+
+The newly added reset logic uses helper functions for the MMIO that
+may fail. However, when the read operation fails, we end up writing
+back uninitialized data to the register, as gcc warns:
+
+drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c: In function 'xgene_enet_link_state':
+drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c:213:2: error: 'data' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c:209:6: note: 'data' was declared here
+ u32 data;
+
+We already print a warning to the console log if that happens,
+the best alternative that I can see is skip the rest of the reset
+sequence if the register value cannot be read: Most likely the
+write would fail as well, and if it succeeded, worse things could
+happen.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Fixes: 3eb7cb9dc946 ("drivers: net: xgene: XFI PCS reset when link is down")
+Cc: Fushen Chen <fchen at apm.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+index d672e71..279ee27 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+@@ -155,19 +155,23 @@ static void xgene_enet_rd_mac(struct xgene_enet_pdata *pdata,
+ rd_addr);
+ }
+
+-static void xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
++static bool xgene_enet_rd_pcs(struct xgene_enet_pdata *pdata,
+ u32 rd_addr, u32 *rd_data)
+ {
+ void __iomem *addr, *rd, *cmd, *cmd_done;
++ bool success;
+
+ addr = pdata->pcs_addr + PCS_ADDR_REG_OFFSET;
+ rd = pdata->pcs_addr + PCS_READ_REG_OFFSET;
+ cmd = pdata->pcs_addr + PCS_COMMAND_REG_OFFSET;
+ cmd_done = pdata->pcs_addr + PCS_COMMAND_DONE_REG_OFFSET;
+
+- if (!xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data))
++ success = xgene_enet_rd_indirect(addr, rd, cmd, cmd_done, rd_addr, rd_data);
++ if (!success)
+ netdev_err(pdata->ndev, "PCS read failed, addr: %04x\n",
+ rd_addr);
++
++ return success;
+ }
+
+ static int xgene_enet_ecc_init(struct xgene_enet_pdata *pdata)
+@@ -208,7 +212,9 @@ static void xgene_pcs_reset(struct xgene_enet_pdata *pdata)
+ {
+ u32 data;
+
+- xgene_enet_rd_pcs(pdata, PCS_CONTROL_1, &data);
++ if (!xgene_enet_rd_pcs(pdata, PCS_CONTROL_1, &data))
++ return;
++
+ xgene_enet_wr_pcs(pdata, PCS_CONTROL_1, data | PCS_CTRL_PCS_RST);
+ xgene_enet_wr_pcs(pdata, PCS_CONTROL_1, data & ~PCS_CTRL_PCS_RST);
+ }
+--
+1.8.3.1
+
diff --git a/SOURCES/1012-net-xgene-fix-backward-compatibility-fix.patch b/SOURCES/1012-net-xgene-fix-backward-compatibility-fix.patch
new file mode 100644
index 0000000..c2a3712
--- /dev/null
+++ b/SOURCES/1012-net-xgene-fix-backward-compatibility-fix.patch
@@ -0,0 +1,47 @@
+From 76ba1e7db4a58d90d8ec9a81df4506913535da5a Mon Sep 17 00:00:00 2001
+From: Arnd Bergmann <arnd at arndb.de>
+Date: Mon, 29 Aug 2016 14:37:14 +0200
+Subject: [PATCH 1012/1018] net: xgene: fix backward compatibility fix
+
+A bugfix for backward compatibility handling introduced undefined
+behavior for the case that of_parse_phandle() does not return
+a valid entry, as "gcc -Wmaybe-unused" reports:
+
+drivers/net/ethernet/apm/xgene/xgene_enet_hw.c: In function 'xgene_enet_phy_connect':
+drivers/net/ethernet/apm/xgene/xgene_enet_hw.c:776:6: error: 'phy_dev' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+drivers/net/ethernet/apm/xgene/xgene_enet_hw.c: In function 'xgene_enet_mdio_config':
+drivers/net/ethernet/apm/xgene/xgene_enet_hw.c:776:6: error: 'phy_dev' may be used uninitialized in this function [-Werror=maybe-uninitialized]
+
+We can work around this by removing the check for zero "np", as
+of_phy_connect() will correctly handle a NULL argument so we fall
+back into the normal error handling case.
+
+Note that I had previously fixed another bug that resulted in the
+exact same warning, but this is a different problem that was
+introduced after my original fix.
+
+Signed-off-by: Arnd Bergmann <arnd at arndb.de>
+Fixes: 03377e381bf4 ("drivers: net: xgene: Fix backward compatibility")
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+index 126f631..8352334 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+@@ -762,10 +762,6 @@ int xgene_enet_phy_connect(struct net_device *ndev)
+ if (dev->of_node) {
+ for (i = 0 ; i < 2; i++) {
+ np = of_parse_phandle(dev->of_node, "phy-handle", i);
+-
+- if (!np)
+- continue;
+-
+ phy_dev = of_phy_connect(ndev, np,
+ &xgene_enet_adjust_link,
+ 0, pdata->phy_mode);
+--
+1.8.3.1
+
diff --git a/SOURCES/1013-net-ethernet-apm-xgene-use-phydev-from-struct-net_de.patch b/SOURCES/1013-net-ethernet-apm-xgene-use-phydev-from-struct-net_de.patch
new file mode 100644
index 0000000..b057d0f
--- /dev/null
+++ b/SOURCES/1013-net-ethernet-apm-xgene-use-phydev-from-struct-net_de.patch
@@ -0,0 +1,150 @@
+From a5088e0b96469357d3ccc4ae729f174b7dc9f671 Mon Sep 17 00:00:00 2001
+From: Philippe Reynes <tremyfr at gmail.com>
+Date: Wed, 9 Nov 2016 18:19:05 -0600
+Subject: [PATCH 1013/1018] net: ethernet: apm: xgene: use phydev from struct
+ net_device
+
+The private structure contain a pointer to phydev, but the structure
+net_device already contain such pointer. So we can remove the pointer
+phy_dev in the private structure, and update the driver to use the
+one contained in struct net_device.
+
+Signed-off-by: Philippe Reynes <tremyfr at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+
+[Apply from upstream commit 4.8 to CentOS 7.3 AltArch]
+Signed-off-by: Duc Dang <dhdang at apm.com>
+---
+ .../net/ethernet/apm/xgene/xgene_enet_ethtool.c | 4 ++--
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 24 +++++++++++-----------
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 8 ++++----
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 -
+ 4 files changed, 18 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+index 22a7b26..e1f44ae 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c
+@@ -57,7 +57,7 @@ static void xgene_get_drvinfo(struct net_device *ndev,
+ static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+- struct phy_device *phydev = pdata->phy_dev;
++ struct phy_device *phydev = ndev->phydev;
+
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+ if (phydev == NULL)
+@@ -96,7 +96,7 @@ static int xgene_get_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ static int xgene_set_settings(struct net_device *ndev, struct ethtool_cmd *cmd)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+- struct phy_device *phydev = pdata->phy_dev;
++ struct phy_device *phydev = ndev->phydev;
+
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_RGMII) {
+ if (!phydev)
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+index 8352334..36b478f 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+@@ -713,7 +713,7 @@ static void xgene_enet_adjust_link(struct net_device *ndev)
+ {
+ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
+ const struct xgene_mac_ops *mac_ops = pdata->mac_ops;
+- struct phy_device *phydev = pdata->phy_dev;
++ struct phy_device *phydev = ndev->phydev;
+
+ if (phydev->link) {
+ if (pdata->phy_speed != phydev->speed) {
+@@ -774,15 +774,13 @@ int xgene_enet_phy_connect(struct net_device *ndev)
+ netdev_err(ndev, "Could not connect to PHY\n");
+ return -ENODEV;
+ }
+-
+- pdata->phy_dev = phy_dev;
+ } else {
+ #ifdef CONFIG_ACPI
+ adev = acpi_phy_find_device(dev);
+ if (adev)
+- pdata->phy_dev = adev->driver_data;
+-
+- phy_dev = pdata->phy_dev;
++ phy_dev = adev->driver_data;
++ else
++ phy_dev = NULL;
+
+ if (!phy_dev ||
+ phy_connect_direct(ndev, phy_dev, &xgene_enet_adjust_link,
+@@ -848,8 +846,6 @@ static int xgene_mdiobus_register(struct xgene_enet_pdata *pdata,
+ if (!phy)
+ return -EIO;
+
+- pdata->phy_dev = phy;
+-
+ return ret;
+ }
+
+@@ -889,14 +885,18 @@ int xgene_enet_mdio_config(struct xgene_enet_pdata *pdata)
+
+ void xgene_enet_phy_disconnect(struct xgene_enet_pdata *pdata)
+ {
+- if (pdata->phy_dev)
+- phy_disconnect(pdata->phy_dev);
++ struct net_device *ndev = pdata->ndev;
++
++ if (ndev->phydev)
++ phy_disconnect(ndev->phydev);
+ }
+
+ void xgene_enet_mdio_remove(struct xgene_enet_pdata *pdata)
+ {
+- if (pdata->phy_dev)
+- phy_disconnect(pdata->phy_dev);
++ struct net_device *ndev = pdata->ndev;
++
++ if (ndev->phydev)
++ phy_disconnect(ndev->phydev);
+
+ mdiobus_unregister(pdata->mdio_bus);
+ mdiobus_free(pdata->mdio_bus);
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index b8b9495..522ba92 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -748,8 +748,8 @@ static int xgene_enet_open(struct net_device *ndev)
+ if (ret)
+ return ret;
+
+- if (pdata->phy_dev) {
+- phy_start(pdata->phy_dev);
++ if (ndev->phydev) {
++ phy_start(ndev->phydev);
+ } else {
+ schedule_delayed_work(&pdata->link_work, PHY_POLL_LINK_OFF);
+ netif_carrier_off(ndev);
+@@ -772,8 +772,8 @@ static int xgene_enet_close(struct net_device *ndev)
+ mac_ops->tx_disable(pdata);
+ mac_ops->rx_disable(pdata);
+
+- if (pdata->phy_dev)
+- phy_stop(pdata->phy_dev);
++ if (ndev->phydev)
++ phy_stop(ndev->phydev);
+ else
+ cancel_delayed_work_sync(&pdata->link_work);
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index b339fc1..7735371 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -174,7 +174,6 @@ struct xgene_cle_ops {
+ struct xgene_enet_pdata {
+ struct net_device *ndev;
+ struct mii_bus *mdio_bus;
+- struct phy_device *phy_dev;
+ int phy_speed;
+ struct clk *clk;
+ struct platform_device *pdev;
+--
+1.8.3.1
+
diff --git a/SOURCES/1014-drivers-net-xgene-Fix-MSS-programming.patch b/SOURCES/1014-drivers-net-xgene-Fix-MSS-programming.patch
new file mode 100644
index 0000000..2954784
--- /dev/null
+++ b/SOURCES/1014-drivers-net-xgene-Fix-MSS-programming.patch
@@ -0,0 +1,297 @@
+From 96703b9e54070f674bb14001c6928d19537c33d1 Mon Sep 17 00:00:00 2001
+From: Iyappan Subramanian <isubramanian at apm.com>
+Date: Thu, 22 Sep 2016 15:47:33 -0700
+Subject: [PATCH 1014/1018] drivers: net: xgene: Fix MSS programming
+
+Current driver programs static value of MSS in hardware register for TSO
+offload engine to segment the TCP payload regardless the MSS value
+provided by network stack.
+
+This patch fixes this by programming hardware registers with the
+stack provided MSS value.
+
+Since the hardware has the limitation of having only 4 MSS registers,
+this patch uses reference count of mss values being used.
+
+Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
+Signed-off-by: Toan Le <toanle at apm.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 7 ++
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 90 ++++++++++++++++++-----
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 8 +-
+ drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 18 ++++-
+ 4 files changed, 100 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+index 8a8d055..8456337 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+@@ -237,6 +237,8 @@ enum xgene_enet_rm {
+ #define TCPHDR_LEN 6
+ #define IPHDR_POS 6
+ #define IPHDR_LEN 6
++#define MSS_POS 20
++#define MSS_LEN 2
+ #define EC_POS 22 /* Enable checksum */
+ #define EC_LEN 1
+ #define ET_POS 23 /* Enable TSO */
+@@ -253,6 +255,11 @@ enum xgene_enet_rm {
+
+ #define LAST_BUFFER (0x7800ULL << BUFDATALEN_POS)
+
++#define TSO_MSS0_POS 0
++#define TSO_MSS0_LEN 14
++#define TSO_MSS1_POS 16
++#define TSO_MSS1_LEN 14
++
+ struct xgene_enet_raw_desc {
+ __le64 m0;
+ __le64 m1;
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 522ba92..429f18f 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -137,6 +137,7 @@ static irqreturn_t xgene_enet_rx_irq(const int irq, void *data)
+ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ struct xgene_enet_raw_desc *raw_desc)
+ {
++ struct xgene_enet_pdata *pdata = netdev_priv(cp_ring->ndev);
+ struct sk_buff *skb;
+ struct device *dev;
+ skb_frag_t *frag;
+@@ -144,6 +145,7 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ u16 skb_index;
+ u8 status;
+ int i, ret = 0;
++ u8 mss_index;
+
+ skb_index = GET_VAL(USERINFO, le64_to_cpu(raw_desc->m0));
+ skb = cp_ring->cp_skb[skb_index];
+@@ -160,6 +162,13 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ DMA_TO_DEVICE);
+ }
+
++ if (GET_BIT(ET, le64_to_cpu(raw_desc->m3))) {
++ mss_index = GET_VAL(MSS, le64_to_cpu(raw_desc->m3));
++ spin_lock(&pdata->mss_lock);
++ pdata->mss_refcnt[mss_index]--;
++ spin_unlock(&pdata->mss_lock);
++ }
++
+ /* Checking for error */
+ status = GET_VAL(LERR, le64_to_cpu(raw_desc->m0));
+ if (unlikely(status > 2)) {
+@@ -178,15 +187,53 @@ static int xgene_enet_tx_completion(struct xgene_enet_desc_ring *cp_ring,
+ return ret;
+ }
+
+-static u64 xgene_enet_work_msg(struct sk_buff *skb)
++static int xgene_enet_setup_mss(struct net_device *ndev, u32 mss)
++{
++ struct xgene_enet_pdata *pdata = netdev_priv(ndev);
++ bool mss_index_found = false;
++ int mss_index;
++ int i;
++
++ spin_lock(&pdata->mss_lock);
++
++ /* Reuse the slot if MSS matches */
++ for (i = 0; !mss_index_found && i < NUM_MSS_REG; i++) {
++ if (pdata->mss[i] == mss) {
++ pdata->mss_refcnt[i]++;
++ mss_index = i;
++ mss_index_found = true;
++ }
++ }
++
++ /* Overwrite the slot with ref_count = 0 */
++ for (i = 0; !mss_index_found && i < NUM_MSS_REG; i++) {
++ if (!pdata->mss_refcnt[i]) {
++ pdata->mss_refcnt[i]++;
++ pdata->mac_ops->set_mss(pdata, mss, i);
++ pdata->mss[i] = mss;
++ mss_index = i;
++ mss_index_found = true;
++ }
++ }
++
++ spin_unlock(&pdata->mss_lock);
++
++ /* No slots with ref_count = 0 available, return busy */
++ if (!mss_index_found)
++ return -EBUSY;
++
++ return mss_index;
++}
++
++static int xgene_enet_work_msg(struct sk_buff *skb, u64 *hopinfo)
+ {
+ struct net_device *ndev = skb->dev;
+ struct iphdr *iph;
+ u8 l3hlen = 0, l4hlen = 0;
+ u8 ethhdr, proto = 0, csum_enable = 0;
+- u64 hopinfo = 0;
+ u32 hdr_len, mss = 0;
+ u32 i, len, nr_frags;
++ int mss_index;
+
+ ethhdr = xgene_enet_hdr_len(skb->data);
+
+@@ -226,7 +273,11 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb)
+ if (!mss || ((skb->len - hdr_len) <= mss))
+ goto out;
+
+- hopinfo |= SET_BIT(ET);
++ mss_index = xgene_enet_setup_mss(ndev, mss);
++ if (unlikely(mss_index < 0))
++ return -EBUSY;
++
++ *hopinfo |= SET_BIT(ET) | SET_VAL(MSS, mss_index);
+ }
+ } else if (iph->protocol == IPPROTO_UDP) {
+ l4hlen = UDP_HDR_SIZE;
+@@ -234,15 +285,15 @@ static u64 xgene_enet_work_msg(struct sk_buff *skb)
+ }
+ out:
+ l3hlen = ip_hdrlen(skb) >> 2;
+- hopinfo |= SET_VAL(TCPHDR, l4hlen) |
+- SET_VAL(IPHDR, l3hlen) |
+- SET_VAL(ETHHDR, ethhdr) |
+- SET_VAL(EC, csum_enable) |
+- SET_VAL(IS, proto) |
+- SET_BIT(IC) |
+- SET_BIT(TYPE_ETH_WORK_MESSAGE);
+-
+- return hopinfo;
++ *hopinfo |= SET_VAL(TCPHDR, l4hlen) |
++ SET_VAL(IPHDR, l3hlen) |
++ SET_VAL(ETHHDR, ethhdr) |
++ SET_VAL(EC, csum_enable) |
++ SET_VAL(IS, proto) |
++ SET_BIT(IC) |
++ SET_BIT(TYPE_ETH_WORK_MESSAGE);
++
++ return 0;
+ }
+
+ static u16 xgene_enet_encode_len(u16 len)
+@@ -282,20 +333,22 @@ static int xgene_enet_setup_tx_desc(struct xgene_enet_desc_ring *tx_ring,
+ dma_addr_t dma_addr, pbuf_addr, *frag_dma_addr;
+ skb_frag_t *frag;
+ u16 tail = tx_ring->tail;
+- u64 hopinfo;
++ u64 hopinfo = 0;
+ u32 len, hw_len;
+ u8 ll = 0, nv = 0, idx = 0;
+ bool split = false;
+ u32 size, offset, ell_bytes = 0;
+ u32 i, fidx, nr_frags, count = 1;
++ int ret;
+
+ raw_desc = &tx_ring->raw_desc[tail];
+ tail = (tail + 1) & (tx_ring->slots - 1);
+ memset(raw_desc, 0, sizeof(struct xgene_enet_raw_desc));
+
+- hopinfo = xgene_enet_work_msg(skb);
+- if (!hopinfo)
+- return -EINVAL;
++ ret = xgene_enet_work_msg(skb, &hopinfo);
++ if (ret)
++ return ret;
++
+ raw_desc->m3 = cpu_to_le64(SET_VAL(HENQNUM, tx_ring->dst_ring_num) |
+ hopinfo);
+
+@@ -435,6 +488,9 @@ static netdev_tx_t xgene_enet_start_xmit(struct sk_buff *skb,
+ return NETDEV_TX_OK;
+
+ count = xgene_enet_setup_tx_desc(tx_ring, skb);
++ if (count == -EBUSY)
++ return NETDEV_TX_BUSY;
++
+ if (count <= 0) {
+ dev_kfree_skb_any(skb);
+ return NETDEV_TX_OK;
+@@ -1669,7 +1725,7 @@ static int xgene_enet_probe(struct platform_device *pdev)
+
+ if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
+ ndev->features |= NETIF_F_TSO;
+- pdata->mss = XGENE_ENET_MSS;
++ spin_lock_init(&pdata->mss_lock);
+ }
+ ndev->hw_features = ndev->features;
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index 7735371..0cda58f 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -47,7 +47,7 @@
+ #define NUM_PKT_BUF 64
+ #define NUM_BUFPOOL 32
+ #define MAX_EXP_BUFFS 256
+-#define XGENE_ENET_MSS 1448
++#define NUM_MSS_REG 4
+ #define XGENE_MIN_ENET_FRAME_SIZE 60
+
+ #define XGENE_MAX_ENET_IRQ 16
+@@ -143,7 +143,7 @@ struct xgene_mac_ops {
+ void (*rx_disable)(struct xgene_enet_pdata *pdata);
+ void (*set_speed)(struct xgene_enet_pdata *pdata);
+ void (*set_mac_addr)(struct xgene_enet_pdata *pdata);
+- void (*set_mss)(struct xgene_enet_pdata *pdata);
++ void (*set_mss)(struct xgene_enet_pdata *pdata, u16 mss, u8 index);
+ void (*link_state)(struct work_struct *work);
+ };
+
+@@ -212,7 +212,9 @@ struct xgene_enet_pdata {
+ u8 eth_bufnum;
+ u8 bp_bufnum;
+ u16 ring_num;
+- u32 mss;
++ u32 mss[NUM_MSS_REG];
++ u32 mss_refcnt[NUM_MSS_REG];
++ spinlock_t mss_lock; /* mss lock */
+ u8 tx_delay;
+ u8 rx_delay;
+ bool mdio_driver;
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+index 279ee27..6475f38 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+@@ -232,9 +232,22 @@ static void xgene_xgmac_set_mac_addr(struct xgene_enet_pdata *pdata)
+ xgene_enet_wr_mac(pdata, HSTMACADR_MSW_ADDR, addr1);
+ }
+
+-static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata)
++static void xgene_xgmac_set_mss(struct xgene_enet_pdata *pdata,
++ u16 mss, u8 index)
+ {
+- xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR, pdata->mss);
++ u8 offset;
++ u32 data;
++
++ offset = (index < 2) ? 0 : 4;
++ xgene_enet_rd_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, &data);
++
++ if (!(index & 0x1))
++ data = SET_VAL(TSO_MSS1, data >> TSO_MSS1_POS) |
++ SET_VAL(TSO_MSS0, mss);
++ else
++ data = SET_VAL(TSO_MSS1, mss) | SET_VAL(TSO_MSS0, data);
++
++ xgene_enet_wr_csr(pdata, XG_TSIF_MSS_REG0_ADDR + offset, data);
+ }
+
+ static u32 xgene_enet_link_status(struct xgene_enet_pdata *pdata)
+@@ -258,7 +271,6 @@ static void xgene_xgmac_init(struct xgene_enet_pdata *pdata)
+ xgene_enet_wr_mac(pdata, AXGMAC_CONFIG_1, data);
+
+ xgene_xgmac_set_mac_addr(pdata);
+- xgene_xgmac_set_mss(pdata);
+
+ xgene_enet_rd_csr(pdata, XG_RSIF_CONFIG_REG_ADDR, &data);
+ data |= CFG_RSIF_FPBUFF_TIMEOUT_EN;
+--
+1.8.3.1
+
diff --git a/SOURCES/1015-drivers-net-xgene-fix-Use-GPIO-to-get-link-status.patch b/SOURCES/1015-drivers-net-xgene-fix-Use-GPIO-to-get-link-status.patch
new file mode 100644
index 0000000..5588ac5
--- /dev/null
+++ b/SOURCES/1015-drivers-net-xgene-fix-Use-GPIO-to-get-link-status.patch
@@ -0,0 +1,91 @@
+From 410b195f44efaaa3a42f6ff0fc5ffaa02ce934d5 Mon Sep 17 00:00:00 2001
+From: Iyappan Subramanian <isubramanian at apm.com>
+Date: Thu, 6 Oct 2016 14:35:57 -0700
+Subject: [PATCH 1015/1018] drivers: net: xgene: fix: Use GPIO to get link
+ status
+
+The link value reported by the link status register is not
+reliable when no SPF module inserted. This patchset fixes this
+issue by using GPIO to determine the link status.
+
+Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
+Signed-off-by: Quan Nguyen <qnguyen at apm.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 6 +++++-
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.h | 1 +
+ drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 19 +++++++++++++++++--
+ 3 files changed, 23 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index 429f18f..f75d955 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -1381,9 +1381,13 @@ static void xgene_enet_gpiod_get(struct xgene_enet_pdata *pdata)
+ {
+ struct device *dev = &pdata->pdev->dev;
+
+- if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII)
++ pdata->sfp_gpio_en = false;
++ if (pdata->phy_mode != PHY_INTERFACE_MODE_XGMII ||
++ (!device_property_present(dev, "sfp-gpios") &&
++ !device_property_present(dev, "rxlos-gpios")))
+ return;
+
++ pdata->sfp_gpio_en = true;
+ pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
+ if (IS_ERR(pdata->sfp_rdy))
+ pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+index 0cda58f..011965b 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.h
+@@ -219,6 +219,7 @@ struct xgene_enet_pdata {
+ u8 rx_delay;
+ bool mdio_driver;
+ struct gpio_desc *sfp_rdy;
++ bool sfp_gpio_en;
+ };
+
+ struct xgene_indirect_ctl {
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+index 6475f38..d1758b0 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c
+@@ -415,16 +415,31 @@ static void xgene_enet_clear(struct xgene_enet_pdata *pdata,
+ xgene_enet_wr_ring_if(pdata, addr, data);
+ }
+
++static int xgene_enet_gpio_lookup(struct xgene_enet_pdata *pdata)
++{
++ struct device *dev = &pdata->pdev->dev;
++
++ pdata->sfp_rdy = gpiod_get(dev, "rxlos", GPIOD_IN);
++ if (IS_ERR(pdata->sfp_rdy))
++ pdata->sfp_rdy = gpiod_get(dev, "sfp", GPIOD_IN);
++
++ if (IS_ERR(pdata->sfp_rdy))
++ return -ENODEV;
++
++ return 0;
++}
++
+ static void xgene_enet_link_state(struct work_struct *work)
+ {
+ struct xgene_enet_pdata *pdata = container_of(to_delayed_work(work),
+ struct xgene_enet_pdata, link_work);
+- struct gpio_desc *sfp_rdy = pdata->sfp_rdy;
+ struct net_device *ndev = pdata->ndev;
+ u32 link_status, poll_interval;
+
+ link_status = xgene_enet_link_status(pdata);
+- if (link_status && !IS_ERR(sfp_rdy) && !gpiod_get_value(sfp_rdy))
++ if (pdata->sfp_gpio_en && link_status &&
++ (!IS_ERR(pdata->sfp_rdy) || !xgene_enet_gpio_lookup(pdata)) &&
++ !gpiod_get_value(pdata->sfp_rdy))
+ link_status = 0;
+
+ if (link_status) {
+--
+1.8.3.1
+
diff --git a/SOURCES/1016-drivers-net-xgene-fix-Disable-coalescing-on-v1-hardw.patch b/SOURCES/1016-drivers-net-xgene-fix-Disable-coalescing-on-v1-hardw.patch
new file mode 100644
index 0000000..5da6d49
--- /dev/null
+++ b/SOURCES/1016-drivers-net-xgene-fix-Disable-coalescing-on-v1-hardw.patch
@@ -0,0 +1,61 @@
+From b125c9d6439cce38fa6938c7b31ab2ed0e17dee6 Mon Sep 17 00:00:00 2001
+From: Iyappan Subramanian <isubramanian at apm.com>
+Date: Mon, 31 Oct 2016 16:00:26 -0700
+Subject: [PATCH 1016/1018] drivers: net: xgene: fix: Disable coalescing on v1
+ hardware
+
+Since ethernet v1 hardware has a bug related to coalescing, disabling
+this feature.
+
+Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
+Signed-off-by: Toan Le <toanle at apm.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.c | 12 ------------
+ drivers/net/ethernet/apm/xgene/xgene_enet_main.c | 3 ++-
+ 2 files changed, 2 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+index 36b478f..85ed9a1 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+@@ -204,17 +204,6 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+ return num_msgs;
+ }
+
+-static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring)
+-{
+- u32 data = 0x7777;
+-
+- xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e);
+- xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data);
+- xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data << 16);
+- xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x40);
+- xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x80);
+-}
+-
+ void xgene_enet_parse_error(struct xgene_enet_desc_ring *ring,
+ struct xgene_enet_pdata *pdata,
+ enum xgene_enet_err_code status)
+@@ -928,5 +917,4 @@ struct xgene_ring_ops xgene_ring1_ops = {
+ .clear = xgene_enet_clear_ring,
+ .wr_cmd = xgene_enet_wr_cmd,
+ .len = xgene_enet_ring_len,
+- .coalesce = xgene_enet_setup_coalescing,
+ };
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+index f75d955..fe34403 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_main.c
+@@ -1188,7 +1188,8 @@ static int xgene_enet_create_desc_rings(struct net_device *ndev)
+ tx_ring->dst_ring_num = xgene_enet_dst_ring_num(cp_ring);
+ }
+
+- pdata->ring_ops->coalesce(pdata->tx_ring[0]);
++ if (pdata->ring_ops->coalesce)
++ pdata->ring_ops->coalesce(pdata->tx_ring[0]);
+ pdata->tx_qcnt_hi = pdata->tx_ring[0]->slots - 128;
+
+ return 0;
+--
+1.8.3.1
+
diff --git a/SOURCES/1017-drivers-net-xgene-fix-Coalescing-values-for-v2-hardw.patch b/SOURCES/1017-drivers-net-xgene-fix-Coalescing-values-for-v2-hardw.patch
new file mode 100644
index 0000000..79203da
--- /dev/null
+++ b/SOURCES/1017-drivers-net-xgene-fix-Coalescing-values-for-v2-hardw.patch
@@ -0,0 +1,67 @@
+From da20928c43a4f6b9390a0fb027dda7d947011686 Mon Sep 17 00:00:00 2001
+From: Iyappan Subramanian <isubramanian at apm.com>
+Date: Mon, 31 Oct 2016 16:00:27 -0700
+Subject: [PATCH 1017/1018] drivers: net: xgene: fix: Coalescing values for v2
+ hardware
+
+Changing the interrupt trigger region id to 2 and the
+corresponding threshold set0/set1 values to 8/16.
+
+Signed-off-by: Iyappan Subramanian <isubramanian at apm.com>
+Signed-off-by: Toan Le <toanle at apm.com>
+---
+ drivers/net/ethernet/apm/xgene/xgene_enet_hw.h | 2 ++
+ drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c | 12 +++++++-----
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+index 8456337..06e598c 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.h
+@@ -55,8 +55,10 @@ enum xgene_enet_rm {
+ #define PREFETCH_BUF_EN BIT(21)
+ #define CSR_RING_ID_BUF 0x000c
+ #define CSR_PBM_COAL 0x0014
++#define CSR_PBM_CTICK0 0x0018
+ #define CSR_PBM_CTICK1 0x001c
+ #define CSR_PBM_CTICK2 0x0020
++#define CSR_PBM_CTICK3 0x0024
+ #define CSR_THRESHOLD0_SET1 0x0030
+ #define CSR_THRESHOLD1_SET1 0x0034
+ #define CSR_RING_NE_INT_MODE 0x017c
+diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
+index 2b76732..af51dd5 100644
+--- a/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
++++ b/drivers/net/ethernet/apm/xgene/xgene_enet_ring2.c
+@@ -30,7 +30,7 @@ static void xgene_enet_ring_init(struct xgene_enet_desc_ring *ring)
+ ring_cfg[0] |= SET_VAL(X2_INTLINE, ring->id & RING_BUFNUM_MASK);
+ ring_cfg[3] |= SET_BIT(X2_DEQINTEN);
+ }
+- ring_cfg[0] |= SET_VAL(X2_CFGCRID, 1);
++ ring_cfg[0] |= SET_VAL(X2_CFGCRID, 2);
+
+ addr >>= 8;
+ ring_cfg[2] |= QCOHERENT | SET_VAL(RINGADDRL, addr);
+@@ -192,13 +192,15 @@ static u32 xgene_enet_ring_len(struct xgene_enet_desc_ring *ring)
+
+ static void xgene_enet_setup_coalescing(struct xgene_enet_desc_ring *ring)
+ {
+- u32 data = 0x7777;
++ u32 data = 0x77777777;
+
+ xgene_enet_ring_wr32(ring, CSR_PBM_COAL, 0x8e);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK0, data);
+ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK1, data);
+- xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data << 16);
+- xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x40);
+- xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x80);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK2, data);
++ xgene_enet_ring_wr32(ring, CSR_PBM_CTICK3, data);
++ xgene_enet_ring_wr32(ring, CSR_THRESHOLD0_SET1, 0x08);
++ xgene_enet_ring_wr32(ring, CSR_THRESHOLD1_SET1, 0x10);
+ }
+
+ struct xgene_ring_ops xgene_ring2_ops = {
+--
+1.8.3.1
+
diff --git a/SPECS/kernel-aarch64.spec b/SPECS/kernel-aarch64.spec
index 84374b8..c44bdc7 100644
--- a/SPECS/kernel-aarch64.spec
+++ b/SPECS/kernel-aarch64.spec
@@ -335,6 +335,13 @@ Patch1007: 1007-perf-xgene-Add-APM-X-Gene-SoC-Performance-Monitoring.patch
Patch1008: 1008-perf-xgene-Remove-bogus-IS_ERR-check.patch
Patch1009: 1009-MAINTAINERS-Add-entry-for-APM-X-Gene-SoC-PMU-driver.patch
Patch1010: 1010-i2c-xgene-Avoid-dma_buffer-overrun.patch
+Patch1011: 1011-net-xgene-fix-error-handling-during-reset.patch
+Patch1012: 1012-net-xgene-fix-backward-compatibility-fix.patch
+Patch1013: 1013-net-ethernet-apm-xgene-use-phydev-from-struct-net_de.patch
+Patch1014: 1014-drivers-net-xgene-Fix-MSS-programming.patch
+Patch1015: 1015-drivers-net-xgene-fix-Use-GPIO-to-get-link-status.patch
+Patch1016: 1016-drivers-net-xgene-fix-Disable-coalescing-on-v1-hardw.patch
+Patch1017: 1017-drivers-net-xgene-fix-Coalescing-values-for-v2-hardw.patch
# QDF2400 Patches
Patch4000: 4000-arm64-Define-Qualcomm-Technologies-ARMv8-CPU.patch
@@ -680,6 +687,13 @@ git am %{PATCH1007}
git am %{PATCH1008}
git am %{PATCH1009}
git am %{PATCH1010}
+git am %{PATCH1011}
+git am %{PATCH1012}
+git am %{PATCH1013}
+git am %{PATCH1014}
+git am %{PATCH1015}
+git am %{PATCH1016}
+git am %{PATCH1017}
# Apply QDF2400 patches
git am %{PATCH4000}
@@ -1459,6 +1473,7 @@ fi
%changelog
* Thu Nov 10 2016 Duc Dang <dhdang at apm.com> [4.5.0-17.el7]
+- Integrate upstream updates for X-Gene Enet driver
- Avoid dma_buffer overrun for SlimPRO I2C driver
- Add X-Gene SoC PMU support
- Add X-Gene HWMon support
--
1.8.3.1
More information about the Arm-dev
mailing list