diff options
author | Fugang Duan <B38611@freescale.com> | 2014-02-20 20:45:20 -0500 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:57:35 -0400 |
commit | d472828dac9afbe09139a8a9aa0805719bec3e89 (patch) | |
tree | a01b0e5b6a5178490f9c868d1616caf023ca50ce /drivers/net/ethernet | |
parent | fcc6fc800470df5651b5339c2521340fbc039860 (diff) |
net: fec: fix potential issue to avoid fec interrupt lost and crc error
The current flow: Set TX BD ready, and then set "INT" and "PINS" bit to
enable tx interrupt generation and crc checksum.
There has potential issue like as:
CPU fec uDMA
Set tx ready bit
uDMA start the BD transmission
Set "INT" bit
Set "PINS" bit
...
Above situation cause fec tx interrupt lost and fec MAC don't do
CRC checksum. The patch fix the potential issue.
Signed-off-by: Fugang Duan <B38611@freescale.com>
Acked-by: Frank Li <Frank.li@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index dde2cd85dfc4..cb3e5fec4897 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c | |||
@@ -386,12 +386,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
386 | netdev_err(ndev, "Tx DMA memory map failed\n"); | 386 | netdev_err(ndev, "Tx DMA memory map failed\n"); |
387 | return NETDEV_TX_OK; | 387 | return NETDEV_TX_OK; |
388 | } | 388 | } |
389 | /* Send it on its way. Tell FEC it's ready, interrupt when done, | ||
390 | * it's the last BD of the frame, and to put the CRC on the end. | ||
391 | */ | ||
392 | status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | ||
393 | | BD_ENET_TX_LAST | BD_ENET_TX_TC); | ||
394 | bdp->cbd_sc = status; | ||
395 | 389 | ||
396 | if (fep->bufdesc_ex) { | 390 | if (fep->bufdesc_ex) { |
397 | 391 | ||
@@ -417,6 +411,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
417 | ebdp->cbd_esc |= FEC_TX_BD_FTYPE(queue); | 411 | ebdp->cbd_esc |= FEC_TX_BD_FTYPE(queue); |
418 | } | 412 | } |
419 | 413 | ||
414 | /* Send it on its way. Tell FEC it's ready, interrupt when done, | ||
415 | * it's the last BD of the frame, and to put the CRC on the end. | ||
416 | */ | ||
417 | status |= (BD_ENET_TX_READY | BD_ENET_TX_INTR | ||
418 | | BD_ENET_TX_LAST | BD_ENET_TX_TC); | ||
419 | bdp->cbd_sc = status; | ||
420 | |||
420 | bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); | 421 | bdp_pre = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); |
421 | if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && | 422 | if ((id_entry->driver_data & FEC_QUIRK_ERR006358) && |
422 | !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { | 423 | !(bdp_pre->cbd_sc & BD_ENET_TX_READY)) { |