* [PATCH net-next 1/5] net: phy: marvell10g: update header comments
2017-12-29 12:44 [PATCH net-next 0/5] marvell10g updates Russell King - ARM Linux
@ 2017-12-29 12:46 ` Russell King
2018-01-02 16:06 ` Andrew Lunn
2017-12-29 12:46 ` [PATCH net-next 2/5] net: phy: marvell10g: add MDI swap reporting Russell King
` (4 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Russell King @ 2017-12-29 12:46 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
Update header comments to indicate the newly found behaviour with XAUI
interfaces.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/marvell10g.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 87f18cee1533..0d503493ac14 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -6,12 +6,18 @@
*
* There appears to be several different data paths through the PHY which
* are automatically managed by the PHY. The following has been determined
- * via observation and experimentation:
+ * via observation and experimentation for a setup using single-lane Serdes:
*
* SGMII PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for <= 1G)
* 10GBASE-KR PHYXS -- BASE-T PCS -- 10G PMA -- AN -- Copper (for 10G)
* 10GBASE-KR PHYXS -- BASE-R PCS -- Fiber
*
+ * With XAUI, observation shows:
+ *
+ * XAUI PHYXS -- <appropriate PCS as above>
+ *
+ * and no switching of the host interface mode occurs.
+ *
* If both the fiber and copper ports are connected, the first to gain
* link takes priority and the other port is completely locked out.
*/
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 2/5] net: phy: marvell10g: add MDI swap reporting
2017-12-29 12:44 [PATCH net-next 0/5] marvell10g updates Russell King - ARM Linux
2017-12-29 12:46 ` [PATCH net-next 1/5] net: phy: marvell10g: update header comments Russell King
@ 2017-12-29 12:46 ` Russell King
2018-01-02 16:08 ` Andrew Lunn
2017-12-29 12:46 ` [PATCH net-next 3/5] net: phy: marvell10g: clean up interface mode switching Russell King
` (3 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Russell King @ 2017-12-29 12:46 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
Add reporting of the MDI swap to the Marvell 10G PHY driver by providing
a generic implementation for the standard 10GBASE-T pair swap register
and polarity register. We also support reading the MDI swap status for
1G and below from a PCS register.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/marvell10g.c | 31 +++++++++++++++++++++++++++++++
drivers/net/phy/phy-c45.c | 33 +++++++++++++++++++++++++++++++++
include/linux/phy.h | 1 +
3 files changed, 65 insertions(+)
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 0d503493ac14..632f2ec15e39 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -31,6 +31,11 @@ enum {
MV_PCS_BASE_R = 0x1000,
MV_PCS_1000BASEX = 0x2000,
+ MV_PCS_PAIRSWAP = 0x8182,
+ MV_PCS_PAIRSWAP_MASK = 0x0003,
+ MV_PCS_PAIRSWAP_AB = 0x0002,
+ MV_PCS_PAIRSWAP_NONE = 0x0003,
+
/* These registers appear at 0x800X and 0xa00X - the 0xa00X control
* registers appear to set themselves to the 0x800X when AN is
* restarted, but status registers appear readable from either.
@@ -267,6 +272,9 @@ static int mv3310_config_aneg(struct phy_device *phydev)
u32 advertising;
int ret;
+ /* We don't support manual MDI control */
+ phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+
if (phydev->autoneg == AUTONEG_DISABLE) {
ret = genphy_c45_pma_setup_forced(phydev);
if (ret < 0)
@@ -356,6 +364,7 @@ static int mv3310_read_status(struct phy_device *phydev)
phydev->link = 0;
phydev->pause = 0;
phydev->asym_pause = 0;
+ phydev->mdix = 0;
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_BASE_R + MDIO_STAT1);
if (val < 0)
@@ -410,6 +419,28 @@ static int mv3310_read_status(struct phy_device *phydev)
return val;
}
+ if (phydev->speed == SPEED_10000) {
+ val = genphy_c45_read_mdix(phydev);
+ if (val < 0)
+ return val;
+ } else {
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_PCS_PAIRSWAP);
+ if (val < 0)
+ return val;
+
+ switch (val & MV_PCS_PAIRSWAP_MASK) {
+ case MV_PCS_PAIRSWAP_AB:
+ phydev->mdix = ETH_TP_MDI_X;
+ break;
+ case MV_PCS_PAIRSWAP_NONE:
+ phydev->mdix = ETH_TP_MDI;
+ break;
+ default:
+ phydev->mdix = ETH_TP_MDI_INVALID;
+ break;
+ }
+ }
+
if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
/* The PHY automatically switches its serdes interface (and
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index dada819c6b78..a4576859afae 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -233,6 +233,39 @@ int genphy_c45_read_pma(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(genphy_c45_read_pma);
+/**
+ * genphy_c45_read_mdix - read mdix status from PMA
+ * @phydev: target phy_device struct
+ */
+int genphy_c45_read_mdix(struct phy_device *phydev)
+{
+ int val;
+
+ if (phydev->speed == SPEED_10000) {
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD,
+ MDIO_PMA_10GBT_SWAPPOL);
+ if (val < 0)
+ return val;
+
+ switch (val) {
+ case MDIO_PMA_10GBT_SWAPPOL_ABNX | MDIO_PMA_10GBT_SWAPPOL_CDNX:
+ phydev->mdix = ETH_TP_MDI;
+ break;
+
+ case 0:
+ phydev->mdix = ETH_TP_MDI_X;
+ break;
+
+ default:
+ phydev->mdix = ETH_TP_MDI_INVALID;
+ break;
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
+
/* The gen10g_* functions are the old Clause 45 stub */
static int gen10g_config_aneg(struct phy_device *phydev)
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 0ee4ece312da..bb89a60716c2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -943,6 +943,7 @@ int genphy_c45_read_lpa(struct phy_device *phydev);
int genphy_c45_read_pma(struct phy_device *phydev);
int genphy_c45_pma_setup_forced(struct phy_device *phydev);
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
+int genphy_c45_read_mdix(struct phy_device *phydev);
static inline int phy_read_status(struct phy_device *phydev)
{
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 3/5] net: phy: marvell10g: clean up interface mode switching
2017-12-29 12:44 [PATCH net-next 0/5] marvell10g updates Russell King - ARM Linux
2017-12-29 12:46 ` [PATCH net-next 1/5] net: phy: marvell10g: update header comments Russell King
2017-12-29 12:46 ` [PATCH net-next 2/5] net: phy: marvell10g: add MDI swap reporting Russell King
@ 2017-12-29 12:46 ` Russell King
2018-01-02 16:09 ` Andrew Lunn
2017-12-29 12:46 ` [PATCH net-next 4/5] net: phy: add helper to convert negotiation result to phy settings Russell King
` (2 subsequent siblings)
5 siblings, 1 reply; 12+ messages in thread
From: Russell King @ 2017-12-29 12:46 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
Centralise the PHY interface mode switching, rather than having it in
two places.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/marvell10g.c | 36 ++++++++++++++++++++----------------
1 file changed, 20 insertions(+), 16 deletions(-)
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index 632f2ec15e39..c01bb2654d69 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -333,6 +333,24 @@ static int mv3310_aneg_done(struct phy_device *phydev)
return genphy_c45_aneg_done(phydev);
}
+static void mv3310_update_interface(struct phy_device *phydev)
+{
+ if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
+ phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
+ /* The PHY automatically switches its serdes interface (and
+ * active PHYXS instance) between Cisco SGMII and 10GBase-KR
+ * modes according to the speed. Florian suggests setting
+ * phydev->interface to communicate this to the MAC. Only do
+ * this if we are already in either SGMII or 10GBase-KR mode.
+ */
+ if (phydev->speed == SPEED_10000)
+ phydev->interface = PHY_INTERFACE_MODE_10GKR;
+ else if (phydev->speed >= SPEED_10 &&
+ phydev->speed < SPEED_10000)
+ phydev->interface = PHY_INTERFACE_MODE_SGMII;
+ }
+}
+
/* 10GBASE-ER,LR,LRM,SR do not support autonegotiation. */
static int mv3310_read_10gbr_status(struct phy_device *phydev)
{
@@ -340,8 +358,7 @@ static int mv3310_read_10gbr_status(struct phy_device *phydev)
phydev->speed = SPEED_10000;
phydev->duplex = DUPLEX_FULL;
- if (phydev->interface == PHY_INTERFACE_MODE_SGMII)
- phydev->interface = PHY_INTERFACE_MODE_10GKR;
+ mv3310_update_interface(phydev);
return 0;
}
@@ -441,20 +458,7 @@ static int mv3310_read_status(struct phy_device *phydev)
}
}
- if ((phydev->interface == PHY_INTERFACE_MODE_SGMII ||
- phydev->interface == PHY_INTERFACE_MODE_10GKR) && phydev->link) {
- /* The PHY automatically switches its serdes interface (and
- * active PHYXS instance) between Cisco SGMII and 10GBase-KR
- * modes according to the speed. Florian suggests setting
- * phydev->interface to communicate this to the MAC. Only do
- * this if we are already in either SGMII or 10GBase-KR mode.
- */
- if (phydev->speed == SPEED_10000)
- phydev->interface = PHY_INTERFACE_MODE_10GKR;
- else if (phydev->speed >= SPEED_10 &&
- phydev->speed < SPEED_10000)
- phydev->interface = PHY_INTERFACE_MODE_SGMII;
- }
+ mv3310_update_interface(phydev);
return 0;
}
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 4/5] net: phy: add helper to convert negotiation result to phy settings
2017-12-29 12:44 [PATCH net-next 0/5] marvell10g updates Russell King - ARM Linux
` (2 preceding siblings ...)
2017-12-29 12:46 ` [PATCH net-next 3/5] net: phy: marvell10g: clean up interface mode switching Russell King
@ 2017-12-29 12:46 ` Russell King
2018-01-02 16:11 ` Andrew Lunn
2017-12-29 12:46 ` [PATCH net-next 5/5] net: phy: marvell10g: add support for half duplex 100M and 10M Russell King
2018-01-02 20:01 ` [PATCH net-next 0/5] marvell10g updates David Miller
5 siblings, 1 reply; 12+ messages in thread
From: Russell King @ 2017-12-29 12:46 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
Add a helper to convert the result of the autonegotiation advertisment
into the PHYs speed and duplex settings. If the result is full duplex,
also extract the pause mode settings from the link partner advertisment.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phy-core.c | 43 +++++++++++++++++++++++++++++++++++++++++++
include/linux/phy.h | 2 ++
2 files changed, 45 insertions(+)
diff --git a/drivers/net/phy/phy-core.c b/drivers/net/phy/phy-core.c
index 9c08850eed16..3d67f182b844 100644
--- a/drivers/net/phy/phy-core.c
+++ b/drivers/net/phy/phy-core.c
@@ -189,6 +189,49 @@ size_t phy_speeds(unsigned int *speeds, size_t size,
return count;
}
+/**
+ * phy_resolve_aneg_linkmode - resolve the advertisments into phy settings
+ * @phydev: The phy_device struct
+ *
+ * Resolve our and the link partner advertisments into their corresponding
+ * speed and duplex. If full duplex was negotiated, extract the pause mode
+ * from the link partner mask.
+ */
+void phy_resolve_aneg_linkmode(struct phy_device *phydev)
+{
+ u32 common = phydev->lp_advertising & phydev->advertising;
+
+ if (common & ADVERTISED_10000baseT_Full) {
+ phydev->speed = SPEED_10000;
+ phydev->duplex = DUPLEX_FULL;
+ } else if (common & ADVERTISED_1000baseT_Full) {
+ phydev->speed = SPEED_1000;
+ phydev->duplex = DUPLEX_FULL;
+ } else if (common & ADVERTISED_1000baseT_Half) {
+ phydev->speed = SPEED_1000;
+ phydev->duplex = DUPLEX_HALF;
+ } else if (common & ADVERTISED_100baseT_Full) {
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_FULL;
+ } else if (common & ADVERTISED_100baseT_Half) {
+ phydev->speed = SPEED_100;
+ phydev->duplex = DUPLEX_HALF;
+ } else if (common & ADVERTISED_10baseT_Full) {
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_FULL;
+ } else if (common & ADVERTISED_10baseT_Half) {
+ phydev->speed = SPEED_10;
+ phydev->duplex = DUPLEX_HALF;
+ }
+
+ if (phydev->duplex == DUPLEX_FULL) {
+ phydev->pause = !!(phydev->lp_advertising & ADVERTISED_Pause);
+ phydev->asym_pause = !!(phydev->lp_advertising &
+ ADVERTISED_Asym_Pause);
+ }
+}
+EXPORT_SYMBOL_GPL(phy_resolve_aneg_linkmode);
+
static void mmd_phy_indirect(struct mii_bus *bus, int phy_addr, int devad,
u16 regnum)
{
diff --git a/include/linux/phy.h b/include/linux/phy.h
index bb89a60716c2..0db52b272fd7 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -693,6 +693,8 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
size_t phy_speeds(unsigned int *speeds, size_t size,
unsigned long *mask, size_t maxbit);
+void phy_resolve_aneg_linkmode(struct phy_device *phydev);
+
/**
* phy_read_mmd - Convenience function for reading a register
* from an MMD on a given PHY.
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread* [PATCH net-next 5/5] net: phy: marvell10g: add support for half duplex 100M and 10M
2017-12-29 12:44 [PATCH net-next 0/5] marvell10g updates Russell King - ARM Linux
` (3 preceding siblings ...)
2017-12-29 12:46 ` [PATCH net-next 4/5] net: phy: add helper to convert negotiation result to phy settings Russell King
@ 2017-12-29 12:46 ` Russell King
2018-01-02 16:13 ` Andrew Lunn
2018-01-02 20:01 ` [PATCH net-next 0/5] marvell10g updates David Miller
5 siblings, 1 reply; 12+ messages in thread
From: Russell King @ 2017-12-29 12:46 UTC (permalink / raw)
To: Andrew Lunn, Florian Fainelli; +Cc: netdev
Add support for half-duplex 100M and 10M copper connections by parsing
the advertisment results rather than trying to decode the negotiated
speed from one of the PHYs "vendor" registers. This allows us to
decode the duplex as well, which means we can support half-duplex mode
for the slower speeds.
Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/marvell10g.c | 37 ++++++++++++-------------------------
1 file changed, 12 insertions(+), 25 deletions(-)
diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c
index c01bb2654d69..26220593c529 100644
--- a/drivers/net/phy/marvell10g.c
+++ b/drivers/net/phy/marvell10g.c
@@ -42,13 +42,6 @@ enum {
*/
MV_AN_CTRL1000 = 0x8000, /* 1000base-T control register */
MV_AN_STAT1000 = 0x8001, /* 1000base-T status register */
-
- /* This register appears to reflect the copper status */
- MV_AN_RESULT = 0xa016,
- MV_AN_RESULT_SPD_10 = BIT(12),
- MV_AN_RESULT_SPD_100 = BIT(13),
- MV_AN_RESULT_SPD_1000 = BIT(14),
- MV_AN_RESULT_SPD_10000 = BIT(15),
};
static int mv3310_modify(struct phy_device *phydev, int devad, u16 reg,
@@ -239,12 +232,18 @@ static int mv3310_config_init(struct phy_device *phydev)
if (val & MDIO_PMA_EXTABLE_1000BKX)
__set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
supported);
- if (val & MDIO_PMA_EXTABLE_100BTX)
+ if (val & MDIO_PMA_EXTABLE_100BTX) {
__set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
supported);
- if (val & MDIO_PMA_EXTABLE_10BT)
+ __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
+ supported);
+ }
+ if (val & MDIO_PMA_EXTABLE_10BT) {
__set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
supported);
+ __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT,
+ supported);
+ }
}
if (!ethtool_convert_link_mode_to_legacy_u32(&mask, supported))
@@ -412,22 +411,8 @@ static int mv3310_read_status(struct phy_device *phydev)
phydev->lp_advertising |= mii_stat1000_to_ethtool_lpa_t(val);
- if (phydev->autoneg == AUTONEG_ENABLE) {
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MV_AN_RESULT);
- if (val < 0)
- return val;
-
- if (val & MV_AN_RESULT_SPD_10000)
- phydev->speed = SPEED_10000;
- else if (val & MV_AN_RESULT_SPD_1000)
- phydev->speed = SPEED_1000;
- else if (val & MV_AN_RESULT_SPD_100)
- phydev->speed = SPEED_100;
- else if (val & MV_AN_RESULT_SPD_10)
- phydev->speed = SPEED_10;
-
- phydev->duplex = DUPLEX_FULL;
- }
+ if (phydev->autoneg == AUTONEG_ENABLE)
+ phy_resolve_aneg_linkmode(phydev);
}
if (phydev->autoneg != AUTONEG_ENABLE) {
@@ -469,7 +454,9 @@ static struct phy_driver mv3310_drivers[] = {
.phy_id_mask = MARVELL_PHY_ID_MASK,
.name = "mv88x3310",
.features = SUPPORTED_10baseT_Full |
+ SUPPORTED_10baseT_Half |
SUPPORTED_100baseT_Full |
+ SUPPORTED_100baseT_Half |
SUPPORTED_1000baseT_Full |
SUPPORTED_Autoneg |
SUPPORTED_TP |
--
2.7.4
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH net-next 0/5] marvell10g updates
2017-12-29 12:44 [PATCH net-next 0/5] marvell10g updates Russell King - ARM Linux
` (4 preceding siblings ...)
2017-12-29 12:46 ` [PATCH net-next 5/5] net: phy: marvell10g: add support for half duplex 100M and 10M Russell King
@ 2018-01-02 20:01 ` David Miller
5 siblings, 0 replies; 12+ messages in thread
From: David Miller @ 2018-01-02 20:01 UTC (permalink / raw)
To: linux; +Cc: andrew, f.fainelli, netdev
From: Russell King - ARM Linux <linux@armlinux.org.uk>
Date: Fri, 29 Dec 2017 12:44:13 +0000
> This series:
> - adds MDI/MDIX reporting
> - adds support for 10/100Mbps half-duplex link modes
> - adds a comment describing the setup on VF610 ZII boards (where
> the phy interface mode doesn't change.)
> - cleans up the phy interace mode switching
Series applied, thank you.
^ permalink raw reply [flat|nested] 12+ messages in thread