1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
From bff033e9aa3ebf9d7e2bb42be9d635e9c65bcbe0 Mon Sep 17 00:00:00 2001
From: Sudheesh Mavila <sudheesh.mavila@amd.com>
Date: Sat, 9 Jan 2021 23:41:36 +0530
Subject: [PATCH 10/10] amd-xgbe: synchronization between AN state machine and
status polling timer thread
xgbe driver uses a TIMEOUT to restart AN process if link is down.
This create issue when TIMEOUT comes in between a KR training or RCC
is in process. The patch avoids AN restart if TIMEOUT happens
during KR cycle or RRC.
TIMEOUT value also reduced to 1 sec to enable fast
synchronization between LP.
Signed-off-by: Sudheesh Mavila <sudheesh.mavila@amd.com>
---
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 29 +++++++++++++++++++--
drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c | 1 +
drivers/net/ethernet/amd/xgbe/xgbe.h | 4 ++-
3 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
index f4359407269a..c70c38d96020 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-mdio.c
@@ -512,6 +512,7 @@ static enum xgbe_an xgbe_an73_tx_training(struct xgbe_prv_data *pdata,
XMDIO_WRITE(pdata, MDIO_MMD_PMAPMD, MDIO_PMA_10GBR_PMD_CTRL, reg);
pdata->kr_done = 1;
+ pdata->kr_start_time = jiffies;
netif_dbg(pdata, link, pdata->netdev,
"KR training initiated\n");
@@ -884,6 +885,8 @@ static void xgbe_an73_state_machine(struct xgbe_prv_data *pdata)
break;
case XGBE_AN_PAGE_RECEIVED:
+ if (xgbe_in_kr_mode(pdata))
+ pdata->an_int = 0;
pdata->an_state = xgbe_an73_page_received(pdata);
pdata->an_supported++;
break;
@@ -1306,11 +1309,34 @@ static bool xgbe_phy_aneg_done(struct xgbe_prv_data *pdata)
static void xgbe_check_link_timeout(struct xgbe_prv_data *pdata)
{
unsigned long link_timeout;
+ int wait = 200;
+ unsigned long kr_time;
+ unsigned long rrc_time;
link_timeout = pdata->link_check + (XGBE_LINK_TIMEOUT * HZ);
if (time_after(jiffies, link_timeout)) {
netif_dbg(pdata, link, pdata->netdev, "AN link timeout\n");
- xgbe_phy_config_aneg(pdata);
+ /* AN restart should not happen within 500ms of start of RRC or KR tarining */
+ /* This loop ensures no AN restart during RRC window and KR training window */
+ while (wait--) {
+ mutex_lock(&pdata->an_mutex);
+ kr_time = pdata->kr_start_time + msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
+ rrc_time = pdata->rrc_start_time + msecs_to_jiffies(XGBE_AN_MS_TIMEOUT);
+ mutex_unlock(&pdata->an_mutex);
+ if (time_after(jiffies, kr_time) && time_after(jiffies, rrc_time))
+ break;
+ if (pdata->an_result == XGBE_AN_COMPLETE)
+ break;
+
+ usleep_range(5000, 6000);
+ }
+ /* AN restart is required, if AN result is not COMPLETE */
+ if (pdata->an_result != XGBE_AN_COMPLETE)
+ xgbe_phy_config_aneg(pdata);
+ else if ((pdata->an_result == XGBE_AN_COMPLETE) &&
+ (xgbe_cur_mode(pdata) == XGBE_MODE_KX_1000))
+ xgbe_phy_config_aneg(pdata);
+
}
}
@@ -1489,7 +1515,6 @@ static int xgbe_phy_start(struct xgbe_prv_data *pdata)
/* Indicate the PHY is up and running */
pdata->phy_started = 1;
- pdata->an_result = XGBE_AN_NO_LINK;
xgbe_an_init(pdata);
xgbe_an_enable_interrupts(pdata);
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
index f3566a480f2d..f24b8121db2e 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
+++ b/drivers/net/ethernet/amd/xgbe/xgbe-phy-v2.c
@@ -2977,6 +2977,7 @@ static void xgbe_phy_cdr_notrack(struct xgbe_prv_data *pdata)
XGBE_PMA_CDR_TRACK_EN_MASK,
XGBE_PMA_CDR_TRACK_EN_OFF);
xgbe_phy_rrc(pdata);
+ pdata->rrc_start_time = jiffies;
phy_data->phy_cdr_notrack = 1;
}
diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h
index c99b34c41f71..3ed98e2f8695 100644
--- a/drivers/net/ethernet/amd/xgbe/xgbe.h
+++ b/drivers/net/ethernet/amd/xgbe/xgbe.h
@@ -288,7 +288,7 @@
/* Auto-negotiation */
#define XGBE_AN_MS_TIMEOUT 500
-#define XGBE_LINK_TIMEOUT 5
+#define XGBE_LINK_TIMEOUT 1
#define XGBE_SGMII_AN_LINK_STATUS BIT(1)
#define XGBE_SGMII_AN_LINK_SPEED (BIT(2) | BIT(3))
@@ -1258,6 +1258,8 @@ struct xgbe_prv_data {
unsigned long an_start;
enum xgbe_an_mode an_mode;
unsigned int kr_done;
+ unsigned long kr_start_time;
+ unsigned long rrc_start_time;
unsigned int cdr_delay_required;
/* I2C support */
--
2.17.1
|