diff options
| -rw-r--r-- | drivers/net/ethernet/freescale/fec.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 32 |
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 { | |||
| 259 | struct fec_enet_delayed_work { | 259 | struct 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 | ||
| 97 | static struct platform_device_id fec_devtype[] = { | 111 | static 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 | ||
| 694 | static void | 722 | static void |
