diff options
author | Fugang Duan <B38611@freescale.com> | 2014-02-20 19:49:21 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:57:50 -0400 |
commit | 450e9b8883469a675b90fb2fa655ee23e852aedd (patch) | |
tree | b5f68a9b68dab97f98c02df0b0c6de985abce124 | |
parent | c390203ac6df37e763a8d38b71096d5c8eeac93a (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.c | 17 |
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 | ||
143 | static struct platform_device_id fec_devtype[] = { | 150 | static 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 | } |