.. | .. |
---|
496 | 496 | reg |= XGBE_KR_TRAINING_ENABLE; |
---|
497 | 497 | reg |= XGBE_KR_TRAINING_START; |
---|
498 | 498 | XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg); |
---|
| 499 | + pdata->kr_start_time = jiffies; |
---|
499 | 500 | |
---|
500 | 501 | netif_dbg(pdata, link, pdata->netdev, |
---|
501 | 502 | "KR training initiated\n"); |
---|
.. | .. |
---|
631 | 632 | xgbe_an_disable(pdata); |
---|
632 | 633 | |
---|
633 | 634 | xgbe_switch_mode(pdata); |
---|
| 635 | + |
---|
| 636 | + pdata->an_result = XGBE_AN_READY; |
---|
634 | 637 | |
---|
635 | 638 | xgbe_an_restart(pdata); |
---|
636 | 639 | |
---|
.. | .. |
---|
1275 | 1278 | static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata) |
---|
1276 | 1279 | { |
---|
1277 | 1280 | unsigned long link_timeout; |
---|
| 1281 | + unsigned long kr_time; |
---|
| 1282 | + int wait; |
---|
1278 | 1283 | |
---|
1279 | 1284 | link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ); |
---|
1280 | 1285 | if (time_after(jiffies, link_timeout)) { |
---|
| 1286 | + if ((xgbe_cur_mode(pdata) == XGBE_MODE_KR) && |
---|
| 1287 | + pdata->phy.autoneg == AUTONEG_ENABLE) { |
---|
| 1288 | + /* AN restart should not happen while KR training is in progress. |
---|
| 1289 | + * The while loop ensures no AN restart during KR training, |
---|
| 1290 | + * waits up to 500ms and AN restart is triggered only if KR |
---|
| 1291 | + * training is failed. |
---|
| 1292 | + */ |
---|
| 1293 | + wait = XGBE_KR_TRAINING_WAIT_ITER; |
---|
| 1294 | + while (wait--) { |
---|
| 1295 | + kr_time = pdata->kr_start_time + |
---|
| 1296 | + msecs_to_jiffies(XGBE_AN_MS_TIMEOUT); |
---|
| 1297 | + if (time_after(jiffies, kr_time)) |
---|
| 1298 | + break; |
---|
| 1299 | + /* AN restart is not required, if AN result is COMPLETE */ |
---|
| 1300 | + if (pdata->an_result == XGBE_AN_COMPLETE) |
---|
| 1301 | + return; |
---|
| 1302 | + usleep_range(10000, 11000); |
---|
| 1303 | + } |
---|
| 1304 | + } |
---|
1281 | 1305 | netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n"); |
---|
1282 | 1306 | xgbe_phy_config_aneg(pdata); |
---|
1283 | 1307 | } |
---|
.. | .. |
---|
1288 | 1312 | return pdata->phy_if.phy_impl.an_outcome(pdata); |
---|
1289 | 1313 | } |
---|
1290 | 1314 | |
---|
1291 | | -static void xgbe_phy_status_result(struct xgbe_prv_data *pdata) |
---|
| 1315 | +static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata) |
---|
1292 | 1316 | { |
---|
1293 | 1317 | struct ethtool_link_ksettings *lks = &pdata->phy.lks; |
---|
1294 | 1318 | enum xgbe_mode mode; |
---|
.. | .. |
---|
1323 | 1347 | |
---|
1324 | 1348 | pdata->phy.duplex = DUPLEX_FULL; |
---|
1325 | 1349 | |
---|
1326 | | - if (xgbe_set_mode(pdata, mode) && pdata->an_again) |
---|
| 1350 | + if (!xgbe_set_mode(pdata, mode)) |
---|
| 1351 | + return false; |
---|
| 1352 | + |
---|
| 1353 | + if (pdata->an_again) |
---|
1327 | 1354 | xgbe_phy_reconfig_aneg(pdata); |
---|
| 1355 | + |
---|
| 1356 | + return true; |
---|
1328 | 1357 | } |
---|
1329 | 1358 | |
---|
1330 | 1359 | static void xgbe_phy_status(struct xgbe_prv_data *pdata) |
---|
.. | .. |
---|
1354 | 1383 | return; |
---|
1355 | 1384 | } |
---|
1356 | 1385 | |
---|
1357 | | - xgbe_phy_status_result(pdata); |
---|
| 1386 | + if (xgbe_phy_status_result(pdata)) |
---|
| 1387 | + return; |
---|
1358 | 1388 | |
---|
1359 | 1389 | if (test_bit(XGBE_LINK_INIT, &pdata->dev_state)) |
---|
1360 | 1390 | clear_bit(XGBE_LINK_INIT, &pdata->dev_state); |
---|
.. | .. |
---|
1390 | 1420 | /* Disable auto-negotiation */ |
---|
1391 | 1421 | xgbe_an_disable_all(pdata); |
---|
1392 | 1422 | |
---|
1393 | | - if (pdata->dev_irq != pdata->an_irq) |
---|
| 1423 | + if (pdata->dev_irq != pdata->an_irq) { |
---|
1394 | 1424 | devm_free_irq(pdata->dev, pdata->an_irq, pdata); |
---|
| 1425 | + tasklet_kill(&pdata->tasklet_an); |
---|
| 1426 | + } |
---|
1395 | 1427 | |
---|
1396 | 1428 | pdata->phy_if.phy_impl.stop(pdata); |
---|
1397 | 1429 | |
---|