diff options
Diffstat (limited to 'drivers/net/ixgbe/ixgbe_ethtool.c')
-rw-r--r-- | drivers/net/ixgbe/ixgbe_ethtool.c | 91 |
1 files changed, 54 insertions, 37 deletions
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c index 36353447716d..a119cbd8dbb8 100644 --- a/drivers/net/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ixgbe/ixgbe_ethtool.c | |||
@@ -103,21 +103,41 @@ static int ixgbe_get_settings(struct net_device *netdev, | |||
103 | struct ethtool_cmd *ecmd) | 103 | struct ethtool_cmd *ecmd) |
104 | { | 104 | { |
105 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 105 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
106 | struct ixgbe_hw *hw = &adapter->hw; | ||
107 | u32 link_speed = 0; | ||
108 | bool link_up; | ||
106 | 109 | ||
107 | ecmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE); | 110 | ecmd->supported = SUPPORTED_10000baseT_Full; |
108 | ecmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE); | 111 | ecmd->autoneg = AUTONEG_ENABLE; |
109 | ecmd->port = PORT_FIBRE; | ||
110 | ecmd->transceiver = XCVR_EXTERNAL; | 112 | ecmd->transceiver = XCVR_EXTERNAL; |
113 | if (hw->phy.media_type == ixgbe_media_type_copper) { | ||
114 | ecmd->supported |= (SUPPORTED_1000baseT_Full | | ||
115 | SUPPORTED_TP | SUPPORTED_Autoneg); | ||
116 | |||
117 | ecmd->advertising = (ADVERTISED_TP | ADVERTISED_Autoneg); | ||
118 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) | ||
119 | ecmd->advertising |= ADVERTISED_10000baseT_Full; | ||
120 | if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | ||
121 | ecmd->advertising |= ADVERTISED_1000baseT_Full; | ||
122 | |||
123 | ecmd->port = PORT_TP; | ||
124 | } else { | ||
125 | ecmd->supported |= SUPPORTED_FIBRE; | ||
126 | ecmd->advertising = (ADVERTISED_10000baseT_Full | | ||
127 | ADVERTISED_FIBRE); | ||
128 | ecmd->port = PORT_FIBRE; | ||
129 | } | ||
111 | 130 | ||
112 | if (netif_carrier_ok(adapter->netdev)) { | 131 | adapter->hw.mac.ops.check_link(hw, &(link_speed), &link_up); |
113 | ecmd->speed = SPEED_10000; | 132 | if (link_up) { |
133 | ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ? | ||
134 | SPEED_10000 : SPEED_1000; | ||
114 | ecmd->duplex = DUPLEX_FULL; | 135 | ecmd->duplex = DUPLEX_FULL; |
115 | } else { | 136 | } else { |
116 | ecmd->speed = -1; | 137 | ecmd->speed = -1; |
117 | ecmd->duplex = -1; | 138 | ecmd->duplex = -1; |
118 | } | 139 | } |
119 | 140 | ||
120 | ecmd->autoneg = AUTONEG_DISABLE; | ||
121 | return 0; | 141 | return 0; |
122 | } | 142 | } |
123 | 143 | ||
@@ -125,17 +145,17 @@ static int ixgbe_set_settings(struct net_device *netdev, | |||
125 | struct ethtool_cmd *ecmd) | 145 | struct ethtool_cmd *ecmd) |
126 | { | 146 | { |
127 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 147 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
148 | struct ixgbe_hw *hw = &adapter->hw; | ||
128 | 149 | ||
129 | if (ecmd->autoneg == AUTONEG_ENABLE || | 150 | switch (hw->phy.media_type) { |
130 | ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL) | 151 | case ixgbe_media_type_fiber: |
131 | return -EINVAL; | 152 | if ((ecmd->autoneg == AUTONEG_ENABLE) || |
132 | 153 | (ecmd->speed + ecmd->duplex != SPEED_10000 + DUPLEX_FULL)) | |
133 | if (netif_running(adapter->netdev)) { | 154 | return -EINVAL; |
134 | ixgbe_down(adapter); | 155 | /* in this case we currently only support 10Gb/FULL */ |
135 | ixgbe_reset(adapter); | 156 | break; |
136 | ixgbe_up(adapter); | 157 | default: |
137 | } else { | 158 | break; |
138 | ixgbe_reset(adapter); | ||
139 | } | 159 | } |
140 | 160 | ||
141 | return 0; | 161 | return 0; |
@@ -147,7 +167,7 @@ static void ixgbe_get_pauseparam(struct net_device *netdev, | |||
147 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 167 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
148 | struct ixgbe_hw *hw = &adapter->hw; | 168 | struct ixgbe_hw *hw = &adapter->hw; |
149 | 169 | ||
150 | pause->autoneg = AUTONEG_DISABLE; | 170 | pause->autoneg = (hw->fc.type == ixgbe_fc_full ? 1 : 0); |
151 | 171 | ||
152 | if (hw->fc.type == ixgbe_fc_rx_pause) { | 172 | if (hw->fc.type == ixgbe_fc_rx_pause) { |
153 | pause->rx_pause = 1; | 173 | pause->rx_pause = 1; |
@@ -165,10 +185,8 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
165 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 185 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
166 | struct ixgbe_hw *hw = &adapter->hw; | 186 | struct ixgbe_hw *hw = &adapter->hw; |
167 | 187 | ||
168 | if (pause->autoneg == AUTONEG_ENABLE) | 188 | if ((pause->autoneg == AUTONEG_ENABLE) || |
169 | return -EINVAL; | 189 | (pause->rx_pause && pause->tx_pause)) |
170 | |||
171 | if (pause->rx_pause && pause->tx_pause) | ||
172 | hw->fc.type = ixgbe_fc_full; | 190 | hw->fc.type = ixgbe_fc_full; |
173 | else if (pause->rx_pause && !pause->tx_pause) | 191 | else if (pause->rx_pause && !pause->tx_pause) |
174 | hw->fc.type = ixgbe_fc_rx_pause; | 192 | hw->fc.type = ixgbe_fc_rx_pause; |
@@ -176,15 +194,15 @@ static int ixgbe_set_pauseparam(struct net_device *netdev, | |||
176 | hw->fc.type = ixgbe_fc_tx_pause; | 194 | hw->fc.type = ixgbe_fc_tx_pause; |
177 | else if (!pause->rx_pause && !pause->tx_pause) | 195 | else if (!pause->rx_pause && !pause->tx_pause) |
178 | hw->fc.type = ixgbe_fc_none; | 196 | hw->fc.type = ixgbe_fc_none; |
197 | else | ||
198 | return -EINVAL; | ||
179 | 199 | ||
180 | hw->fc.original_type = hw->fc.type; | 200 | hw->fc.original_type = hw->fc.type; |
181 | 201 | ||
182 | if (netif_running(adapter->netdev)) { | 202 | if (netif_running(netdev)) |
183 | ixgbe_down(adapter); | 203 | ixgbe_reinit_locked(adapter); |
184 | ixgbe_up(adapter); | 204 | else |
185 | } else { | ||
186 | ixgbe_reset(adapter); | 205 | ixgbe_reset(adapter); |
187 | } | ||
188 | 206 | ||
189 | return 0; | 207 | return 0; |
190 | } | 208 | } |
@@ -203,12 +221,10 @@ static int ixgbe_set_rx_csum(struct net_device *netdev, u32 data) | |||
203 | else | 221 | else |
204 | adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; | 222 | adapter->flags &= ~IXGBE_FLAG_RX_CSUM_ENABLED; |
205 | 223 | ||
206 | if (netif_running(netdev)) { | 224 | if (netif_running(netdev)) |
207 | ixgbe_down(adapter); | 225 | ixgbe_reinit_locked(adapter); |
208 | ixgbe_up(adapter); | 226 | else |
209 | } else { | ||
210 | ixgbe_reset(adapter); | 227 | ixgbe_reset(adapter); |
211 | } | ||
212 | 228 | ||
213 | return 0; | 229 | return 0; |
214 | } | 230 | } |
@@ -662,7 +678,10 @@ static int ixgbe_set_ringparam(struct net_device *netdev, | |||
662 | return 0; | 678 | return 0; |
663 | } | 679 | } |
664 | 680 | ||
665 | if (netif_running(adapter->netdev)) | 681 | while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state)) |
682 | msleep(1); | ||
683 | |||
684 | if (netif_running(netdev)) | ||
666 | ixgbe_down(adapter); | 685 | ixgbe_down(adapter); |
667 | 686 | ||
668 | /* | 687 | /* |
@@ -733,6 +752,7 @@ err_setup: | |||
733 | if (netif_running(adapter->netdev)) | 752 | if (netif_running(adapter->netdev)) |
734 | ixgbe_up(adapter); | 753 | ixgbe_up(adapter); |
735 | 754 | ||
755 | clear_bit(__IXGBE_RESETTING, &adapter->state); | ||
736 | return err; | 756 | return err; |
737 | } | 757 | } |
738 | 758 | ||
@@ -820,11 +840,8 @@ static int ixgbe_nway_reset(struct net_device *netdev) | |||
820 | { | 840 | { |
821 | struct ixgbe_adapter *adapter = netdev_priv(netdev); | 841 | struct ixgbe_adapter *adapter = netdev_priv(netdev); |
822 | 842 | ||
823 | if (netif_running(netdev)) { | 843 | if (netif_running(netdev)) |
824 | ixgbe_down(adapter); | 844 | ixgbe_reinit_locked(adapter); |
825 | ixgbe_reset(adapter); | ||
826 | ixgbe_up(adapter); | ||
827 | } | ||
828 | 845 | ||
829 | return 0; | 846 | return 0; |
830 | } | 847 | } |