aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBruce Allan <bruce.w.allan@intel.com>2011-12-15 19:45:51 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2012-01-26 02:12:29 -0500
commit508da4264add2eb13bd4d32bb896e79e6f8821fc (patch)
tree04f530b35714efdd0afd5457e11a7dc3efe47d32
parent55aa69854a93d7aaf123a882b0b1f93c86cf3c7e (diff)
e1000e: re-factor ethtool get/set ring parameter
Make it more like how igb does it, with some additional error checking. Signed-off-by: Bruce Allan <bruce.w.allan@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/e1000e/ethtool.c136
1 files changed, 77 insertions, 59 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 01c73aee7fdb..ffb6c14cbbb8 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -605,94 +605,112 @@ static void e1000_get_ringparam(struct net_device *netdev,
605 struct ethtool_ringparam *ring) 605 struct ethtool_ringparam *ring)
606{ 606{
607 struct e1000_adapter *adapter = netdev_priv(netdev); 607 struct e1000_adapter *adapter = netdev_priv(netdev);
608 struct e1000_ring *tx_ring = adapter->tx_ring;
609 struct e1000_ring *rx_ring = adapter->rx_ring;
610 608
611 ring->rx_max_pending = E1000_MAX_RXD; 609 ring->rx_max_pending = E1000_MAX_RXD;
612 ring->tx_max_pending = E1000_MAX_TXD; 610 ring->tx_max_pending = E1000_MAX_TXD;
613 ring->rx_pending = rx_ring->count; 611 ring->rx_pending = adapter->rx_ring_count;
614 ring->tx_pending = tx_ring->count; 612 ring->tx_pending = adapter->tx_ring_count;
615} 613}
616 614
617static int e1000_set_ringparam(struct net_device *netdev, 615static int e1000_set_ringparam(struct net_device *netdev,
618 struct ethtool_ringparam *ring) 616 struct ethtool_ringparam *ring)
619{ 617{
620 struct e1000_adapter *adapter = netdev_priv(netdev); 618 struct e1000_adapter *adapter = netdev_priv(netdev);
621 struct e1000_ring *tx_ring, *tx_old; 619 struct e1000_ring *temp_tx = NULL, *temp_rx = NULL;
622 struct e1000_ring *rx_ring, *rx_old; 620 int err = 0, size = sizeof(struct e1000_ring);
623 int err; 621 bool set_tx = false, set_rx = false;
622 u16 new_rx_count, new_tx_count;
624 623
625 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) 624 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
626 return -EINVAL; 625 return -EINVAL;
627 626
628 while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) 627 new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD,
629 usleep_range(1000, 2000); 628 E1000_MAX_RXD);
629 new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE);
630 630
631 if (netif_running(adapter->netdev)) 631 new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD,
632 e1000e_down(adapter); 632 E1000_MAX_TXD);
633 new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE);
633 634
634 tx_old = adapter->tx_ring; 635 if ((new_tx_count == adapter->tx_ring_count) &&
635 rx_old = adapter->rx_ring; 636 (new_rx_count == adapter->rx_ring_count))
637 /* nothing to do */
638 return 0;
636 639
637 err = -ENOMEM; 640 while (test_and_set_bit(__E1000_RESETTING, &adapter->state))
638 tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL); 641 usleep_range(1000, 2000);
639 if (!tx_ring)
640 goto err_alloc_tx;
641 642
642 rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL); 643 if (!netif_running(adapter->netdev)) {
643 if (!rx_ring) 644 /* Set counts now and allocate resources during open() */
644 goto err_alloc_rx; 645 adapter->tx_ring->count = new_tx_count;
646 adapter->rx_ring->count = new_rx_count;
647 adapter->tx_ring_count = new_tx_count;
648 adapter->rx_ring_count = new_rx_count;
649 goto clear_reset;
650 }
645 651
646 adapter->tx_ring = tx_ring; 652 set_tx = (new_tx_count != adapter->tx_ring_count);
647 adapter->rx_ring = rx_ring; 653 set_rx = (new_rx_count != adapter->rx_ring_count);
648 654
649 rx_ring->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); 655 /* Allocate temporary storage for ring updates */
650 rx_ring->count = min(rx_ring->count, (u32)(E1000_MAX_RXD)); 656 if (set_tx) {
651 rx_ring->count = ALIGN(rx_ring->count, REQ_RX_DESCRIPTOR_MULTIPLE); 657 temp_tx = vmalloc(size);
658 if (!temp_tx) {
659 err = -ENOMEM;
660 goto free_temp;
661 }
662 }
663 if (set_rx) {
664 temp_rx = vmalloc(size);
665 if (!temp_rx) {
666 err = -ENOMEM;
667 goto free_temp;
668 }
669 }
652 670
653 tx_ring->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); 671 e1000e_down(adapter);
654 tx_ring->count = min(tx_ring->count, (u32)(E1000_MAX_TXD));
655 tx_ring->count = ALIGN(tx_ring->count, REQ_TX_DESCRIPTOR_MULTIPLE);
656 672
657 if (netif_running(adapter->netdev)) { 673 /*
658 /* Try to get new resources before deleting old */ 674 * We can't just free everything and then setup again, because the
659 err = e1000e_setup_rx_resources(rx_ring); 675 * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring
676 * structs. First, attempt to allocate new resources...
677 */
678 if (set_tx) {
679 memcpy(temp_tx, adapter->tx_ring, size);
680 temp_tx->count = new_tx_count;
681 err = e1000e_setup_tx_resources(temp_tx);
660 if (err) 682 if (err)
661 goto err_setup_rx; 683 goto err_setup;
662 err = e1000e_setup_tx_resources(tx_ring); 684 }
685 if (set_rx) {
686 memcpy(temp_rx, adapter->rx_ring, size);
687 temp_rx->count = new_rx_count;
688 err = e1000e_setup_rx_resources(temp_rx);
663 if (err) 689 if (err)
664 goto err_setup_tx; 690 goto err_setup_rx;
691 }
665 692
666 /* 693 /* ...then free the old resources and copy back any new ring data */
667 * restore the old in order to free it, 694 if (set_tx) {
668 * then add in the new
669 */
670 adapter->rx_ring = rx_old;
671 adapter->tx_ring = tx_old;
672 e1000e_free_rx_resources(adapter->rx_ring);
673 e1000e_free_tx_resources(adapter->tx_ring); 695 e1000e_free_tx_resources(adapter->tx_ring);
674 kfree(tx_old); 696 memcpy(adapter->tx_ring, temp_tx, size);
675 kfree(rx_old); 697 adapter->tx_ring_count = new_tx_count;
676 adapter->rx_ring = rx_ring; 698 }
677 adapter->tx_ring = tx_ring; 699 if (set_rx) {
678 err = e1000e_up(adapter); 700 e1000e_free_rx_resources(adapter->rx_ring);
679 if (err) 701 memcpy(adapter->rx_ring, temp_rx, size);
680 goto err_setup; 702 adapter->rx_ring_count = new_rx_count;
681 } 703 }
682 704
683 clear_bit(__E1000_RESETTING, &adapter->state);
684 return 0;
685err_setup_tx:
686 e1000e_free_rx_resources(rx_ring);
687err_setup_rx: 705err_setup_rx:
688 adapter->rx_ring = rx_old; 706 if (err && set_tx)
689 adapter->tx_ring = tx_old; 707 e1000e_free_tx_resources(temp_tx);
690 kfree(rx_ring);
691err_alloc_rx:
692 kfree(tx_ring);
693err_alloc_tx:
694 e1000e_up(adapter);
695err_setup: 708err_setup:
709 e1000e_up(adapter);
710free_temp:
711 vfree(temp_tx);
712 vfree(temp_rx);
713clear_reset:
696 clear_bit(__E1000_RESETTING, &adapter->state); 714 clear_bit(__E1000_RESETTING, &adapter->state);
697 return err; 715 return err;
698} 716}