diff options
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 102 |
1 files changed, 50 insertions, 52 deletions
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index 56b20d17d0e4..872c3374ddfa 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | |||
@@ -887,24 +887,23 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
887 | struct ethtool_ringparam *ring) | 887 | struct ethtool_ringparam *ring) |
888 | { | 888 | { |
889 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 889 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
890 | struct ixgbe_ring *temp_tx_ring, *temp_rx_ring; | 890 | struct ixgbe_ring *temp_ring; |
891 | int i, err = 0; | 891 | int i, err = 0; |
892 | u32 new_rx_count, new_tx_count; | 892 | u32 new_rx_count, new_tx_count; |
893 | bool need_update = false; | ||
894 | 893 | ||
895 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) | 894 | if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) |
896 | return -EINVAL; | 895 | return -EINVAL; |
897 | 896 | ||
898 | new_rx_count = max_t(u32, ring->rx_pending, IXGBE_MIN_RXD); | 897 | new_tx_count = clamp_t(u32, ring->tx_pending, |
899 | new_rx_count = min_t(u32, new_rx_count, IXGBE_MAX_RXD); | 898 | IXGBE_MIN_TXD, IXGBE_MAX_TXD); |
900 | new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); | ||
901 | |||
902 | new_tx_count = max_t(u32, ring->tx_pending, IXGBE_MIN_TXD); | ||
903 | new_tx_count = min_t(u32, new_tx_count, IXGBE_MAX_TXD); | ||
904 | new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); | 899 | new_tx_count = ALIGN(new_tx_count, IXGBE_REQ_TX_DESCRIPTOR_MULTIPLE); |
905 | 900 | ||
906 | if ((new_tx_count == adapter->tx_ring[0]->count) && | 901 | new_rx_count = clamp_t(u32, ring->rx_pending, |
907 | (new_rx_count == adapter->rx_ring[0]->count)) { | 902 | IXGBE_MIN_RXD, IXGBE_MAX_RXD); |
903 | new_rx_count = ALIGN(new_rx_count, IXGBE_REQ_RX_DESCRIPTOR_MULTIPLE); | ||
904 | |||
905 | if ((new_tx_count == adapter->tx_ring_count) && | ||
906 | (new_rx_count == adapter->rx_ring_count)) { | ||
908 | /* nothing to do */ | 907 | /* nothing to do */ |
909 | return 0; | 908 | return 0; |
910 | } | 909 | } |
@@ -922,81 +921,80 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
922 | goto clear_reset; | 921 | goto clear_reset; |
923 | } | 922 | } |
924 | 923 | ||
925 | temp_tx_ring = vmalloc(adapter->num_tx_queues * sizeof(struct ixgbe_ring)); | 924 | /* allocate temporary buffer to store rings in */ |
926 | if (!temp_tx_ring) { | 925 | i = max_t(int, adapter->num_tx_queues, adapter->num_rx_queues); |
926 | temp_ring = vmalloc(i * sizeof(struct ixgbe_ring)); | ||
927 | |||
928 | if (!temp_ring) { | ||
927 | err = -ENOMEM; | 929 | err = -ENOMEM; |
928 | goto clear_reset; | 930 | goto clear_reset; |
929 | } | 931 | } |
930 | 932 | ||
933 | ixgbe_down(adapter); | ||
934 | |||
935 | /* | ||
936 | * Setup new Tx resources and free the old Tx resources in that order. | ||
937 | * We can then assign the new resources to the rings via a memcpy. | ||
938 | * The advantage to this approach is that we are guaranteed to still | ||
939 | * have resources even in the case of an allocation failure. | ||
940 | */ | ||
931 | if (new_tx_count != adapter->tx_ring_count) { | 941 | if (new_tx_count != adapter->tx_ring_count) { |
932 | for (i = 0; i < adapter->num_tx_queues; i++) { | 942 | for (i = 0; i < adapter->num_tx_queues; i++) { |
933 | memcpy(&temp_tx_ring[i], adapter->tx_ring[i], | 943 | memcpy(&temp_ring[i], adapter->tx_ring[i], |
934 | sizeof(struct ixgbe_ring)); | 944 | sizeof(struct ixgbe_ring)); |
935 | temp_tx_ring[i].count = new_tx_count; | 945 | |
936 | err = ixgbe_setup_tx_resources(&temp_tx_ring[i]); | 946 | temp_ring[i].count = new_tx_count; |
947 | err = ixgbe_setup_tx_resources(&temp_ring[i]); | ||
937 | if (err) { | 948 | if (err) { |
938 | while (i) { | 949 | while (i) { |
939 | i--; | 950 | i--; |
940 | ixgbe_free_tx_resources(&temp_tx_ring[i]); | 951 | ixgbe_free_tx_resources(&temp_ring[i]); |
941 | } | 952 | } |
942 | goto clear_reset; | 953 | goto err_setup; |
943 | } | 954 | } |
944 | } | 955 | } |
945 | need_update = true; | ||
946 | } | ||
947 | 956 | ||
948 | temp_rx_ring = vmalloc(adapter->num_rx_queues * sizeof(struct ixgbe_ring)); | 957 | for (i = 0; i < adapter->num_tx_queues; i++) { |
949 | if (!temp_rx_ring) { | 958 | ixgbe_free_tx_resources(adapter->tx_ring[i]); |
950 | err = -ENOMEM; | 959 | |
951 | goto err_setup; | 960 | memcpy(adapter->tx_ring[i], &temp_ring[i], |
961 | sizeof(struct ixgbe_ring)); | ||
962 | } | ||
963 | |||
964 | adapter->tx_ring_count = new_tx_count; | ||
952 | } | 965 | } |
953 | 966 | ||
967 | /* Repeat the process for the Rx rings if needed */ | ||
954 | if (new_rx_count != adapter->rx_ring_count) { | 968 | if (new_rx_count != adapter->rx_ring_count) { |
955 | for (i = 0; i < adapter->num_rx_queues; i++) { | 969 | for (i = 0; i < adapter->num_rx_queues; i++) { |
956 | memcpy(&temp_rx_ring[i], adapter->rx_ring[i], | 970 | memcpy(&temp_ring[i], adapter->rx_ring[i], |
957 | sizeof(struct ixgbe_ring)); | 971 | sizeof(struct ixgbe_ring)); |
958 | temp_rx_ring[i].count = new_rx_count; | 972 | |
959 | err = ixgbe_setup_rx_resources(&temp_rx_ring[i]); | 973 | temp_ring[i].count = new_rx_count; |
974 | err = ixgbe_setup_rx_resources(&temp_ring[i]); | ||
960 | if (err) { | 975 | if (err) { |
961 | while (i) { | 976 | while (i) { |
962 | i--; | 977 | i--; |
963 | ixgbe_free_rx_resources(&temp_rx_ring[i]); | 978 | ixgbe_free_rx_resources(&temp_ring[i]); |
964 | } | 979 | } |
965 | goto err_setup; | 980 | goto err_setup; |
966 | } | 981 | } |
982 | |||
967 | } | 983 | } |
968 | need_update = true; | ||
969 | } | ||
970 | 984 | ||
971 | /* if rings need to be updated, here's the place to do it in one shot */ | 985 | for (i = 0; i < adapter->num_rx_queues; i++) { |
972 | if (need_update) { | 986 | ixgbe_free_rx_resources(adapter->rx_ring[i]); |
973 | ixgbe_down(adapter); | ||
974 | 987 | ||
975 | /* tx */ | 988 | memcpy(adapter->rx_ring[i], &temp_ring[i], |
976 | if (new_tx_count != adapter->tx_ring_count) { | 989 | sizeof(struct ixgbe_ring)); |
977 | for (i = 0; i < adapter->num_tx_queues; i++) { | ||
978 | ixgbe_free_tx_resources(adapter->tx_ring[i]); | ||
979 | memcpy(adapter->tx_ring[i], &temp_tx_ring[i], | ||
980 | sizeof(struct ixgbe_ring)); | ||
981 | } | ||
982 | adapter->tx_ring_count = new_tx_count; | ||
983 | } | 990 | } |
984 | 991 | ||
985 | /* rx */ | 992 | adapter->rx_ring_count = new_rx_count; |
986 | if (new_rx_count != adapter->rx_ring_count) { | ||
987 | for (i = 0; i < adapter->num_rx_queues; i++) { | ||
988 | ixgbe_free_rx_resources(adapter->rx_ring[i]); | ||
989 | memcpy(adapter->rx_ring[i], &temp_rx_ring[i], | ||
990 | sizeof(struct ixgbe_ring)); | ||
991 | } | ||
992 | adapter->rx_ring_count = new_rx_count; | ||
993 | } | ||
994 | ixgbe_up(adapter); | ||
995 | } | 993 | } |
996 | 994 | ||
997 | vfree(temp_rx_ring); | ||
998 | err_setup: | 995 | err_setup: |
999 | vfree(temp_tx_ring); | 996 | ixgbe_up(adapter); |
997 | vfree(temp_ring); | ||
1000 | clear_reset: | 998 | clear_reset: |
1001 | clear_bit(__IXGBE_RESETTING, &adapter->state); | 999 | clear_bit(__IXGBE_RESETTING, &adapter->state); |
1002 | return err; | 1000 | return err; |