Skip to content

Commit 80c8252

Browse files
committed
Merge branch 'amd-xgbe-pfc-and-kr-training-fixes'
Raju Rangoju says: ==================== amd-xgbe: PFC and KR-Training fixes This patch series fixes the issues in kr-training and pfc 0001 - There is difference in the TX Flow Control registers (TFCR) between the revisions of the hardware. Update the driver to use the TFCR based on the reported version of the hardware. 0002 - AN restart triggered during KR training not only aborts the KR training process but also move the HW to unstable state. Add the necessary changes to fix kr-taining. ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 0ea90f3 + 926446a commit 80c8252

File tree

3 files changed

+41
-8
lines changed

3 files changed

+41
-8
lines changed

drivers/net/ethernet/amd/xgbe/xgbe-dev.c

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -524,19 +524,28 @@ static void xgbe_disable_vxlan(struct xgbe_prv_data *pdata)
524524
netif_dbg(pdata, drv, pdata->netdev, "VXLAN acceleration disabled\n");
525525
}
526526

527+
static unsigned int xgbe_get_fc_queue_count(struct xgbe_prv_data *pdata)
528+
{
529+
unsigned int max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
530+
531+
/* From MAC ver 30H the TFCR is per priority, instead of per queue */
532+
if (XGMAC_GET_BITS(pdata->hw_feat.version, MAC_VR, SNPSVER) >= 0x30)
533+
return max_q_count;
534+
else
535+
return min_t(unsigned int, pdata->tx_q_count, max_q_count);
536+
}
537+
527538
static int xgbe_disable_tx_flow_control(struct xgbe_prv_data *pdata)
528539
{
529-
unsigned int max_q_count, q_count;
530540
unsigned int reg, reg_val;
531-
unsigned int i;
541+
unsigned int i, q_count;
532542

533543
/* Clear MTL flow control */
534544
for (i = 0; i < pdata->rx_q_count; i++)
535545
XGMAC_MTL_IOWRITE_BITS(pdata, i, MTL_Q_RQOMR, EHFC, 0);
536546

537547
/* Clear MAC flow control */
538-
max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
539-
q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
548+
q_count = xgbe_get_fc_queue_count(pdata);
540549
reg = MAC_Q0TFCR;
541550
for (i = 0; i < q_count; i++) {
542551
reg_val = XGMAC_IOREAD(pdata, reg);
@@ -553,9 +562,8 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
553562
{
554563
struct ieee_pfc *pfc = pdata->pfc;
555564
struct ieee_ets *ets = pdata->ets;
556-
unsigned int max_q_count, q_count;
557565
unsigned int reg, reg_val;
558-
unsigned int i;
566+
unsigned int i, q_count;
559567

560568
/* Set MTL flow control */
561569
for (i = 0; i < pdata->rx_q_count; i++) {
@@ -579,8 +587,7 @@ static int xgbe_enable_tx_flow_control(struct xgbe_prv_data *pdata)
579587
}
580588

581589
/* Set MAC flow control */
582-
max_q_count = XGMAC_MAX_FLOW_CONTROL_QUEUES;
583-
q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
590+
q_count = xgbe_get_fc_queue_count(pdata);
584591
reg = MAC_Q0TFCR;
585592
for (i = 0; i < q_count; i++) {
586593
reg_val = XGMAC_IOREAD(pdata, reg);

drivers/net/ethernet/amd/xgbe/xgbe-mdio.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,6 +496,7 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
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 @@ static enum xgbe_an xgbe_an73_incompat_link(struct xgbe_prv_data *pdata)
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;
@@ -1275,9 +1278,30 @@ static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
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
}

drivers/net/ethernet/amd/xgbe/xgbe.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@
290290
/* Auto-negotiation */
291291
#define XGBE_AN_MS_TIMEOUT 500
292292
#define XGBE_LINK_TIMEOUT 5
293+
#define XGBE_KR_TRAINING_WAIT_ITER 50
293294

294295
#define XGBE_SGMII_AN_LINK_STATUS BIT(1)
295296
#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3))
@@ -1280,6 +1281,7 @@ struct xgbe_prv_data {
12801281
unsigned int parallel_detect;
12811282
unsigned int fec_ability;
12821283
unsigned long an_start;
1284+
unsigned long kr_start_time;
12831285
enum xgbe_an_mode an_mode;
12841286

12851287
/* I2C support */

0 commit comments

Comments
 (0)