mirror of
git://git.openwrt.org/openwrt/openwrt.git
synced 2025-12-07 05:04:00 -05:00
generic: backport phylink patches for PCS/PHY caps OPs
Backport phylink patches for PCS/PHY caps OPs. This makes it easier to align future generic PCS patch and permit supporting special PHY that needs specific tune if "in-band" mode is enabled (for example Aeonsemi PHYs) This is also mainly using the upstream version of the Mediatek patch 739-net-add-negotiation-of-in-band-capabilities. All affected patch automatically refreshed. Link: https://github.com/openwrt/openwrt/pull/20461 Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
This commit is contained in:
parent
0636e89e10
commit
813ecda1f3
@ -0,0 +1,41 @@
|
||||
From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:01:44 +0000
|
||||
Subject: [PATCH 1/5] net: phylink: move manual flow control setting
|
||||
|
||||
Move the handling of manual flow control configuration to a common
|
||||
location during resolve. We currently evaluate this for all but
|
||||
fixed links.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1484,7 +1484,6 @@ static void phylink_resolve(struct work_
|
||||
switch (pl->cur_link_an_mode) {
|
||||
case MLO_AN_PHY:
|
||||
link_state = pl->phy_state;
|
||||
- phylink_apply_manual_flow(pl, &link_state);
|
||||
mac_config = link_state.link;
|
||||
break;
|
||||
|
||||
@@ -1545,11 +1544,13 @@ static void phylink_resolve(struct work_
|
||||
link_state.pause = pl->phy_state.pause;
|
||||
mac_config = true;
|
||||
}
|
||||
- phylink_apply_manual_flow(pl, &link_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+ if (pl->cur_link_an_mode != MLO_AN_FIXED)
|
||||
+ phylink_apply_manual_flow(pl, &link_state);
|
||||
+
|
||||
if (mac_config) {
|
||||
if (link_state.interface != pl->link_config.interface) {
|
||||
/* The interface has changed, force the link down and
|
||||
@ -0,0 +1,42 @@
|
||||
From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:01:50 +0000
|
||||
Subject: [PATCH 2/5] net: phylink: move MLO_AN_FIXED resolve handling to if()
|
||||
statement
|
||||
|
||||
The switch() statement doesn't sit very well with the preceeding if()
|
||||
statements, and results in excessive indentation that spoils code
|
||||
readability. Begin cleaning this up by converting the MLO_AN_FIXED case
|
||||
to an if() statement.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1480,6 +1480,9 @@ static void phylink_resolve(struct work_
|
||||
} else if (pl->link_failed) {
|
||||
link_state.link = false;
|
||||
retrigger = true;
|
||||
+ } else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ phylink_get_fixed_state(pl, &link_state);
|
||||
+ mac_config = link_state.link;
|
||||
} else {
|
||||
switch (pl->cur_link_an_mode) {
|
||||
case MLO_AN_PHY:
|
||||
@@ -1487,11 +1490,6 @@ static void phylink_resolve(struct work_
|
||||
mac_config = link_state.link;
|
||||
break;
|
||||
|
||||
- case MLO_AN_FIXED:
|
||||
- phylink_get_fixed_state(pl, &link_state);
|
||||
- mac_config = link_state.link;
|
||||
- break;
|
||||
-
|
||||
case MLO_AN_INBAND:
|
||||
phylink_mac_pcs_get_state(pl, &link_state);
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:01:55 +0000
|
||||
Subject: [PATCH 3/5] net: phylink: move MLO_AN_PHY resolve handling to if()
|
||||
statement
|
||||
|
||||
The switch() statement doesn't sit very well with the preceeding if()
|
||||
statements, and results in excessive indentation that spoils code
|
||||
readability. Continue cleaning this up by converting the MLO_AN_PHY
|
||||
case to use an if() statmeent.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1483,13 +1483,11 @@ static void phylink_resolve(struct work_
|
||||
} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
phylink_get_fixed_state(pl, &link_state);
|
||||
mac_config = link_state.link;
|
||||
+ } else if (pl->cur_link_an_mode == MLO_AN_PHY) {
|
||||
+ link_state = pl->phy_state;
|
||||
+ mac_config = link_state.link;
|
||||
} else {
|
||||
switch (pl->cur_link_an_mode) {
|
||||
- case MLO_AN_PHY:
|
||||
- link_state = pl->phy_state;
|
||||
- mac_config = link_state.link;
|
||||
- break;
|
||||
-
|
||||
case MLO_AN_INBAND:
|
||||
phylink_mac_pcs_get_state(pl, &link_state);
|
||||
|
||||
@ -0,0 +1,127 @@
|
||||
From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:02:00 +0000
|
||||
Subject: [PATCH 4/5] net: phylink: remove switch() statement in resolve
|
||||
handling
|
||||
|
||||
The switch() statement doesn't sit very well with the preceeding if()
|
||||
statements, so let's just convert everything to if()s. As a result of
|
||||
the two preceding commits, there is now only one case in the switch()
|
||||
statement. Remove the switch statement and reduce the code indentation.
|
||||
Code reformatting will be in the following commit.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 94 +++++++++++++++++++--------------------
|
||||
1 file changed, 45 insertions(+), 49 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1487,60 +1487,56 @@ static void phylink_resolve(struct work_
|
||||
link_state = pl->phy_state;
|
||||
mac_config = link_state.link;
|
||||
} else {
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
- case MLO_AN_INBAND:
|
||||
- phylink_mac_pcs_get_state(pl, &link_state);
|
||||
-
|
||||
- /* The PCS may have a latching link-fail indicator.
|
||||
- * If the link was up, bring the link down and
|
||||
- * re-trigger the resolve. Otherwise, re-read the
|
||||
- * PCS state to get the current status of the link.
|
||||
+ phylink_mac_pcs_get_state(pl, &link_state);
|
||||
+
|
||||
+ /* The PCS may have a latching link-fail indicator.
|
||||
+ * If the link was up, bring the link down and
|
||||
+ * re-trigger the resolve. Otherwise, re-read the
|
||||
+ * PCS state to get the current status of the link.
|
||||
+ */
|
||||
+ if (!link_state.link) {
|
||||
+ if (cur_link_state)
|
||||
+ retrigger = true;
|
||||
+ else
|
||||
+ phylink_mac_pcs_get_state(pl,
|
||||
+ &link_state);
|
||||
+ }
|
||||
+
|
||||
+ /* If we have a phy, the "up" state is the union of
|
||||
+ * both the PHY and the MAC
|
||||
+ */
|
||||
+ if (pl->phydev)
|
||||
+ link_state.link &= pl->phy_state.link;
|
||||
+
|
||||
+ /* Only update if the PHY link is up */
|
||||
+ if (pl->phydev && pl->phy_state.link) {
|
||||
+ /* If the interface has changed, force a
|
||||
+ * link down event if the link isn't already
|
||||
+ * down, and re-resolve.
|
||||
*/
|
||||
- if (!link_state.link) {
|
||||
- if (cur_link_state)
|
||||
- retrigger = true;
|
||||
- else
|
||||
- phylink_mac_pcs_get_state(pl,
|
||||
- &link_state);
|
||||
+ if (link_state.interface !=
|
||||
+ pl->phy_state.interface) {
|
||||
+ retrigger = true;
|
||||
+ link_state.link = false;
|
||||
}
|
||||
+ link_state.interface = pl->phy_state.interface;
|
||||
|
||||
- /* If we have a phy, the "up" state is the union of
|
||||
- * both the PHY and the MAC
|
||||
+ /* If we are doing rate matching, then the
|
||||
+ * link speed/duplex comes from the PHY
|
||||
*/
|
||||
- if (pl->phydev)
|
||||
- link_state.link &= pl->phy_state.link;
|
||||
-
|
||||
- /* Only update if the PHY link is up */
|
||||
- if (pl->phydev && pl->phy_state.link) {
|
||||
- /* If the interface has changed, force a
|
||||
- * link down event if the link isn't already
|
||||
- * down, and re-resolve.
|
||||
- */
|
||||
- if (link_state.interface !=
|
||||
- pl->phy_state.interface) {
|
||||
- retrigger = true;
|
||||
- link_state.link = false;
|
||||
- }
|
||||
- link_state.interface = pl->phy_state.interface;
|
||||
-
|
||||
- /* If we are doing rate matching, then the
|
||||
- * link speed/duplex comes from the PHY
|
||||
- */
|
||||
- if (pl->phy_state.rate_matching) {
|
||||
- link_state.rate_matching =
|
||||
- pl->phy_state.rate_matching;
|
||||
- link_state.speed = pl->phy_state.speed;
|
||||
- link_state.duplex =
|
||||
- pl->phy_state.duplex;
|
||||
- }
|
||||
-
|
||||
- /* If we have a PHY, we need to update with
|
||||
- * the PHY flow control bits.
|
||||
- */
|
||||
- link_state.pause = pl->phy_state.pause;
|
||||
- mac_config = true;
|
||||
+ if (pl->phy_state.rate_matching) {
|
||||
+ link_state.rate_matching =
|
||||
+ pl->phy_state.rate_matching;
|
||||
+ link_state.speed = pl->phy_state.speed;
|
||||
+ link_state.duplex =
|
||||
+ pl->phy_state.duplex;
|
||||
}
|
||||
- break;
|
||||
+
|
||||
+ /* If we have a PHY, we need to update with
|
||||
+ * the PHY flow control bits.
|
||||
+ */
|
||||
+ link_state.pause = pl->phy_state.pause;
|
||||
+ mac_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:02:05 +0000
|
||||
Subject: [PATCH 5/5] net: phylink: clean up phylink_resolve()
|
||||
|
||||
Now that we have reduced the indentation level, clean up the code
|
||||
formatting.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 35 ++++++++++++++++-------------------
|
||||
1 file changed, 16 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1489,51 +1489,48 @@ static void phylink_resolve(struct work_
|
||||
} else {
|
||||
phylink_mac_pcs_get_state(pl, &link_state);
|
||||
|
||||
- /* The PCS may have a latching link-fail indicator.
|
||||
- * If the link was up, bring the link down and
|
||||
- * re-trigger the resolve. Otherwise, re-read the
|
||||
- * PCS state to get the current status of the link.
|
||||
+ /* The PCS may have a latching link-fail indicator. If the link
|
||||
+ * was up, bring the link down and re-trigger the resolve.
|
||||
+ * Otherwise, re-read the PCS state to get the current status
|
||||
+ * of the link.
|
||||
*/
|
||||
if (!link_state.link) {
|
||||
if (cur_link_state)
|
||||
retrigger = true;
|
||||
else
|
||||
- phylink_mac_pcs_get_state(pl,
|
||||
- &link_state);
|
||||
+ phylink_mac_pcs_get_state(pl, &link_state);
|
||||
}
|
||||
|
||||
- /* If we have a phy, the "up" state is the union of
|
||||
- * both the PHY and the MAC
|
||||
+ /* If we have a phy, the "up" state is the union of both the
|
||||
+ * PHY and the MAC
|
||||
*/
|
||||
if (pl->phydev)
|
||||
link_state.link &= pl->phy_state.link;
|
||||
|
||||
/* Only update if the PHY link is up */
|
||||
if (pl->phydev && pl->phy_state.link) {
|
||||
- /* If the interface has changed, force a
|
||||
- * link down event if the link isn't already
|
||||
- * down, and re-resolve.
|
||||
+ /* If the interface has changed, force a link down
|
||||
+ * event if the link isn't already down, and re-resolve.
|
||||
*/
|
||||
- if (link_state.interface !=
|
||||
- pl->phy_state.interface) {
|
||||
+ if (link_state.interface != pl->phy_state.interface) {
|
||||
retrigger = true;
|
||||
link_state.link = false;
|
||||
}
|
||||
+
|
||||
link_state.interface = pl->phy_state.interface;
|
||||
|
||||
- /* If we are doing rate matching, then the
|
||||
- * link speed/duplex comes from the PHY
|
||||
+ /* If we are doing rate matching, then the link
|
||||
+ * speed/duplex comes from the PHY
|
||||
*/
|
||||
if (pl->phy_state.rate_matching) {
|
||||
link_state.rate_matching =
|
||||
pl->phy_state.rate_matching;
|
||||
link_state.speed = pl->phy_state.speed;
|
||||
- link_state.duplex =
|
||||
- pl->phy_state.duplex;
|
||||
+ link_state.duplex = pl->phy_state.duplex;
|
||||
}
|
||||
|
||||
- /* If we have a PHY, we need to update with
|
||||
- * the PHY flow control bits.
|
||||
+ /* If we have a PHY, we need to update with the PHY
|
||||
+ * flow control bits.
|
||||
*/
|
||||
link_state.pause = pl->phy_state.pause;
|
||||
mac_config = true;
|
||||
@ -0,0 +1,95 @@
|
||||
From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:30:47 +0000
|
||||
Subject: [PATCH 01/13] net: phylink: pass phylink and pcs into
|
||||
phylink_pcs_neg_mode()
|
||||
|
||||
Move the call to phylink_pcs_neg_mode() in phylink_major_config() after
|
||||
we have selected the appropriate PCS to allow the PCS to be passed in.
|
||||
|
||||
Add struct phylink and struct phylink_pcs pointers to
|
||||
phylink_pcs_neg_mode() and pass in the appropriate structures. Set
|
||||
pl->pcs_neg_mode before returning, and remove the return value.
|
||||
|
||||
This will allow the capabilities of the PCS and any PHY to be used when
|
||||
deciding which pcs_neg_mode should be used.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1102,7 +1102,8 @@ static void phylink_pcs_an_restart(struc
|
||||
|
||||
/**
|
||||
* phylink_pcs_neg_mode() - helper to determine PCS inband mode
|
||||
- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
|
||||
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
+ * @pcs: a pointer to &struct phylink_pcs
|
||||
* @interface: interface mode to be used
|
||||
* @advertising: adertisement ethtool link mode mask
|
||||
*
|
||||
@@ -1119,11 +1120,13 @@ static void phylink_pcs_an_restart(struc
|
||||
* Note: this is for cases where the PCS itself is involved in negotiation
|
||||
* (e.g. Clause 37, SGMII and similar) not Clause 73.
|
||||
*/
|
||||
-static unsigned int phylink_pcs_neg_mode(unsigned int mode,
|
||||
- phy_interface_t interface,
|
||||
- const unsigned long *advertising)
|
||||
+static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface,
|
||||
+ const unsigned long *advertising)
|
||||
{
|
||||
- unsigned int neg_mode;
|
||||
+ unsigned int neg_mode, mode;
|
||||
+
|
||||
+ mode = pl->cur_link_an_mode;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
@@ -1164,7 +1167,7 @@ static unsigned int phylink_pcs_neg_mode
|
||||
break;
|
||||
}
|
||||
|
||||
- return neg_mode;
|
||||
+ pl->pcs_neg_mode = neg_mode;
|
||||
}
|
||||
|
||||
static void phylink_major_config(struct phylink *pl, bool restart,
|
||||
@@ -1178,10 +1181,6 @@ static void phylink_major_config(struct
|
||||
|
||||
phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
|
||||
|
||||
- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
|
||||
- state->interface,
|
||||
- state->advertising);
|
||||
-
|
||||
if (pl->using_mac_select_pcs) {
|
||||
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
|
||||
if (IS_ERR(pcs)) {
|
||||
@@ -1194,6 +1193,8 @@ static void phylink_major_config(struct
|
||||
pcs_changed = pcs && pl->pcs != pcs;
|
||||
}
|
||||
|
||||
+ phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
|
||||
+
|
||||
phylink_pcs_poll_stop(pl);
|
||||
|
||||
if (pl->mac_ops->mac_prepare) {
|
||||
@@ -1284,9 +1285,8 @@ static int phylink_change_inband_advert(
|
||||
pl->link_config.pause);
|
||||
|
||||
/* Recompute the PCS neg mode */
|
||||
- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
|
||||
- pl->link_config.interface,
|
||||
- pl->link_config.advertising);
|
||||
+ phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
|
||||
+ pl->link_config.advertising);
|
||||
|
||||
neg_mode = pl->cur_link_an_mode;
|
||||
if (pl->pcs->neg_mode)
|
||||
@ -0,0 +1,290 @@
|
||||
From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:30:52 +0000
|
||||
Subject: [PATCH 02/13] net: phylink: split cur_link_an_mode into requested and
|
||||
active
|
||||
|
||||
There is an interdependence between the current link_an_mode and
|
||||
pcs_neg_mode that some drivers rely upon to know whether inband or PHY
|
||||
mode will be used.
|
||||
|
||||
In order to support detection of PCS and PHY inband capabilities
|
||||
resulting in automatic selection of inband or PHY mode, we need to
|
||||
cater for this, and support changing the MAC link_an_mode. However, we
|
||||
end up with an inter-dependency between the current link_an_mode and
|
||||
pcs_neg_mode.
|
||||
|
||||
To solve this, split the current link_an_mode into the requested
|
||||
link_an_mode and active link_an_mode. The requested link_an_mode will
|
||||
always be passed to phylink_pcs_neg_mode(), and the active link_an_mode
|
||||
will be used for everything else, and only updated during
|
||||
phylink_major_config(). This will ensure that phylink_pcs_neg_mode()'s
|
||||
link_an_mode will not depend on the active link_an_mode that will,
|
||||
in a future patch, depend on pcs_neg_mode.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 60 ++++++++++++++++++++-------------------
|
||||
1 file changed, 31 insertions(+), 29 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -56,7 +56,8 @@ struct phylink {
|
||||
struct phy_device *phydev;
|
||||
phy_interface_t link_interface; /* PHY_INTERFACE_xxx */
|
||||
u8 cfg_link_an_mode; /* MLO_AN_xxx */
|
||||
- u8 cur_link_an_mode;
|
||||
+ u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */
|
||||
+ u8 act_link_an_mode; /* Active MLO_AN_xxx mode */
|
||||
u8 link_port; /* The current non-phy ethtool port */
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
||||
|
||||
@@ -1082,13 +1083,13 @@ static void phylink_mac_config(struct ph
|
||||
|
||||
phylink_dbg(pl,
|
||||
"%s: mode=%s/%s/%s adv=%*pb pause=%02x\n",
|
||||
- __func__, phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ __func__, phylink_an_mode_str(pl->act_link_an_mode),
|
||||
phy_modes(st.interface),
|
||||
phy_rate_matching_to_str(st.rate_matching),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising,
|
||||
st.pause);
|
||||
|
||||
- pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st);
|
||||
+ pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st);
|
||||
}
|
||||
|
||||
static void phylink_pcs_an_restart(struct phylink *pl)
|
||||
@@ -1096,7 +1097,7 @@ static void phylink_pcs_an_restart(struc
|
||||
if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
pl->link_config.advertising) &&
|
||||
phy_interface_mode_is_8023z(pl->link_config.interface) &&
|
||||
- phylink_autoneg_inband(pl->cur_link_an_mode))
|
||||
+ phylink_autoneg_inband(pl->act_link_an_mode))
|
||||
pl->pcs->ops->pcs_an_restart(pl->pcs);
|
||||
}
|
||||
|
||||
@@ -1126,7 +1127,7 @@ static void phylink_pcs_neg_mode(struct
|
||||
{
|
||||
unsigned int neg_mode, mode;
|
||||
|
||||
- mode = pl->cur_link_an_mode;
|
||||
+ mode = pl->req_link_an_mode;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
@@ -1168,6 +1169,7 @@ static void phylink_pcs_neg_mode(struct
|
||||
}
|
||||
|
||||
pl->pcs_neg_mode = neg_mode;
|
||||
+ pl->act_link_an_mode = mode;
|
||||
}
|
||||
|
||||
static void phylink_major_config(struct phylink *pl, bool restart,
|
||||
@@ -1198,7 +1200,7 @@ static void phylink_major_config(struct
|
||||
phylink_pcs_poll_stop(pl);
|
||||
|
||||
if (pl->mac_ops->mac_prepare) {
|
||||
- err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
|
||||
+ err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode,
|
||||
state->interface);
|
||||
if (err < 0) {
|
||||
phylink_err(pl, "mac_prepare failed: %pe\n",
|
||||
@@ -1232,7 +1234,7 @@ static void phylink_major_config(struct
|
||||
if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
|
||||
phylink_pcs_enable(pl->pcs);
|
||||
|
||||
- neg_mode = pl->cur_link_an_mode;
|
||||
+ neg_mode = pl->act_link_an_mode;
|
||||
if (pl->pcs && pl->pcs->neg_mode)
|
||||
neg_mode = pl->pcs_neg_mode;
|
||||
|
||||
@@ -1248,7 +1250,7 @@ static void phylink_major_config(struct
|
||||
phylink_pcs_an_restart(pl);
|
||||
|
||||
if (pl->mac_ops->mac_finish) {
|
||||
- err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode,
|
||||
+ err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode,
|
||||
state->interface);
|
||||
if (err < 0)
|
||||
phylink_err(pl, "mac_finish failed: %pe\n",
|
||||
@@ -1279,7 +1281,7 @@ static int phylink_change_inband_advert(
|
||||
return 0;
|
||||
|
||||
phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
|
||||
- phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(pl->link_config.interface),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
|
||||
pl->link_config.pause);
|
||||
@@ -1288,7 +1290,7 @@ static int phylink_change_inband_advert(
|
||||
phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
|
||||
pl->link_config.advertising);
|
||||
|
||||
- neg_mode = pl->cur_link_an_mode;
|
||||
+ neg_mode = pl->act_link_an_mode;
|
||||
if (pl->pcs->neg_mode)
|
||||
neg_mode = pl->pcs_neg_mode;
|
||||
|
||||
@@ -1353,7 +1355,7 @@ static void phylink_mac_initial_config(s
|
||||
{
|
||||
struct phylink_link_state link_state;
|
||||
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->req_link_an_mode) {
|
||||
case MLO_AN_PHY:
|
||||
link_state = pl->phy_state;
|
||||
break;
|
||||
@@ -1427,14 +1429,14 @@ static void phylink_link_up(struct phyli
|
||||
|
||||
pl->cur_interface = link_state.interface;
|
||||
|
||||
- neg_mode = pl->cur_link_an_mode;
|
||||
+ neg_mode = pl->act_link_an_mode;
|
||||
if (pl->pcs && pl->pcs->neg_mode)
|
||||
neg_mode = pl->pcs_neg_mode;
|
||||
|
||||
phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
|
||||
duplex);
|
||||
|
||||
- pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
|
||||
+ pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode,
|
||||
pl->cur_interface, speed, duplex,
|
||||
!!(link_state.pause & MLO_PAUSE_TX), rx_pause);
|
||||
|
||||
@@ -1454,7 +1456,7 @@ static void phylink_link_down(struct phy
|
||||
|
||||
if (ndev)
|
||||
netif_carrier_off(ndev);
|
||||
- pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
|
||||
+ pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
|
||||
pl->cur_interface);
|
||||
phylink_info(pl, "Link is Down\n");
|
||||
}
|
||||
@@ -1480,10 +1482,10 @@ static void phylink_resolve(struct work_
|
||||
} else if (pl->link_failed) {
|
||||
link_state.link = false;
|
||||
retrigger = true;
|
||||
- } else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ } else if (pl->act_link_an_mode == MLO_AN_FIXED) {
|
||||
phylink_get_fixed_state(pl, &link_state);
|
||||
mac_config = link_state.link;
|
||||
- } else if (pl->cur_link_an_mode == MLO_AN_PHY) {
|
||||
+ } else if (pl->act_link_an_mode == MLO_AN_PHY) {
|
||||
link_state = pl->phy_state;
|
||||
mac_config = link_state.link;
|
||||
} else {
|
||||
@@ -1537,7 +1539,7 @@ static void phylink_resolve(struct work_
|
||||
}
|
||||
}
|
||||
|
||||
- if (pl->cur_link_an_mode != MLO_AN_FIXED)
|
||||
+ if (pl->act_link_an_mode != MLO_AN_FIXED)
|
||||
phylink_apply_manual_flow(pl, &link_state);
|
||||
|
||||
if (mac_config) {
|
||||
@@ -1661,7 +1663,7 @@ int phylink_set_fixed_link(struct phylin
|
||||
pl->link_config.an_complete = 1;
|
||||
|
||||
pl->cfg_link_an_mode = MLO_AN_FIXED;
|
||||
- pl->cur_link_an_mode = pl->cfg_link_an_mode;
|
||||
+ pl->req_link_an_mode = pl->cfg_link_an_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1756,7 +1758,7 @@ struct phylink *phylink_create(struct ph
|
||||
}
|
||||
}
|
||||
|
||||
- pl->cur_link_an_mode = pl->cfg_link_an_mode;
|
||||
+ pl->req_link_an_mode = pl->cfg_link_an_mode;
|
||||
|
||||
ret = phylink_register_sfp(pl, fwnode);
|
||||
if (ret < 0) {
|
||||
@@ -2213,7 +2215,7 @@ void phylink_start(struct phylink *pl)
|
||||
ASSERT_RTNL();
|
||||
|
||||
phylink_info(pl, "configuring for %s/%s link mode\n",
|
||||
- phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(pl->link_config.interface));
|
||||
|
||||
/* Always set the carrier off */
|
||||
@@ -2472,7 +2474,7 @@ int phylink_ethtool_ksettings_get(struct
|
||||
|
||||
linkmode_copy(kset->link_modes.supported, pl->supported);
|
||||
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->act_link_an_mode) {
|
||||
case MLO_AN_FIXED:
|
||||
/* We are using fixed settings. Report these as the
|
||||
* current link settings - and note that these also
|
||||
@@ -2564,7 +2566,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
/* If we have a fixed link, refuse to change link parameters.
|
||||
* If the link parameters match, accept them but do nothing.
|
||||
*/
|
||||
- if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ if (pl->req_link_an_mode == MLO_AN_FIXED) {
|
||||
if (s->speed != pl->link_config.speed ||
|
||||
s->duplex != pl->link_config.duplex)
|
||||
return -EINVAL;
|
||||
@@ -2580,7 +2582,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
* is our default case) but do not allow the advertisement to
|
||||
* be changed. If the advertisement matches, simply return.
|
||||
*/
|
||||
- if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ if (pl->req_link_an_mode == MLO_AN_FIXED) {
|
||||
if (!linkmode_equal(config.advertising,
|
||||
pl->link_config.advertising))
|
||||
return -EINVAL;
|
||||
@@ -2620,7 +2622,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
linkmode_copy(support, pl->supported);
|
||||
if (phylink_validate(pl, support, &config)) {
|
||||
phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
|
||||
- phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(config.interface),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, support);
|
||||
return -EINVAL;
|
||||
@@ -2720,7 +2722,7 @@ int phylink_ethtool_set_pauseparam(struc
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
- if (pl->cur_link_an_mode == MLO_AN_FIXED)
|
||||
+ if (pl->req_link_an_mode == MLO_AN_FIXED)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!phylink_test(pl->supported, Pause) &&
|
||||
@@ -2984,7 +2986,7 @@ static int phylink_mii_read(struct phyli
|
||||
struct phylink_link_state state;
|
||||
int val = 0xffff;
|
||||
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->act_link_an_mode) {
|
||||
case MLO_AN_FIXED:
|
||||
if (phy_id == 0) {
|
||||
phylink_get_fixed_state(pl, &state);
|
||||
@@ -3009,7 +3011,7 @@ static int phylink_mii_read(struct phyli
|
||||
static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
|
||||
unsigned int reg, unsigned int val)
|
||||
{
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->act_link_an_mode) {
|
||||
case MLO_AN_FIXED:
|
||||
break;
|
||||
|
||||
@@ -3199,9 +3201,9 @@ static void phylink_sfp_set_config(struc
|
||||
changed = true;
|
||||
}
|
||||
|
||||
- if (pl->cur_link_an_mode != mode ||
|
||||
+ if (pl->req_link_an_mode != mode ||
|
||||
pl->link_config.interface != state->interface) {
|
||||
- pl->cur_link_an_mode = mode;
|
||||
+ pl->req_link_an_mode = mode;
|
||||
pl->link_config.interface = state->interface;
|
||||
|
||||
changed = true;
|
||||
@ -0,0 +1,66 @@
|
||||
From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:30:57 +0000
|
||||
Subject: [PATCH 03/13] net: phylink: add debug for phylink_major_config()
|
||||
|
||||
Now that we have a more complexity in phylink_major_config(), augment
|
||||
the debugging so we can see what's going on there.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 27 ++++++++++++++++++++++++++-
|
||||
1 file changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -176,6 +176,24 @@ static const char *phylink_an_mode_str(u
|
||||
return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
|
||||
}
|
||||
|
||||
+static const char *phylink_pcs_mode_str(unsigned int mode)
|
||||
+{
|
||||
+ if (!mode)
|
||||
+ return "none";
|
||||
+
|
||||
+ if (mode & PHYLINK_PCS_NEG_OUTBAND)
|
||||
+ return "outband";
|
||||
+
|
||||
+ if (mode & PHYLINK_PCS_NEG_INBAND) {
|
||||
+ if (mode & PHYLINK_PCS_NEG_ENABLED)
|
||||
+ return "inband,an-enabled";
|
||||
+ else
|
||||
+ return "inband,an-disabled";
|
||||
+ }
|
||||
+
|
||||
+ return "unknown";
|
||||
+}
|
||||
+
|
||||
static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
|
||||
{
|
||||
switch (interface) {
|
||||
@@ -1181,7 +1199,9 @@ static void phylink_major_config(struct
|
||||
unsigned int neg_mode;
|
||||
int err;
|
||||
|
||||
- phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
|
||||
+ phylink_dbg(pl, "major config, requested %s/%s\n",
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
+ phy_modes(state->interface));
|
||||
|
||||
if (pl->using_mac_select_pcs) {
|
||||
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
|
||||
@@ -1197,6 +1217,11 @@ static void phylink_major_config(struct
|
||||
|
||||
phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
|
||||
|
||||
+ phylink_dbg(pl, "major config, active %s/%s/%s\n",
|
||||
+ phylink_an_mode_str(pl->act_link_an_mode),
|
||||
+ phylink_pcs_mode_str(pl->pcs_neg_mode),
|
||||
+ phy_modes(state->interface));
|
||||
+
|
||||
phylink_pcs_poll_stop(pl);
|
||||
|
||||
if (pl->mac_ops->mac_prepare) {
|
||||
@ -0,0 +1,118 @@
|
||||
From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:02 +0000
|
||||
Subject: [PATCH 04/13] net: phy: add phy_inband_caps()
|
||||
|
||||
Add a method to query the PHY's in-band capabilities for a PHY
|
||||
interface mode.
|
||||
|
||||
Where the interface mode does not have in-band capability, or the PHY
|
||||
driver has not been updated to return this information, then
|
||||
phy_inband_caps() should return zero. Otherwise, PHY drivers will
|
||||
return a value consisting of the following flags:
|
||||
|
||||
LINK_INBAND_DISABLE indicates that the hardware does not support
|
||||
in-band signalling, or can have in-band signalling configured via
|
||||
software to be disabled.
|
||||
|
||||
LINK_INBAND_ENABLE indicates that the hardware will use in-band
|
||||
signalling, or can have in-band signalling configured via software
|
||||
to be enabled.
|
||||
|
||||
LINK_INBAND_BYPASS indicates that the hardware has the ability to
|
||||
bypass in-band signalling when enabled after a timeout if the link
|
||||
partner does not respond to its in-band signalling.
|
||||
|
||||
This reports the PHY capabilities for the particular interface mode,
|
||||
not the current configuration.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phy.c | 21 +++++++++++++++++++++
|
||||
include/linux/phy.h | 28 ++++++++++++++++++++++++++++
|
||||
2 files changed, 49 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -1049,6 +1049,27 @@ static int phy_check_link_status(struct
|
||||
}
|
||||
|
||||
/**
|
||||
+ * phy_inband_caps - query which in-band signalling modes are supported
|
||||
+ * @phydev: a pointer to a &struct phy_device
|
||||
+ * @interface: the interface mode for the PHY
|
||||
+ *
|
||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
|
||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
|
||||
+ * returns a bit mask of the LINK_INBAND_* values from
|
||||
+ * &enum link_inband_signalling to describe which inband modes are supported
|
||||
+ * by the PHY for this interface mode.
|
||||
+ */
|
||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ if (phydev->drv && phydev->drv->inband_caps)
|
||||
+ return phydev->drv->inband_caps(phydev, interface);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(phy_inband_caps);
|
||||
+
|
||||
+/**
|
||||
* _phy_start_aneg - start auto-negotiation for this PHY device
|
||||
* @phydev: the phy_device struct
|
||||
*
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -816,6 +816,24 @@ struct phy_tdr_config {
|
||||
#define PHY_PAIR_ALL -1
|
||||
|
||||
/**
|
||||
+ * enum link_inband_signalling - in-band signalling modes that are supported
|
||||
+ *
|
||||
+ * @LINK_INBAND_DISABLE: in-band signalling can be disabled
|
||||
+ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass
|
||||
+ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass
|
||||
+ *
|
||||
+ * The possible and required bits can only be used if the valid bit is set.
|
||||
+ * If possible is clear, that means inband signalling can not be used.
|
||||
+ * Required is only valid when possible is set, and means that inband
|
||||
+ * signalling must be used.
|
||||
+ */
|
||||
+enum link_inband_signalling {
|
||||
+ LINK_INBAND_DISABLE = BIT(0),
|
||||
+ LINK_INBAND_ENABLE = BIT(1),
|
||||
+ LINK_INBAND_BYPASS = BIT(2),
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision
|
||||
* Avoidance) Reconciliation Sublayer.
|
||||
*
|
||||
@@ -954,6 +972,14 @@ struct phy_driver {
|
||||
int (*get_features)(struct phy_device *phydev);
|
||||
|
||||
/**
|
||||
+ * @inband_caps: query whether in-band is supported for the given PHY
|
||||
+ * interface mode. Returns a bitmask of bits defined by enum
|
||||
+ * link_inband_signalling.
|
||||
+ */
|
||||
+ unsigned int (*inband_caps)(struct phy_device *phydev,
|
||||
+ phy_interface_t interface);
|
||||
+
|
||||
+ /**
|
||||
* @get_rate_matching: Get the supported type of rate matching for a
|
||||
* particular phy interface. This is used by phy consumers to determine
|
||||
* whether to advertise lower-speed modes for that interface. It is
|
||||
@@ -1832,6 +1858,8 @@ int phy_config_aneg(struct phy_device *p
|
||||
int _phy_start_aneg(struct phy_device *phydev);
|
||||
int phy_start_aneg(struct phy_device *phydev);
|
||||
int phy_aneg_done(struct phy_device *phydev);
|
||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface);
|
||||
int phy_speed_down(struct phy_device *phydev, bool sync);
|
||||
int phy_speed_up(struct phy_device *phydev);
|
||||
bool phy_check_valid(int speed, int duplex, unsigned long *features);
|
||||
@ -0,0 +1,41 @@
|
||||
From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:07 +0000
|
||||
Subject: [PATCH 05/13] net: phy: bcm84881: implement phy_inband_caps() method
|
||||
|
||||
BCM84881 has no support for inband signalling, so this is a trivial
|
||||
implementation that returns no support for inband.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/bcm84881.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/bcm84881.c
|
||||
+++ b/drivers/net/phy/bcm84881.c
|
||||
@@ -235,11 +235,21 @@ static int bcm84881_read_status(struct p
|
||||
return genphy_c45_read_mdix(phydev);
|
||||
}
|
||||
|
||||
+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
|
||||
+ * or 802.3z control word, so inband will not work.
|
||||
+ */
|
||||
+static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver bcm84881_drivers[] = {
|
||||
{
|
||||
.phy_id = 0xae025150,
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.name = "Broadcom BCM84881",
|
||||
+ .inband_caps = bcm84881_inband_caps,
|
||||
.config_init = bcm84881_config_init,
|
||||
.probe = bcm84881_probe,
|
||||
.get_features = bcm84881_get_features,
|
||||
@ -0,0 +1,63 @@
|
||||
From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:12 +0000
|
||||
Subject: [PATCH 06/13] net: phy: marvell: implement phy_inband_caps() method
|
||||
|
||||
Provide an implementation for phy_inband_caps() for Marvell PHYs used
|
||||
on SFP modules, so that phylink knows the PHYs capabilities.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/marvell.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -716,6 +716,20 @@ static int marvell_config_aneg_fiber(str
|
||||
return genphy_check_and_restart_aneg(phydev, changed);
|
||||
}
|
||||
|
||||
+static unsigned int m88e1111_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ /* In 1000base-X and SGMII modes, the inband mode can be changed
|
||||
+ * through the Fibre page BMCR ANENABLE bit.
|
||||
+ */
|
||||
+ if (interface == PHY_INTERFACE_MODE_1000BASEX ||
|
||||
+ interface == PHY_INTERFACE_MODE_SGMII)
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE |
|
||||
+ LINK_INBAND_BYPASS;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int m88e1111_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
|
||||
@@ -3667,6 +3681,7 @@ static struct phy_driver marvell_drivers
|
||||
.name = "Marvell 88E1112",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
+ .inband_caps = m88e1111_inband_caps,
|
||||
.config_init = m88e1112_config_init,
|
||||
.config_aneg = marvell_config_aneg,
|
||||
.config_intr = marvell_config_intr,
|
||||
@@ -3688,6 +3703,7 @@ static struct phy_driver marvell_drivers
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
.probe = marvell_probe,
|
||||
+ .inband_caps = m88e1111_inband_caps,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -3711,6 +3727,7 @@ static struct phy_driver marvell_drivers
|
||||
.name = "Marvell 88E1111 (Finisar)",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
+ .inband_caps = m88e1111_inband_caps,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@ -0,0 +1,79 @@
|
||||
From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:18 +0000
|
||||
Subject: [PATCH 07/13] net: phy: add phy_config_inband()
|
||||
|
||||
Add a method to configure the PHY's in-band mode.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++++++++
|
||||
include/linux/phy.h | 6 ++++++
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -1070,6 +1070,38 @@ unsigned int phy_inband_caps(struct phy_
|
||||
EXPORT_SYMBOL_GPL(phy_inband_caps);
|
||||
|
||||
/**
|
||||
+ * phy_config_inband - configure the desired PHY in-band mode
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @modes: in-band modes to configure
|
||||
+ *
|
||||
+ * Description: disables, enables or enables-with-bypass in-band signalling
|
||||
+ * between the PHY and host system.
|
||||
+ *
|
||||
+ * Returns: zero on success, or negative errno value.
|
||||
+ */
|
||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ if (!!(modes & LINK_INBAND_DISABLE) +
|
||||
+ !!(modes & LINK_INBAND_ENABLE) +
|
||||
+ !!(modes & LINK_INBAND_BYPASS) != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&phydev->lock);
|
||||
+ if (!phydev->drv)
|
||||
+ err = -EIO;
|
||||
+ else if (!phydev->drv->config_inband)
|
||||
+ err = -EOPNOTSUPP;
|
||||
+ else
|
||||
+ err = phydev->drv->config_inband(phydev, modes);
|
||||
+ mutex_unlock(&phydev->lock);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+EXPORT_SYMBOL(phy_config_inband);
|
||||
+
|
||||
+/**
|
||||
* _phy_start_aneg - start auto-negotiation for this PHY device
|
||||
* @phydev: the phy_device struct
|
||||
*
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -980,6 +980,11 @@ struct phy_driver {
|
||||
phy_interface_t interface);
|
||||
|
||||
/**
|
||||
+ * @config_inband: configure in-band mode for the PHY
|
||||
+ */
|
||||
+ int (*config_inband)(struct phy_device *phydev, unsigned int modes);
|
||||
+
|
||||
+ /**
|
||||
* @get_rate_matching: Get the supported type of rate matching for a
|
||||
* particular phy interface. This is used by phy consumers to determine
|
||||
* whether to advertise lower-speed modes for that interface. It is
|
||||
@@ -1860,6 +1865,7 @@ int phy_start_aneg(struct phy_device *ph
|
||||
int phy_aneg_done(struct phy_device *phydev);
|
||||
unsigned int phy_inband_caps(struct phy_device *phydev,
|
||||
phy_interface_t interface);
|
||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes);
|
||||
int phy_speed_down(struct phy_device *phydev, bool sync);
|
||||
int phy_speed_up(struct phy_device *phydev);
|
||||
bool phy_check_valid(int speed, int duplex, unsigned long *features);
|
||||
@ -0,0 +1,77 @@
|
||||
From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:23 +0000
|
||||
Subject: [PATCH 08/13] net: phy: marvell: implement config_inband() method
|
||||
|
||||
Implement the config_inband() method for Marvell 88E1112, 88E1111,
|
||||
and Finisar's 88E1111 variant.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/marvell.c | 31 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 31 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -730,6 +730,34 @@ static unsigned int m88e1111_inband_caps
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
|
||||
+{
|
||||
+ u16 extsr, bmcr;
|
||||
+ int err;
|
||||
+
|
||||
+ if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX &&
|
||||
+ phydev->interface != PHY_INTERFACE_MODE_SGMII)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (modes == LINK_INBAND_BYPASS)
|
||||
+ extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS;
|
||||
+ else
|
||||
+ extsr = 0;
|
||||
+
|
||||
+ if (modes == LINK_INBAND_DISABLE)
|
||||
+ bmcr = 0;
|
||||
+ else
|
||||
+ bmcr = BMCR_ANENABLE;
|
||||
+
|
||||
+ err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
|
||||
+ MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
|
||||
+ if (err < 0)
|
||||
+ return extsr;
|
||||
+
|
||||
+ return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
|
||||
+ BMCR_ANENABLE, bmcr);
|
||||
+}
|
||||
+
|
||||
static int m88e1111_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
|
||||
@@ -3682,6 +3710,7 @@ static struct phy_driver marvell_drivers
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
.inband_caps = m88e1111_inband_caps,
|
||||
+ .config_inband = m88e1111_config_inband,
|
||||
.config_init = m88e1112_config_init,
|
||||
.config_aneg = marvell_config_aneg,
|
||||
.config_intr = marvell_config_intr,
|
||||
@@ -3704,6 +3733,7 @@ static struct phy_driver marvell_drivers
|
||||
.flags = PHY_POLL_CABLE_TEST,
|
||||
.probe = marvell_probe,
|
||||
.inband_caps = m88e1111_inband_caps,
|
||||
+ .config_inband = m88e1111_config_inband,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -3728,6 +3758,7 @@ static struct phy_driver marvell_drivers
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
.inband_caps = m88e1111_inband_caps,
|
||||
+ .config_inband = m88e1111_config_inband,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@ -0,0 +1,159 @@
|
||||
From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:28 +0000
|
||||
Subject: [PATCH 09/13] net: phylink: add pcs_inband_caps() method
|
||||
|
||||
Add a pcs_inband_caps() method to query the PCS for its inband link
|
||||
capabilities, and use this to determine whether link modes used with
|
||||
optical SFPs can be supported.
|
||||
|
||||
When a PCS does not provide a method, we allow inband negotiation to
|
||||
be either on or off, making this a no-op until the pcs_inband_caps()
|
||||
method is implemented by a PCS driver.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 60 +++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/phylink.h | 17 +++++++++++
|
||||
2 files changed, 77 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1007,6 +1007,15 @@ static void phylink_resolve_an_pause(str
|
||||
}
|
||||
}
|
||||
|
||||
+static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ if (pcs && pcs->ops->pcs_inband_caps)
|
||||
+ return pcs->ops->pcs_inband_caps(pcs, interface);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void phylink_pcs_pre_config(struct phylink_pcs *pcs,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
@@ -1060,6 +1069,24 @@ static void phylink_pcs_link_up(struct p
|
||||
pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
|
||||
}
|
||||
|
||||
+/* Query inband for a specific interface mode, asking the MAC for the
|
||||
+ * PCS which will be used to handle the interface mode.
|
||||
+ */
|
||||
+static unsigned int phylink_inband_caps(struct phylink *pl,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ struct phylink_pcs *pcs;
|
||||
+
|
||||
+ if (!pl->mac_ops->mac_select_pcs)
|
||||
+ return 0;
|
||||
+
|
||||
+ pcs = pl->mac_ops->mac_select_pcs(pl->config, interface);
|
||||
+ if (!pcs)
|
||||
+ return 0;
|
||||
+
|
||||
+ return phylink_pcs_inband_caps(pcs, interface);
|
||||
+}
|
||||
+
|
||||
static void phylink_pcs_poll_stop(struct phylink *pl)
|
||||
{
|
||||
if (pl->cfg_link_an_mode == MLO_AN_INBAND)
|
||||
@@ -2530,6 +2557,26 @@ int phylink_ethtool_ksettings_get(struct
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
|
||||
|
||||
+static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl,
|
||||
+ phy_interface_t interface,
|
||||
+ unsigned long *adv)
|
||||
+{
|
||||
+ unsigned int inband = phylink_inband_caps(pl, interface);
|
||||
+ unsigned int mask;
|
||||
+
|
||||
+ /* If the PCS doesn't implement inband support, be permissive. */
|
||||
+ if (!inband)
|
||||
+ return true;
|
||||
+
|
||||
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv))
|
||||
+ mask = LINK_INBAND_ENABLE;
|
||||
+ else
|
||||
+ mask = LINK_INBAND_DISABLE;
|
||||
+
|
||||
+ /* Check whether the PCS implements the required mode */
|
||||
+ return !!(inband & mask);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* phylink_ethtool_ksettings_set() - set the link settings
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
@@ -2665,6 +2712,13 @@ int phylink_ethtool_ksettings_set(struct
|
||||
phylink_is_empty_linkmode(config.advertising))
|
||||
return -EINVAL;
|
||||
|
||||
+ /* Validate the autonegotiation state. We don't have a PHY in this
|
||||
+ * situation, so the PCS is the media-facing entity.
|
||||
+ */
|
||||
+ if (!phylink_validate_pcs_inband_autoneg(pl, config.interface,
|
||||
+ config.advertising))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
mutex_lock(&pl->state_mutex);
|
||||
pl->link_config.speed = config.speed;
|
||||
pl->link_config.duplex = config.duplex;
|
||||
@@ -3349,6 +3403,12 @@ static int phylink_sfp_config_optical(st
|
||||
phylink_dbg(pl, "optical SFP: chosen %s interface\n",
|
||||
phy_modes(interface));
|
||||
|
||||
+ if (!phylink_validate_pcs_inband_autoneg(pl, interface,
|
||||
+ config.advertising)) {
|
||||
+ phylink_err(pl, "autoneg setting not compatible with PCS");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
config.interface = interface;
|
||||
|
||||
/* Ignore errors if we're expecting a PHY to attach later */
|
||||
--- a/include/linux/phylink.h
|
||||
+++ b/include/linux/phylink.h
|
||||
@@ -419,6 +419,7 @@ struct phylink_pcs {
|
||||
/**
|
||||
* struct phylink_pcs_ops - MAC PCS operations structure.
|
||||
* @pcs_validate: validate the link configuration.
|
||||
+ * @pcs_inband_caps: query inband support for interface mode.
|
||||
* @pcs_enable: enable the PCS.
|
||||
* @pcs_disable: disable the PCS.
|
||||
* @pcs_pre_config: pre-mac_config method (for errata)
|
||||
@@ -434,6 +435,8 @@ struct phylink_pcs {
|
||||
struct phylink_pcs_ops {
|
||||
int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
|
||||
const struct phylink_link_state *state);
|
||||
+ unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface);
|
||||
int (*pcs_enable)(struct phylink_pcs *pcs);
|
||||
void (*pcs_disable)(struct phylink_pcs *pcs);
|
||||
void (*pcs_pre_config)(struct phylink_pcs *pcs,
|
||||
@@ -471,6 +474,20 @@ int pcs_validate(struct phylink_pcs *pcs
|
||||
const struct phylink_link_state *state);
|
||||
|
||||
/**
|
||||
+ * pcs_inband_caps - query PCS in-band capabilities for interface mode.
|
||||
+ * @pcs: a pointer to a &struct phylink_pcs.
|
||||
+ * @interface: interface mode to be queried
|
||||
+ *
|
||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
|
||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
|
||||
+ * returns a bit mask of the LINK_INBAND_* values from
|
||||
+ * &enum link_inband_signalling to describe which inband modes are supported
|
||||
+ * for this interface mode.
|
||||
+ */
|
||||
+unsigned int pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface);
|
||||
+
|
||||
+/**
|
||||
* pcs_enable() - enable the PCS.
|
||||
* @pcs: a pointer to a &struct phylink_pcs.
|
||||
*/
|
||||
@ -0,0 +1,64 @@
|
||||
From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:33 +0000
|
||||
Subject: [PATCH 10/13] net: mvneta: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for Marvell NETA
|
||||
interfaces.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++----------
|
||||
1 file changed, 17 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -3960,20 +3960,27 @@ static struct mvneta_port *mvneta_pcs_to
|
||||
return container_of(pcs, struct mvneta_port, phylink_pcs);
|
||||
}
|
||||
|
||||
-static int mvneta_pcs_validate(struct phylink_pcs *pcs,
|
||||
- unsigned long *supported,
|
||||
- const struct phylink_link_state *state)
|
||||
+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
{
|
||||
- /* We only support QSGMII, SGMII, 802.3z and RGMII modes.
|
||||
- * When in 802.3z mode, we must have AN enabled:
|
||||
+ /* When operating in an 802.3z mode, we must have AN enabled:
|
||||
* "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
|
||||
* When <PortType> = 1 (1000BASE-X) this field must be set to 1."
|
||||
+ * Therefore, inband is "required".
|
||||
*/
|
||||
- if (phy_interface_mode_is_8023z(state->interface) &&
|
||||
- !phylink_test(state->advertising, Autoneg))
|
||||
- return -EINVAL;
|
||||
+ if (phy_interface_mode_is_8023z(interface))
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
|
||||
- return 0;
|
||||
+ /* QSGMII, SGMII and RGMII can be configured to use inband
|
||||
+ * signalling of the AN result. Indicate these as "possible".
|
||||
+ */
|
||||
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
+ interface == PHY_INTERFACE_MODE_QSGMII ||
|
||||
+ phy_interface_mode_is_rgmii(interface))
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ /* For any other modes, indicate that inband is not supported. */
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
}
|
||||
|
||||
static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
|
||||
@@ -4071,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
|
||||
- .pcs_validate = mvneta_pcs_validate,
|
||||
+ .pcs_inband_caps = mvneta_pcs_inband_caps,
|
||||
.pcs_get_state = mvneta_pcs_get_state,
|
||||
.pcs_config = mvneta_pcs_config,
|
||||
.pcs_an_restart = mvneta_pcs_an_restart,
|
||||
@ -0,0 +1,62 @@
|
||||
From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:38 +0000
|
||||
Subject: [PATCH 11/13] net: mvpp2: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for Marvell PP2
|
||||
interfaces.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 ++++++++++++-------
|
||||
1 file changed, 16 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
||||
@@ -6237,19 +6237,26 @@ static const struct phylink_pcs_ops mvpp
|
||||
.pcs_config = mvpp2_xlg_pcs_config,
|
||||
};
|
||||
|
||||
-static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs,
|
||||
- unsigned long *supported,
|
||||
- const struct phylink_link_state *state)
|
||||
+static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
{
|
||||
- /* When in 802.3z mode, we must have AN enabled:
|
||||
+ /* When operating in an 802.3z mode, we must have AN enabled:
|
||||
* Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
|
||||
* When <PortType> = 1 (1000BASE-X) this field must be set to 1.
|
||||
+ * Therefore, inband is "required".
|
||||
*/
|
||||
- if (phy_interface_mode_is_8023z(state->interface) &&
|
||||
- !phylink_test(state->advertising, Autoneg))
|
||||
- return -EINVAL;
|
||||
+ if (phy_interface_mode_is_8023z(interface))
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
|
||||
- return 0;
|
||||
+ /* SGMII and RGMII can be configured to use inband signalling of the
|
||||
+ * AN result. Indicate these as "possible".
|
||||
+ */
|
||||
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
+ phy_interface_mode_is_rgmii(interface))
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ /* For any other modes, indicate that inband is not supported. */
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
}
|
||||
|
||||
static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
|
||||
@@ -6356,7 +6363,7 @@ static void mvpp2_gmac_pcs_an_restart(st
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = {
|
||||
- .pcs_validate = mvpp2_gmac_pcs_validate,
|
||||
+ .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps,
|
||||
.pcs_get_state = mvpp2_gmac_pcs_get_state,
|
||||
.pcs_config = mvpp2_gmac_pcs_config,
|
||||
.pcs_an_restart = mvpp2_gmac_pcs_an_restart,
|
||||
@ -0,0 +1,228 @@
|
||||
From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:43 +0000
|
||||
Subject: [PATCH 12/13] net: phylink: add negotiation of in-band capabilities
|
||||
|
||||
Support for in-band signalling with Serdes links is uncertain. Some
|
||||
PHYs do not support in-band for e.g. SGMII. Some PCS do not support
|
||||
in-band for 2500Base-X. Some PCS require in-band for Base-X protocols.
|
||||
|
||||
Simply using what is in DT is insufficient when we have hot-pluggable
|
||||
PHYs e.g. in the form of SFP modules, which may not provide the
|
||||
in-band signalling.
|
||||
|
||||
In order to address this, we have introduced phy_inband_caps() and
|
||||
pcs_inband_caps() functions to allow phylink to retrieve the
|
||||
capabilities from each end of the PCS/PHY link. This commit adds code
|
||||
to resolve whether in-band will be used in the various scenarios that
|
||||
we have: In-band not being used, PHY present using SGMII or Base-X,
|
||||
PHY not present. We also deal with no capabilties provided.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 154 +++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 144 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -75,6 +75,7 @@ struct phylink {
|
||||
|
||||
struct mutex state_mutex;
|
||||
struct phylink_link_state phy_state;
|
||||
+ unsigned int phy_ib_mode;
|
||||
struct work_struct resolve;
|
||||
unsigned int pcs_neg_mode;
|
||||
unsigned int pcs_state;
|
||||
@@ -1170,10 +1171,18 @@ static void phylink_pcs_neg_mode(struct
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising)
|
||||
{
|
||||
+ unsigned int pcs_ib_caps = 0;
|
||||
+ unsigned int phy_ib_caps = 0;
|
||||
unsigned int neg_mode, mode;
|
||||
+ enum {
|
||||
+ INBAND_CISCO_SGMII,
|
||||
+ INBAND_BASEX,
|
||||
+ } type;
|
||||
|
||||
mode = pl->req_link_an_mode;
|
||||
|
||||
+ pl->phy_ib_mode = 0;
|
||||
+
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
@@ -1185,10 +1194,7 @@ static void phylink_pcs_neg_mode(struct
|
||||
* inband communication. Note: there exist PHYs that run
|
||||
* with SGMII but do not send the inband data.
|
||||
*/
|
||||
- if (!phylink_autoneg_inband(mode))
|
||||
- neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
- else
|
||||
- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ type = INBAND_CISCO_SGMII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
@@ -1199,18 +1205,139 @@ static void phylink_pcs_neg_mode(struct
|
||||
* as well, but drivers may not support this, so may
|
||||
* need to override this.
|
||||
*/
|
||||
- if (!phylink_autoneg_inband(mode))
|
||||
+ type = INBAND_BASEX;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
+ pl->act_link_an_mode = mode;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pcs)
|
||||
+ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
|
||||
+
|
||||
+ if (pl->phydev)
|
||||
+ phy_ib_caps = phy_inband_caps(pl->phydev, interface);
|
||||
+
|
||||
+ phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n",
|
||||
+ phy_modes(interface), pcs_ib_caps, phy_ib_caps);
|
||||
+
|
||||
+ if (!phylink_autoneg_inband(mode)) {
|
||||
+ bool pcs_ib_only = false;
|
||||
+ bool phy_ib_only = false;
|
||||
+
|
||||
+ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) {
|
||||
+ /* PCS supports reporting in-band capabilities, and
|
||||
+ * supports more than disable mode.
|
||||
+ */
|
||||
+ if (pcs_ib_caps & LINK_INBAND_DISABLE)
|
||||
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ else if (pcs_ib_caps & LINK_INBAND_ENABLE)
|
||||
+ pcs_ib_only = true;
|
||||
+ }
|
||||
+
|
||||
+ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) {
|
||||
+ /* PHY supports in-band capabilities, and supports
|
||||
+ * more than disable mode.
|
||||
+ */
|
||||
+ if (phy_ib_caps & LINK_INBAND_DISABLE)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_DISABLE;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_BYPASS)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_BYPASS;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_ENABLE)
|
||||
+ phy_ib_only = true;
|
||||
+ }
|
||||
+
|
||||
+ /* If either the PCS or PHY requires inband to be enabled,
|
||||
+ * this is an invalid configuration. Provide a diagnostic
|
||||
+ * message for this case, but don't try to force the issue.
|
||||
+ */
|
||||
+ if (pcs_ib_only || phy_ib_only)
|
||||
+ phylink_warn(pl,
|
||||
+ "firmware wants %s mode, but %s%s%s requires inband\n",
|
||||
+ phylink_an_mode_str(mode),
|
||||
+ pcs_ib_only ? "PCS" : "",
|
||||
+ pcs_ib_only && phy_ib_only ? " and " : "",
|
||||
+ phy_ib_only ? "PHY" : "");
|
||||
+
|
||||
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ } else if (type == INBAND_CISCO_SGMII || pl->phydev) {
|
||||
+ /* For SGMII modes which are designed to be used with PHYs, or
|
||||
+ * Base-X with a PHY, we try to use in-band mode where-ever
|
||||
+ * possible. However, there are some PHYs e.g. BCM84881 which
|
||||
+ * do not support in-band.
|
||||
+ */
|
||||
+ const unsigned int inband_ok = LINK_INBAND_ENABLE |
|
||||
+ LINK_INBAND_BYPASS;
|
||||
+ const unsigned int outband_ok = LINK_INBAND_DISABLE |
|
||||
+ LINK_INBAND_BYPASS;
|
||||
+ /* PCS PHY
|
||||
+ * D E D E
|
||||
+ * 0 0 0 0 no information inband enabled
|
||||
+ * 1 0 0 0 pcs doesn't support outband
|
||||
+ * 0 1 0 0 pcs required inband enabled
|
||||
+ * 1 1 0 0 pcs optional inband enabled
|
||||
+ * 0 0 1 0 phy doesn't support outband
|
||||
+ * 1 0 1 0 pcs+phy doesn't support outband
|
||||
+ * 0 1 1 0 pcs required, phy doesn't support, invalid
|
||||
+ * 1 1 1 0 pcs optional, phy doesn't support, outband
|
||||
+ * 0 0 0 1 phy required inband enabled
|
||||
+ * 1 0 0 1 pcs doesn't support, phy required, invalid
|
||||
+ * 0 1 0 1 pcs+phy required inband enabled
|
||||
+ * 1 1 0 1 pcs optional, phy required inband enabled
|
||||
+ * 0 0 1 1 phy optional inband enabled
|
||||
+ * 1 0 1 1 pcs doesn't support, phy optional, outband
|
||||
+ * 0 1 1 1 pcs required, phy optional inband enabled
|
||||
+ * 1 1 1 1 pcs+phy optional inband enabled
|
||||
+ */
|
||||
+ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) &&
|
||||
+ (!phy_ib_caps || phy_ib_caps & inband_ok)) {
|
||||
+ /* In-band supported or unknown at both ends. Enable
|
||||
+ * in-band mode with or without bypass at the PHY.
|
||||
+ */
|
||||
+ if (phy_ib_caps & LINK_INBAND_ENABLE)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_ENABLE;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_BYPASS)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_BYPASS;
|
||||
+
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) &&
|
||||
+ (!phy_ib_caps || phy_ib_caps & outband_ok)) {
|
||||
+ /* Either in-band not supported at at least one end.
|
||||
+ * In-band bypass at the other end is possible.
|
||||
+ */
|
||||
+ if (phy_ib_caps & LINK_INBAND_DISABLE)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_DISABLE;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_BYPASS)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_BYPASS;
|
||||
+
|
||||
neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ if (pl->phydev)
|
||||
+ mode = MLO_AN_PHY;
|
||||
+ } else {
|
||||
+ /* invalid */
|
||||
+ phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band",
|
||||
+ phy_modes(interface));
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* For Base-X without a PHY */
|
||||
+ if (pcs_ib_caps == LINK_INBAND_DISABLE)
|
||||
+ /* If the PCS doesn't support inband, then inband must
|
||||
+ * be disabled.
|
||||
+ */
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
|
||||
+ else if (pcs_ib_caps == LINK_INBAND_ENABLE)
|
||||
+ /* If the PCS requires inband, then inband must always
|
||||
+ * be enabled.
|
||||
+ */
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
advertising))
|
||||
neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
else
|
||||
neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
- break;
|
||||
}
|
||||
|
||||
pl->pcs_neg_mode = neg_mode;
|
||||
@@ -1309,6 +1436,13 @@ static void phylink_major_config(struct
|
||||
ERR_PTR(err));
|
||||
}
|
||||
|
||||
+ if (pl->phydev && pl->phy_ib_mode) {
|
||||
+ err = phy_config_inband(pl->phydev, pl->phy_ib_mode);
|
||||
+ if (err < 0)
|
||||
+ phylink_err(pl, "phy_config_inband: %pe\n",
|
||||
+ ERR_PTR(err));
|
||||
+ }
|
||||
+
|
||||
if (pl->sfp_bus) {
|
||||
rate_kbd = phylink_interface_signal_rate(state->interface);
|
||||
if (rate_kbd)
|
||||
@ -0,0 +1,110 @@
|
||||
From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:48 +0000
|
||||
Subject: [PATCH 13/13] net: phylink: remove phylink_phy_no_inband()
|
||||
|
||||
Remove phylink_phy_no_inband() now that we are handling the lack of
|
||||
inband negotiation by querying the capabilities of the PHY and PCS,
|
||||
and the BCM84881 PHY driver provides us the information necessary to
|
||||
make the decision.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 27 ++++++---------------------
|
||||
1 file changed, 6 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -3394,10 +3394,11 @@ static phy_interface_t phylink_choose_sf
|
||||
return interface;
|
||||
}
|
||||
|
||||
-static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
|
||||
+static void phylink_sfp_set_config(struct phylink *pl,
|
||||
unsigned long *supported,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
+ u8 mode = MLO_AN_INBAND;
|
||||
bool changed = false;
|
||||
|
||||
phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
|
||||
@@ -3431,8 +3432,7 @@ static void phylink_sfp_set_config(struc
|
||||
phylink_mac_initial_config(pl, false);
|
||||
}
|
||||
|
||||
-static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
|
||||
- struct phy_device *phy)
|
||||
+static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy)
|
||||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
|
||||
@@ -3472,7 +3472,7 @@ static int phylink_sfp_config_phy(struct
|
||||
if (ret) {
|
||||
phylink_err(pl,
|
||||
"validation of %s/%s with support %*pb failed: %pe\n",
|
||||
- phylink_an_mode_str(mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(config.interface),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, support,
|
||||
ERR_PTR(ret));
|
||||
@@ -3481,7 +3481,7 @@ static int phylink_sfp_config_phy(struct
|
||||
|
||||
pl->link_port = pl->sfp_port;
|
||||
|
||||
- phylink_sfp_set_config(pl, mode, support, &config);
|
||||
+ phylink_sfp_set_config(pl, support, &config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3556,7 +3556,7 @@ static int phylink_sfp_config_optical(st
|
||||
|
||||
pl->link_port = pl->sfp_port;
|
||||
|
||||
- phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config);
|
||||
+ phylink_sfp_set_config(pl, pl->sfp_support, &config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3627,20 +3627,10 @@ static void phylink_sfp_link_up(void *up
|
||||
phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK);
|
||||
}
|
||||
|
||||
-/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
|
||||
- * or 802.3z control word, so inband will not work.
|
||||
- */
|
||||
-static bool phylink_phy_no_inband(struct phy_device *phy)
|
||||
-{
|
||||
- return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
|
||||
- 0xae025150, 0xfffffff0);
|
||||
-}
|
||||
-
|
||||
static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
|
||||
{
|
||||
struct phylink *pl = upstream;
|
||||
phy_interface_t interface;
|
||||
- u8 mode;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -3652,17 +3642,12 @@ static int phylink_sfp_connect_phy(void
|
||||
*/
|
||||
phy_support_asym_pause(phy);
|
||||
|
||||
- if (phylink_phy_no_inband(phy))
|
||||
- mode = MLO_AN_PHY;
|
||||
- else
|
||||
- mode = MLO_AN_INBAND;
|
||||
-
|
||||
/* Set the PHY's host supported interfaces */
|
||||
phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
|
||||
pl->config->supported_interfaces);
|
||||
|
||||
/* Do the initial configuration */
|
||||
- ret = phylink_sfp_config_phy(pl, mode, phy);
|
||||
+ ret = phylink_sfp_config_phy(pl, phy);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 5 Dec 2024 09:42:24 +0000
|
||||
Subject: [PATCH 1/3] net: pcs: pcs-lynx: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for the Lynx PCS.
|
||||
|
||||
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-lynx.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-lynx.c
|
||||
+++ b/drivers/net/pcs/pcs-lynx.c
|
||||
@@ -35,6 +35,27 @@ enum sgmii_speed {
|
||||
#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
|
||||
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
|
||||
|
||||
+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ case PHY_INTERFACE_MODE_QSGMII:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ case PHY_INTERFACE_MODE_10GBASER:
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
+
|
||||
+ case PHY_INTERFACE_MODE_USXGMII:
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
@@ -306,6 +327,7 @@ static void lynx_pcs_link_up(struct phyl
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
|
||||
+ .pcs_inband_caps = lynx_pcs_inband_caps,
|
||||
.pcs_get_state = lynx_pcs_get_state,
|
||||
.pcs_config = lynx_pcs_config,
|
||||
.pcs_an_restart = lynx_pcs_an_restart,
|
||||
@ -0,0 +1,47 @@
|
||||
From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 5 Dec 2024 09:42:29 +0000
|
||||
Subject: [PATCH 2/3] net: pcs: pcs-mtk-lynxi: implement pcs_inband_caps()
|
||||
method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for the LynxI PCS.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
@@ -88,6 +88,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_
|
||||
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
|
||||
}
|
||||
|
||||
+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ case PHY_INTERFACE_MODE_QSGMII:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
@@ -241,6 +256,7 @@ static void mtk_pcs_lynxi_disable(struct
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
|
||||
+ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps,
|
||||
.pcs_get_state = mtk_pcs_lynxi_get_state,
|
||||
.pcs_config = mtk_pcs_lynxi_config,
|
||||
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
|
||||
@ -0,0 +1,58 @@
|
||||
From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 5 Dec 2024 09:42:34 +0000
|
||||
Subject: [PATCH 3/3] net: pcs: xpcs: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS inband capabilities to phylink for XPCS.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-xpcs.c
|
||||
+++ b/drivers/net/pcs/pcs-xpcs.c
|
||||
@@ -608,6 +608,33 @@ static int xpcs_validate(struct phylink_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
|
||||
+ const struct dw_xpcs_compat *compat;
|
||||
+
|
||||
+ compat = xpcs_find_compat(xpcs->desc, interface);
|
||||
+ if (!compat)
|
||||
+ return 0;
|
||||
+
|
||||
+ switch (compat->an_mode) {
|
||||
+ case DW_AN_C73:
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ case DW_AN_C37_SGMII:
|
||||
+ case DW_AN_C37_1000BASEX:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ case DW_10GBASER:
|
||||
+ case DW_2500BASEX:
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
|
||||
{
|
||||
int i, j;
|
||||
@@ -1365,6 +1392,7 @@ static const struct dw_xpcs_desc xpcs_de
|
||||
|
||||
static const struct phylink_pcs_ops xpcs_phylink_ops = {
|
||||
.pcs_validate = xpcs_validate,
|
||||
+ .pcs_inband_caps = xpcs_inband_caps,
|
||||
.pcs_config = xpcs_config,
|
||||
.pcs_get_state = xpcs_get_state,
|
||||
.pcs_an_restart = xpcs_an_restart,
|
||||
@ -194,7 +194,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
{ PHY_ID_BCM72165, 0xfffffff0, },
|
||||
--- a/drivers/net/phy/bcm84881.c
|
||||
+++ b/drivers/net/phy/bcm84881.c
|
||||
@@ -252,7 +252,7 @@ static struct phy_driver bcm84881_driver
|
||||
@@ -262,7 +262,7 @@ static struct phy_driver bcm84881_driver
|
||||
module_phy_driver(bcm84881_drivers);
|
||||
|
||||
/* FIXME: module auto-loading for Clause 45 PHYs seems non-functional */
|
||||
@ -403,7 +403,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
};
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -4133,7 +4133,7 @@ static struct phy_driver marvell_drivers
|
||||
@@ -4181,7 +4181,7 @@ static struct phy_driver marvell_drivers
|
||||
|
||||
module_phy_driver(marvell_drivers);
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
if (!phydev->drv->led_polarity_set)
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -874,8 +874,9 @@ struct phy_plca_status {
|
||||
@@ -892,8 +892,9 @@ struct phy_plca_status {
|
||||
|
||||
/* Modes for PHY LED configuration */
|
||||
enum phy_led_modes {
|
||||
|
||||
@ -281,7 +281,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
}
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1004,7 +1004,8 @@ struct phy_driver {
|
||||
@@ -1035,7 +1035,8 @@ struct phy_driver {
|
||||
* driver for the given phydev. If NULL, matching is based on
|
||||
* phy_id and phy_id_mask.
|
||||
*/
|
||||
|
||||
@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
static ssize_t
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1906,6 +1906,9 @@ char *phy_attached_info_irq(struct phy_d
|
||||
@@ -1940,6 +1940,9 @@ char *phy_attached_info_irq(struct phy_d
|
||||
__malloc;
|
||||
void phy_attached_info(struct phy_device *phydev);
|
||||
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
From 8cc5f4cb94c0b1c7c1ba8013c14fd02ffb1a25f3 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:01:44 +0000
|
||||
Subject: [PATCH 1/5] net: phylink: move manual flow control setting
|
||||
|
||||
Move the handling of manual flow control configuration to a common
|
||||
location during resolve. We currently evaluate this for all but
|
||||
fixed links.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQe-002Feh-T1@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1433,7 +1433,6 @@ static void phylink_resolve(struct work_
|
||||
switch (pl->cur_link_an_mode) {
|
||||
case MLO_AN_PHY:
|
||||
link_state = pl->phy_state;
|
||||
- phylink_apply_manual_flow(pl, &link_state);
|
||||
mac_config = link_state.link;
|
||||
break;
|
||||
|
||||
@@ -1494,11 +1493,13 @@ static void phylink_resolve(struct work_
|
||||
link_state.pause = pl->phy_state.pause;
|
||||
mac_config = true;
|
||||
}
|
||||
- phylink_apply_manual_flow(pl, &link_state);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
+ if (pl->cur_link_an_mode != MLO_AN_FIXED)
|
||||
+ phylink_apply_manual_flow(pl, &link_state);
|
||||
+
|
||||
if (mac_config) {
|
||||
if (link_state.interface != pl->link_config.interface) {
|
||||
/* The interface has changed, force the link down and
|
||||
@ -0,0 +1,42 @@
|
||||
From 92abfcb4ced482afbe65d18980e6734fe1e62a34 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:01:50 +0000
|
||||
Subject: [PATCH 2/5] net: phylink: move MLO_AN_FIXED resolve handling to if()
|
||||
statement
|
||||
|
||||
The switch() statement doesn't sit very well with the preceeding if()
|
||||
statements, and results in excessive indentation that spoils code
|
||||
readability. Begin cleaning this up by converting the MLO_AN_FIXED case
|
||||
to an if() statement.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQk-002Fen-1A@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1429,6 +1429,9 @@ static void phylink_resolve(struct work_
|
||||
} else if (pl->mac_link_dropped) {
|
||||
link_state.link = false;
|
||||
retrigger = true;
|
||||
+ } else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ phylink_get_fixed_state(pl, &link_state);
|
||||
+ mac_config = link_state.link;
|
||||
} else {
|
||||
switch (pl->cur_link_an_mode) {
|
||||
case MLO_AN_PHY:
|
||||
@@ -1436,11 +1439,6 @@ static void phylink_resolve(struct work_
|
||||
mac_config = link_state.link;
|
||||
break;
|
||||
|
||||
- case MLO_AN_FIXED:
|
||||
- phylink_get_fixed_state(pl, &link_state);
|
||||
- mac_config = link_state.link;
|
||||
- break;
|
||||
-
|
||||
case MLO_AN_INBAND:
|
||||
phylink_mac_pcs_get_state(pl, &link_state);
|
||||
|
||||
@ -0,0 +1,37 @@
|
||||
From f0f46c2a3d8ea9d1427298c8103a777d9e616c29 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:01:55 +0000
|
||||
Subject: [PATCH 3/5] net: phylink: move MLO_AN_PHY resolve handling to if()
|
||||
statement
|
||||
|
||||
The switch() statement doesn't sit very well with the preceeding if()
|
||||
statements, and results in excessive indentation that spoils code
|
||||
readability. Continue cleaning this up by converting the MLO_AN_PHY
|
||||
case to use an if() statmeent.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQp-002Fet-5W@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 8 +++-----
|
||||
1 file changed, 3 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1432,13 +1432,11 @@ static void phylink_resolve(struct work_
|
||||
} else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
phylink_get_fixed_state(pl, &link_state);
|
||||
mac_config = link_state.link;
|
||||
+ } else if (pl->cur_link_an_mode == MLO_AN_PHY) {
|
||||
+ link_state = pl->phy_state;
|
||||
+ mac_config = link_state.link;
|
||||
} else {
|
||||
switch (pl->cur_link_an_mode) {
|
||||
- case MLO_AN_PHY:
|
||||
- link_state = pl->phy_state;
|
||||
- mac_config = link_state.link;
|
||||
- break;
|
||||
-
|
||||
case MLO_AN_INBAND:
|
||||
phylink_mac_pcs_get_state(pl, &link_state);
|
||||
|
||||
@ -0,0 +1,127 @@
|
||||
From d1a16dbbd84e02d2a6dcfcb8d5c4b8b2c0289f00 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:02:00 +0000
|
||||
Subject: [PATCH 4/5] net: phylink: remove switch() statement in resolve
|
||||
handling
|
||||
|
||||
The switch() statement doesn't sit very well with the preceeding if()
|
||||
statements, so let's just convert everything to if()s. As a result of
|
||||
the two preceding commits, there is now only one case in the switch()
|
||||
statement. Remove the switch statement and reduce the code indentation.
|
||||
Code reformatting will be in the following commit.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQu-002Fez-AA@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 94 +++++++++++++++++++--------------------
|
||||
1 file changed, 45 insertions(+), 49 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1436,60 +1436,56 @@ static void phylink_resolve(struct work_
|
||||
link_state = pl->phy_state;
|
||||
mac_config = link_state.link;
|
||||
} else {
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
- case MLO_AN_INBAND:
|
||||
- phylink_mac_pcs_get_state(pl, &link_state);
|
||||
-
|
||||
- /* The PCS may have a latching link-fail indicator.
|
||||
- * If the link was up, bring the link down and
|
||||
- * re-trigger the resolve. Otherwise, re-read the
|
||||
- * PCS state to get the current status of the link.
|
||||
+ phylink_mac_pcs_get_state(pl, &link_state);
|
||||
+
|
||||
+ /* The PCS may have a latching link-fail indicator.
|
||||
+ * If the link was up, bring the link down and
|
||||
+ * re-trigger the resolve. Otherwise, re-read the
|
||||
+ * PCS state to get the current status of the link.
|
||||
+ */
|
||||
+ if (!link_state.link) {
|
||||
+ if (cur_link_state)
|
||||
+ retrigger = true;
|
||||
+ else
|
||||
+ phylink_mac_pcs_get_state(pl,
|
||||
+ &link_state);
|
||||
+ }
|
||||
+
|
||||
+ /* If we have a phy, the "up" state is the union of
|
||||
+ * both the PHY and the MAC
|
||||
+ */
|
||||
+ if (pl->phydev)
|
||||
+ link_state.link &= pl->phy_state.link;
|
||||
+
|
||||
+ /* Only update if the PHY link is up */
|
||||
+ if (pl->phydev && pl->phy_state.link) {
|
||||
+ /* If the interface has changed, force a
|
||||
+ * link down event if the link isn't already
|
||||
+ * down, and re-resolve.
|
||||
*/
|
||||
- if (!link_state.link) {
|
||||
- if (cur_link_state)
|
||||
- retrigger = true;
|
||||
- else
|
||||
- phylink_mac_pcs_get_state(pl,
|
||||
- &link_state);
|
||||
+ if (link_state.interface !=
|
||||
+ pl->phy_state.interface) {
|
||||
+ retrigger = true;
|
||||
+ link_state.link = false;
|
||||
}
|
||||
+ link_state.interface = pl->phy_state.interface;
|
||||
|
||||
- /* If we have a phy, the "up" state is the union of
|
||||
- * both the PHY and the MAC
|
||||
+ /* If we are doing rate matching, then the
|
||||
+ * link speed/duplex comes from the PHY
|
||||
*/
|
||||
- if (pl->phydev)
|
||||
- link_state.link &= pl->phy_state.link;
|
||||
-
|
||||
- /* Only update if the PHY link is up */
|
||||
- if (pl->phydev && pl->phy_state.link) {
|
||||
- /* If the interface has changed, force a
|
||||
- * link down event if the link isn't already
|
||||
- * down, and re-resolve.
|
||||
- */
|
||||
- if (link_state.interface !=
|
||||
- pl->phy_state.interface) {
|
||||
- retrigger = true;
|
||||
- link_state.link = false;
|
||||
- }
|
||||
- link_state.interface = pl->phy_state.interface;
|
||||
-
|
||||
- /* If we are doing rate matching, then the
|
||||
- * link speed/duplex comes from the PHY
|
||||
- */
|
||||
- if (pl->phy_state.rate_matching) {
|
||||
- link_state.rate_matching =
|
||||
- pl->phy_state.rate_matching;
|
||||
- link_state.speed = pl->phy_state.speed;
|
||||
- link_state.duplex =
|
||||
- pl->phy_state.duplex;
|
||||
- }
|
||||
-
|
||||
- /* If we have a PHY, we need to update with
|
||||
- * the PHY flow control bits.
|
||||
- */
|
||||
- link_state.pause = pl->phy_state.pause;
|
||||
- mac_config = true;
|
||||
+ if (pl->phy_state.rate_matching) {
|
||||
+ link_state.rate_matching =
|
||||
+ pl->phy_state.rate_matching;
|
||||
+ link_state.speed = pl->phy_state.speed;
|
||||
+ link_state.duplex =
|
||||
+ pl->phy_state.duplex;
|
||||
}
|
||||
- break;
|
||||
+
|
||||
+ /* If we have a PHY, we need to update with
|
||||
+ * the PHY flow control bits.
|
||||
+ */
|
||||
+ link_state.pause = pl->phy_state.pause;
|
||||
+ mac_config = true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,85 @@
|
||||
From bc08ce37d99a3992e975a0f397503cb23404f25a Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Fri, 8 Nov 2024 16:02:05 +0000
|
||||
Subject: [PATCH 5/5] net: phylink: clean up phylink_resolve()
|
||||
|
||||
Now that we have reduced the indentation level, clean up the code
|
||||
formatting.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1t9RQz-002Ff5-EA@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 35 ++++++++++++++++-------------------
|
||||
1 file changed, 16 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1438,51 +1438,48 @@ static void phylink_resolve(struct work_
|
||||
} else {
|
||||
phylink_mac_pcs_get_state(pl, &link_state);
|
||||
|
||||
- /* The PCS may have a latching link-fail indicator.
|
||||
- * If the link was up, bring the link down and
|
||||
- * re-trigger the resolve. Otherwise, re-read the
|
||||
- * PCS state to get the current status of the link.
|
||||
+ /* The PCS may have a latching link-fail indicator. If the link
|
||||
+ * was up, bring the link down and re-trigger the resolve.
|
||||
+ * Otherwise, re-read the PCS state to get the current status
|
||||
+ * of the link.
|
||||
*/
|
||||
if (!link_state.link) {
|
||||
if (cur_link_state)
|
||||
retrigger = true;
|
||||
else
|
||||
- phylink_mac_pcs_get_state(pl,
|
||||
- &link_state);
|
||||
+ phylink_mac_pcs_get_state(pl, &link_state);
|
||||
}
|
||||
|
||||
- /* If we have a phy, the "up" state is the union of
|
||||
- * both the PHY and the MAC
|
||||
+ /* If we have a phy, the "up" state is the union of both the
|
||||
+ * PHY and the MAC
|
||||
*/
|
||||
if (pl->phydev)
|
||||
link_state.link &= pl->phy_state.link;
|
||||
|
||||
/* Only update if the PHY link is up */
|
||||
if (pl->phydev && pl->phy_state.link) {
|
||||
- /* If the interface has changed, force a
|
||||
- * link down event if the link isn't already
|
||||
- * down, and re-resolve.
|
||||
+ /* If the interface has changed, force a link down
|
||||
+ * event if the link isn't already down, and re-resolve.
|
||||
*/
|
||||
- if (link_state.interface !=
|
||||
- pl->phy_state.interface) {
|
||||
+ if (link_state.interface != pl->phy_state.interface) {
|
||||
retrigger = true;
|
||||
link_state.link = false;
|
||||
}
|
||||
+
|
||||
link_state.interface = pl->phy_state.interface;
|
||||
|
||||
- /* If we are doing rate matching, then the
|
||||
- * link speed/duplex comes from the PHY
|
||||
+ /* If we are doing rate matching, then the link
|
||||
+ * speed/duplex comes from the PHY
|
||||
*/
|
||||
if (pl->phy_state.rate_matching) {
|
||||
link_state.rate_matching =
|
||||
pl->phy_state.rate_matching;
|
||||
link_state.speed = pl->phy_state.speed;
|
||||
- link_state.duplex =
|
||||
- pl->phy_state.duplex;
|
||||
+ link_state.duplex = pl->phy_state.duplex;
|
||||
}
|
||||
|
||||
- /* If we have a PHY, we need to update with
|
||||
- * the PHY flow control bits.
|
||||
+ /* If we have a PHY, we need to update with the PHY
|
||||
+ * flow control bits.
|
||||
*/
|
||||
link_state.pause = pl->phy_state.pause;
|
||||
mac_config = true;
|
||||
@ -0,0 +1,166 @@
|
||||
From 5e5401d6612ef599ad45785b941eebda7effc90f Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 4 Jan 2024 09:47:36 +0000
|
||||
Subject: [PATCH] net: phylink: move phylink_pcs_neg_mode() into phylink.c
|
||||
|
||||
Move phylink_pcs_neg_mode() from the header file into the .c file since
|
||||
nothing should be using it.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 66 +++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/phylink.h | 66 ---------------------------------------
|
||||
2 files changed, 66 insertions(+), 66 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1116,6 +1116,72 @@ static void phylink_pcs_an_restart(struc
|
||||
pl->pcs->ops->pcs_an_restart(pl->pcs);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * phylink_pcs_neg_mode() - helper to determine PCS inband mode
|
||||
+ * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
|
||||
+ * @interface: interface mode to be used
|
||||
+ * @advertising: adertisement ethtool link mode mask
|
||||
+ *
|
||||
+ * Determines the negotiation mode to be used by the PCS, and returns
|
||||
+ * one of:
|
||||
+ *
|
||||
+ * - %PHYLINK_PCS_NEG_NONE: interface mode does not support inband
|
||||
+ * - %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY)
|
||||
+ * will be used.
|
||||
+ * - %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg
|
||||
+ * disabled
|
||||
+ * - %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled
|
||||
+ *
|
||||
+ * Note: this is for cases where the PCS itself is involved in negotiation
|
||||
+ * (e.g. Clause 37, SGMII and similar) not Clause 73.
|
||||
+ */
|
||||
+static unsigned int phylink_pcs_neg_mode(unsigned int mode,
|
||||
+ phy_interface_t interface,
|
||||
+ const unsigned long *advertising)
|
||||
+{
|
||||
+ unsigned int neg_mode;
|
||||
+
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ case PHY_INTERFACE_MODE_QSGMII:
|
||||
+ case PHY_INTERFACE_MODE_QUSGMII:
|
||||
+ case PHY_INTERFACE_MODE_USXGMII:
|
||||
+ /* These protocols are designed for use with a PHY which
|
||||
+ * communicates its negotiation result back to the MAC via
|
||||
+ * inband communication. Note: there exist PHYs that run
|
||||
+ * with SGMII but do not send the inband data.
|
||||
+ */
|
||||
+ if (!phylink_autoneg_inband(mode))
|
||||
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ else
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ break;
|
||||
+
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ /* 1000base-X is designed for use media-side for Fibre
|
||||
+ * connections, and thus the Autoneg bit needs to be
|
||||
+ * taken into account. We also do this for 2500base-X
|
||||
+ * as well, but drivers may not support this, so may
|
||||
+ * need to override this.
|
||||
+ */
|
||||
+ if (!phylink_autoneg_inband(mode))
|
||||
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
+ advertising))
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ else
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return neg_mode;
|
||||
+}
|
||||
+
|
||||
static void phylink_major_config(struct phylink *pl, bool restart,
|
||||
const struct phylink_link_state *state)
|
||||
{
|
||||
--- a/include/linux/phylink.h
|
||||
+++ b/include/linux/phylink.h
|
||||
@@ -99,72 +99,6 @@ static inline bool phylink_autoneg_inban
|
||||
}
|
||||
|
||||
/**
|
||||
- * phylink_pcs_neg_mode() - helper to determine PCS inband mode
|
||||
- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
|
||||
- * @interface: interface mode to be used
|
||||
- * @advertising: adertisement ethtool link mode mask
|
||||
- *
|
||||
- * Determines the negotiation mode to be used by the PCS, and returns
|
||||
- * one of:
|
||||
- *
|
||||
- * - %PHYLINK_PCS_NEG_NONE: interface mode does not support inband
|
||||
- * - %PHYLINK_PCS_NEG_OUTBAND: an out of band mode (e.g. reading the PHY)
|
||||
- * will be used.
|
||||
- * - %PHYLINK_PCS_NEG_INBAND_DISABLED: inband mode selected but autoneg
|
||||
- * disabled
|
||||
- * - %PHYLINK_PCS_NEG_INBAND_ENABLED: inband mode selected and autoneg enabled
|
||||
- *
|
||||
- * Note: this is for cases where the PCS itself is involved in negotiation
|
||||
- * (e.g. Clause 37, SGMII and similar) not Clause 73.
|
||||
- */
|
||||
-static inline unsigned int phylink_pcs_neg_mode(unsigned int mode,
|
||||
- phy_interface_t interface,
|
||||
- const unsigned long *advertising)
|
||||
-{
|
||||
- unsigned int neg_mode;
|
||||
-
|
||||
- switch (interface) {
|
||||
- case PHY_INTERFACE_MODE_SGMII:
|
||||
- case PHY_INTERFACE_MODE_QSGMII:
|
||||
- case PHY_INTERFACE_MODE_QUSGMII:
|
||||
- case PHY_INTERFACE_MODE_USXGMII:
|
||||
- /* These protocols are designed for use with a PHY which
|
||||
- * communicates its negotiation result back to the MAC via
|
||||
- * inband communication. Note: there exist PHYs that run
|
||||
- * with SGMII but do not send the inband data.
|
||||
- */
|
||||
- if (!phylink_autoneg_inband(mode))
|
||||
- neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
- else
|
||||
- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
- break;
|
||||
-
|
||||
- case PHY_INTERFACE_MODE_1000BASEX:
|
||||
- case PHY_INTERFACE_MODE_2500BASEX:
|
||||
- /* 1000base-X is designed for use media-side for Fibre
|
||||
- * connections, and thus the Autoneg bit needs to be
|
||||
- * taken into account. We also do this for 2500base-X
|
||||
- * as well, but drivers may not support this, so may
|
||||
- * need to override this.
|
||||
- */
|
||||
- if (!phylink_autoneg_inband(mode))
|
||||
- neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
- else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
- advertising))
|
||||
- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
- else
|
||||
- neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
- break;
|
||||
- }
|
||||
-
|
||||
- return neg_mode;
|
||||
-}
|
||||
-
|
||||
-/**
|
||||
* struct phylink_link_state - link state structure
|
||||
* @advertising: ethtool bitmask containing advertised link modes
|
||||
* @lp_advertising: ethtool bitmask containing link partner advertised link
|
||||
@ -0,0 +1,95 @@
|
||||
From 17ed1911f9c8d4f9af8e13b2c95103ee06dadc0f Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:30:47 +0000
|
||||
Subject: [PATCH 01/13] net: phylink: pass phylink and pcs into
|
||||
phylink_pcs_neg_mode()
|
||||
|
||||
Move the call to phylink_pcs_neg_mode() in phylink_major_config() after
|
||||
we have selected the appropriate PCS to allow the PCS to be passed in.
|
||||
|
||||
Add struct phylink and struct phylink_pcs pointers to
|
||||
phylink_pcs_neg_mode() and pass in the appropriate structures. Set
|
||||
pl->pcs_neg_mode before returning, and remove the return value.
|
||||
|
||||
This will allow the capabilities of the PCS and any PHY to be used when
|
||||
deciding which pcs_neg_mode should be used.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrP-006ITh-6u@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 26 +++++++++++++-------------
|
||||
1 file changed, 13 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1118,7 +1118,8 @@ static void phylink_pcs_an_restart(struc
|
||||
|
||||
/**
|
||||
* phylink_pcs_neg_mode() - helper to determine PCS inband mode
|
||||
- * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
|
||||
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
+ * @pcs: a pointer to &struct phylink_pcs
|
||||
* @interface: interface mode to be used
|
||||
* @advertising: adertisement ethtool link mode mask
|
||||
*
|
||||
@@ -1135,11 +1136,13 @@ static void phylink_pcs_an_restart(struc
|
||||
* Note: this is for cases where the PCS itself is involved in negotiation
|
||||
* (e.g. Clause 37, SGMII and similar) not Clause 73.
|
||||
*/
|
||||
-static unsigned int phylink_pcs_neg_mode(unsigned int mode,
|
||||
- phy_interface_t interface,
|
||||
- const unsigned long *advertising)
|
||||
+static void phylink_pcs_neg_mode(struct phylink *pl, struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface,
|
||||
+ const unsigned long *advertising)
|
||||
{
|
||||
- unsigned int neg_mode;
|
||||
+ unsigned int neg_mode, mode;
|
||||
+
|
||||
+ mode = pl->cur_link_an_mode;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
@@ -1179,7 +1182,7 @@ static unsigned int phylink_pcs_neg_mode
|
||||
break;
|
||||
}
|
||||
|
||||
- return neg_mode;
|
||||
+ pl->pcs_neg_mode = neg_mode;
|
||||
}
|
||||
|
||||
static void phylink_major_config(struct phylink *pl, bool restart,
|
||||
@@ -1193,10 +1196,6 @@ static void phylink_major_config(struct
|
||||
|
||||
phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
|
||||
|
||||
- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
|
||||
- state->interface,
|
||||
- state->advertising);
|
||||
-
|
||||
if (pl->using_mac_select_pcs) {
|
||||
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
|
||||
if (IS_ERR(pcs)) {
|
||||
@@ -1209,6 +1208,8 @@ static void phylink_major_config(struct
|
||||
pcs_changed = pcs && pl->pcs != pcs;
|
||||
}
|
||||
|
||||
+ phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
|
||||
+
|
||||
phylink_pcs_poll_stop(pl);
|
||||
|
||||
if (pl->mac_ops->mac_prepare) {
|
||||
@@ -1299,9 +1300,8 @@ static int phylink_change_inband_advert(
|
||||
pl->link_config.pause);
|
||||
|
||||
/* Recompute the PCS neg mode */
|
||||
- pl->pcs_neg_mode = phylink_pcs_neg_mode(pl->cur_link_an_mode,
|
||||
- pl->link_config.interface,
|
||||
- pl->link_config.advertising);
|
||||
+ phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
|
||||
+ pl->link_config.advertising);
|
||||
|
||||
neg_mode = pl->cur_link_an_mode;
|
||||
if (pl->pcs->neg_mode)
|
||||
@ -0,0 +1,281 @@
|
||||
From 1f92ead7e15003f632b5f138e8138095e0997d3d Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:30:52 +0000
|
||||
Subject: [PATCH 02/13] net: phylink: split cur_link_an_mode into requested and
|
||||
active
|
||||
|
||||
There is an interdependence between the current link_an_mode and
|
||||
pcs_neg_mode that some drivers rely upon to know whether inband or PHY
|
||||
mode will be used.
|
||||
|
||||
In order to support detection of PCS and PHY inband capabilities
|
||||
resulting in automatic selection of inband or PHY mode, we need to
|
||||
cater for this, and support changing the MAC link_an_mode. However, we
|
||||
end up with an inter-dependency between the current link_an_mode and
|
||||
pcs_neg_mode.
|
||||
|
||||
To solve this, split the current link_an_mode into the requested
|
||||
link_an_mode and active link_an_mode. The requested link_an_mode will
|
||||
always be passed to phylink_pcs_neg_mode(), and the active link_an_mode
|
||||
will be used for everything else, and only updated during
|
||||
phylink_major_config(). This will ensure that phylink_pcs_neg_mode()'s
|
||||
link_an_mode will not depend on the active link_an_mode that will,
|
||||
in a future patch, depend on pcs_neg_mode.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrU-006ITn-Ai@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 60 ++++++++++++++++++++-------------------
|
||||
1 file changed, 31 insertions(+), 29 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -56,7 +56,8 @@ struct phylink {
|
||||
struct phy_device *phydev;
|
||||
phy_interface_t link_interface; /* PHY_INTERFACE_xxx */
|
||||
u8 cfg_link_an_mode; /* MLO_AN_xxx */
|
||||
- u8 cur_link_an_mode;
|
||||
+ u8 req_link_an_mode; /* Requested MLO_AN_xxx mode */
|
||||
+ u8 act_link_an_mode; /* Active MLO_AN_xxx mode */
|
||||
u8 link_port; /* The current non-phy ethtool port */
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
|
||||
|
||||
@@ -1098,13 +1099,13 @@ static void phylink_mac_config(struct ph
|
||||
|
||||
phylink_dbg(pl,
|
||||
"%s: mode=%s/%s/%s adv=%*pb pause=%02x\n",
|
||||
- __func__, phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ __func__, phylink_an_mode_str(pl->act_link_an_mode),
|
||||
phy_modes(st.interface),
|
||||
phy_rate_matching_to_str(st.rate_matching),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, st.advertising,
|
||||
st.pause);
|
||||
|
||||
- pl->mac_ops->mac_config(pl->config, pl->cur_link_an_mode, &st);
|
||||
+ pl->mac_ops->mac_config(pl->config, pl->act_link_an_mode, &st);
|
||||
}
|
||||
|
||||
static void phylink_pcs_an_restart(struct phylink *pl)
|
||||
@@ -1112,7 +1113,7 @@ static void phylink_pcs_an_restart(struc
|
||||
if (pl->pcs && linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
pl->link_config.advertising) &&
|
||||
phy_interface_mode_is_8023z(pl->link_config.interface) &&
|
||||
- phylink_autoneg_inband(pl->cur_link_an_mode))
|
||||
+ phylink_autoneg_inband(pl->act_link_an_mode))
|
||||
pl->pcs->ops->pcs_an_restart(pl->pcs);
|
||||
}
|
||||
|
||||
@@ -1142,7 +1143,7 @@ static void phylink_pcs_neg_mode(struct
|
||||
{
|
||||
unsigned int neg_mode, mode;
|
||||
|
||||
- mode = pl->cur_link_an_mode;
|
||||
+ mode = pl->req_link_an_mode;
|
||||
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
@@ -1183,6 +1184,7 @@ static void phylink_pcs_neg_mode(struct
|
||||
}
|
||||
|
||||
pl->pcs_neg_mode = neg_mode;
|
||||
+ pl->act_link_an_mode = mode;
|
||||
}
|
||||
|
||||
static void phylink_major_config(struct phylink *pl, bool restart,
|
||||
@@ -1213,7 +1215,7 @@ static void phylink_major_config(struct
|
||||
phylink_pcs_poll_stop(pl);
|
||||
|
||||
if (pl->mac_ops->mac_prepare) {
|
||||
- err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
|
||||
+ err = pl->mac_ops->mac_prepare(pl->config, pl->act_link_an_mode,
|
||||
state->interface);
|
||||
if (err < 0) {
|
||||
phylink_err(pl, "mac_prepare failed: %pe\n",
|
||||
@@ -1247,7 +1249,7 @@ static void phylink_major_config(struct
|
||||
if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
|
||||
phylink_pcs_enable(pl->pcs);
|
||||
|
||||
- neg_mode = pl->cur_link_an_mode;
|
||||
+ neg_mode = pl->act_link_an_mode;
|
||||
if (pl->pcs && pl->pcs->neg_mode)
|
||||
neg_mode = pl->pcs_neg_mode;
|
||||
|
||||
@@ -1263,7 +1265,7 @@ static void phylink_major_config(struct
|
||||
phylink_pcs_an_restart(pl);
|
||||
|
||||
if (pl->mac_ops->mac_finish) {
|
||||
- err = pl->mac_ops->mac_finish(pl->config, pl->cur_link_an_mode,
|
||||
+ err = pl->mac_ops->mac_finish(pl->config, pl->act_link_an_mode,
|
||||
state->interface);
|
||||
if (err < 0)
|
||||
phylink_err(pl, "mac_finish failed: %pe\n",
|
||||
@@ -1294,7 +1296,7 @@ static int phylink_change_inband_advert(
|
||||
return 0;
|
||||
|
||||
phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
|
||||
- phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(pl->link_config.interface),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
|
||||
pl->link_config.pause);
|
||||
@@ -1303,7 +1305,7 @@ static int phylink_change_inband_advert(
|
||||
phylink_pcs_neg_mode(pl, pl->pcs, pl->link_config.interface,
|
||||
pl->link_config.advertising);
|
||||
|
||||
- neg_mode = pl->cur_link_an_mode;
|
||||
+ neg_mode = pl->act_link_an_mode;
|
||||
if (pl->pcs->neg_mode)
|
||||
neg_mode = pl->pcs_neg_mode;
|
||||
|
||||
@@ -1368,7 +1370,7 @@ static void phylink_mac_initial_config(s
|
||||
{
|
||||
struct phylink_link_state link_state;
|
||||
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->req_link_an_mode) {
|
||||
case MLO_AN_PHY:
|
||||
link_state = pl->phy_state;
|
||||
break;
|
||||
@@ -1442,14 +1444,14 @@ static void phylink_link_up(struct phyli
|
||||
|
||||
pl->cur_interface = link_state.interface;
|
||||
|
||||
- neg_mode = pl->cur_link_an_mode;
|
||||
+ neg_mode = pl->act_link_an_mode;
|
||||
if (pl->pcs && pl->pcs->neg_mode)
|
||||
neg_mode = pl->pcs_neg_mode;
|
||||
|
||||
phylink_pcs_link_up(pl->pcs, neg_mode, pl->cur_interface, speed,
|
||||
duplex);
|
||||
|
||||
- pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->cur_link_an_mode,
|
||||
+ pl->mac_ops->mac_link_up(pl->config, pl->phydev, pl->act_link_an_mode,
|
||||
pl->cur_interface, speed, duplex,
|
||||
!!(link_state.pause & MLO_PAUSE_TX), rx_pause);
|
||||
|
||||
@@ -1469,7 +1471,7 @@ static void phylink_link_down(struct phy
|
||||
|
||||
if (ndev)
|
||||
netif_carrier_off(ndev);
|
||||
- pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
|
||||
+ pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
|
||||
pl->cur_interface);
|
||||
phylink_info(pl, "Link is Down\n");
|
||||
}
|
||||
@@ -1495,10 +1497,10 @@ static void phylink_resolve(struct work_
|
||||
} else if (pl->mac_link_dropped) {
|
||||
link_state.link = false;
|
||||
retrigger = true;
|
||||
- } else if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ } else if (pl->act_link_an_mode == MLO_AN_FIXED) {
|
||||
phylink_get_fixed_state(pl, &link_state);
|
||||
mac_config = link_state.link;
|
||||
- } else if (pl->cur_link_an_mode == MLO_AN_PHY) {
|
||||
+ } else if (pl->act_link_an_mode == MLO_AN_PHY) {
|
||||
link_state = pl->phy_state;
|
||||
mac_config = link_state.link;
|
||||
} else {
|
||||
@@ -1552,7 +1554,7 @@ static void phylink_resolve(struct work_
|
||||
}
|
||||
}
|
||||
|
||||
- if (pl->cur_link_an_mode != MLO_AN_FIXED)
|
||||
+ if (pl->act_link_an_mode != MLO_AN_FIXED)
|
||||
phylink_apply_manual_flow(pl, &link_state);
|
||||
|
||||
if (mac_config) {
|
||||
@@ -1729,7 +1731,7 @@ struct phylink *phylink_create(struct ph
|
||||
}
|
||||
}
|
||||
|
||||
- pl->cur_link_an_mode = pl->cfg_link_an_mode;
|
||||
+ pl->req_link_an_mode = pl->cfg_link_an_mode;
|
||||
|
||||
ret = phylink_register_sfp(pl, fwnode);
|
||||
if (ret < 0) {
|
||||
@@ -2126,7 +2128,7 @@ void phylink_start(struct phylink *pl)
|
||||
ASSERT_RTNL();
|
||||
|
||||
phylink_info(pl, "configuring for %s/%s link mode\n",
|
||||
- phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(pl->link_config.interface));
|
||||
|
||||
/* Always set the carrier off */
|
||||
@@ -2385,7 +2387,7 @@ int phylink_ethtool_ksettings_get(struct
|
||||
|
||||
linkmode_copy(kset->link_modes.supported, pl->supported);
|
||||
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->act_link_an_mode) {
|
||||
case MLO_AN_FIXED:
|
||||
/* We are using fixed settings. Report these as the
|
||||
* current link settings - and note that these also
|
||||
@@ -2477,7 +2479,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
/* If we have a fixed link, refuse to change link parameters.
|
||||
* If the link parameters match, accept them but do nothing.
|
||||
*/
|
||||
- if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ if (pl->req_link_an_mode == MLO_AN_FIXED) {
|
||||
if (s->speed != pl->link_config.speed ||
|
||||
s->duplex != pl->link_config.duplex)
|
||||
return -EINVAL;
|
||||
@@ -2493,7 +2495,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
* is our default case) but do not allow the advertisement to
|
||||
* be changed. If the advertisement matches, simply return.
|
||||
*/
|
||||
- if (pl->cur_link_an_mode == MLO_AN_FIXED) {
|
||||
+ if (pl->req_link_an_mode == MLO_AN_FIXED) {
|
||||
if (!linkmode_equal(config.advertising,
|
||||
pl->link_config.advertising))
|
||||
return -EINVAL;
|
||||
@@ -2533,7 +2535,7 @@ int phylink_ethtool_ksettings_set(struct
|
||||
linkmode_copy(support, pl->supported);
|
||||
if (phylink_validate(pl, support, &config)) {
|
||||
phylink_err(pl, "validation of %s/%s with support %*pb failed\n",
|
||||
- phylink_an_mode_str(pl->cur_link_an_mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(config.interface),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, support);
|
||||
return -EINVAL;
|
||||
@@ -2633,7 +2635,7 @@ int phylink_ethtool_set_pauseparam(struc
|
||||
|
||||
ASSERT_RTNL();
|
||||
|
||||
- if (pl->cur_link_an_mode == MLO_AN_FIXED)
|
||||
+ if (pl->req_link_an_mode == MLO_AN_FIXED)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!phylink_test(pl->supported, Pause) &&
|
||||
@@ -2897,7 +2899,7 @@ static int phylink_mii_read(struct phyli
|
||||
struct phylink_link_state state;
|
||||
int val = 0xffff;
|
||||
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->act_link_an_mode) {
|
||||
case MLO_AN_FIXED:
|
||||
if (phy_id == 0) {
|
||||
phylink_get_fixed_state(pl, &state);
|
||||
@@ -2922,7 +2924,7 @@ static int phylink_mii_read(struct phyli
|
||||
static int phylink_mii_write(struct phylink *pl, unsigned int phy_id,
|
||||
unsigned int reg, unsigned int val)
|
||||
{
|
||||
- switch (pl->cur_link_an_mode) {
|
||||
+ switch (pl->act_link_an_mode) {
|
||||
case MLO_AN_FIXED:
|
||||
break;
|
||||
|
||||
@@ -3125,9 +3127,9 @@ static void phylink_sfp_set_config(struc
|
||||
changed = true;
|
||||
}
|
||||
|
||||
- if (pl->cur_link_an_mode != mode ||
|
||||
+ if (pl->req_link_an_mode != mode ||
|
||||
pl->link_config.interface != state->interface) {
|
||||
- pl->cur_link_an_mode = mode;
|
||||
+ pl->req_link_an_mode = mode;
|
||||
pl->link_config.interface = state->interface;
|
||||
|
||||
changed = true;
|
||||
@ -0,0 +1,66 @@
|
||||
From 4e7d000286fe8e12f2d88032711ffab3ab658b12 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:30:57 +0000
|
||||
Subject: [PATCH 03/13] net: phylink: add debug for phylink_major_config()
|
||||
|
||||
Now that we have a more complexity in phylink_major_config(), augment
|
||||
the debugging so we can see what's going on there.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrZ-006ITt-Fa@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 27 ++++++++++++++++++++++++++-
|
||||
1 file changed, 26 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -163,6 +163,24 @@ static const char *phylink_an_mode_str(u
|
||||
return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
|
||||
}
|
||||
|
||||
+static const char *phylink_pcs_mode_str(unsigned int mode)
|
||||
+{
|
||||
+ if (!mode)
|
||||
+ return "none";
|
||||
+
|
||||
+ if (mode & PHYLINK_PCS_NEG_OUTBAND)
|
||||
+ return "outband";
|
||||
+
|
||||
+ if (mode & PHYLINK_PCS_NEG_INBAND) {
|
||||
+ if (mode & PHYLINK_PCS_NEG_ENABLED)
|
||||
+ return "inband,an-enabled";
|
||||
+ else
|
||||
+ return "inband,an-disabled";
|
||||
+ }
|
||||
+
|
||||
+ return "unknown";
|
||||
+}
|
||||
+
|
||||
static unsigned int phylink_interface_signal_rate(phy_interface_t interface)
|
||||
{
|
||||
switch (interface) {
|
||||
@@ -1196,7 +1214,9 @@ static void phylink_major_config(struct
|
||||
unsigned int neg_mode;
|
||||
int err;
|
||||
|
||||
- phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
|
||||
+ phylink_dbg(pl, "major config, requested %s/%s\n",
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
+ phy_modes(state->interface));
|
||||
|
||||
if (pl->using_mac_select_pcs) {
|
||||
pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
|
||||
@@ -1212,6 +1232,11 @@ static void phylink_major_config(struct
|
||||
|
||||
phylink_pcs_neg_mode(pl, pcs, state->interface, state->advertising);
|
||||
|
||||
+ phylink_dbg(pl, "major config, active %s/%s/%s\n",
|
||||
+ phylink_an_mode_str(pl->act_link_an_mode),
|
||||
+ phylink_pcs_mode_str(pl->pcs_neg_mode),
|
||||
+ phy_modes(state->interface));
|
||||
+
|
||||
phylink_pcs_poll_stop(pl);
|
||||
|
||||
if (pl->mac_ops->mac_prepare) {
|
||||
@ -0,0 +1,118 @@
|
||||
From b4c7698dd95f253c6958d8c6ac219098009bf28a Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:02 +0000
|
||||
Subject: [PATCH 04/13] net: phy: add phy_inband_caps()
|
||||
|
||||
Add a method to query the PHY's in-band capabilities for a PHY
|
||||
interface mode.
|
||||
|
||||
Where the interface mode does not have in-band capability, or the PHY
|
||||
driver has not been updated to return this information, then
|
||||
phy_inband_caps() should return zero. Otherwise, PHY drivers will
|
||||
return a value consisting of the following flags:
|
||||
|
||||
LINK_INBAND_DISABLE indicates that the hardware does not support
|
||||
in-band signalling, or can have in-band signalling configured via
|
||||
software to be disabled.
|
||||
|
||||
LINK_INBAND_ENABLE indicates that the hardware will use in-band
|
||||
signalling, or can have in-band signalling configured via software
|
||||
to be enabled.
|
||||
|
||||
LINK_INBAND_BYPASS indicates that the hardware has the ability to
|
||||
bypass in-band signalling when enabled after a timeout if the link
|
||||
partner does not respond to its in-band signalling.
|
||||
|
||||
This reports the PHY capabilities for the particular interface mode,
|
||||
not the current configuration.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUre-006ITz-KF@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phy.c | 21 +++++++++++++++++++++
|
||||
include/linux/phy.h | 28 ++++++++++++++++++++++++++++
|
||||
2 files changed, 49 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -973,6 +973,27 @@ static int phy_check_link_status(struct
|
||||
}
|
||||
|
||||
/**
|
||||
+ * phy_inband_caps - query which in-band signalling modes are supported
|
||||
+ * @phydev: a pointer to a &struct phy_device
|
||||
+ * @interface: the interface mode for the PHY
|
||||
+ *
|
||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
|
||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
|
||||
+ * returns a bit mask of the LINK_INBAND_* values from
|
||||
+ * &enum link_inband_signalling to describe which inband modes are supported
|
||||
+ * by the PHY for this interface mode.
|
||||
+ */
|
||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ if (phydev->drv && phydev->drv->inband_caps)
|
||||
+ return phydev->drv->inband_caps(phydev, interface);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(phy_inband_caps);
|
||||
+
|
||||
+/**
|
||||
* _phy_start_aneg - start auto-negotiation for this PHY device
|
||||
* @phydev: the phy_device struct
|
||||
*
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -790,6 +790,24 @@ struct phy_tdr_config {
|
||||
#define PHY_PAIR_ALL -1
|
||||
|
||||
/**
|
||||
+ * enum link_inband_signalling - in-band signalling modes that are supported
|
||||
+ *
|
||||
+ * @LINK_INBAND_DISABLE: in-band signalling can be disabled
|
||||
+ * @LINK_INBAND_ENABLE: in-band signalling can be enabled without bypass
|
||||
+ * @LINK_INBAND_BYPASS: in-band signalling can be enabled with bypass
|
||||
+ *
|
||||
+ * The possible and required bits can only be used if the valid bit is set.
|
||||
+ * If possible is clear, that means inband signalling can not be used.
|
||||
+ * Required is only valid when possible is set, and means that inband
|
||||
+ * signalling must be used.
|
||||
+ */
|
||||
+enum link_inband_signalling {
|
||||
+ LINK_INBAND_DISABLE = BIT(0),
|
||||
+ LINK_INBAND_ENABLE = BIT(1),
|
||||
+ LINK_INBAND_BYPASS = BIT(2),
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
* struct phy_plca_cfg - Configuration of the PLCA (Physical Layer Collision
|
||||
* Avoidance) Reconciliation Sublayer.
|
||||
*
|
||||
@@ -919,6 +937,14 @@ struct phy_driver {
|
||||
int (*get_features)(struct phy_device *phydev);
|
||||
|
||||
/**
|
||||
+ * @inband_caps: query whether in-band is supported for the given PHY
|
||||
+ * interface mode. Returns a bitmask of bits defined by enum
|
||||
+ * link_inband_signalling.
|
||||
+ */
|
||||
+ unsigned int (*inband_caps)(struct phy_device *phydev,
|
||||
+ phy_interface_t interface);
|
||||
+
|
||||
+ /**
|
||||
* @get_rate_matching: Get the supported type of rate matching for a
|
||||
* particular phy interface. This is used by phy consumers to determine
|
||||
* whether to advertise lower-speed modes for that interface. It is
|
||||
@@ -1735,6 +1761,8 @@ void phy_stop(struct phy_device *phydev)
|
||||
int phy_config_aneg(struct phy_device *phydev);
|
||||
int phy_start_aneg(struct phy_device *phydev);
|
||||
int phy_aneg_done(struct phy_device *phydev);
|
||||
+unsigned int phy_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface);
|
||||
int phy_speed_down(struct phy_device *phydev, bool sync);
|
||||
int phy_speed_up(struct phy_device *phydev);
|
||||
bool phy_check_valid(int speed, int duplex, unsigned long *features);
|
||||
@ -0,0 +1,41 @@
|
||||
From c64c7fa0a774d9da72071a8517e359992baac982 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:07 +0000
|
||||
Subject: [PATCH 05/13] net: phy: bcm84881: implement phy_inband_caps() method
|
||||
|
||||
BCM84881 has no support for inband signalling, so this is a trivial
|
||||
implementation that returns no support for inband.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Acked-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Link: https://patch.msgid.link/E1tIUrj-006IU6-ON@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/bcm84881.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/bcm84881.c
|
||||
+++ b/drivers/net/phy/bcm84881.c
|
||||
@@ -223,11 +223,21 @@ static int bcm84881_read_status(struct p
|
||||
return genphy_c45_read_mdix(phydev);
|
||||
}
|
||||
|
||||
+/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
|
||||
+ * or 802.3z control word, so inband will not work.
|
||||
+ */
|
||||
+static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
+}
|
||||
+
|
||||
static struct phy_driver bcm84881_drivers[] = {
|
||||
{
|
||||
.phy_id = 0xae025150,
|
||||
.phy_id_mask = 0xfffffff0,
|
||||
.name = "Broadcom BCM84881",
|
||||
+ .inband_caps = bcm84881_inband_caps,
|
||||
.config_init = bcm84881_config_init,
|
||||
.probe = bcm84881_probe,
|
||||
.get_features = bcm84881_get_features,
|
||||
@ -0,0 +1,63 @@
|
||||
From 1c86828dff88e28b8ade6bddeee0163a023faf91 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:12 +0000
|
||||
Subject: [PATCH 06/13] net: phy: marvell: implement phy_inband_caps() method
|
||||
|
||||
Provide an implementation for phy_inband_caps() for Marvell PHYs used
|
||||
on SFP modules, so that phylink knows the PHYs capabilities.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUro-006IUC-Rq@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/marvell.c | 17 +++++++++++++++++
|
||||
1 file changed, 17 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -673,6 +673,20 @@ static int marvell_config_aneg_fiber(str
|
||||
return genphy_check_and_restart_aneg(phydev, changed);
|
||||
}
|
||||
|
||||
+static unsigned int m88e1111_inband_caps(struct phy_device *phydev,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ /* In 1000base-X and SGMII modes, the inband mode can be changed
|
||||
+ * through the Fibre page BMCR ANENABLE bit.
|
||||
+ */
|
||||
+ if (interface == PHY_INTERFACE_MODE_1000BASEX ||
|
||||
+ interface == PHY_INTERFACE_MODE_SGMII)
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE |
|
||||
+ LINK_INBAND_BYPASS;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int m88e1111_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
|
||||
@@ -3292,6 +3306,7 @@ static struct phy_driver marvell_drivers
|
||||
.name = "Marvell 88E1112",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
+ .inband_caps = m88e1111_inband_caps,
|
||||
.config_init = m88e1112_config_init,
|
||||
.config_aneg = marvell_config_aneg,
|
||||
.config_intr = marvell_config_intr,
|
||||
@@ -3312,6 +3327,7 @@ static struct phy_driver marvell_drivers
|
||||
.name = "Marvell 88E1111",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
+ .inband_caps = m88e1111_inband_caps,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -3333,6 +3349,7 @@ static struct phy_driver marvell_drivers
|
||||
.name = "Marvell 88E1111 (Finisar)",
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
+ .inband_caps = m88e1111_inband_caps,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@ -0,0 +1,79 @@
|
||||
From 5d58a890c02770ba8d790b1f3c6e8c0e20514dc2 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:18 +0000
|
||||
Subject: [PATCH 07/13] net: phy: add phy_config_inband()
|
||||
|
||||
Add a method to configure the PHY's in-band mode.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUru-006IUI-08@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phy.c | 32 ++++++++++++++++++++++++++++++++
|
||||
include/linux/phy.h | 6 ++++++
|
||||
2 files changed, 38 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phy.c
|
||||
+++ b/drivers/net/phy/phy.c
|
||||
@@ -994,6 +994,38 @@ unsigned int phy_inband_caps(struct phy_
|
||||
EXPORT_SYMBOL_GPL(phy_inband_caps);
|
||||
|
||||
/**
|
||||
+ * phy_config_inband - configure the desired PHY in-band mode
|
||||
+ * @phydev: the phy_device struct
|
||||
+ * @modes: in-band modes to configure
|
||||
+ *
|
||||
+ * Description: disables, enables or enables-with-bypass in-band signalling
|
||||
+ * between the PHY and host system.
|
||||
+ *
|
||||
+ * Returns: zero on success, or negative errno value.
|
||||
+ */
|
||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ if (!!(modes & LINK_INBAND_DISABLE) +
|
||||
+ !!(modes & LINK_INBAND_ENABLE) +
|
||||
+ !!(modes & LINK_INBAND_BYPASS) != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&phydev->lock);
|
||||
+ if (!phydev->drv)
|
||||
+ err = -EIO;
|
||||
+ else if (!phydev->drv->config_inband)
|
||||
+ err = -EOPNOTSUPP;
|
||||
+ else
|
||||
+ err = phydev->drv->config_inband(phydev, modes);
|
||||
+ mutex_unlock(&phydev->lock);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+EXPORT_SYMBOL(phy_config_inband);
|
||||
+
|
||||
+/**
|
||||
* _phy_start_aneg - start auto-negotiation for this PHY device
|
||||
* @phydev: the phy_device struct
|
||||
*
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -945,6 +945,11 @@ struct phy_driver {
|
||||
phy_interface_t interface);
|
||||
|
||||
/**
|
||||
+ * @config_inband: configure in-band mode for the PHY
|
||||
+ */
|
||||
+ int (*config_inband)(struct phy_device *phydev, unsigned int modes);
|
||||
+
|
||||
+ /**
|
||||
* @get_rate_matching: Get the supported type of rate matching for a
|
||||
* particular phy interface. This is used by phy consumers to determine
|
||||
* whether to advertise lower-speed modes for that interface. It is
|
||||
@@ -1763,6 +1768,7 @@ int phy_start_aneg(struct phy_device *ph
|
||||
int phy_aneg_done(struct phy_device *phydev);
|
||||
unsigned int phy_inband_caps(struct phy_device *phydev,
|
||||
phy_interface_t interface);
|
||||
+int phy_config_inband(struct phy_device *phydev, unsigned int modes);
|
||||
int phy_speed_down(struct phy_device *phydev, bool sync);
|
||||
int phy_speed_up(struct phy_device *phydev);
|
||||
bool phy_check_valid(int speed, int duplex, unsigned long *features);
|
||||
@ -0,0 +1,77 @@
|
||||
From a219912e0fec73c346e64ef47013cb2e152f88fc Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:23 +0000
|
||||
Subject: [PATCH 08/13] net: phy: marvell: implement config_inband() method
|
||||
|
||||
Implement the config_inband() method for Marvell 88E1112, 88E1111,
|
||||
and Finisar's 88E1111 variant.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUrz-006IUO-3r@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/marvell.c | 31 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 31 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/marvell.c
|
||||
+++ b/drivers/net/phy/marvell.c
|
||||
@@ -687,6 +687,34 @@ static unsigned int m88e1111_inband_caps
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
|
||||
+{
|
||||
+ u16 extsr, bmcr;
|
||||
+ int err;
|
||||
+
|
||||
+ if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX &&
|
||||
+ phydev->interface != PHY_INTERFACE_MODE_SGMII)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (modes == LINK_INBAND_BYPASS)
|
||||
+ extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS;
|
||||
+ else
|
||||
+ extsr = 0;
|
||||
+
|
||||
+ if (modes == LINK_INBAND_DISABLE)
|
||||
+ bmcr = 0;
|
||||
+ else
|
||||
+ bmcr = BMCR_ANENABLE;
|
||||
+
|
||||
+ err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
|
||||
+ MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
|
||||
+ if (err < 0)
|
||||
+ return extsr;
|
||||
+
|
||||
+ return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
|
||||
+ BMCR_ANENABLE, bmcr);
|
||||
+}
|
||||
+
|
||||
static int m88e1111_config_aneg(struct phy_device *phydev)
|
||||
{
|
||||
int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
|
||||
@@ -3307,6 +3335,7 @@ static struct phy_driver marvell_drivers
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
.inband_caps = m88e1111_inband_caps,
|
||||
+ .config_inband = m88e1111_config_inband,
|
||||
.config_init = m88e1112_config_init,
|
||||
.config_aneg = marvell_config_aneg,
|
||||
.config_intr = marvell_config_intr,
|
||||
@@ -3328,6 +3357,7 @@ static struct phy_driver marvell_drivers
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
.inband_caps = m88e1111_inband_caps,
|
||||
+ .config_inband = m88e1111_config_inband,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@@ -3350,6 +3380,7 @@ static struct phy_driver marvell_drivers
|
||||
/* PHY_GBIT_FEATURES */
|
||||
.probe = marvell_probe,
|
||||
.inband_caps = m88e1111_inband_caps,
|
||||
+ .config_inband = m88e1111_config_inband,
|
||||
.config_init = m88e1111gbe_config_init,
|
||||
.config_aneg = m88e1111_config_aneg,
|
||||
.read_status = marvell_read_status,
|
||||
@ -0,0 +1,159 @@
|
||||
From df874f9e52c340cc6f0a0014a97b778f67d46849 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:28 +0000
|
||||
Subject: [PATCH 09/13] net: phylink: add pcs_inband_caps() method
|
||||
|
||||
Add a pcs_inband_caps() method to query the PCS for its inband link
|
||||
capabilities, and use this to determine whether link modes used with
|
||||
optical SFPs can be supported.
|
||||
|
||||
When a PCS does not provide a method, we allow inband negotiation to
|
||||
be either on or off, making this a no-op until the pcs_inband_caps()
|
||||
method is implemented by a PCS driver.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUs4-006IUU-7K@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 60 +++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/phylink.h | 17 +++++++++++
|
||||
2 files changed, 77 insertions(+)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1038,6 +1038,15 @@ static void phylink_resolve_an_pause(str
|
||||
}
|
||||
}
|
||||
|
||||
+static unsigned int phylink_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ if (pcs && pcs->ops->pcs_inband_caps)
|
||||
+ return pcs->ops->pcs_inband_caps(pcs, interface);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void phylink_pcs_pre_config(struct phylink_pcs *pcs,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
@@ -1091,6 +1100,24 @@ static void phylink_pcs_link_up(struct p
|
||||
pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
|
||||
}
|
||||
|
||||
+/* Query inband for a specific interface mode, asking the MAC for the
|
||||
+ * PCS which will be used to handle the interface mode.
|
||||
+ */
|
||||
+static unsigned int phylink_inband_caps(struct phylink *pl,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ struct phylink_pcs *pcs;
|
||||
+
|
||||
+ if (!pl->mac_ops->mac_select_pcs)
|
||||
+ return 0;
|
||||
+
|
||||
+ pcs = pl->mac_ops->mac_select_pcs(pl->config, interface);
|
||||
+ if (!pcs)
|
||||
+ return 0;
|
||||
+
|
||||
+ return phylink_pcs_inband_caps(pcs, interface);
|
||||
+}
|
||||
+
|
||||
static void phylink_pcs_poll_stop(struct phylink *pl)
|
||||
{
|
||||
if (pl->cfg_link_an_mode == MLO_AN_INBAND)
|
||||
@@ -2443,6 +2470,26 @@ int phylink_ethtool_ksettings_get(struct
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
|
||||
|
||||
+static bool phylink_validate_pcs_inband_autoneg(struct phylink *pl,
|
||||
+ phy_interface_t interface,
|
||||
+ unsigned long *adv)
|
||||
+{
|
||||
+ unsigned int inband = phylink_inband_caps(pl, interface);
|
||||
+ unsigned int mask;
|
||||
+
|
||||
+ /* If the PCS doesn't implement inband support, be permissive. */
|
||||
+ if (!inband)
|
||||
+ return true;
|
||||
+
|
||||
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv))
|
||||
+ mask = LINK_INBAND_ENABLE;
|
||||
+ else
|
||||
+ mask = LINK_INBAND_DISABLE;
|
||||
+
|
||||
+ /* Check whether the PCS implements the required mode */
|
||||
+ return !!(inband & mask);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* phylink_ethtool_ksettings_set() - set the link settings
|
||||
* @pl: a pointer to a &struct phylink returned from phylink_create()
|
||||
@@ -2578,6 +2625,13 @@ int phylink_ethtool_ksettings_set(struct
|
||||
phylink_is_empty_linkmode(config.advertising))
|
||||
return -EINVAL;
|
||||
|
||||
+ /* Validate the autonegotiation state. We don't have a PHY in this
|
||||
+ * situation, so the PCS is the media-facing entity.
|
||||
+ */
|
||||
+ if (!phylink_validate_pcs_inband_autoneg(pl, config.interface,
|
||||
+ config.advertising))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
mutex_lock(&pl->state_mutex);
|
||||
pl->link_config.speed = config.speed;
|
||||
pl->link_config.duplex = config.duplex;
|
||||
@@ -3274,6 +3328,12 @@ static int phylink_sfp_config_optical(st
|
||||
phylink_dbg(pl, "optical SFP: chosen %s interface\n",
|
||||
phy_modes(interface));
|
||||
|
||||
+ if (!phylink_validate_pcs_inband_autoneg(pl, interface,
|
||||
+ config.advertising)) {
|
||||
+ phylink_err(pl, "autoneg setting not compatible with PCS");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
config.interface = interface;
|
||||
|
||||
/* Ignore errors if we're expecting a PHY to attach later */
|
||||
--- a/include/linux/phylink.h
|
||||
+++ b/include/linux/phylink.h
|
||||
@@ -432,6 +432,7 @@ struct phylink_pcs {
|
||||
/**
|
||||
* struct phylink_pcs_ops - MAC PCS operations structure.
|
||||
* @pcs_validate: validate the link configuration.
|
||||
+ * @pcs_inband_caps: query inband support for interface mode.
|
||||
* @pcs_enable: enable the PCS.
|
||||
* @pcs_disable: disable the PCS.
|
||||
* @pcs_pre_config: pre-mac_config method (for errata)
|
||||
@@ -445,6 +446,8 @@ struct phylink_pcs {
|
||||
struct phylink_pcs_ops {
|
||||
int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
|
||||
const struct phylink_link_state *state);
|
||||
+ unsigned int (*pcs_inband_caps)(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface);
|
||||
int (*pcs_enable)(struct phylink_pcs *pcs);
|
||||
void (*pcs_disable)(struct phylink_pcs *pcs);
|
||||
void (*pcs_pre_config)(struct phylink_pcs *pcs,
|
||||
@@ -481,6 +484,20 @@ int pcs_validate(struct phylink_pcs *pcs
|
||||
const struct phylink_link_state *state);
|
||||
|
||||
/**
|
||||
+ * pcs_inband_caps - query PCS in-band capabilities for interface mode.
|
||||
+ * @pcs: a pointer to a &struct phylink_pcs.
|
||||
+ * @interface: interface mode to be queried
|
||||
+ *
|
||||
+ * Returns zero if it is unknown what in-band signalling is supported by the
|
||||
+ * PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
|
||||
+ * returns a bit mask of the LINK_INBAND_* values from
|
||||
+ * &enum link_inband_signalling to describe which inband modes are supported
|
||||
+ * for this interface mode.
|
||||
+ */
|
||||
+unsigned int pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface);
|
||||
+
|
||||
+/**
|
||||
* pcs_enable() - enable the PCS.
|
||||
* @pcs: a pointer to a &struct phylink_pcs.
|
||||
*/
|
||||
@ -0,0 +1,64 @@
|
||||
From 513e8fb8fa32035b3325e2e14fb9598f8cb545e9 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:33 +0000
|
||||
Subject: [PATCH 10/13] net: mvneta: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for Marvell NETA
|
||||
interfaces.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUs9-006IUb-Au@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/marvell/mvneta.c | 27 +++++++++++++++++----------
|
||||
1 file changed, 17 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -3959,20 +3959,27 @@ static struct mvneta_port *mvneta_pcs_to
|
||||
return container_of(pcs, struct mvneta_port, phylink_pcs);
|
||||
}
|
||||
|
||||
-static int mvneta_pcs_validate(struct phylink_pcs *pcs,
|
||||
- unsigned long *supported,
|
||||
- const struct phylink_link_state *state)
|
||||
+static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
{
|
||||
- /* We only support QSGMII, SGMII, 802.3z and RGMII modes.
|
||||
- * When in 802.3z mode, we must have AN enabled:
|
||||
+ /* When operating in an 802.3z mode, we must have AN enabled:
|
||||
* "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
|
||||
* When <PortType> = 1 (1000BASE-X) this field must be set to 1."
|
||||
+ * Therefore, inband is "required".
|
||||
*/
|
||||
- if (phy_interface_mode_is_8023z(state->interface) &&
|
||||
- !phylink_test(state->advertising, Autoneg))
|
||||
- return -EINVAL;
|
||||
+ if (phy_interface_mode_is_8023z(interface))
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
|
||||
- return 0;
|
||||
+ /* QSGMII, SGMII and RGMII can be configured to use inband
|
||||
+ * signalling of the AN result. Indicate these as "possible".
|
||||
+ */
|
||||
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
+ interface == PHY_INTERFACE_MODE_QSGMII ||
|
||||
+ phy_interface_mode_is_rgmii(interface))
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ /* For any other modes, indicate that inband is not supported. */
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
}
|
||||
|
||||
static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
|
||||
@@ -4070,7 +4077,7 @@ static void mvneta_pcs_an_restart(struct
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
|
||||
- .pcs_validate = mvneta_pcs_validate,
|
||||
+ .pcs_inband_caps = mvneta_pcs_inband_caps,
|
||||
.pcs_get_state = mvneta_pcs_get_state,
|
||||
.pcs_config = mvneta_pcs_config,
|
||||
.pcs_an_restart = mvneta_pcs_an_restart,
|
||||
@ -0,0 +1,62 @@
|
||||
From d4169f0c7665afb8d8adb5e1b1df3db88517d0ad Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:38 +0000
|
||||
Subject: [PATCH 11/13] net: mvpp2: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for Marvell PP2
|
||||
interfaces.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUsE-006IUh-E7@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
.../net/ethernet/marvell/mvpp2/mvpp2_main.c | 25 ++++++++++++-------
|
||||
1 file changed, 16 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c
|
||||
@@ -6214,19 +6214,26 @@ static const struct phylink_pcs_ops mvpp
|
||||
.pcs_config = mvpp2_xlg_pcs_config,
|
||||
};
|
||||
|
||||
-static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs,
|
||||
- unsigned long *supported,
|
||||
- const struct phylink_link_state *state)
|
||||
+static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
{
|
||||
- /* When in 802.3z mode, we must have AN enabled:
|
||||
+ /* When operating in an 802.3z mode, we must have AN enabled:
|
||||
* Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
|
||||
* When <PortType> = 1 (1000BASE-X) this field must be set to 1.
|
||||
+ * Therefore, inband is "required".
|
||||
*/
|
||||
- if (phy_interface_mode_is_8023z(state->interface) &&
|
||||
- !phylink_test(state->advertising, Autoneg))
|
||||
- return -EINVAL;
|
||||
+ if (phy_interface_mode_is_8023z(interface))
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
|
||||
- return 0;
|
||||
+ /* SGMII and RGMII can be configured to use inband signalling of the
|
||||
+ * AN result. Indicate these as "possible".
|
||||
+ */
|
||||
+ if (interface == PHY_INTERFACE_MODE_SGMII ||
|
||||
+ phy_interface_mode_is_rgmii(interface))
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ /* For any other modes, indicate that inband is not supported. */
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
}
|
||||
|
||||
static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
|
||||
@@ -6333,7 +6340,7 @@ static void mvpp2_gmac_pcs_an_restart(st
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = {
|
||||
- .pcs_validate = mvpp2_gmac_pcs_validate,
|
||||
+ .pcs_inband_caps = mvpp2_gmac_pcs_inband_caps,
|
||||
.pcs_get_state = mvpp2_gmac_pcs_get_state,
|
||||
.pcs_config = mvpp2_gmac_pcs_config,
|
||||
.pcs_an_restart = mvpp2_gmac_pcs_an_restart,
|
||||
@ -0,0 +1,228 @@
|
||||
From 5fd0f1a02e750e2db4038dee60edea669ce5aab1 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:43 +0000
|
||||
Subject: [PATCH 12/13] net: phylink: add negotiation of in-band capabilities
|
||||
|
||||
Support for in-band signalling with Serdes links is uncertain. Some
|
||||
PHYs do not support in-band for e.g. SGMII. Some PCS do not support
|
||||
in-band for 2500Base-X. Some PCS require in-band for Base-X protocols.
|
||||
|
||||
Simply using what is in DT is insufficient when we have hot-pluggable
|
||||
PHYs e.g. in the form of SFP modules, which may not provide the
|
||||
in-band signalling.
|
||||
|
||||
In order to address this, we have introduced phy_inband_caps() and
|
||||
pcs_inband_caps() functions to allow phylink to retrieve the
|
||||
capabilities from each end of the PCS/PHY link. This commit adds code
|
||||
to resolve whether in-band will be used in the various scenarios that
|
||||
we have: In-band not being used, PHY present using SGMII or Base-X,
|
||||
PHY not present. We also deal with no capabilties provided.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUsJ-006IUn-H3@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 154 +++++++++++++++++++++++++++++++++++---
|
||||
1 file changed, 144 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -75,6 +75,7 @@ struct phylink {
|
||||
|
||||
struct mutex state_mutex;
|
||||
struct phylink_link_state phy_state;
|
||||
+ unsigned int phy_ib_mode;
|
||||
struct work_struct resolve;
|
||||
unsigned int pcs_neg_mode;
|
||||
unsigned int pcs_state;
|
||||
@@ -1186,10 +1187,18 @@ static void phylink_pcs_neg_mode(struct
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising)
|
||||
{
|
||||
+ unsigned int pcs_ib_caps = 0;
|
||||
+ unsigned int phy_ib_caps = 0;
|
||||
unsigned int neg_mode, mode;
|
||||
+ enum {
|
||||
+ INBAND_CISCO_SGMII,
|
||||
+ INBAND_BASEX,
|
||||
+ } type;
|
||||
|
||||
mode = pl->req_link_an_mode;
|
||||
|
||||
+ pl->phy_ib_mode = 0;
|
||||
+
|
||||
switch (interface) {
|
||||
case PHY_INTERFACE_MODE_SGMII:
|
||||
case PHY_INTERFACE_MODE_QSGMII:
|
||||
@@ -1200,10 +1209,7 @@ static void phylink_pcs_neg_mode(struct
|
||||
* inband communication. Note: there exist PHYs that run
|
||||
* with SGMII but do not send the inband data.
|
||||
*/
|
||||
- if (!phylink_autoneg_inband(mode))
|
||||
- neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
- else
|
||||
- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ type = INBAND_CISCO_SGMII;
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_1000BASEX:
|
||||
@@ -1214,18 +1220,139 @@ static void phylink_pcs_neg_mode(struct
|
||||
* as well, but drivers may not support this, so may
|
||||
* need to override this.
|
||||
*/
|
||||
- if (!phylink_autoneg_inband(mode))
|
||||
+ type = INBAND_BASEX;
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ pl->pcs_neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
+ pl->act_link_an_mode = mode;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (pcs)
|
||||
+ pcs_ib_caps = phylink_pcs_inband_caps(pcs, interface);
|
||||
+
|
||||
+ if (pl->phydev)
|
||||
+ phy_ib_caps = phy_inband_caps(pl->phydev, interface);
|
||||
+
|
||||
+ phylink_dbg(pl, "interface %s inband modes: pcs=%02x phy=%02x\n",
|
||||
+ phy_modes(interface), pcs_ib_caps, phy_ib_caps);
|
||||
+
|
||||
+ if (!phylink_autoneg_inband(mode)) {
|
||||
+ bool pcs_ib_only = false;
|
||||
+ bool phy_ib_only = false;
|
||||
+
|
||||
+ if (pcs_ib_caps && pcs_ib_caps != LINK_INBAND_DISABLE) {
|
||||
+ /* PCS supports reporting in-band capabilities, and
|
||||
+ * supports more than disable mode.
|
||||
+ */
|
||||
+ if (pcs_ib_caps & LINK_INBAND_DISABLE)
|
||||
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ else if (pcs_ib_caps & LINK_INBAND_ENABLE)
|
||||
+ pcs_ib_only = true;
|
||||
+ }
|
||||
+
|
||||
+ if (phy_ib_caps && phy_ib_caps != LINK_INBAND_DISABLE) {
|
||||
+ /* PHY supports in-band capabilities, and supports
|
||||
+ * more than disable mode.
|
||||
+ */
|
||||
+ if (phy_ib_caps & LINK_INBAND_DISABLE)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_DISABLE;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_BYPASS)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_BYPASS;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_ENABLE)
|
||||
+ phy_ib_only = true;
|
||||
+ }
|
||||
+
|
||||
+ /* If either the PCS or PHY requires inband to be enabled,
|
||||
+ * this is an invalid configuration. Provide a diagnostic
|
||||
+ * message for this case, but don't try to force the issue.
|
||||
+ */
|
||||
+ if (pcs_ib_only || phy_ib_only)
|
||||
+ phylink_warn(pl,
|
||||
+ "firmware wants %s mode, but %s%s%s requires inband\n",
|
||||
+ phylink_an_mode_str(mode),
|
||||
+ pcs_ib_only ? "PCS" : "",
|
||||
+ pcs_ib_only && phy_ib_only ? " and " : "",
|
||||
+ phy_ib_only ? "PHY" : "");
|
||||
+
|
||||
+ neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ } else if (type == INBAND_CISCO_SGMII || pl->phydev) {
|
||||
+ /* For SGMII modes which are designed to be used with PHYs, or
|
||||
+ * Base-X with a PHY, we try to use in-band mode where-ever
|
||||
+ * possible. However, there are some PHYs e.g. BCM84881 which
|
||||
+ * do not support in-band.
|
||||
+ */
|
||||
+ const unsigned int inband_ok = LINK_INBAND_ENABLE |
|
||||
+ LINK_INBAND_BYPASS;
|
||||
+ const unsigned int outband_ok = LINK_INBAND_DISABLE |
|
||||
+ LINK_INBAND_BYPASS;
|
||||
+ /* PCS PHY
|
||||
+ * D E D E
|
||||
+ * 0 0 0 0 no information inband enabled
|
||||
+ * 1 0 0 0 pcs doesn't support outband
|
||||
+ * 0 1 0 0 pcs required inband enabled
|
||||
+ * 1 1 0 0 pcs optional inband enabled
|
||||
+ * 0 0 1 0 phy doesn't support outband
|
||||
+ * 1 0 1 0 pcs+phy doesn't support outband
|
||||
+ * 0 1 1 0 pcs required, phy doesn't support, invalid
|
||||
+ * 1 1 1 0 pcs optional, phy doesn't support, outband
|
||||
+ * 0 0 0 1 phy required inband enabled
|
||||
+ * 1 0 0 1 pcs doesn't support, phy required, invalid
|
||||
+ * 0 1 0 1 pcs+phy required inband enabled
|
||||
+ * 1 1 0 1 pcs optional, phy required inband enabled
|
||||
+ * 0 0 1 1 phy optional inband enabled
|
||||
+ * 1 0 1 1 pcs doesn't support, phy optional, outband
|
||||
+ * 0 1 1 1 pcs required, phy optional inband enabled
|
||||
+ * 1 1 1 1 pcs+phy optional inband enabled
|
||||
+ */
|
||||
+ if ((!pcs_ib_caps || pcs_ib_caps & inband_ok) &&
|
||||
+ (!phy_ib_caps || phy_ib_caps & inband_ok)) {
|
||||
+ /* In-band supported or unknown at both ends. Enable
|
||||
+ * in-band mode with or without bypass at the PHY.
|
||||
+ */
|
||||
+ if (phy_ib_caps & LINK_INBAND_ENABLE)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_ENABLE;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_BYPASS)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_BYPASS;
|
||||
+
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ } else if ((!pcs_ib_caps || pcs_ib_caps & outband_ok) &&
|
||||
+ (!phy_ib_caps || phy_ib_caps & outband_ok)) {
|
||||
+ /* Either in-band not supported at at least one end.
|
||||
+ * In-band bypass at the other end is possible.
|
||||
+ */
|
||||
+ if (phy_ib_caps & LINK_INBAND_DISABLE)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_DISABLE;
|
||||
+ else if (phy_ib_caps & LINK_INBAND_BYPASS)
|
||||
+ pl->phy_ib_mode = LINK_INBAND_BYPASS;
|
||||
+
|
||||
neg_mode = PHYLINK_PCS_NEG_OUTBAND;
|
||||
+ if (pl->phydev)
|
||||
+ mode = MLO_AN_PHY;
|
||||
+ } else {
|
||||
+ /* invalid */
|
||||
+ phylink_warn(pl, "%s: incompatible in-band capabilities, trying in-band",
|
||||
+ phy_modes(interface));
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
+ }
|
||||
+ } else {
|
||||
+ /* For Base-X without a PHY */
|
||||
+ if (pcs_ib_caps == LINK_INBAND_DISABLE)
|
||||
+ /* If the PCS doesn't support inband, then inband must
|
||||
+ * be disabled.
|
||||
+ */
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
|
||||
+ else if (pcs_ib_caps == LINK_INBAND_ENABLE)
|
||||
+ /* If the PCS requires inband, then inband must always
|
||||
+ * be enabled.
|
||||
+ */
|
||||
+ neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
else if (linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
|
||||
advertising))
|
||||
neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
|
||||
else
|
||||
neg_mode = PHYLINK_PCS_NEG_INBAND_DISABLED;
|
||||
- break;
|
||||
-
|
||||
- default:
|
||||
- neg_mode = PHYLINK_PCS_NEG_NONE;
|
||||
- break;
|
||||
}
|
||||
|
||||
pl->pcs_neg_mode = neg_mode;
|
||||
@@ -1324,6 +1451,13 @@ static void phylink_major_config(struct
|
||||
ERR_PTR(err));
|
||||
}
|
||||
|
||||
+ if (pl->phydev && pl->phy_ib_mode) {
|
||||
+ err = phy_config_inband(pl->phydev, pl->phy_ib_mode);
|
||||
+ if (err < 0)
|
||||
+ phylink_err(pl, "phy_config_inband: %pe\n",
|
||||
+ ERR_PTR(err));
|
||||
+ }
|
||||
+
|
||||
if (pl->sfp_bus) {
|
||||
rate_kbd = phylink_interface_signal_rate(state->interface);
|
||||
if (rate_kbd)
|
||||
@ -0,0 +1,110 @@
|
||||
From 77ac9a8b2536e0eaca6c6f21070068458bf55981 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Tue, 3 Dec 2024 15:31:48 +0000
|
||||
Subject: [PATCH 13/13] net: phylink: remove phylink_phy_no_inband()
|
||||
|
||||
Remove phylink_phy_no_inband() now that we are handling the lack of
|
||||
inband negotiation by querying the capabilities of the PHY and PCS,
|
||||
and the BCM84881 PHY driver provides us the information necessary to
|
||||
make the decision.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tIUsO-006IUt-KN@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/phylink.c | 27 ++++++---------------------
|
||||
1 file changed, 6 insertions(+), 21 deletions(-)
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -3320,10 +3320,11 @@ static phy_interface_t phylink_choose_sf
|
||||
return interface;
|
||||
}
|
||||
|
||||
-static void phylink_sfp_set_config(struct phylink *pl, u8 mode,
|
||||
+static void phylink_sfp_set_config(struct phylink *pl,
|
||||
unsigned long *supported,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
+ u8 mode = MLO_AN_INBAND;
|
||||
bool changed = false;
|
||||
|
||||
phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n",
|
||||
@@ -3357,8 +3358,7 @@ static void phylink_sfp_set_config(struc
|
||||
phylink_mac_initial_config(pl, false);
|
||||
}
|
||||
|
||||
-static int phylink_sfp_config_phy(struct phylink *pl, u8 mode,
|
||||
- struct phy_device *phy)
|
||||
+static int phylink_sfp_config_phy(struct phylink *pl, struct phy_device *phy)
|
||||
{
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support1);
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(support);
|
||||
@@ -3398,7 +3398,7 @@ static int phylink_sfp_config_phy(struct
|
||||
if (ret) {
|
||||
phylink_err(pl,
|
||||
"validation of %s/%s with support %*pb failed: %pe\n",
|
||||
- phylink_an_mode_str(mode),
|
||||
+ phylink_an_mode_str(pl->req_link_an_mode),
|
||||
phy_modes(config.interface),
|
||||
__ETHTOOL_LINK_MODE_MASK_NBITS, support,
|
||||
ERR_PTR(ret));
|
||||
@@ -3407,7 +3407,7 @@ static int phylink_sfp_config_phy(struct
|
||||
|
||||
pl->link_port = pl->sfp_port;
|
||||
|
||||
- phylink_sfp_set_config(pl, mode, support, &config);
|
||||
+ phylink_sfp_set_config(pl, support, &config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3481,7 +3481,7 @@ static int phylink_sfp_config_optical(st
|
||||
|
||||
pl->link_port = pl->sfp_port;
|
||||
|
||||
- phylink_sfp_set_config(pl, MLO_AN_INBAND, pl->sfp_support, &config);
|
||||
+ phylink_sfp_set_config(pl, pl->sfp_support, &config);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3552,20 +3552,10 @@ static void phylink_sfp_link_up(void *up
|
||||
phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_LINK);
|
||||
}
|
||||
|
||||
-/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
|
||||
- * or 802.3z control word, so inband will not work.
|
||||
- */
|
||||
-static bool phylink_phy_no_inband(struct phy_device *phy)
|
||||
-{
|
||||
- return phy->is_c45 && phy_id_compare(phy->c45_ids.device_ids[1],
|
||||
- 0xae025150, 0xfffffff0);
|
||||
-}
|
||||
-
|
||||
static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
|
||||
{
|
||||
struct phylink *pl = upstream;
|
||||
phy_interface_t interface;
|
||||
- u8 mode;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
@@ -3577,17 +3567,12 @@ static int phylink_sfp_connect_phy(void
|
||||
*/
|
||||
phy_support_asym_pause(phy);
|
||||
|
||||
- if (phylink_phy_no_inband(phy))
|
||||
- mode = MLO_AN_PHY;
|
||||
- else
|
||||
- mode = MLO_AN_INBAND;
|
||||
-
|
||||
/* Set the PHY's host supported interfaces */
|
||||
phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
|
||||
pl->config->supported_interfaces);
|
||||
|
||||
/* Do the initial configuration */
|
||||
- ret = phylink_sfp_config_phy(pl, mode, phy);
|
||||
+ ret = phylink_sfp_config_phy(pl, phy);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
From 6561f0e547be221f411fda5eddfcc5bd8bb058a5 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 5 Dec 2024 09:42:24 +0000
|
||||
Subject: [PATCH 1/3] net: pcs: pcs-lynx: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for the Lynx PCS.
|
||||
|
||||
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tJ8NM-006L5J-AH@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-lynx.c | 22 ++++++++++++++++++++++
|
||||
1 file changed, 22 insertions(+)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-lynx.c
|
||||
+++ b/drivers/net/pcs/pcs-lynx.c
|
||||
@@ -35,6 +35,27 @@ enum sgmii_speed {
|
||||
#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
|
||||
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
|
||||
|
||||
+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ case PHY_INTERFACE_MODE_QSGMII:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ case PHY_INTERFACE_MODE_10GBASER:
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
+
|
||||
+ case PHY_INTERFACE_MODE_USXGMII:
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
@@ -307,6 +328,7 @@ static void lynx_pcs_link_up(struct phyl
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
|
||||
+ .pcs_inband_caps = lynx_pcs_inband_caps,
|
||||
.pcs_get_state = lynx_pcs_get_state,
|
||||
.pcs_config = lynx_pcs_config,
|
||||
.pcs_an_restart = lynx_pcs_an_restart,
|
||||
@ -0,0 +1,47 @@
|
||||
From 520d29bdda86915b3caf8c72825a574bff212553 Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 5 Dec 2024 09:42:29 +0000
|
||||
Subject: [PATCH 2/3] net: pcs: pcs-mtk-lynxi: implement pcs_inband_caps()
|
||||
method
|
||||
|
||||
Report the PCS in-band capabilities to phylink for the LynxI PCS.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tJ8NR-006L5P-E3@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-mtk-lynxi.c | 16 ++++++++++++++++
|
||||
1 file changed, 16 insertions(+)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
@@ -88,6 +88,21 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_
|
||||
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
|
||||
}
|
||||
|
||||
+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ switch (interface) {
|
||||
+ case PHY_INTERFACE_MODE_1000BASEX:
|
||||
+ case PHY_INTERFACE_MODE_2500BASEX:
|
||||
+ case PHY_INTERFACE_MODE_SGMII:
|
||||
+ case PHY_INTERFACE_MODE_QSGMII:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
@@ -241,6 +256,7 @@ static void mtk_pcs_lynxi_disable(struct
|
||||
}
|
||||
|
||||
static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
|
||||
+ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps,
|
||||
.pcs_get_state = mtk_pcs_lynxi_get_state,
|
||||
.pcs_config = mtk_pcs_lynxi_config,
|
||||
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
|
||||
@ -0,0 +1,58 @@
|
||||
From 484d0170d6c6bbb5213d037664e9a551f793bacd Mon Sep 17 00:00:00 2001
|
||||
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
|
||||
Date: Thu, 5 Dec 2024 09:42:34 +0000
|
||||
Subject: [PATCH 3/3] net: pcs: xpcs: implement pcs_inband_caps() method
|
||||
|
||||
Report the PCS inband capabilities to phylink for XPCS.
|
||||
|
||||
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
|
||||
Link: https://patch.msgid.link/E1tJ8NW-006L5V-I9@rmk-PC.armlinux.org.uk
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/pcs/pcs-xpcs.c | 28 ++++++++++++++++++++++++++++
|
||||
1 file changed, 28 insertions(+)
|
||||
|
||||
--- a/drivers/net/pcs/pcs-xpcs.c
|
||||
+++ b/drivers/net/pcs/pcs-xpcs.c
|
||||
@@ -628,6 +628,33 @@ static int xpcs_validate(struct phylink_
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
|
||||
+ phy_interface_t interface)
|
||||
+{
|
||||
+ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
|
||||
+ const struct xpcs_compat *compat;
|
||||
+
|
||||
+ compat = xpcs_find_compat(xpcs->id, interface);
|
||||
+ if (!compat)
|
||||
+ return 0;
|
||||
+
|
||||
+ switch (compat->an_mode) {
|
||||
+ case DW_AN_C73:
|
||||
+ return LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ case DW_AN_C37_SGMII:
|
||||
+ case DW_AN_C37_1000BASEX:
|
||||
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
|
||||
+
|
||||
+ case DW_10GBASER:
|
||||
+ case DW_2500BASEX:
|
||||
+ return LINK_INBAND_DISABLE;
|
||||
+
|
||||
+ default:
|
||||
+ return 0;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
|
||||
{
|
||||
int i, j;
|
||||
@@ -1331,6 +1358,7 @@ static const struct xpcs_id xpcs_id_list
|
||||
|
||||
static const struct phylink_pcs_ops xpcs_phylink_ops = {
|
||||
.pcs_validate = xpcs_validate,
|
||||
+ .pcs_inband_caps = xpcs_inband_caps,
|
||||
.pcs_config = xpcs_config,
|
||||
.pcs_get_state = xpcs_get_state,
|
||||
.pcs_an_restart = xpcs_an_restart,
|
||||
@ -242,7 +242,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
refcount_t refcnt;
|
||||
unsigned long flags;
|
||||
size_t priv_size;
|
||||
@@ -1966,10 +1967,10 @@ int phy_ethtool_get_link_ksettings(struc
|
||||
@@ -2000,10 +2001,10 @@ int phy_ethtool_get_link_ksettings(struc
|
||||
int phy_ethtool_set_link_ksettings(struct net_device *ndev,
|
||||
const struct ethtool_link_ksettings *cmd);
|
||||
int phy_ethtool_nway_reset(struct net_device *ndev);
|
||||
@ -255,7 +255,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
|
||||
int __init mdio_bus_init(void);
|
||||
void mdio_bus_exit(void);
|
||||
@@ -1992,46 +1993,65 @@ int __phy_hwtstamp_set(struct phy_device
|
||||
@@ -2026,46 +2027,65 @@ int __phy_hwtstamp_set(struct phy_device
|
||||
struct kernel_hwtstamp_config *config,
|
||||
struct netlink_ext_ack *extack);
|
||||
|
||||
|
||||
@ -171,7 +171,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
* @regnum: register number to modify
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -2054,6 +2054,22 @@ static inline int __phy_package_write(st
|
||||
@@ -2088,6 +2088,22 @@ static inline int __phy_package_write(st
|
||||
return __mdiobus_write(phydev->mdio.bus, addr, regnum, val);
|
||||
}
|
||||
|
||||
|
||||
@ -170,7 +170,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
refcount_t refcnt;
|
||||
unsigned long flags;
|
||||
size_t priv_size;
|
||||
@@ -1968,9 +1971,12 @@ int phy_ethtool_set_link_ksettings(struc
|
||||
@@ -2002,9 +2005,12 @@ int phy_ethtool_set_link_ksettings(struc
|
||||
const struct ethtool_link_ksettings *cmd);
|
||||
int phy_ethtool_nway_reset(struct net_device *ndev);
|
||||
int phy_package_join(struct phy_device *phydev, int base_addr, size_t priv_size);
|
||||
|
||||
@ -89,7 +89,7 @@ Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
}
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1846,7 +1846,7 @@ int genphy_write_mmd_unsupported(struct
|
||||
@@ -1880,7 +1880,7 @@ int genphy_write_mmd_unsupported(struct
|
||||
|
||||
/* Clause 37 */
|
||||
int genphy_c37_config_aneg(struct phy_device *phydev);
|
||||
|
||||
@ -261,7 +261,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
}
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -972,7 +972,8 @@ struct phy_driver {
|
||||
@@ -1003,7 +1003,8 @@ struct phy_driver {
|
||||
* driver for the given phydev. If NULL, matching is based on
|
||||
* phy_id and phy_id_mask.
|
||||
*/
|
||||
|
||||
@ -97,7 +97,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
static ssize_t
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1812,6 +1812,9 @@ char *phy_attached_info_irq(struct phy_d
|
||||
@@ -1846,6 +1846,9 @@ char *phy_attached_info_irq(struct phy_d
|
||||
__malloc;
|
||||
void phy_attached_info(struct phy_device *phydev);
|
||||
|
||||
|
||||
@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
cdev->brightness_set_blocking = phy_led_set_brightness;
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -867,6 +867,15 @@ struct phy_led {
|
||||
@@ -885,6 +885,15 @@ struct phy_led {
|
||||
|
||||
#define to_phy_led(d) container_of(d, struct phy_led, led_cdev)
|
||||
|
||||
@ -76,7 +76,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
/**
|
||||
* struct phy_driver - Driver structure for a particular PHY type
|
||||
*
|
||||
@@ -1144,6 +1153,19 @@ struct phy_driver {
|
||||
@@ -1175,6 +1184,19 @@ struct phy_driver {
|
||||
int (*led_hw_control_get)(struct phy_device *dev, u8 index,
|
||||
unsigned long *rules);
|
||||
|
||||
|
||||
@ -39,7 +39,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
if (!phydev->drv->led_polarity_set)
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -869,8 +869,9 @@ struct phy_led {
|
||||
@@ -887,8 +887,9 @@ struct phy_led {
|
||||
|
||||
/* Modes for PHY LED configuration */
|
||||
enum phy_led_modes {
|
||||
|
||||
@ -17,7 +17,7 @@ Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -712,18 +712,16 @@ static int phylink_validate_mask(struct
|
||||
@@ -732,18 +732,16 @@ static int phylink_validate_mask(struct
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, };
|
||||
__ETHTOOL_DECLARE_LINK_MODE_MASK(s);
|
||||
struct phylink_link_state t;
|
||||
|
||||
@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -704,26 +704,44 @@ static int phylink_validate_mac_and_pcs(
|
||||
@@ -724,26 +724,44 @@ static int phylink_validate_mac_and_pcs(
|
||||
return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -704,7 +704,7 @@ static int phylink_validate_mac_and_pcs(
|
||||
@@ -724,7 +724,7 @@ static int phylink_validate_mac_and_pcs(
|
||||
return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
|
||||
}
|
||||
|
||||
@ -26,7 +26,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
const unsigned long *supported,
|
||||
const struct phylink_link_state *state,
|
||||
phy_interface_t interface,
|
||||
@@ -719,6 +719,9 @@ static void phylink_validate_one(struct
|
||||
@@ -739,6 +739,9 @@ static void phylink_validate_one(struct
|
||||
tmp_state = *state;
|
||||
tmp_state.interface = interface;
|
||||
|
||||
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
if (!phylink_validate_mac_and_pcs(pl, tmp_supported, &tmp_state)) {
|
||||
phylink_dbg(pl, " interface %u (%s) rate match %s supports %*pbl\n",
|
||||
interface, phy_modes(interface),
|
||||
@@ -740,7 +743,7 @@ static int phylink_validate_mask(struct
|
||||
@@ -760,7 +763,7 @@ static int phylink_validate_mask(struct
|
||||
int interface;
|
||||
|
||||
for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX)
|
||||
|
||||
@ -17,7 +17,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -734,7 +734,8 @@ static void phylink_validate_one(struct
|
||||
@@ -754,7 +754,8 @@ static void phylink_validate_one(struct
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
struct phylink_link_state *state,
|
||||
const unsigned long *interfaces)
|
||||
{
|
||||
@@ -743,7 +744,7 @@ static int phylink_validate_mask(struct
|
||||
@@ -763,7 +764,7 @@ static int phylink_validate_mask(struct
|
||||
int interface;
|
||||
|
||||
for_each_set_bit(interface, interfaces, PHY_INTERFACE_MODE_MAX)
|
||||
@ -36,7 +36,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
all_s, all_adv);
|
||||
|
||||
linkmode_copy(supported, all_s);
|
||||
@@ -758,7 +759,8 @@ static int phylink_validate(struct phyli
|
||||
@@ -778,7 +779,8 @@ static int phylink_validate(struct phyli
|
||||
const unsigned long *interfaces = pl->config->supported_interfaces;
|
||||
|
||||
if (state->interface == PHY_INTERFACE_MODE_NA)
|
||||
@ -46,7 +46,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
if (!test_bit(state->interface, interfaces))
|
||||
return -EINVAL;
|
||||
@@ -3194,7 +3196,8 @@ static int phylink_sfp_config_optical(st
|
||||
@@ -3465,7 +3467,8 @@ static int phylink_sfp_config_optical(st
|
||||
/* For all the interfaces that are supported, reduce the sfp_support
|
||||
* mask to only those link modes that can be supported.
|
||||
*/
|
||||
|
||||
@ -22,7 +22,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -1775,6 +1775,35 @@ static void phylink_phy_change(struct ph
|
||||
@@ -2019,6 +2019,35 @@ static void phylink_phy_change(struct ph
|
||||
phylink_pause_to_str(pl->phy_state.pause));
|
||||
}
|
||||
|
||||
@ -58,7 +58,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
|
||||
phy_interface_t interface)
|
||||
{
|
||||
@@ -1795,32 +1824,9 @@ static int phylink_bringup_phy(struct ph
|
||||
@@ -2039,32 +2068,9 @@ static int phylink_bringup_phy(struct ph
|
||||
memset(&config, 0, sizeof(config));
|
||||
linkmode_copy(supported, phy->supported);
|
||||
linkmode_copy(config.advertising, phy->advertising);
|
||||
|
||||
@ -40,7 +40,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -121,6 +121,19 @@ do { \
|
||||
@@ -123,6 +123,19 @@ do { \
|
||||
})
|
||||
#endif
|
||||
|
||||
@ -60,7 +60,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
/**
|
||||
* phylink_set_port_modes() - set the port type modes in the ethtool mask
|
||||
* @mask: ethtool link mode mask
|
||||
@@ -1779,6 +1792,47 @@ static int phylink_validate_phy(struct p
|
||||
@@ -2023,6 +2036,47 @@ static int phylink_validate_phy(struct p
|
||||
unsigned long *supported,
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
@ -108,7 +108,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
/* Check whether we would use rate matching for the proposed interface
|
||||
* mode.
|
||||
*/
|
||||
@@ -3047,19 +3101,6 @@ static void phylink_sfp_detach(void *ups
|
||||
@@ -3318,19 +3372,6 @@ static void phylink_sfp_detach(void *ups
|
||||
pl->netdev->sfp_bus = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
@@ -129,14 +129,23 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
|
||||
@ -41,7 +41,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
}
|
||||
|
||||
static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
|
||||
@@ -142,7 +151,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
@@ -157,7 +166,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
|
||||
bool mode_changed = false, changed;
|
||||
@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
int advertise, link_timer;
|
||||
|
||||
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
|
||||
@@ -165,9 +174,8 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
@@ -180,9 +189,8 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII)
|
||||
sgm_mode |= SGMII_SPEED_DUPLEX_AN;
|
||||
|
||||
@ -13,7 +13,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
|
||||
@@ -114,14 +114,23 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
@@ -129,14 +129,23 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
struct phylink_link_state *state)
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
|
||||
@ -41,7 +41,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
}
|
||||
|
||||
static void mtk_sgmii_reset(struct mtk_pcs_lynxi *mpcs)
|
||||
@@ -142,7 +151,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
@@ -157,7 +166,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs = pcs_to_mtk_pcs_lynxi(pcs);
|
||||
bool mode_changed = false, changed;
|
||||
@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
int advertise, link_timer;
|
||||
|
||||
advertise = phylink_mii_c22_pcs_encode_advertisement(interface,
|
||||
@@ -165,9 +174,8 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
@@ -180,9 +189,8 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
if (neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED) {
|
||||
if (interface == PHY_INTERFACE_MODE_SGMII)
|
||||
sgm_mode |= SGMII_SPEED_DUPLEX_AN;
|
||||
|
||||
@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
sysfs_remove_link(&dev->dev.kobj, "phydev");
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -996,6 +996,12 @@ struct phy_driver {
|
||||
@@ -1027,6 +1027,12 @@ struct phy_driver {
|
||||
/** @handle_interrupt: Override default interrupt handling */
|
||||
irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -2086,7 +2086,7 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
@@ -2264,7 +2264,7 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
{
|
||||
struct fwnode_handle *phy_fwnode;
|
||||
struct phy_device *phy_dev;
|
||||
@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
/* Fixed links and 802.3z are handled without needing a PHY */
|
||||
if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
|
||||
@@ -2116,6 +2116,25 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
@@ -2294,6 +2294,25 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
if (pl->config->mac_requires_rxc)
|
||||
flags |= PHY_F_RXC_ALWAYS_ON;
|
||||
|
||||
|
||||
@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
|
||||
{
|
||||
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
|
||||
@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
@@ -117,6 +139,17 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
FIELD_GET(SGMII_LPA, adv));
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising,
|
||||
@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
@@ -162,6 +195,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
SGMII_PHYA_PWD);
|
||||
|
||||
/* Reset SGMII PCS state */
|
||||
@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
|
||||
SGMII_SW_RESET);
|
||||
|
||||
@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct
|
||||
@@ -248,10 +282,29 @@ static void mtk_pcs_lynxi_link_up(struct
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
mpcs->interface = PHY_INTERFACE_MODE_NA;
|
||||
}
|
||||
|
||||
@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_
|
||||
@@ -262,11 +315,12 @@ static const struct phylink_pcs_ops mtk_
|
||||
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
|
||||
.pcs_link_up = mtk_pcs_lynxi_link_up,
|
||||
.pcs_disable = mtk_pcs_lynxi_disable,
|
||||
@ -151,7 +151,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs;
|
||||
u32 id, ver;
|
||||
@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
@@ -274,29 +328,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
|
||||
ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
|
||||
if (ret < 0)
|
||||
@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
mpcs->ana_rgc3 = ana_rgc3;
|
||||
mpcs->regmap = regmap;
|
||||
@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
@@ -307,6 +365,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
mpcs->interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
return &mpcs->pcs;
|
||||
@ -206,7 +206,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
}
|
||||
EXPORT_SYMBOL(mtk_pcs_lynxi_create);
|
||||
|
||||
@@ -303,5 +368,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
|
||||
@@ -319,5 +384,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
|
||||
}
|
||||
EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
|
||||
|
||||
|
||||
@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
|
||||
sysfs_remove_link(&dev->dev.kobj, "phydev");
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -977,6 +977,12 @@ struct phy_driver {
|
||||
@@ -1008,6 +1008,12 @@ struct phy_driver {
|
||||
/** @handle_interrupt: Override default interrupt handling */
|
||||
irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -2017,7 +2017,7 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
@@ -2261,7 +2261,7 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
{
|
||||
struct fwnode_handle *phy_fwnode;
|
||||
struct phy_device *phy_dev;
|
||||
@ -29,7 +29,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
/* Fixed links and 802.3z are handled without needing a PHY */
|
||||
if (pl->cfg_link_an_mode == MLO_AN_FIXED ||
|
||||
@@ -2044,6 +2044,25 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
@@ -2288,6 +2288,25 @@ int phylink_fwnode_phy_connect(struct ph
|
||||
pl->link_config.interface = pl->link_interface;
|
||||
}
|
||||
|
||||
|
||||
@ -79,7 +79,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
|
||||
{
|
||||
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
|
||||
@@ -102,6 +124,17 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
@@ -117,6 +139,17 @@ static void mtk_pcs_lynxi_get_state(stru
|
||||
FIELD_GET(SGMII_LPA, adv));
|
||||
}
|
||||
|
||||
@ -97,7 +97,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
static int mtk_pcs_lynxi_config(struct phylink_pcs *pcs, unsigned int neg_mode,
|
||||
phy_interface_t interface,
|
||||
const unsigned long *advertising,
|
||||
@@ -147,6 +180,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
@@ -162,6 +195,7 @@ static int mtk_pcs_lynxi_config(struct p
|
||||
SGMII_PHYA_PWD);
|
||||
|
||||
/* Reset SGMII PCS state */
|
||||
@ -105,7 +105,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
regmap_set_bits(mpcs->regmap, SGMSYS_RESERVED_0,
|
||||
SGMII_SW_RESET);
|
||||
|
||||
@@ -233,10 +267,29 @@ static void mtk_pcs_lynxi_link_up(struct
|
||||
@@ -248,10 +282,29 @@ static void mtk_pcs_lynxi_link_up(struct
|
||||
}
|
||||
}
|
||||
|
||||
@ -135,7 +135,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
mpcs->interface = PHY_INTERFACE_MODE_NA;
|
||||
}
|
||||
|
||||
@@ -246,11 +299,12 @@ static const struct phylink_pcs_ops mtk_
|
||||
@@ -262,11 +315,12 @@ static const struct phylink_pcs_ops mtk_
|
||||
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
|
||||
.pcs_link_up = mtk_pcs_lynxi_link_up,
|
||||
.pcs_disable = mtk_pcs_lynxi_disable,
|
||||
@ -151,7 +151,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
{
|
||||
struct mtk_pcs_lynxi *mpcs;
|
||||
u32 id, ver;
|
||||
@@ -258,29 +312,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
@@ -274,29 +328,33 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
|
||||
ret = regmap_read(regmap, SGMSYS_PCS_DEVICE_ID, &id);
|
||||
if (ret < 0)
|
||||
@ -192,7 +192,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
|
||||
mpcs->ana_rgc3 = ana_rgc3;
|
||||
mpcs->regmap = regmap;
|
||||
@@ -291,6 +349,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
@@ -307,6 +365,13 @@ struct phylink_pcs *mtk_pcs_lynxi_create
|
||||
mpcs->interface = PHY_INTERFACE_MODE_NA;
|
||||
|
||||
return &mpcs->pcs;
|
||||
@ -206,7 +206,7 @@ Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
||||
}
|
||||
EXPORT_SYMBOL(mtk_pcs_lynxi_create);
|
||||
|
||||
@@ -303,4 +368,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
|
||||
@@ -319,4 +384,142 @@ void mtk_pcs_lynxi_destroy(struct phylin
|
||||
}
|
||||
EXPORT_SYMBOL(mtk_pcs_lynxi_destroy);
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
|
||||
case PHY_INTERFACE_MODE_QUSGMII:
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -230,6 +230,7 @@ static int phylink_interface_max_speed(p
|
||||
@@ -250,6 +250,7 @@ static int phylink_interface_max_speed(p
|
||||
case PHY_INTERFACE_MODE_GMII:
|
||||
return SPEED_1000;
|
||||
|
||||
@ -44,7 +44,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
case PHY_INTERFACE_MODE_10G_QXGMII:
|
||||
return SPEED_2500;
|
||||
@@ -544,6 +545,7 @@ static unsigned long phylink_get_capabil
|
||||
@@ -564,6 +565,7 @@ static unsigned long phylink_get_capabil
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
|
||||
@ -25,7 +25,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
|
||||
case PHY_INTERFACE_MODE_QUSGMII:
|
||||
--- a/drivers/net/phy/phylink.c
|
||||
+++ b/drivers/net/phy/phylink.c
|
||||
@@ -231,6 +231,7 @@ static int phylink_interface_max_speed(p
|
||||
@@ -251,6 +251,7 @@ static int phylink_interface_max_speed(p
|
||||
return SPEED_1000;
|
||||
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
@ -33,7 +33,7 @@ Signed-off-by: Bhaskar Upadhaya <Bhaskar.Upadhaya@nxp.com>
|
||||
return SPEED_2500;
|
||||
|
||||
case PHY_INTERFACE_MODE_5GBASER:
|
||||
@@ -539,6 +540,7 @@ unsigned long phylink_get_capabilities(p
|
||||
@@ -559,6 +560,7 @@ unsigned long phylink_get_capabilities(p
|
||||
break;
|
||||
|
||||
case PHY_INTERFACE_MODE_2500BASEX:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
---
|
||||
--- a/drivers/net/ethernet/marvell/mvneta.c
|
||||
+++ b/drivers/net/ethernet/marvell/mvneta.c
|
||||
@@ -5296,6 +5296,16 @@ static int mvneta_setup_tc(struct net_de
|
||||
@@ -5303,6 +5303,16 @@ static int mvneta_setup_tc(struct net_de
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@ Signed-off-by: Felix Fietkau <nbd@nbd.name>
|
||||
static const struct net_device_ops mvneta_netdev_ops = {
|
||||
.ndo_open = mvneta_open,
|
||||
.ndo_stop = mvneta_stop,
|
||||
@@ -5306,6 +5316,9 @@ static const struct net_device_ops mvnet
|
||||
@@ -5313,6 +5323,9 @@ static const struct net_device_ops mvnet
|
||||
.ndo_fix_features = mvneta_fix_features,
|
||||
.ndo_get_stats64 = mvneta_get_stats64,
|
||||
.ndo_eth_ioctl = mvneta_ioctl,
|
||||
|
||||
@ -170,7 +170,7 @@ Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
/* This is optional functionality. If not supported, we may get an error
|
||||
--- a/include/linux/phy.h
|
||||
+++ b/include/linux/phy.h
|
||||
@@ -1897,6 +1897,7 @@ int genphy_c45_an_config_aneg(struct phy
|
||||
@@ -1931,6 +1931,7 @@ int genphy_c45_an_config_aneg(struct phy
|
||||
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
|
||||
int genphy_c45_read_mdix(struct phy_device *phydev);
|
||||
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user