aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fs_enet
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fs_enet')
-rw-r--r--drivers/net/fs_enet/mac-fcc.c49
1 files changed, 43 insertions, 6 deletions
diff --git a/drivers/net/fs_enet/mac-fcc.c b/drivers/net/fs_enet/mac-fcc.c
index 714da967fa19..0ae65a2f1ab9 100644
--- a/drivers/net/fs_enet/mac-fcc.c
+++ b/drivers/net/fs_enet/mac-fcc.c
@@ -504,17 +504,54 @@ static int get_regs_len(struct net_device *dev)
504} 504}
505 505
506/* Some transmit errors cause the transmitter to shut 506/* Some transmit errors cause the transmitter to shut
507 * down. We now issue a restart transmit. Since the 507 * down. We now issue a restart transmit.
508 * errors close the BD and update the pointers, the restart 508 * Also, to workaround 8260 device erratum CPM37, we must
509 * _should_ pick up without having to reset any of our 509 * disable and then re-enable the transmitterfollowing a
510 * pointers either. Also, To workaround 8260 device erratum 510 * Late Collision, Underrun, or Retry Limit error.
511 * CPM37, we must disable and then re-enable the transmitter 511 * In addition, tbptr may point beyond BDs beyond still marked
512 * following a Late Collision, Underrun, or Retry Limit error. 512 * as ready due to internal pipelining, so we need to look back
513 * through the BDs and adjust tbptr to point to the last BD
514 * marked as ready. This may result in some buffers being
515 * retransmitted.
513 */ 516 */
514static void tx_restart(struct net_device *dev) 517static void tx_restart(struct net_device *dev)
515{ 518{
516 struct fs_enet_private *fep = netdev_priv(dev); 519 struct fs_enet_private *fep = netdev_priv(dev);
517 fcc_t __iomem *fccp = fep->fcc.fccp; 520 fcc_t __iomem *fccp = fep->fcc.fccp;
521 const struct fs_platform_info *fpi = fep->fpi;
522 fcc_enet_t __iomem *ep = fep->fcc.ep;
523 cbd_t __iomem *curr_tbptr;
524 cbd_t __iomem *recheck_bd;
525 cbd_t __iomem *prev_bd;
526 cbd_t __iomem *last_tx_bd;
527
528 last_tx_bd = fep->tx_bd_base + (fpi->tx_ring * sizeof(cbd_t));
529
530 /* get the current bd held in TBPTR and scan back from this point */
531 recheck_bd = curr_tbptr = (cbd_t __iomem *)
532 ((R32(ep, fen_genfcc.fcc_tbptr) - fep->ring_mem_addr) +
533 fep->ring_base);
534
535 prev_bd = (recheck_bd == fep->tx_bd_base) ? last_tx_bd : recheck_bd - 1;
536
537 /* Move through the bds in reverse, look for the earliest buffer
538 * that is not ready. Adjust TBPTR to the following buffer */
539 while ((CBDR_SC(prev_bd) & BD_ENET_TX_READY) != 0) {
540 /* Go back one buffer */
541 recheck_bd = prev_bd;
542
543 /* update the previous buffer */
544 prev_bd = (prev_bd == fep->tx_bd_base) ? last_tx_bd : prev_bd - 1;
545
546 /* We should never see all bds marked as ready, check anyway */
547 if (recheck_bd == curr_tbptr)
548 break;
549 }
550 /* Now update the TBPTR and dirty flag to the current buffer */
551 W32(ep, fen_genfcc.fcc_tbptr,
552 (uint) (((void *)recheck_bd - fep->ring_base) +
553 fep->ring_mem_addr));
554 fep->dirty_tx = recheck_bd;
518 555
519 C32(fccp, fcc_gfmr, FCC_GFMR_ENT); 556 C32(fccp, fcc_gfmr, FCC_GFMR_ENT);
520 udelay(10); 557 udelay(10);