aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorClaudiu Manoil <claudiu.manoil@freescale.com>2014-02-24 05:13:46 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-24 19:38:20 -0500
commitf19015baa23b9130acbf290e1d65c70193e34ff1 (patch)
treeaa785ebd0bafdcc86316e0a19e944ce77f1bac21
parent0851133bb5ad9d95fceccac9fc67b798041b73e2 (diff)
gianfar: Fix Tx int miss, dont write IC on-the-fly
Programming the interrupt coalescing (IC) registers while the controller/DMA is on may incur the loss of one Tx confirmation interrupt, under certain conditions. This is a subtle hw race because it does not occur during a burst of Tx packets. It has been observed on p2020 devices that, if just one packet is being xmit'ed, the Tx confirmation doesn't trigger and BQL evetually blocks the Tx queues, followed by Tx timeout and an un-responsive device. This issue was not apparent prior to introducing BQL support, as a late Tx confirmation was not an issue back then and the next burst of Tx frames would have triggered the Tx confirmation/ Tx ring cleanup anyway. Bottom line, the hw specifications state that the IC registers should not be programmed while the Rx/Tx blocks (the DMA) are enabled. Further more, these registers are currently re-written with the same values on the processing path, over and over again. To fix this, rewriting the IC registers has been removed from the processing path (napi poll). A complete MAC reset procedure has been implemented for the ethtool -c option instead, to reliably update these registers while the controller is stopped. Signed-off-by: Claudiu Manoil <claudiu.manoil@freescale.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/freescale/gianfar.c99
-rw-r--r--drivers/net/ethernet/freescale/gianfar_ethtool.c66
2 files changed, 77 insertions, 88 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c
index 4eac25f66605..c5b9320f7629 100644
--- a/drivers/net/ethernet/freescale/gianfar.c
+++ b/drivers/net/ethernet/freescale/gianfar.c
@@ -412,6 +412,47 @@ static void gfar_mac_tx_config(struct gfar_private *priv)
412 gfar_write(&regs->tctrl, tctrl); 412 gfar_write(&regs->tctrl, tctrl);
413} 413}
414 414
415static void gfar_configure_coalescing(struct gfar_private *priv,
416 unsigned long tx_mask, unsigned long rx_mask)
417{
418 struct gfar __iomem *regs = priv->gfargrp[0].regs;
419 u32 __iomem *baddr;
420
421 if (priv->mode == MQ_MG_MODE) {
422 int i = 0;
423
424 baddr = &regs->txic0;
425 for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
426 gfar_write(baddr + i, 0);
427 if (likely(priv->tx_queue[i]->txcoalescing))
428 gfar_write(baddr + i, priv->tx_queue[i]->txic);
429 }
430
431 baddr = &regs->rxic0;
432 for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
433 gfar_write(baddr + i, 0);
434 if (likely(priv->rx_queue[i]->rxcoalescing))
435 gfar_write(baddr + i, priv->rx_queue[i]->rxic);
436 }
437 } else {
438 /* Backward compatible case -- even if we enable
439 * multiple queues, there's only single reg to program
440 */
441 gfar_write(&regs->txic, 0);
442 if (likely(priv->tx_queue[0]->txcoalescing))
443 gfar_write(&regs->txic, priv->tx_queue[0]->txic);
444
445 gfar_write(&regs->rxic, 0);
446 if (unlikely(priv->rx_queue[0]->rxcoalescing))
447 gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
448 }
449}
450
451void gfar_configure_coalescing_all(struct gfar_private *priv)
452{
453 gfar_configure_coalescing(priv, 0xFF, 0xFF);
454}
455
415static struct net_device_stats *gfar_get_stats(struct net_device *dev) 456static struct net_device_stats *gfar_get_stats(struct net_device *dev)
416{ 457{
417 struct gfar_private *priv = netdev_priv(dev); 458 struct gfar_private *priv = netdev_priv(dev);
@@ -1837,47 +1878,6 @@ void gfar_start(struct gfar_private *priv)
1837 priv->ndev->trans_start = jiffies; /* prevent tx timeout */ 1878 priv->ndev->trans_start = jiffies; /* prevent tx timeout */
1838} 1879}
1839 1880
1840static void gfar_configure_coalescing(struct gfar_private *priv,
1841 unsigned long tx_mask, unsigned long rx_mask)
1842{
1843 struct gfar __iomem *regs = priv->gfargrp[0].regs;
1844 u32 __iomem *baddr;
1845
1846 if (priv->mode == MQ_MG_MODE) {
1847 int i = 0;
1848
1849 baddr = &regs->txic0;
1850 for_each_set_bit(i, &tx_mask, priv->num_tx_queues) {
1851 gfar_write(baddr + i, 0);
1852 if (likely(priv->tx_queue[i]->txcoalescing))
1853 gfar_write(baddr + i, priv->tx_queue[i]->txic);
1854 }
1855
1856 baddr = &regs->rxic0;
1857 for_each_set_bit(i, &rx_mask, priv->num_rx_queues) {
1858 gfar_write(baddr + i, 0);
1859 if (likely(priv->rx_queue[i]->rxcoalescing))
1860 gfar_write(baddr + i, priv->rx_queue[i]->rxic);
1861 }
1862 } else {
1863 /* Backward compatible case -- even if we enable
1864 * multiple queues, there's only single reg to program
1865 */
1866 gfar_write(&regs->txic, 0);
1867 if (likely(priv->tx_queue[0]->txcoalescing))
1868 gfar_write(&regs->txic, priv->tx_queue[0]->txic);
1869
1870 gfar_write(&regs->rxic, 0);
1871 if (unlikely(priv->rx_queue[0]->rxcoalescing))
1872 gfar_write(&regs->rxic, priv->rx_queue[0]->rxic);
1873 }
1874}
1875
1876void gfar_configure_coalescing_all(struct gfar_private *priv)
1877{
1878 gfar_configure_coalescing(priv, 0xFF, 0xFF);
1879}
1880
1881static void free_grp_irqs(struct gfar_priv_grp *grp) 1881static void free_grp_irqs(struct gfar_priv_grp *grp)
1882{ 1882{
1883 free_irq(gfar_irq(grp, TX)->irq, grp); 1883 free_irq(gfar_irq(grp, TX)->irq, grp);
@@ -2812,17 +2812,6 @@ static int gfar_poll_sq(struct napi_struct *napi, int budget)
2812 gfar_write(&regs->rstat, gfargrp->rstat); 2812 gfar_write(&regs->rstat, gfargrp->rstat);
2813 2813
2814 gfar_write(&regs->imask, IMASK_DEFAULT); 2814 gfar_write(&regs->imask, IMASK_DEFAULT);
2815
2816 /* If we are coalescing interrupts, update the timer
2817 * Otherwise, clear it
2818 */
2819 gfar_write(&regs->txic, 0);
2820 if (likely(tx_queue->txcoalescing))
2821 gfar_write(&regs->txic, tx_queue->txic);
2822
2823 gfar_write(&regs->rxic, 0);
2824 if (unlikely(rx_queue->rxcoalescing))
2825 gfar_write(&regs->rxic, rx_queue->rxic);
2826 } 2815 }
2827 2816
2828 return work_done; 2817 return work_done;
@@ -2892,12 +2881,6 @@ static int gfar_poll(struct napi_struct *napi, int budget)
2892 gfar_write(&regs->rstat, gfargrp->rstat); 2881 gfar_write(&regs->rstat, gfargrp->rstat);
2893 2882
2894 gfar_write(&regs->imask, IMASK_DEFAULT); 2883 gfar_write(&regs->imask, IMASK_DEFAULT);
2895
2896 /* If we are coalescing interrupts, update the timer
2897 * Otherwise, clear it
2898 */
2899 gfar_configure_coalescing(priv, gfargrp->rx_bit_map,
2900 gfargrp->tx_bit_map);
2901 } 2884 }
2902 2885
2903 return work_done; 2886 return work_done;
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c
index 45219d4d09b4..891dbee6e6c1 100644
--- a/drivers/net/ethernet/freescale/gianfar_ethtool.c
+++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c
@@ -360,25 +360,11 @@ static int gfar_scoalesce(struct net_device *dev,
360 struct ethtool_coalesce *cvals) 360 struct ethtool_coalesce *cvals)
361{ 361{
362 struct gfar_private *priv = netdev_priv(dev); 362 struct gfar_private *priv = netdev_priv(dev);
363 int i = 0; 363 int i, err = 0;
364 364
365 if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) 365 if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE))
366 return -EOPNOTSUPP; 366 return -EOPNOTSUPP;
367 367
368 /* Set up rx coalescing */
369 /* As of now, we will enable/disable coalescing for all
370 * queues together in case of eTSEC2, this will be modified
371 * along with the ethtool interface
372 */
373 if ((cvals->rx_coalesce_usecs == 0) ||
374 (cvals->rx_max_coalesced_frames == 0)) {
375 for (i = 0; i < priv->num_rx_queues; i++)
376 priv->rx_queue[i]->rxcoalescing = 0;
377 } else {
378 for (i = 0; i < priv->num_rx_queues; i++)
379 priv->rx_queue[i]->rxcoalescing = 1;
380 }
381
382 if (NULL == priv->phydev) 368 if (NULL == priv->phydev)
383 return -ENODEV; 369 return -ENODEV;
384 370
@@ -395,6 +381,32 @@ static int gfar_scoalesce(struct net_device *dev,
395 return -EINVAL; 381 return -EINVAL;
396 } 382 }
397 383
384 /* Check the bounds of the values */
385 if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
386 netdev_info(dev, "Coalescing is limited to %d microseconds\n",
387 GFAR_MAX_COAL_USECS);
388 return -EINVAL;
389 }
390
391 if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
392 netdev_info(dev, "Coalescing is limited to %d frames\n",
393 GFAR_MAX_COAL_FRAMES);
394 return -EINVAL;
395 }
396
397 while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state))
398 cpu_relax();
399
400 /* Set up rx coalescing */
401 if ((cvals->rx_coalesce_usecs == 0) ||
402 (cvals->rx_max_coalesced_frames == 0)) {
403 for (i = 0; i < priv->num_rx_queues; i++)
404 priv->rx_queue[i]->rxcoalescing = 0;
405 } else {
406 for (i = 0; i < priv->num_rx_queues; i++)
407 priv->rx_queue[i]->rxcoalescing = 1;
408 }
409
398 for (i = 0; i < priv->num_rx_queues; i++) { 410 for (i = 0; i < priv->num_rx_queues; i++) {
399 priv->rx_queue[i]->rxic = mk_ic_value( 411 priv->rx_queue[i]->rxic = mk_ic_value(
400 cvals->rx_max_coalesced_frames, 412 cvals->rx_max_coalesced_frames,
@@ -411,28 +423,22 @@ static int gfar_scoalesce(struct net_device *dev,
411 priv->tx_queue[i]->txcoalescing = 1; 423 priv->tx_queue[i]->txcoalescing = 1;
412 } 424 }
413 425
414 /* Check the bounds of the values */
415 if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) {
416 netdev_info(dev, "Coalescing is limited to %d microseconds\n",
417 GFAR_MAX_COAL_USECS);
418 return -EINVAL;
419 }
420
421 if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) {
422 netdev_info(dev, "Coalescing is limited to %d frames\n",
423 GFAR_MAX_COAL_FRAMES);
424 return -EINVAL;
425 }
426
427 for (i = 0; i < priv->num_tx_queues; i++) { 426 for (i = 0; i < priv->num_tx_queues; i++) {
428 priv->tx_queue[i]->txic = mk_ic_value( 427 priv->tx_queue[i]->txic = mk_ic_value(
429 cvals->tx_max_coalesced_frames, 428 cvals->tx_max_coalesced_frames,
430 gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); 429 gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs));
431 } 430 }
432 431
433 gfar_configure_coalescing_all(priv); 432 if (dev->flags & IFF_UP) {
433 stop_gfar(dev);
434 err = startup_gfar(dev);
435 } else {
436 gfar_mac_reset(priv);
437 }
434 438
435 return 0; 439 clear_bit_unlock(GFAR_RESETTING, &priv->state);
440
441 return err;
436} 442}
437 443
438/* Fills in rvals with the current ring parameters. Currently, 444/* Fills in rvals with the current ring parameters. Currently,