diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/gianfar_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/freescale/gianfar_ethtool.c | 165 |
1 files changed, 65 insertions, 100 deletions
diff --git a/drivers/net/ethernet/freescale/gianfar_ethtool.c b/drivers/net/ethernet/freescale/gianfar_ethtool.c index 63d234419cc1..891dbee6e6c1 100644 --- a/drivers/net/ethernet/freescale/gianfar_ethtool.c +++ b/drivers/net/ethernet/freescale/gianfar_ethtool.c | |||
@@ -44,10 +44,6 @@ | |||
44 | 44 | ||
45 | #include "gianfar.h" | 45 | #include "gianfar.h" |
46 | 46 | ||
47 | extern void gfar_start(struct net_device *dev); | ||
48 | extern int gfar_clean_rx_ring(struct gfar_priv_rx_q *rx_queue, | ||
49 | int rx_work_limit); | ||
50 | |||
51 | #define GFAR_MAX_COAL_USECS 0xffff | 47 | #define GFAR_MAX_COAL_USECS 0xffff |
52 | #define GFAR_MAX_COAL_FRAMES 0xff | 48 | #define GFAR_MAX_COAL_FRAMES 0xff |
53 | static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, | 49 | static void gfar_fill_stats(struct net_device *dev, struct ethtool_stats *dummy, |
@@ -364,25 +360,11 @@ static int gfar_scoalesce(struct net_device *dev, | |||
364 | struct ethtool_coalesce *cvals) | 360 | struct ethtool_coalesce *cvals) |
365 | { | 361 | { |
366 | struct gfar_private *priv = netdev_priv(dev); | 362 | struct gfar_private *priv = netdev_priv(dev); |
367 | int i = 0; | 363 | int i, err = 0; |
368 | 364 | ||
369 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) | 365 | if (!(priv->device_flags & FSL_GIANFAR_DEV_HAS_COALESCE)) |
370 | return -EOPNOTSUPP; | 366 | return -EOPNOTSUPP; |
371 | 367 | ||
372 | /* Set up rx coalescing */ | ||
373 | /* As of now, we will enable/disable coalescing for all | ||
374 | * queues together in case of eTSEC2, this will be modified | ||
375 | * along with the ethtool interface | ||
376 | */ | ||
377 | if ((cvals->rx_coalesce_usecs == 0) || | ||
378 | (cvals->rx_max_coalesced_frames == 0)) { | ||
379 | for (i = 0; i < priv->num_rx_queues; i++) | ||
380 | priv->rx_queue[i]->rxcoalescing = 0; | ||
381 | } else { | ||
382 | for (i = 0; i < priv->num_rx_queues; i++) | ||
383 | priv->rx_queue[i]->rxcoalescing = 1; | ||
384 | } | ||
385 | |||
386 | if (NULL == priv->phydev) | 368 | if (NULL == priv->phydev) |
387 | return -ENODEV; | 369 | return -ENODEV; |
388 | 370 | ||
@@ -399,6 +381,32 @@ static int gfar_scoalesce(struct net_device *dev, | |||
399 | return -EINVAL; | 381 | return -EINVAL; |
400 | } | 382 | } |
401 | 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 | |||
402 | for (i = 0; i < priv->num_rx_queues; i++) { | 410 | for (i = 0; i < priv->num_rx_queues; i++) { |
403 | priv->rx_queue[i]->rxic = mk_ic_value( | 411 | priv->rx_queue[i]->rxic = mk_ic_value( |
404 | cvals->rx_max_coalesced_frames, | 412 | cvals->rx_max_coalesced_frames, |
@@ -415,28 +423,22 @@ static int gfar_scoalesce(struct net_device *dev, | |||
415 | priv->tx_queue[i]->txcoalescing = 1; | 423 | priv->tx_queue[i]->txcoalescing = 1; |
416 | } | 424 | } |
417 | 425 | ||
418 | /* Check the bounds of the values */ | ||
419 | if (cvals->tx_coalesce_usecs > GFAR_MAX_COAL_USECS) { | ||
420 | netdev_info(dev, "Coalescing is limited to %d microseconds\n", | ||
421 | GFAR_MAX_COAL_USECS); | ||
422 | return -EINVAL; | ||
423 | } | ||
424 | |||
425 | if (cvals->tx_max_coalesced_frames > GFAR_MAX_COAL_FRAMES) { | ||
426 | netdev_info(dev, "Coalescing is limited to %d frames\n", | ||
427 | GFAR_MAX_COAL_FRAMES); | ||
428 | return -EINVAL; | ||
429 | } | ||
430 | |||
431 | for (i = 0; i < priv->num_tx_queues; i++) { | 426 | for (i = 0; i < priv->num_tx_queues; i++) { |
432 | priv->tx_queue[i]->txic = mk_ic_value( | 427 | priv->tx_queue[i]->txic = mk_ic_value( |
433 | cvals->tx_max_coalesced_frames, | 428 | cvals->tx_max_coalesced_frames, |
434 | gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); | 429 | gfar_usecs2ticks(priv, cvals->tx_coalesce_usecs)); |
435 | } | 430 | } |
436 | 431 | ||
437 | 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 | } | ||
438 | |||
439 | clear_bit_unlock(GFAR_RESETTING, &priv->state); | ||
438 | 440 | ||
439 | return 0; | 441 | return err; |
440 | } | 442 | } |
441 | 443 | ||
442 | /* Fills in rvals with the current ring parameters. Currently, | 444 | /* Fills in rvals with the current ring parameters. Currently, |
@@ -467,15 +469,13 @@ static void gfar_gringparam(struct net_device *dev, | |||
467 | } | 469 | } |
468 | 470 | ||
469 | /* Change the current ring parameters, stopping the controller if | 471 | /* Change the current ring parameters, stopping the controller if |
470 | * necessary so that we don't mess things up while we're in | 472 | * necessary so that we don't mess things up while we're in motion. |
471 | * motion. We wait for the ring to be clean before reallocating | ||
472 | * the rings. | ||
473 | */ | 473 | */ |
474 | static int gfar_sringparam(struct net_device *dev, | 474 | static int gfar_sringparam(struct net_device *dev, |
475 | struct ethtool_ringparam *rvals) | 475 | struct ethtool_ringparam *rvals) |
476 | { | 476 | { |
477 | struct gfar_private *priv = netdev_priv(dev); | 477 | struct gfar_private *priv = netdev_priv(dev); |
478 | int err = 0, i = 0; | 478 | int err = 0, i; |
479 | 479 | ||
480 | if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) | 480 | if (rvals->rx_pending > GFAR_RX_MAX_RING_SIZE) |
481 | return -EINVAL; | 481 | return -EINVAL; |
@@ -493,44 +493,25 @@ static int gfar_sringparam(struct net_device *dev, | |||
493 | return -EINVAL; | 493 | return -EINVAL; |
494 | } | 494 | } |
495 | 495 | ||
496 | while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) | ||
497 | cpu_relax(); | ||
496 | 498 | ||
497 | if (dev->flags & IFF_UP) { | 499 | if (dev->flags & IFF_UP) |
498 | unsigned long flags; | ||
499 | |||
500 | /* Halt TX and RX, and process the frames which | ||
501 | * have already been received | ||
502 | */ | ||
503 | local_irq_save(flags); | ||
504 | lock_tx_qs(priv); | ||
505 | lock_rx_qs(priv); | ||
506 | |||
507 | gfar_halt(dev); | ||
508 | |||
509 | unlock_rx_qs(priv); | ||
510 | unlock_tx_qs(priv); | ||
511 | local_irq_restore(flags); | ||
512 | |||
513 | for (i = 0; i < priv->num_rx_queues; i++) | ||
514 | gfar_clean_rx_ring(priv->rx_queue[i], | ||
515 | priv->rx_queue[i]->rx_ring_size); | ||
516 | |||
517 | /* Now we take down the rings to rebuild them */ | ||
518 | stop_gfar(dev); | 500 | stop_gfar(dev); |
519 | } | ||
520 | 501 | ||
521 | /* Change the size */ | 502 | /* Change the sizes */ |
522 | for (i = 0; i < priv->num_rx_queues; i++) { | 503 | for (i = 0; i < priv->num_rx_queues; i++) |
523 | priv->rx_queue[i]->rx_ring_size = rvals->rx_pending; | 504 | priv->rx_queue[i]->rx_ring_size = rvals->rx_pending; |
505 | |||
506 | for (i = 0; i < priv->num_tx_queues; i++) | ||
524 | priv->tx_queue[i]->tx_ring_size = rvals->tx_pending; | 507 | priv->tx_queue[i]->tx_ring_size = rvals->tx_pending; |
525 | priv->tx_queue[i]->num_txbdfree = | ||
526 | priv->tx_queue[i]->tx_ring_size; | ||
527 | } | ||
528 | 508 | ||
529 | /* Rebuild the rings with the new size */ | 509 | /* Rebuild the rings with the new size */ |
530 | if (dev->flags & IFF_UP) { | 510 | if (dev->flags & IFF_UP) |
531 | err = startup_gfar(dev); | 511 | err = startup_gfar(dev); |
532 | netif_tx_wake_all_queues(dev); | 512 | |
533 | } | 513 | clear_bit_unlock(GFAR_RESETTING, &priv->state); |
514 | |||
534 | return err; | 515 | return err; |
535 | } | 516 | } |
536 | 517 | ||
@@ -608,43 +589,29 @@ static int gfar_spauseparam(struct net_device *dev, | |||
608 | 589 | ||
609 | int gfar_set_features(struct net_device *dev, netdev_features_t features) | 590 | int gfar_set_features(struct net_device *dev, netdev_features_t features) |
610 | { | 591 | { |
611 | struct gfar_private *priv = netdev_priv(dev); | ||
612 | unsigned long flags; | ||
613 | int err = 0, i = 0; | ||
614 | netdev_features_t changed = dev->features ^ features; | 592 | netdev_features_t changed = dev->features ^ features; |
593 | struct gfar_private *priv = netdev_priv(dev); | ||
594 | int err = 0; | ||
615 | 595 | ||
616 | if (changed & (NETIF_F_HW_VLAN_CTAG_TX|NETIF_F_HW_VLAN_CTAG_RX)) | 596 | if (!(changed & (NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | |
617 | gfar_vlan_mode(dev, features); | 597 | NETIF_F_RXCSUM))) |
618 | |||
619 | if (!(changed & NETIF_F_RXCSUM)) | ||
620 | return 0; | 598 | return 0; |
621 | 599 | ||
622 | if (dev->flags & IFF_UP) { | 600 | while (test_and_set_bit_lock(GFAR_RESETTING, &priv->state)) |
623 | /* Halt TX and RX, and process the frames which | 601 | cpu_relax(); |
624 | * have already been received | ||
625 | */ | ||
626 | local_irq_save(flags); | ||
627 | lock_tx_qs(priv); | ||
628 | lock_rx_qs(priv); | ||
629 | |||
630 | gfar_halt(dev); | ||
631 | 602 | ||
632 | unlock_tx_qs(priv); | 603 | dev->features = features; |
633 | unlock_rx_qs(priv); | ||
634 | local_irq_restore(flags); | ||
635 | |||
636 | for (i = 0; i < priv->num_rx_queues; i++) | ||
637 | gfar_clean_rx_ring(priv->rx_queue[i], | ||
638 | priv->rx_queue[i]->rx_ring_size); | ||
639 | 604 | ||
605 | if (dev->flags & IFF_UP) { | ||
640 | /* Now we take down the rings to rebuild them */ | 606 | /* Now we take down the rings to rebuild them */ |
641 | stop_gfar(dev); | 607 | stop_gfar(dev); |
642 | |||
643 | dev->features = features; | ||
644 | |||
645 | err = startup_gfar(dev); | 608 | err = startup_gfar(dev); |
646 | netif_tx_wake_all_queues(dev); | 609 | } else { |
610 | gfar_mac_reset(priv); | ||
647 | } | 611 | } |
612 | |||
613 | clear_bit_unlock(GFAR_RESETTING, &priv->state); | ||
614 | |||
648 | return err; | 615 | return err; |
649 | } | 616 | } |
650 | 617 | ||
@@ -1610,9 +1577,6 @@ static int gfar_write_filer_table(struct gfar_private *priv, | |||
1610 | if (tab->index > MAX_FILER_IDX - 1) | 1577 | if (tab->index > MAX_FILER_IDX - 1) |
1611 | return -EBUSY; | 1578 | return -EBUSY; |
1612 | 1579 | ||
1613 | /* Avoid inconsistent filer table to be processed */ | ||
1614 | lock_rx_qs(priv); | ||
1615 | |||
1616 | /* Fill regular entries */ | 1580 | /* Fill regular entries */ |
1617 | for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); | 1581 | for (; i < MAX_FILER_IDX - 1 && (tab->fe[i].ctrl | tab->fe[i].ctrl); |
1618 | i++) | 1582 | i++) |
@@ -1625,8 +1589,6 @@ static int gfar_write_filer_table(struct gfar_private *priv, | |||
1625 | */ | 1589 | */ |
1626 | gfar_write_filer(priv, i, 0x20, 0x0); | 1590 | gfar_write_filer(priv, i, 0x20, 0x0); |
1627 | 1591 | ||
1628 | unlock_rx_qs(priv); | ||
1629 | |||
1630 | return 0; | 1592 | return 0; |
1631 | } | 1593 | } |
1632 | 1594 | ||
@@ -1831,6 +1793,9 @@ static int gfar_set_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd) | |||
1831 | struct gfar_private *priv = netdev_priv(dev); | 1793 | struct gfar_private *priv = netdev_priv(dev); |
1832 | int ret = 0; | 1794 | int ret = 0; |
1833 | 1795 | ||
1796 | if (test_bit(GFAR_RESETTING, &priv->state)) | ||
1797 | return -EBUSY; | ||
1798 | |||
1834 | mutex_lock(&priv->rx_queue_access); | 1799 | mutex_lock(&priv->rx_queue_access); |
1835 | 1800 | ||
1836 | switch (cmd->cmd) { | 1801 | switch (cmd->cmd) { |