Skip to content

Commit f029c40

Browse files
committed
Merge branch 'net-add-negotiation-of-in-band-capabilities'
Russell King says: ==================== net: add negotiation of in-band capabilities This is a repost without RFC for this series, shrunk down to 13 patches by removing the non-Marvell PCS. Phylink's handling of in-band has been deficient for a long time, and people keep hitting problems with it. Notably, situations with the way- to-late standardized 2500Base-X and whether that should or should not have in-band enabled. We have also been carrying a hack in the form of phylink_phy_no_inband() for a PHY that has been used on a SFP module, but has no in-band capabilities, not even for SGMII. When phylink is trying to operate in in-band mode, this series will look at the capabilities of the MAC-side PCS and PHY, and work out whether in-band can or should be used, programming the PHY as appropriate. This includes in-band bypass mode at the PHY. We don't... yet... support bypass on the MAC side PCS, because that requires yet more complexity. Patch 1 passes struct phylink and struct phylink_pcs into phylink_pcs_neg_mode() so we can look at more state in this function in a future patch. Patch 2 splits "cur_link_an_mode" (the MLO_AN_* mode) into two separate purposes - a requested and an active mode. The active mode is the one we will be using for the MAC, which becomes dependent on the result of in-band negotiation. Patch 3 adds debug to phylink_major_config() so we can see what is going on with the requested and active AN modes. Patch 4 adds to phylib a method to get the in-band capabilities of the PHY from phylib. Patches 5 and 6 add implementations for BCM84881 and some Marvell PHYs found on SFPs. Patch 7 adds to phylib a method to configure the PHY in-band signalling, and patch 8 implements it for those Marvell PHYs that support the method in patch 4. Patch 9 does the same as patch 4 but for the MAC-side PCS, with patches 10 and 11 adding support to Marvell NETA and PP2. Patch 12 adds the code to phylink_pcs_neg_mode() which looks at the capabilities, and works out whether to use in-band or out-band mode for driving the link between the MAC PCS and PHY. Patch 13 removes the phylink_phy_no_inband() hack now that we are publishing the in-band capabilities from the BCM84881 PHY driver. Three more PCS, omitted from this series due to the limit of 15 patches, will be sent once this has been merged. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 4485043 + 77ac9a8 commit f029c40

File tree

8 files changed

+474
-92
lines changed

8 files changed

+474
-92
lines changed

drivers/net/ethernet/marvell/mvneta.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3960,20 +3960,27 @@ static struct mvneta_port *mvneta_pcs_to_port(struct phylink_pcs *pcs)
39603960
return container_of(pcs, struct mvneta_port, phylink_pcs);
39613961
}
39623962

3963-
static int mvneta_pcs_validate(struct phylink_pcs *pcs,
3964-
unsigned long *supported,
3965-
const struct phylink_link_state *state)
3963+
static unsigned int mvneta_pcs_inband_caps(struct phylink_pcs *pcs,
3964+
phy_interface_t interface)
39663965
{
3967-
/* We only support QSGMII, SGMII, 802.3z and RGMII modes.
3968-
* When in 802.3z mode, we must have AN enabled:
3966+
/* When operating in an 802.3z mode, we must have AN enabled:
39693967
* "Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
39703968
* When <PortType> = 1 (1000BASE-X) this field must be set to 1."
3969+
* Therefore, inband is "required".
39713970
*/
3972-
if (phy_interface_mode_is_8023z(state->interface) &&
3973-
!phylink_test(state->advertising, Autoneg))
3974-
return -EINVAL;
3971+
if (phy_interface_mode_is_8023z(interface))
3972+
return LINK_INBAND_ENABLE;
39753973

3976-
return 0;
3974+
/* QSGMII, SGMII and RGMII can be configured to use inband
3975+
* signalling of the AN result. Indicate these as "possible".
3976+
*/
3977+
if (interface == PHY_INTERFACE_MODE_SGMII ||
3978+
interface == PHY_INTERFACE_MODE_QSGMII ||
3979+
phy_interface_mode_is_rgmii(interface))
3980+
return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
3981+
3982+
/* For any other modes, indicate that inband is not supported. */
3983+
return LINK_INBAND_DISABLE;
39773984
}
39783985

39793986
static void mvneta_pcs_get_state(struct phylink_pcs *pcs,
@@ -4071,7 +4078,7 @@ static void mvneta_pcs_an_restart(struct phylink_pcs *pcs)
40714078
}
40724079

