hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
....@@ -496,6 +496,7 @@
496496 reg |= XGBE_KR_TRAINING_ENABLE;
497497 reg |= XGBE_KR_TRAINING_START;
498498 XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
499
+ pdata->kr_start_time = jiffies;
499500
500501 netif_dbg(pdata, link, pdata->netdev,
501502 "KR training initiated\n");
....@@ -632,6 +633,8 @@
632633
633634 xgbe_switch_mode(pdata);
634635
636
+ pdata->an_result = XGBE_AN_READY;
637
+
635638 xgbe_an_restart(pdata);
636639
637640 return XGBE_AN_INCOMPAT_LINK;
....@@ -688,9 +691,9 @@
688691 }
689692 }
690693
691
-static void xgbe_an_isr_task(unsigned long data)
694
+static void xgbe_an_isr_task(struct tasklet_struct *t)
692695 {
693
- struct xgbe_prv_data *pdata = (struct xgbe_prv_data *)data;
696
+ struct xgbe_prv_data *pdata = from_tasklet(pdata, t, tasklet_an);
694697
695698 netif_dbg(pdata, intr, pdata->netdev, "AN interrupt received\n");
696699
....@@ -715,14 +718,14 @@
715718 if (pdata->isr_as_tasklet)
716719 tasklet_schedule(&pdata->tasklet_an);
717720 else
718
- xgbe_an_isr_task((unsigned long)pdata);
721
+ xgbe_an_isr_task(&pdata->tasklet_an);
719722
720723 return IRQ_HANDLED;
721724 }
722725
723726 static irqreturn_t xgbe_an_combined_isr(struct xgbe_prv_data *pdata)
724727 {
725
- xgbe_an_isr_task((unsigned long)pdata);
728
+ xgbe_an_isr_task(&pdata->tasklet_an);
726729
727730 return IRQ_HANDLED;
728731 }
....@@ -1275,9 +1278,30 @@
12751278 static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
12761279 {
12771280 unsigned long link_timeout;
1281
+ unsigned long kr_time;
1282
+ int wait;
12781283
12791284 link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
12801285 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
+ }
12811305 netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
12821306 xgbe_phy_config_aneg(pdata);
12831307 }
....@@ -1288,7 +1312,7 @@
12881312 return pdata->phy_if.phy_impl.an_outcome(pdata);
12891313 }
12901314
1291
-static void xgbe_phy_status_result(struct xgbe_prv_data *pdata)
1315
+static bool xgbe_phy_status_result(struct xgbe_prv_data *pdata)
12921316 {
12931317 struct ethtool_link_ksettings *lks = &pdata->phy.lks;
12941318 enum xgbe_mode mode;
....@@ -1323,8 +1347,13 @@
13231347
13241348 pdata->phy.duplex = DUPLEX_FULL;
13251349
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)
13271354 xgbe_phy_reconfig_aneg(pdata);
1355
+
1356
+ return true;
13281357 }
13291358
13301359 static void xgbe_phy_status(struct xgbe_prv_data *pdata)
....@@ -1354,7 +1383,8 @@
13541383 return;
13551384 }
13561385
1357
- xgbe_phy_status_result(pdata);
1386
+ if (xgbe_phy_status_result(pdata))
1387
+ return;
13581388
13591389 if (test_bit(XGBE_LINK_INIT, &pdata->dev_state))
13601390 clear_bit(XGBE_LINK_INIT, &pdata->dev_state);
....@@ -1390,8 +1420,10 @@
13901420 /* Disable auto-negotiation */
13911421 xgbe_an_disable_all(pdata);
13921422
1393
- if (pdata->dev_irq != pdata->an_irq)
1423
+ if (pdata->dev_irq != pdata->an_irq) {
13941424 devm_free_irq(pdata->dev, pdata->an_irq, pdata);
1425
+ tasklet_kill(&pdata->tasklet_an);
1426
+ }
13951427
13961428 pdata->phy_if.phy_impl.stop(pdata);
13971429
....@@ -1413,8 +1445,7 @@
14131445
14141446 /* If we have a separate AN irq, enable it */
14151447 if (pdata->dev_irq != pdata->an_irq) {
1416
- tasklet_init(&pdata->tasklet_an, xgbe_an_isr_task,
1417
- (unsigned long)pdata);
1448
+ tasklet_setup(&pdata->tasklet_an, xgbe_an_isr_task);
14181449
14191450 ret = devm_request_irq(pdata->dev, pdata->an_irq,
14201451 xgbe_an_isr, 0, pdata->an_name,