aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/skge.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r--drivers/net/skge.c125
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 */
185static 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
183static int skge_get_settings(struct net_device *dev, 213static 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
227static 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
256static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 235static 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