| @@ -331,13 +331,15 @@ static void xgbe_switch_mode(struct xgbe_prv_data *pdata) · 330 unmodified lines |
| 331 | xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata)); | 331 | xgbe_change_mode(pdata, pdata->phy_if.phy_impl.switch_mode(pdata)); |
| 332 | } | 332 | } |
| 333 | | 333 | |
| 334 | static void xgbe_set_mode(struct xgbe_prv_data *pdata, | 334 | static bool xgbe_set_mode(struct xgbe_prv_data *pdata, |
| 335 | enum xgbe_mode mode) | 335 | enum xgbe_mode mode) |
| 336 | { | 336 | { |
| 337 | if (mode == xgbe_cur_mode(pdata)) | 337 | if (mode == xgbe_cur_mode(pdata)) |
| 338 | return; | 338 | return false; |
| 339 | | 339 | |
| 340 | xgbe_change_mode(pdata, mode); | 340 | xgbe_change_mode(pdata, mode); |
| | 341 | |
| | 342 | return true; |
| 341 | } | 343 | } |
| 342 | | 344 | |
| 343 | static bool xgbe_use_mode(struct xgbe_prv_data *pdata, | 345 | static bool xgbe_use_mode(struct xgbe_prv_data *pdata, |
| @@ -1178,21 +1180,23 @@ static int xgbe_phy_config_fixed(struct xgbe_prv_data *pdata) · 834 unmodified lines |
| 1178 | return 0; | 1180 | return 0; |
| 1179 | } | 1181 | } |
| 1180 | | 1182 | |
| 1181 | static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) | 1183 | static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata, bool set_mode) |
| 1182 | { | 1184 | { |
| 1183 | int ret; | 1185 | int ret; |
| 1184 | | 1186 | |
| | 1187 | mutex_lock(&pdata->an_mutex); |
| | 1188 | |
| 1185 | set_bit(XGBE_LINK_INIT, &pdata->dev_state); | 1189 | set_bit(XGBE_LINK_INIT, &pdata->dev_state); |
| 1186 | pdata->link_check = jiffies; | 1190 | pdata->link_check = jiffies; |
| 1187 | | 1191 | |
| 1188 | ret = pdata->phy_if.phy_impl.an_config(pdata); | 1192 | ret = pdata->phy_if.phy_impl.an_config(pdata); |
| 1189 | if (ret) | 1193 | if (ret) |
| 1190 | return ret; | 1194 | goto out; |
| 1191 | | 1195 | |
| 1192 | if (pdata->phy.autoneg != AUTONEG_ENABLE) { | 1196 | if (pdata->phy.autoneg != AUTONEG_ENABLE) { |
| 1193 | ret = xgbe_phy_config_fixed(pdata); | 1197 | ret = xgbe_phy_config_fixed(pdata); |
| 1194 | if (ret || !pdata->kr_redrv) | 1198 | if (ret || !pdata->kr_redrv) |
| 1195 | return ret; | 1199 | goto out; |
| 1196 | | 1200 | |
| 1197 | netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n"); | 1201 | netif_dbg(pdata, link, pdata->netdev, "AN redriver support\n"); |
| 1198 | } else { | 1202 | } else { |
| @@ -1202,24 +1206,27 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) · 3 unmodified lines |
| 1202 | /* Disable auto-negotiation interrupt */ | 1206 | /* Disable auto-negotiation interrupt */ |
| 1203 | disable_irq(pdata->an_irq); | 1207 | disable_irq(pdata->an_irq); |
| 1204 | | 1208 | |
| 1205 | /* Start auto-negotiation in a supported mode */ | 1209 | if (set_mode) { |
| 1206 | if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { | 1210 | /* Start auto-negotiation in a supported mode */ |
| 1207 | xgbe_set_mode(pdata, XGBE_MODE_KR); | 1211 | if (xgbe_use_mode(pdata, XGBE_MODE_KR)) { |
| 1208 | } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { | 1212 | xgbe_set_mode(pdata, XGBE_MODE_KR); |
| 1209 | xgbe_set_mode(pdata, XGBE_MODE_KX_2500); | 1213 | } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_2500)) { |
| 1210 | } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { | 1214 | xgbe_set_mode(pdata, XGBE_MODE_KX_2500); |
| 1211 | xgbe_set_mode(pdata, XGBE_MODE_KX_1000); | 1215 | } else if (xgbe_use_mode(pdata, XGBE_MODE_KX_1000)) { |
| 1212 | } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) { | 1216 | xgbe_set_mode(pdata, XGBE_MODE_KX_1000); |
| 1213 | xgbe_set_mode(pdata, XGBE_MODE_SFI); | 1217 | } else if (xgbe_use_mode(pdata, XGBE_MODE_SFI)) { |
| 1214 | } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) { | 1218 | xgbe_set_mode(pdata, XGBE_MODE_SFI); |
| 1215 | xgbe_set_mode(pdata, XGBE_MODE_X); | 1219 | } else if (xgbe_use_mode(pdata, XGBE_MODE_X)) { |
| 1216 | } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) { | 1220 | xgbe_set_mode(pdata, XGBE_MODE_X); |
| 1217 | xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000); | 1221 | } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_1000)) { |
| 1218 | } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) { | 1222 | xgbe_set_mode(pdata, XGBE_MODE_SGMII_1000); |
| 1219 | xgbe_set_mode(pdata, XGBE_MODE_SGMII_100); | 1223 | } else if (xgbe_use_mode(pdata, XGBE_MODE_SGMII_100)) { |
| 1220 | } else { | 1224 | xgbe_set_mode(pdata, XGBE_MODE_SGMII_100); |
| 1221 | enable_irq(pdata->an_irq); | 1225 | } else { |
| 1222 | return -EINVAL; | 1226 | enable_irq(pdata->an_irq); |
| | 1227 | ret = -EINVAL; |
| | 1228 | goto out; |
| | 1229 | } |
| 1223 | } | 1230 | } |
| 1224 | | 1231 | |
| 1225 | /* Disable and stop any in progress auto-negotiation */ | 1232 | /* Disable and stop any in progress auto-negotiation */ |
| @@ -1239,16 +1246,7 @@ static int __xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) · 13 unmodified lines |
| 1239 | xgbe_an_init(pdata); | 1246 | xgbe_an_init(pdata); |
| 1240 | xgbe_an_restart(pdata); | 1247 | xgbe_an_restart(pdata); |
| 1241 | | 1248 | |
| 1242 | return 0; | 1249 | out: |
| 1243 | } | | |
| 1244 | | | |
| 1245 | static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) | | |
| 1246 | { | | |
| 1247 | int ret; | | |
| 1248 | | | |
| 1249 | mutex_lock(&pdata->an_mutex); | | |
| 1250 | | | |
| 1251 | ret = __xgbe_phy_config_aneg(pdata); | | |
| 1252 | if (ret) | 1250 | if (ret) |
| 1253 | set_bit(XGBE_LINK_ERR, &pdata->dev_state); | 1251 | set_bit(XGBE_LINK_ERR, &pdata->dev_state); |
| 1254 | else | 1252 | else |
| @@ -1259,6 +1257,16 @@ static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) · 4 unmodified lines |
| 1259 | return ret; | 1257 | return ret; |
| 1260 | } | 1258 | } |
| 1261 | | 1259 | |
| | 1260 | static int xgbe_phy_config_aneg(struct xgbe_prv_data *pdata) |
| | 1261 | { |
| | 1262 | return __xgbe_phy_config_aneg(pdata, true); |
| | 1263 | } |
| | 1264 | |
| | 1265 | static int xgbe_phy_reconfig_aneg(struct xgbe_prv_data *pdata) |
| | 1266 | { |
| | 1267 | return __xgbe_phy_config_aneg(pdata, false); |
| | 1268 | } |
| | 1269 | |
| 1262 | static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata) | 1270 | static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata) |
| 1263 | { | 1271 | { |
| 1264 | return (pdata->an_result == XGBE_AN_COMPLETE); | 1272 | return (pdata->an_result == XGBE_AN_COMPLETE); |
| @@ -1315,7 +1323,8 @@ static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) · 50 unmodified lines |
| 1315 | | 1323 | |
| 1316 | pdata->phy.duplex = DUPLEX_FULL; | 1324 | pdata->phy.duplex = DUPLEX_FULL; |
| 1317 | | 1325 | |
| 1318 | xgbe_set_mode(pdata, mode); | 1326 | if (xgbe_set_mode(pdata, mode) && pdata->an_again) |
| | 1327 | xgbe_phy_reconfig_aneg(pdata); |
| 1319 | } | 1328 | } |
| 1320 | | 1329 | |
| 1321 | static void xgbe_phy_status(struct xgbe_prv_data *pdata) | 1330 | static void xgbe_phy_status(struct xgbe_prv_data *pdata) |