diff options
-rw-r--r-- | drivers/net/skge.c | 125 |
1 files changed, 65 insertions, 60 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 68de7f748a81..81b8fe9581c7 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -179,6 +179,36 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
179 | return 0; | 179 | return 0; |
180 | } | 180 | } |
181 | 181 | ||
182 | /* Determine supported/adverised modes based on hardware. | ||
183 | * Note: ethtoool ADVERTISED_xxx == SUPPORTED_xxx | ||
184 | */ | ||
185 | static u32 skge_supported_modes(const struct skge_hw *hw) | ||
186 | { | ||
187 | u32 supported; | ||
188 | |||
189 | if (iscopper(hw)) { | ||
190 | supported = SUPPORTED_10baseT_Half | ||
191 | | SUPPORTED_10baseT_Full | ||
192 | | SUPPORTED_100baseT_Half | ||
193 | | SUPPORTED_100baseT_Full | ||
194 | | SUPPORTED_1000baseT_Half | ||
195 | | SUPPORTED_1000baseT_Full | ||
196 | | SUPPORTED_Autoneg| SUPPORTED_TP; | ||
197 | |||
198 | if (hw->chip_id == CHIP_ID_GENESIS) | ||
199 | supported &= ~(SUPPORTED_10baseT_Half | ||
200 | | SUPPORTED_10baseT_Full | ||
201 | | SUPPORTED_100baseT_Half | ||
202 | | SUPPORTED_100baseT_Full); | ||
203 | |||
204 | else if (hw->chip_id == CHIP_ID_YUKON) | ||
205 | supported &= ~SUPPORTED_1000baseT_Half; | ||
206 | } else | ||
207 | supported = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE | ||
208 | | SUPPORTED_Autoneg; | ||
209 | |||
210 | return supported; | ||
211 | } | ||
182 | 212 | ||
183 | static int skge_get_settings(struct net_device *dev, | 213 | static int skge_get_settings(struct net_device *dev, |
184 | struct ethtool_cmd *ecmd) | 214 | struct ethtool_cmd *ecmd) |
@@ -187,35 +217,13 @@ static int skge_get_settings(struct net_device *dev, | |||
187 | struct skge_hw *hw = skge->hw; | 217 | struct skge_hw *hw = skge->hw; |
188 | 218 | ||
189 | ecmd->transceiver = XCVR_INTERNAL; | 219 | ecmd->transceiver = XCVR_INTERNAL; |
220 | ecmd->supported = skge_supported_modes(hw); | ||
190 | 221 | ||
191 | if (iscopper(hw)) { | 222 | if (iscopper(hw)) { |
192 | if (hw->chip_id == CHIP_ID_GENESIS) | ||
193 | ecmd->supported = SUPPORTED_1000baseT_Full | ||
194 | | SUPPORTED_1000baseT_Half | ||
195 | | SUPPORTED_Autoneg | SUPPORTED_TP; | ||
196 | else { | ||
197 | ecmd->supported = SUPPORTED_10baseT_Half | ||
198 | | SUPPORTED_10baseT_Full | ||
199 | | SUPPORTED_100baseT_Half | ||
200 | | SUPPORTED_100baseT_Full | ||
201 | | SUPPORTED_1000baseT_Half | ||
202 | | SUPPORTED_1000baseT_Full | ||
203 | | SUPPORTED_Autoneg| SUPPORTED_TP; | ||
204 | |||
205 | if (hw->chip_id == CHIP_ID_YUKON) | ||
206 | ecmd->supported &= ~SUPPORTED_1000baseT_Half; | ||
207 | |||
208 | } | ||
209 | |||
210 | ecmd->port = PORT_TP; | 223 | ecmd->port = PORT_TP; |
211 | ecmd->phy_address = hw->phy_addr; | 224 | ecmd->phy_address = hw->phy_addr; |
212 | } else { | 225 | } else |
213 | ecmd->supported = SUPPORTED_1000baseT_Full | ||
214 | | SUPPORTED_FIBRE | ||
215 | | SUPPORTED_Autoneg; | ||
216 | |||
217 | ecmd->port = PORT_FIBRE; | 226 | ecmd->port = PORT_FIBRE; |
218 | } | ||
219 | 227 | ||
220 | ecmd->advertising = skge->advertising; | 228 | ecmd->advertising = skge->advertising; |
221 | ecmd->autoneg = skge->autoneg; | 229 | ecmd->autoneg = skge->autoneg; |
@@ -224,60 +232,57 @@ static int skge_get_settings(struct net_device *dev, | |||
224 | return 0; | 232 | return 0; |
225 | } | 233 | } |
226 | 234 | ||
227 | static u32 skge_modes(const struct skge_hw *hw) | ||
228 | { | ||
229 | u32 modes = ADVERTISED_Autoneg | ||
230 | | ADVERTISED_1000baseT_Full | ADVERTISED_1000baseT_Half | ||
231 | | ADVERTISED_100baseT_Full | ADVERTISED_100baseT_Half | ||
232 | | ADVERTISED_10baseT_Full | ADVERTISED_10baseT_Half; | ||
233 | |||
234 | if (iscopper(hw)) { | ||
235 | modes |= ADVERTISED_TP; | ||
236 | switch (hw->chip_id) { | ||
237 | case CHIP_ID_GENESIS: | ||
238 | modes &= ~(ADVERTISED_100baseT_Full | ||
239 | | ADVERTISED_100baseT_Half | ||
240 | | ADVERTISED_10baseT_Full | ||
241 | | ADVERTISED_10baseT_Half); | ||
242 | break; | ||
243 | |||
244 | case CHIP_ID_YUKON: | ||
245 | modes &= ~ADVERTISED_1000baseT_Half; | ||
246 | break; | ||
247 | |||
248 | } | ||
249 | } else { | ||
250 | modes |= ADVERTISED_FIBRE; | ||
251 | modes &= ~ADVERTISED_1000baseT_Half; | ||
252 | } | ||
253 | return modes; | ||
254 | } | ||
255 | |||
256 | static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 235 | static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
257 | { | 236 | { |
258 | struct skge_port *skge = netdev_priv(dev); | 237 | struct skge_port *skge = netdev_priv(dev); |
259 | const struct skge_hw *hw = skge->hw; | 238 | const struct skge_hw *hw = skge->hw; |
239 | u32 supported = skge_supported_modes(hw); | ||
260 | 240 | ||
261 | if (ecmd->autoneg == AUTONEG_ENABLE) { | 241 | if (ecmd->autoneg == AUTONEG_ENABLE) { |
262 | if (ecmd->advertising & skge_modes(hw)) | 242 | ecmd->advertising = supported; |
263 | return -EINVAL; | 243 | skge->duplex = -1; |
244 | skge->speed = -1; | ||
264 | } else { | 245 | } else { |
265 | switch (ecmd->speed) { | 246 | u32 setting; |
247 | |||
248 | switch(ecmd->speed) { | ||
266 | case SPEED_1000: | 249 | case SPEED_1000: |
250 | if (ecmd->duplex == DUPLEX_FULL) | ||
251 | setting = SUPPORTED_1000baseT_Full; | ||
252 | else if (ecmd->duplex == DUPLEX_HALF) | ||
253 | setting = SUPPORTED_1000baseT_Half; | ||
254 | else | ||
255 | return -EINVAL; | ||
267 | break; | 256 | break; |
268 | case SPEED_100: | 257 | case SPEED_100: |
258 | if (ecmd->duplex == DUPLEX_FULL) | ||
259 | setting = SUPPORTED_100baseT_Full; | ||
260 | else if (ecmd->duplex == DUPLEX_HALF) | ||
261 | setting = SUPPORTED_100baseT_Half; | ||
262 | else | ||
263 | return -EINVAL; | ||
264 | break; | ||
265 | |||
269 | case SPEED_10: | 266 | case SPEED_10: |
270 | if (iscopper(hw) || hw->chip_id == CHIP_ID_GENESIS) | 267 | if (ecmd->duplex == DUPLEX_FULL) |
268 | setting = SUPPORTED_10baseT_Full; | ||
269 | else if (ecmd->duplex == DUPLEX_HALF) | ||
270 | setting = SUPPORTED_10baseT_Half; | ||
271 | else | ||
271 | return -EINVAL; | 272 | return -EINVAL; |
272 | break; | 273 | break; |
273 | default: | 274 | default: |
274 | return -EINVAL; | 275 | return -EINVAL; |
275 | } | 276 | } |
277 | |||
278 | if ((setting & supported) == 0) | ||
279 | return -EINVAL; | ||
280 | |||
281 | skge->speed = ecmd->speed; | ||
282 | skge->duplex = ecmd->duplex; | ||
276 | } | 283 | } |
277 | 284 | ||
278 | skge->autoneg = ecmd->autoneg; | 285 | skge->autoneg = ecmd->autoneg; |
279 | skge->speed = ecmd->speed; | ||
280 | skge->duplex = ecmd->duplex; | ||
281 | skge->advertising = ecmd->advertising; | 286 | skge->advertising = ecmd->advertising; |
282 | 287 | ||
283 | if (netif_running(dev)) { | 288 | if (netif_running(dev)) { |
@@ -2973,7 +2978,7 @@ static struct net_device *skge_devinit(struct skge_hw *hw, int port, | |||
2973 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 2978 | skge->flow_control = FLOW_MODE_SYMMETRIC; |
2974 | skge->duplex = -1; | 2979 | skge->duplex = -1; |
2975 | skge->speed = -1; | 2980 | skge->speed = -1; |
2976 | skge->advertising = skge_modes(hw); | 2981 | skge->advertising = skge_supported_modes(hw); |
2977 | 2982 | ||
2978 | hw->dev[port] = dev; | 2983 | hw->dev[port] = dev; |
2979 | 2984 | ||