aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFugang Duan <B38611@freescale.com>2014-02-20 19:49:21 -0500
committerNitin Garg <nitin.garg@freescale.com>2014-04-16 09:57:50 -0400
commit450e9b8883469a675b90fb2fa655ee23e852aedd (patch)
treeb5f68a9b68dab97f98c02df0b0c6de985abce124
parentc390203ac6df37e763a8d38b71096d5c8eeac93a (diff)
ENGR00300156 net: fec: Workaround for imx6sx enet tx hang when enable three queues
When enable three queues on imx6sx enet, and then do tx performance test with iperf tool, after some time running, tx hang. Found that: If uDMA is running, software set TDAR may cause tx hang. If uDMA is in idle, software set TDAR don't cause tx hang. There is a TDAR race condition for mutliQ when the software sets TDAR and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles). This will cause the udma_tx and udma_tx_arbiter state machines to hang. The issue exist at i.MX6SX enet IP. So, the Workaround is checking TDAR status four time, if TDAR cleared by hardware and then write TDAR, otherwise don't set TDAR. The patch is only one Workaround for the issue TKT210582. Signed-off-by: Fugang Duan <B38611@freescale.com>
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c17
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index ecc1c14841f4..f5e88a25ed1d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -139,6 +139,13 @@ static const u16 fec_enet_vlan_pri_to_queue[8] = {1, 1, 1, 1, 2, 2, 2, 2};
139 * independent rings 139 * independent rings
140 */ 140 */
141#define FEC_QUIRK_HAS_AVB (1 << 10) 141#define FEC_QUIRK_HAS_AVB (1 << 10)
142/*
143 * There is a TDAR race condition for mutliQ when the software sets TDAR
144 * and the UDMA clears TDAR simultaneously or in a small window (2-4 cycles).
145 * This will cause the udma_tx and udma_tx_arbiter state machines to hang.
146 * The issue exist at i.MX6SX enet IP.
147 */
148#define FEC_QUIRK_TKT210582 (1 << 11)
142 149
143static struct platform_device_id fec_devtype[] = { 150static struct platform_device_id fec_devtype[] = {
144 { 151 {
@@ -167,7 +174,8 @@ static struct platform_device_id fec_devtype[] = {
167 .name = "imx6sx-fec", 174 .name = "imx6sx-fec",
168 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 175 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
169 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 176 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
170 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB, 177 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_HAS_AVB |
178 FEC_QUIRK_TKT210582,
171 }, { 179 }, {
172 /* sentinel */ 180 /* sentinel */
173 } 181 }
@@ -440,7 +448,12 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
440 netif_tx_stop_queue(nq); 448 netif_tx_stop_queue(nq);
441 449
442 /* Trigger transmission start */ 450 /* Trigger transmission start */
443 writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue)); 451 if (!(id_entry->driver_data & FEC_QUIRK_TKT210582) ||
452 !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
453 !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
454 !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)) ||
455 !readl(fep->hwp + FEC_X_DES_ACTIVE(queue)))
456 writel(0, fep->hwp + FEC_X_DES_ACTIVE(queue));
444 457
445 return NETDEV_TX_OK; 458 return NETDEV_TX_OK;
446} 459}