40734080
static const struct phylink_pcs_ops mvneta_phylink_pcs_ops = {
4074-
.pcs_validate = mvneta_pcs_validate,
4081+
.pcs_inband_caps = mvneta_pcs_inband_caps,
40754082
.pcs_get_state = mvneta_pcs_get_state,
40764083
.pcs_config = mvneta_pcs_config,
40774084
.pcs_an_restart = mvneta_pcs_an_restart,

drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6224,19 +6224,26 @@ static const struct phylink_pcs_ops mvpp2_phylink_xlg_pcs_ops = {
62246224
.pcs_config = mvpp2_xlg_pcs_config,
62256225
};
62266226

6227-
static int mvpp2_gmac_pcs_validate(struct phylink_pcs *pcs,
6228-
unsigned long *supported,
6229-
const struct phylink_link_state *state)
6227+
static unsigned int mvpp2_gmac_pcs_inband_caps(struct phylink_pcs *pcs,
6228+
phy_interface_t interface)
62306229
{
6231-
/* When in 802.3z mode, we must have AN enabled:
6230+
/* When operating in an 802.3z mode, we must have AN enabled:
62326231
* Bit 2 Field InBandAnEn In-band Auto-Negotiation enable. ...
62336232
* When <PortType> = 1 (1000BASE-X) this field must be set to 1.
6233+
* Therefore, inband is "required".
62346234
*/
6235-
if (phy_interface_mode_is_8023z(state->interface) &&
6236-
!phylink_test(state->advertising, Autoneg))
6237-
return -EINVAL;
6235+
if (phy_interface_mode_is_8023z(interface))
6236+
return LINK_INBAND_ENABLE;
62386237

6239-
return 0;
6238+
/* SGMII and RGMII can be configured to use inband signalling of the
6239+
* AN result. Indicate these as "possible".
6240+
*/
6241+
if (interface == PHY_INTERFACE_MODE_SGMII ||
6242+
phy_interface_mode_is_rgmii(interface))
6243+
return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
6244+
6245+
/* For any other modes, indicate that inband is not supported. */
6246+
return LINK_INBAND_DISABLE;
62406247
}
62416248

62426249
static void mvpp2_gmac_pcs_get_state(struct phylink_pcs *pcs,
@@ -6343,7 +6350,7 @@ static void mvpp2_gmac_pcs_an_restart(struct phylink_pcs *pcs)
63436350
}
63446351

63456352
static const struct phylink_pcs_ops mvpp2_phylink_gmac_pcs_ops = {
6346-
.pcs_validate = mvpp2_gmac_pcs_validate,
6353+
.pcs_inband_caps = mvpp2_gmac_pcs_inband_caps,
63476354
.pcs_get_state = mvpp2_gmac_pcs_get_state,
63486355
.pcs_config = mvpp2_gmac_pcs_config,
63496356
.pcs_an_restart = mvpp2_gmac_pcs_an_restart,

drivers/net/phy/bcm84881.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,11 +235,21 @@ static int bcm84881_read_status(struct phy_device *phydev)
235235
return genphy_c45_read_mdix(phydev);
236236
}
237237

238+
/* The Broadcom BCM84881 in the Methode DM7052 is unable to provide a SGMII
239+
* or 802.3z control word, so inband will not work.
240+
*/
241+
static unsigned int bcm84881_inband_caps(struct phy_device *phydev,
242+
phy_interface_t interface)
243+
{
244+
return LINK_INBAND_DISABLE;
245+
}
246+
238247
static struct phy_driver bcm84881_drivers[] = {
239248
{
240249
.phy_id = 0xae025150,
241250
.phy_id_mask = 0xfffffff0,
242251
.name = "Broadcom BCM84881",
252+
.inband_caps = bcm84881_inband_caps,
243253
.config_init = bcm84881_config_init,
244254
.probe = bcm84881_probe,
245255
.get_features = bcm84881_get_features,

drivers/net/phy/marvell.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -717,6 +717,48 @@ static int marvell_config_aneg_fiber(struct phy_device *phydev)
717717
return genphy_check_and_restart_aneg(phydev, changed);
718718
}
719719

720+
static unsigned int m88e1111_inband_caps(struct phy_device *phydev,
721+
phy_interface_t interface)
722+
{
723+
/* In 1000base-X and SGMII modes, the inband mode can be changed
724+
* through the Fibre page BMCR ANENABLE bit.
725+
*/
726+
if (interface == PHY_INTERFACE_MODE_1000BASEX ||
727+
interface == PHY_INTERFACE_MODE_SGMII)
728+
return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE |
729+
LINK_INBAND_BYPASS;
730+
731+
return 0;
732+
}
733+
734+
static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes)
735+
{
736+
u16 extsr, bmcr;
737+
int err;
738+
739+
if (phydev->interface != PHY_INTERFACE_MODE_1000BASEX &&
740+
phydev->interface != PHY_INTERFACE_MODE_SGMII)
741+
return -EINVAL;
742+
743+
if (modes == LINK_INBAND_BYPASS)
744+
extsr = MII_M1111_HWCFG_SERIAL_AN_BYPASS;
745+
else
746+
extsr = 0;
747+
748+
if (modes == LINK_INBAND_DISABLE)
749+
bmcr = 0;
750+
else
751+
bmcr = BMCR_ANENABLE;
752+
753+
err = phy_modify(phydev, MII_M1111_PHY_EXT_SR,
754+
MII_M1111_HWCFG_SERIAL_AN_BYPASS, extsr);
755+
if (err < 0)
756+
return extsr;
757+
758+
return phy_modify_paged(phydev, MII_MARVELL_FIBER_PAGE, MII_BMCR,
759+
BMCR_ANENABLE, bmcr);
760+
}
761+
720762
static int m88e1111_config_aneg(struct phy_device *phydev)
721763
{
722764
int extsr = phy_read(phydev, MII_M1111_PHY_EXT_SR);
@@ -3677,6 +3719,8 @@ static struct phy_driver marvell_drivers[] = {
36773719
.name = "Marvell 88E1112",
36783720
/* PHY_GBIT_FEATURES */
36793721
.probe = marvell_probe,
3722+
.inband_caps = m88e1111_inband_caps,
3723+
.config_inband = m88e1111_config_inband,
36803724
.config_init = m88e1112_config_init,
36813725
.config_aneg = marvell_config_aneg,
36823726
.config_intr = marvell_config_intr,
@@ -3698,6 +3742,8 @@ static struct phy_driver marvell_drivers[] = {
36983742
/* PHY_GBIT_FEATURES */
36993743
.flags = PHY_POLL_CABLE_TEST,
37003744
.probe = marvell_probe,
3745+
.inband_caps = m88e1111_inband_caps,
3746+
.config_inband = m88e1111_config_inband,
37013747
.config_init = m88e1111gbe_config_init,
37023748
.config_aneg = m88e1111_config_aneg,
37033749
.read_status = marvell_read_status,
@@ -3721,6 +3767,8 @@ static struct phy_driver marvell_drivers[] = {
37213767
.name = "Marvell 88E1111 (Finisar)",
37223768
/* PHY_GBIT_FEATURES */
37233769
.probe = marvell_probe,
3770+
.inband_caps = m88e1111_inband_caps,
3771+
.config_inband = m88e1111_config_inband,
37243772
.config_init = m88e1111gbe_config_init,
37253773
.config_aneg = m88e1111_config_aneg,
37263774
.read_status = marvell_read_status,

drivers/net/phy/phy.c

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,6 +1005,59 @@ static int phy_check_link_status(struct phy_device *phydev)
10051005
return 0;
10061006
}
10071007

1008+
/**
1009+
* phy_inband_caps - query which in-band signalling modes are supported
1010+
* @phydev: a pointer to a &struct phy_device
1011+
* @interface: the interface mode for the PHY
1012+
*
1013+
* Returns zero if it is unknown what in-band signalling is supported by the
1014+
* PHY (e.g. because the PHY driver doesn't implement the method.) Otherwise,
1015+
* returns a bit mask of the LINK_INBAND_* values from
1016+
* &enum link_inband_signalling to describe which inband modes are supported
1017+
* by the PHY for this interface mode.
1018+
*/
1019+
unsigned int phy_inband_caps(struct phy_device *phydev,
1020+
phy_interface_t interface)
1021+
{
1022+
if (phydev->drv && phydev->drv->inband_caps)
1023+
return phydev->drv->inband_caps(phydev, interface);
1024+
1025+
return 0;
1026+
}
1027+
EXPORT_SYMBOL_GPL(phy_inband_caps);
1028+
1029+
/**
1030+
* phy_config_inband - configure the desired PHY in-band mode
1031+
* @phydev: the phy_device struct
1032+
* @modes: in-band modes to configure
1033+
*
1034+
* Description: disables, enables or enables-with-bypass in-band signalling
1035+
* between the PHY and host system.
1036+
*
1037+
* Returns: zero on success, or negative errno value.
1038+
*/
1039+
int phy_config_inband(struct phy_device *phydev, unsigned int modes)
1040+
{
1041+
int err;
1042+
1043+
if (!!(modes & LINK_INBAND_DISABLE) +
1044+
!!(modes & LINK_INBAND_ENABLE) +
1045+
!!(modes & LINK_INBAND_BYPASS) != 1)
1046+
return -EINVAL;
1047+
1048+
mutex_lock(&phydev->lock);
1049+
if (!phydev->drv)
1050+
err = -EIO;
1051+
else if (!phydev->drv->config_inband)
1052+
err = -EOPNOTSUPP;
1053+
else
1054+
err = phydev->drv->config_inband(phydev, modes);
1055+
mutex_unlock(&phydev->lock);
1056+
1057+
return err;
1058+
}
1059+
EXPORT_SYMBOL(phy_config_inband);
1060+
10081061
/**
10091062
* _phy_start_aneg - start auto-negotiation for this PHY device
10101063
* @phydev: the phy_device struct

0 commit comments

Comments
 (0)