aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/freescale/fec.h1
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c32
2 files changed, 31 insertions, 2 deletions
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 2b0a0ea4f8e7..ae236009f1a8 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -259,6 +259,7 @@ struct bufdesc_ex {
259struct fec_enet_delayed_work { 259struct fec_enet_delayed_work {
260 struct delayed_work delay_work; 260 struct delayed_work delay_work;
261 bool timeout; 261 bool timeout;
262 bool trig_tx;
262}; 263};
263 264
264/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and 265/* The FEC buffer descriptors track the ring buffers. The rx_bd_base and
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index f0f0e96453a0..0dda45481d16 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -93,6 +93,20 @@ static void set_multicast_list(struct net_device *ndev);
93#define FEC_QUIRK_HAS_CSUM (1 << 5) 93#define FEC_QUIRK_HAS_CSUM (1 << 5)
94/* Controller has hardware vlan support */ 94/* Controller has hardware vlan support */
95#define FEC_QUIRK_HAS_VLAN (1 << 6) 95#define FEC_QUIRK_HAS_VLAN (1 << 6)
96/* ENET IP errata ERR006358
97 *
98 * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
99 * detected as not set during a prior frame transmission, then the
100 * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
101 * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
102 * If the ready bit in the transmit buffer descriptor (TxBD[R]) is previously
103 * detected as not set during a prior frame transmission, then the
104 * ENET_TDAR[TDAR] bit is cleared at a later time, even if additional TxBDs
105 * were added to the ring and the ENET_TDAR[TDAR] bit is set. This results in
106 * frames not being transmitted until there is a 0-to-1 transition on
107 * ENET_TDAR[TDAR].
108 */
109#define FEC_QUIRK_ERR006358 (1 << 7)
96 110
97static struct platform_device_id fec_devtype[] = { 111static struct platform_device_id fec_devtype[] = {
98 { 112 {
@@ -112,7 +126,7 @@ static struct platform_device_id fec_devtype[] = {
112 .name = "imx6q-fec", 126 .name = "imx6q-fec",
113 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT | 127 .driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_HAS_GBIT |
114 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM | 128 FEC_QUIRK_HAS_BUFDESC_EX | FEC_QUIRK_HAS_CSUM |
115 FEC_QUIRK_HAS_VLAN, 129 FEC_QUIRK_HAS_VLAN | FEC_QUIRK_ERR006358,
116 }, { 130 }, {
117 .name = "mvf600-fec", 131 .name = "mvf600-fec",
118 .driver_data = FEC_QUIRK_ENET_MAC, 132 .driver_data = FEC_QUIRK_ENET_MAC,
@@ -275,7 +289,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
275 struct fec_enet_private *fep = netdev_priv(ndev); 289 struct fec_enet_private *fep = netdev_priv(ndev);
276 const struct platform_device_id *id_entry = 290 const struct platform_device_id *id_entry =
277 platform_get_device_id(fep->pdev); 291 platform_get_device_id(fep->pdev);
278 struct bufdesc *bdp; 292 struct bufdesc *bdp, *bdp_pre;
279 void *bufaddr; 293 void *bufaddr;
280 unsigned short status; 294 unsigned short status;
281 unsigned int index; 295 unsigned int index;
@@ -370,6 +384,15 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
370 ebdp->cbd_esc |= BD_ENET_TX_PINS; 384 ebdp->cbd_esc |= BD_ENET_TX_PINS;
371 } 385 }
372 } 386 }
387
388 bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex);
389 if ((id_entry->driver_data & FEC_QUIRK_ERR006358) &&
390 !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) {
391 fep->delay_work.trig_tx = true;
392 schedule_delayed_work(&(fep->delay_work.delay_work),
393 msecs_to_jiffies(1));
394 }
395
373 /* If this was the last BD in the ring, start at the beginning again. */ 396 /* If this was the last BD in the ring, start at the beginning again. */
374 if (status & BD_ENET_TX_WRAP) 397 if (status & BD_ENET_TX_WRAP)
375 bdp = fep->tx_bd_base; 398 bdp = fep->tx_bd_base;
@@ -689,6 +712,11 @@ static void fec_enet_work(struct work_struct *work)
689 fec_restart(fep->netdev, fep->full_duplex); 712 fec_restart(fep->netdev, fep->full_duplex);
690 netif_wake_queue(fep->netdev); 713 netif_wake_queue(fep->netdev);
691 } 714 }
715
716 if (fep->delay_work.trig_tx) {
717 fep->delay_work.trig_tx = false;
718 writel(0, fep->hwp + FEC_X_DES_ACTIVE);
719 }
692} 720}
693 721
694static void 722static void