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