From: Dimitri Fedrau <dima.fedrau@gmail.com>
To: "Ilya A. Evenbach" <ievenbach@aurora.tech>
Cc: netdev@vger.kernel.org
Subject: Re: [PATCH] [88q2xxx] Add support for handling master/slave in forced mode
Date: Thu, 21 Aug 2025 10:02:05 +0200 [thread overview]
Message-ID: <20250821080205.GA5542@legfed1> (raw)
In-Reply-To: <20250820181143.2288755-2-ievenbach@aurora.tech>
Hi Ilya,
Am Wed, Aug 20, 2025 at 11:11:43AM -0700 schrieb Ilya A. Evenbach:
> 88q2xxx PHYs have non-standard way of setting master/slave in
> forced mode.
> This change adds support for changing and reporting this setting
> correctly through ethtool.
>
> Signed-off-by: Ilya A. Evenbach <ievenbach@aurora.tech>
> ---
> drivers/net/phy/marvell-88q2xxx.c | 106 ++++++++++++++++++++++++++++--
> 1 file changed, 101 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/net/phy/marvell-88q2xxx.c b/drivers/net/phy/marvell-88q2xxx.c
> index f3d83b04c953..b94d574fd9b7 100644
> --- a/drivers/net/phy/marvell-88q2xxx.c
> +++ b/drivers/net/phy/marvell-88q2xxx.c
> @@ -118,6 +118,11 @@
> #define MV88Q2XXX_LED_INDEX_TX_ENABLE 0
> #define MV88Q2XXX_LED_INDEX_GPIO 1
>
> +/* Marvell vendor PMA/PMD control for forced master/slave when AN is disabled */
> +#define PMAPMD_MVL_PMAPMD_CTL 0x0834
Already defined, see MDIO_PMA_PMD_BT1_CTRL.
> +#define MASTER_MODE BIT(14)
Already defines, see MDIO_PMA_PMD_BT1_CTRL_CFG_MST.
> +#define MODE_MASK BIT(14)
> +
> struct mv88q2xxx_priv {
> bool enable_led0;
> };
> @@ -377,13 +382,57 @@ static int mv88q2xxx_read_link(struct phy_device *phydev)
> static int mv88q2xxx_read_master_slave_state(struct phy_device *phydev)
> {
> int ret;
> + int adv_l, adv_m, stat, stat2;
> +
> + /* In forced mode, state and config are controlled via PMAPMD 0x834 */
> + if (phydev->autoneg == AUTONEG_DISABLE) {
> + ret = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, PMAPMD_MVL_PMAPMD_CTL);
> + if (ret < 0)
> + return ret;
> +
> + if (ret & MASTER_MODE) {
> + phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
> + phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE;
> + } else {
> + phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
> + phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_FORCE;
> + }
> + return 0;
> + }
>
> - phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
> - ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
> - if (ret < 0)
> - return ret;
>
> - if (ret & MDIO_MMD_AN_MV_STAT_LOCAL_MASTER)
> + adv_l = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_L);
> + if (adv_l < 0)
> + return adv_l;
> + adv_m = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_T1_ADV_M);
> + if (adv_m < 0)
> + return adv_m;
> +
> + if (adv_l & MDIO_AN_T1_ADV_L_FORCE_MS)
> + phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_FORCE;
> + else if (adv_m & MDIO_AN_T1_ADV_M_MST)
> + phydev->master_slave_get = MASTER_SLAVE_CFG_MASTER_PREFERRED;
> + else
> + phydev->master_slave_get = MASTER_SLAVE_CFG_SLAVE_PREFERRED;
> +
> + stat = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT);
> + if (stat < 0)
> + return stat;
> +
> + if (stat & MDIO_MMD_AN_MV_STAT_MS_CONF_FAULT) {
> + phydev->master_slave_state = MASTER_SLAVE_STATE_ERR;
> + return 0;
> + }
> +
> + stat2 = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_MMD_AN_MV_STAT2);
> + if (stat2 < 0)
> + return stat2;
> + if (!(stat2 & MDIO_MMD_AN_MV_STAT2_AN_RESOLVED)) {
> + phydev->master_slave_state = MASTER_SLAVE_STATE_UNKNOWN;
> + return 0;
> + }
> +
> + if (stat & MDIO_MMD_AN_MV_STAT_LOCAL_MASTER)
> phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER;
> else
> phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE;
> @@ -391,6 +440,34 @@ static int mv88q2xxx_read_master_slave_state(struct phy_device *phydev)
> return 0;
> }
>
Is there a issue with the function you are trying to fix ? Seems that
you copied some generic functions into it.
> +static int mv88q2xxx_setup_master_slave_forced(struct phy_device *phydev)
> +{
> + int ret = 0;
> +
> + switch (phydev->master_slave_set) {
> + case MASTER_SLAVE_CFG_MASTER_FORCE:
> + case MASTER_SLAVE_CFG_MASTER_PREFERRED:
> + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_PMAPMD,
> + PMAPMD_MVL_PMAPMD_CTL,
> + MODE_MASK, MASTER_MODE);
> + break;
> + case MASTER_SLAVE_CFG_SLAVE_FORCE:
> + case MASTER_SLAVE_CFG_SLAVE_PREFERRED:
> + ret = phy_modify_mmd_changed(phydev, MDIO_MMD_PMAPMD,
> + PMAPMD_MVL_PMAPMD_CTL,
> + MODE_MASK, 0);
> + break;
> + case MASTER_SLAVE_CFG_UNKNOWN:
> + case MASTER_SLAVE_CFG_UNSUPPORTED:
> + default:
> + phydev_warn(phydev, "Unsupported Master/Slave mode\n");
> + ret = 0;
> + break;
> + }
> +
> + return ret;
> +}
> +
This function does the same as genphy_c45_pma_baset1_setup_master_slave.
Please use the generic function. Besides you are introducing register
PMAPMD_MVL_PMAPMD_CTL which is MDIO_PMA_PMD_BT1_CTRL.
> static int mv88q2xxx_read_aneg_speed(struct phy_device *phydev)
> {
> int ret;
> @@ -448,6 +525,11 @@ static int mv88q2xxx_read_status(struct phy_device *phydev)
> if (ret < 0)
> return ret;
>
> + /* Populate master/slave status also for forced modes */
> + ret = mv88q2xxx_read_master_slave_state(phydev);
> + if (ret < 0 && ret != -EOPNOTSUPP)
> + return ret;
> +
> return genphy_c45_read_pma(phydev);
> }
>
Why ? This function is only used in case AUTONEG_ENABLE.
> @@ -478,6 +560,20 @@ static int mv88q2xxx_config_aneg(struct phy_device *phydev)
> if (ret)
> return ret;
>
> + /* Configure Base-T1 master/slave per phydev->master_slave_set.
> + * For AN disabled, program PMAPMD role directly; otherwise rely on
> + * the standard Base-T1 AN advertisement bits.
> + */
> + if (phydev->autoneg == AUTONEG_DISABLE) {
> + ret = mv88q2xxx_setup_master_slave_forced(phydev);
> + if (ret)
> + return ret;
> + } else {
> + ret = genphy_c45_pma_baset1_setup_master_slave(phydev);
> + if (ret)
> + return ret;
> + }
> +
> return phydev->drv->soft_reset(phydev);
> }
>
I don't see any reason why genphy_c45_config_aneg isn't sufficient here.
In case AUTONEG_DISABLE, genphy_c45_pma_setup_forced is called and calls
genphy_c45_pma_baset1_setup_master_slave which is basically the same as
mv88q2xxx_setup_master_slave_forced.
In case AUTONEG_ENABLE, calling genphy_c45_pma_baset1_setup_master_slave is
wrong, please look how genphy_c45_an_config_aneg is implemented.
Please take other users of the driver into CC, they did a lot of
reviewing and testing in the past. If there is some issue with the
driver, they should know:
"Niklas Söderlund" <niklas.soderlund+renesas@ragnatech.se>
"Gregor Herburger" <gregor.herburger@ew.tq-group.com>
"Stefan Eichenberger" <eichest@gmail.com>
"Geert Uytterhoeven" <geert@linux-m68k.org>
Which device are you using, and why did you need this patch ? Is there
any issue you are trying to fix ? On my side I did a lot of testing with
the different modes and never experienced any problems so far.
Best regards,
Dimitri Fedrau
next prev parent reply other threads:[~2025-08-21 8:02 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-08-19 21:29 [PATCH] [88q2xxx] Add support for handling master/slave in forced mode Ilya A. Evenbach
2025-08-19 22:13 ` Andrew Lunn
2025-08-20 18:11 ` Ilya A. Evenbach
2025-08-20 18:11 ` [PATCH] [88q2xxx] Add support for handling master/slave in forced mode Ilya A. Evenbach
2025-08-21 0:35 ` Jakub Kicinski
2025-08-21 8:02 ` Dimitri Fedrau [this message]
[not found] ` <CAJmffrpUTzH0_siTUZodX7Gu5JPRvkgUb+73CgXSWu1QSzegSA@mail.gmail.com>
2025-08-22 6:58 ` Dimitri Fedrau
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250821080205.GA5542@legfed1 \
--to=dima.fedrau@gmail.com \
--cc=ievenbach@aurora.tech \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.