diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_ethtool.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 129 |
1 files changed, 83 insertions, 46 deletions
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 18ecba7f6ecb..aafc120f164e 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
@@ -129,6 +129,15 @@ static int ixgbe_get_settings(struct net_device *netdev, | |||
129 | ecmd->advertising |= ADVERTISED_10000baseT_Full; | 129 | ecmd->advertising |= ADVERTISED_10000baseT_Full; |
130 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | 130 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) |
131 | ecmd->advertising |= ADVERTISED_1000baseT_Full; | 131 | ecmd->advertising |= ADVERTISED_1000baseT_Full; |
132 | /* | ||
133 | * It's possible that phy.autoneg_advertised may not be | ||
134 | * set yet. If so display what the default would be - | ||
135 | * both 1G and 10G supported. | ||
136 | */ | ||
137 | if (!(ecmd->advertising & (ADVERTISED_1000baseT_Full | | ||
138 | ADVERTISED_10000baseT_Full))) | ||
139 | ecmd->advertising |= (ADVERTISED_10000baseT_Full | | ||
140 | ADVERTISED_1000baseT_Full); | ||
132 | 141 | ||
133 | ecmd->port = PORT_TP; | 142 | ecmd->port = PORT_TP; |
134 | } else if (hw->phy.media_type == ixgbe_media_type_backplane) { | 143 | } else if (hw->phy.media_type == ixgbe_media_type_backplane) { |
@@ -225,7 +234,16 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, | |||
225 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 234 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
226 | struct ixgbe_hw *hw = &adapter->hw; | 235 | struct ixgbe_hw *hw = &adapter->hw; |
227 | 236 | ||
228 | pause->autoneg = (hw->fc.current_mode == ixgbe_fc_full ? 1 : 0); | 237 | /* |
238 | * Flow Control Autoneg isn't on if | ||
239 | * - we didn't ask for it OR | ||
240 | * - it failed, we know this by tx & rx being off | ||
241 | */ | ||
242 | if (hw->fc.disable_fc_autoneg || | ||
243 | (hw->fc.current_mode == ixgbe_fc_none)) | ||
244 | pause->autoneg = 0; | ||
245 | else | ||
246 | pause->autoneg = 1; | ||
229 | 247 | ||
230 | if (hw->fc.current_mode == ixgbe_fc_rx_pause) { | 248 | if (hw->fc.current_mode == ixgbe_fc_rx_pause) { |
231 | pause->rx_pause = 1; | 249 | pause->rx_pause = 1; |
@@ -243,8 +261,12 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
243 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 261 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
244 | struct ixgbe_hw *hw = &adapter->hw; | 262 | struct ixgbe_hw *hw = &adapter->hw; |
245 | 263 | ||
246 | if ((pause->autoneg == AUTONEG_ENABLE) || | 264 | if (pause->autoneg != AUTONEG_ENABLE) |
247 | (pause->rx_pause && pause->tx_pause)) | 265 | hw->fc.disable_fc_autoneg = true; |
266 | else | ||
267 | hw->fc.disable_fc_autoneg = false; | ||
268 | |||
269 | if (pause->rx_pause && pause->tx_pause) | ||
248 | hw->fc.requested_mode = ixgbe_fc_full; | 270 | hw->fc.requested_mode = ixgbe_fc_full; |
249 | else if (pause->rx_pause && !pause->tx_pause) | 271 | else if (pause->rx_pause && !pause->tx_pause) |
250 | hw->fc.requested_mode = ixgbe_fc_rx_pause; | 272 | hw->fc.requested_mode = ixgbe_fc_rx_pause; |
@@ -712,9 +734,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
712 | struct ethtool_ringparam *ring) | 734 | struct ethtool_ringparam *ring) |
713 | { | 735 | { |
714 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 736 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
715 | struct ixgbe_ring *temp_ring; | 737 | struct ixgbe_ring *temp_tx_ring, *temp_rx_ring; |
716 | int i, err; | 738 | int i, err; |
717 | u32 new_rx_count, new_tx_count; | 739 | u32 new_rx_count, new_tx_count; |
740 | bool need_update = false; | ||
718 | 741 | ||
719 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) | 742 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
720 | return -EINVAL; | 743 | return -EINVAL; |
@@ -733,80 +756,94 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
733 | return 0; | 756 | return 0; |
734 | } | 757 | } |
735 | 758 | ||
736 | temp_ring = kcalloc(adapter->num_tx_queues, | ||
737 | sizeof(struct ixgbe_ring), GFP_KERNEL); | ||
738 | if (!temp_ring) | ||
739 | return -ENOMEM; | ||
740 | |||
741 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) | 759 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) |
742 | msleep(1); | 760 | msleep(1); |
743 | 761 | ||
744 | if (new_tx_count != adapter->tx_ring->count) { | 762 | temp_tx_ring = kcalloc(adapter->num_tx_queues, |
763 | sizeof(struct ixgbe_ring), GFP_KERNEL); | ||
764 | if (!temp_tx_ring) { | ||
765 | err = -ENOMEM; | ||
766 | goto err_setup; | ||
767 | } | ||
768 | |||
769 | if (new_tx_count != adapter->tx_ring_count) { | ||
770 | memcpy(temp_tx_ring, adapter->tx_ring, | ||
771 | adapter->num_tx_queues * sizeof(struct ixgbe_ring)); | ||
745 | for (i = 0; i < adapter->num_tx_queues; i++) { | 772 | for (i = 0; i < adapter->num_tx_queues; i++) { |
746 | temp_ring[i].count = new_tx_count; | 773 | temp_tx_ring[i].count = new_tx_count; |
747 | err = ixgbe_setup_tx_resources(adapter, &temp_ring[i]); | 774 | err = ixgbe_setup_tx_resources(adapter, |
775 | &temp_tx_ring[i]); | ||
748 | if (err) { | 776 | if (err) { |
749 | while (i) { | 777 | while (i) { |
750 | i--; | 778 | i--; |
751 | ixgbe_free_tx_resources(adapter, | 779 | ixgbe_free_tx_resources(adapter, |
752 | &temp_ring[i]); | 780 | &temp_tx_ring[i]); |
753 | } | 781 | } |
754 | goto err_setup; | 782 | goto err_setup; |
755 | } | 783 | } |
756 | temp_ring[i].v_idx = adapter->tx_ring[i].v_idx; | 784 | temp_tx_ring[i].v_idx = adapter->tx_ring[i].v_idx; |
757 | } | 785 | } |
758 | if (netif_running(netdev)) | 786 | need_update = true; |
759 | netdev->netdev_ops->ndo_stop(netdev); | ||
760 | ixgbe_reset_interrupt_capability(adapter); | ||
761 | ixgbe_napi_del_all(adapter); | ||
762 | INIT_LIST_HEAD(&netdev->napi_list); | ||
763 | kfree(adapter->tx_ring); | ||
764 | adapter->tx_ring = temp_ring; | ||
765 | temp_ring = NULL; | ||
766 | adapter->tx_ring_count = new_tx_count; | ||
767 | } | 787 | } |
768 | 788 | ||
769 | temp_ring = kcalloc(adapter->num_rx_queues, | 789 | temp_rx_ring = kcalloc(adapter->num_rx_queues, |
770 | sizeof(struct ixgbe_ring), GFP_KERNEL); | 790 | sizeof(struct ixgbe_ring), GFP_KERNEL); |
771 | if (!temp_ring) { | 791 | if ((!temp_rx_ring) && (need_update)) { |
772 | if (netif_running(netdev)) | 792 | for (i = 0; i < adapter->num_tx_queues; i++) |
773 | netdev->netdev_ops->ndo_open(netdev); | 793 | ixgbe_free_tx_resources(adapter, &temp_tx_ring[i]); |
774 | return -ENOMEM; | 794 | kfree(temp_tx_ring); |
795 | err = -ENOMEM; | ||
796 | goto err_setup; | ||
775 | } | 797 | } |
776 | 798 | ||
777 | if (new_rx_count != adapter->rx_ring->count) { | 799 | if (new_rx_count != adapter->rx_ring_count) { |
800 | memcpy(temp_rx_ring, adapter->rx_ring, | ||
801 | adapter->num_rx_queues * sizeof(struct ixgbe_ring)); | ||
778 | for (i = 0; i < adapter->num_rx_queues; i++) { | 802 | for (i = 0; i < adapter->num_rx_queues; i++) { |
779 | temp_ring[i].count = new_rx_count; | 803 | temp_rx_ring[i].count = new_rx_count; |
780 | err = ixgbe_setup_rx_resources(adapter, &temp_ring[i]); | 804 | err = ixgbe_setup_rx_resources(adapter, |
805 | &temp_rx_ring[i]); | ||
781 | if (err) { | 806 | if (err) { |
782 | while (i) { | 807 | while (i) { |
783 | i--; | 808 | i--; |
784 | ixgbe_free_rx_resources(adapter, | 809 | ixgbe_free_rx_resources(adapter, |
785 | &temp_ring[i]); | 810 | &temp_rx_ring[i]); |
786 | } | 811 | } |
787 | goto err_setup; | 812 | goto err_setup; |
788 | } | 813 | } |
789 | temp_ring[i].v_idx = adapter->rx_ring[i].v_idx; | 814 | temp_rx_ring[i].v_idx = adapter->rx_ring[i].v_idx; |
790 | } | 815 | } |
816 | need_update = true; | ||
817 | } | ||
818 | |||
819 | /* if rings need to be updated, here's the place to do it in one shot */ | ||
820 | if (need_update) { | ||
791 | if (netif_running(netdev)) | 821 | if (netif_running(netdev)) |
792 | netdev->netdev_ops->ndo_stop(netdev); | 822 | ixgbe_down(adapter); |
793 | ixgbe_reset_interrupt_capability(adapter); | 823 | |
794 | ixgbe_napi_del_all(adapter); | 824 | /* tx */ |
795 | INIT_LIST_HEAD(&netdev->napi_list); | 825 | if (new_tx_count != adapter->tx_ring_count) { |
796 | kfree(adapter->rx_ring); | 826 | kfree(adapter->tx_ring); |
797 | adapter->rx_ring = temp_ring; | 827 | adapter->tx_ring = temp_tx_ring; |
798 | temp_ring = NULL; | 828 | temp_tx_ring = NULL; |
799 | 829 | adapter->tx_ring_count = new_tx_count; | |
800 | adapter->rx_ring_count = new_rx_count; | 830 | } |
831 | |||
832 | /* rx */ | ||
833 | if (new_rx_count != adapter->rx_ring_count) { | ||
834 | kfree(adapter->rx_ring); | ||
835 | adapter->rx_ring = temp_rx_ring; | ||
836 | temp_rx_ring = NULL; | ||
837 | adapter->rx_ring_count = new_rx_count; | ||
838 | } | ||
801 | } | 839 | } |
802 | 840 | ||
803 | /* success! */ | 841 | /* success! */ |
804 | err = 0; | 842 | err = 0; |
805 | err_setup: | ||
806 | ixgbe_init_interrupt_scheme(adapter); | ||
807 | if (netif_running(netdev)) | 843 | if (netif_running(netdev)) |
808 | netdev->netdev_ops->ndo_open(netdev); | 844 | ixgbe_up(adapter); |
809 | 845 | ||
846 | err_setup: | ||
810 | clear_bit(__IXGBE_RESETTING, &adapter->state); | 847 | clear_bit(__IXGBE_RESETTING, &adapter->state); |
811 | return err; | 848 | return err; |
812 | } | 849 | } |