From nobody Sat Jul 5 00:49:47 2025 Delivered-To: importer2@patchew.org Received-SPF: pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; envelope-from=linux-kernel-owner@vger.kernel.org; helo=vger.kernel.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org ARC-Seal: i=1; a=rsa-sha256; t=1618347551; cv=none; d=zohomail.com; s=zohoarc; b=cF8Z8Ghf/wstiVVLRrakZwkQo8DXwI/w8OjuN3d5GPLyJVdMl0qgw6pEjtq9+ULu4iGjtReDIc0PWH8iboX8v30i6Lgh/ubEWVAsmHlxN6kNb0CyHpPjYoau6q8A8MYZyR706Us8U15Hp8KRWLGL/5EmNvPBN3Gjrm1ViTDnxGM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1618347551; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Id:MIME-Version:Message-ID:References:Subject:To; bh=GaETeXh3QNDnTw1n0Xmq6nMlGEY5lscGDaw/KEQGkwA=; b=YeUN70ZbGXo3e2/8GWsNHvugtRrsiXCiKgsh6k0653iKTc8i/A38VngaqlLDAulUSwoStKS65JHZNa5z9qfZd8yu86UX6P4r8AD+yrEmL6x6tQSrAbUVx+guOF5hUqkmlH2mfUJt+t5nfvM++o2HBnTxdRPZx7SzW4e3jNGeo4E= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mx.zohomail.com with SMTP id 1618347551275156.26335103382883; Tue, 13 Apr 2021 13:59:11 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1346507AbhDMU73 (ORCPT ); Tue, 13 Apr 2021 16:59:29 -0400 Received: from mail.pr-group.ru ([178.18.215.3]:59155 "EHLO mail.pr-group.ru" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232402AbhDMU7M (ORCPT ); Tue, 13 Apr 2021 16:59:12 -0400 Received: from localhost.localdomain ([178.70.223.189]) (authenticated user i.bornyakov@metrotek.ru) by mail.pr-group.ru with ESMTPSA (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256 bits)); Tue, 13 Apr 2021 23:58:36 +0300 DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=metrotek.ru; s=mail; h=from:subject:date:message-id:to:cc:mime-version:content-transfer-encoding: in-reply-to:references; bh=/aTBJVFX50k+S1wGyOU3fkdhg0U1Mrm97VtsE/Bpsqw=; b=cZv9dDYtt7o8UwFCZPgNEfRq9+rknxd+MyqT3V1VyMSti9f9Es15HCA8ENkfaUi9v6N2i/eb1dYeQ t5JdnfdqosQOvtmTtp9lHOl1TFleF04voHUZqeAILYBlGotfC6kRVZrn3JTwC4u5g+Wg1ILuZOr3Yd YVJkhc+kxvMdlXdcIL/ZlVt1SzQc8z+lmcOTd94Wwa+hLNdI0M5JVEKgSdcfxP51bCLuyA9T6ziYML B2QqVqzZtYYydC9SellyMxwpb5oNUGXkO3qLlS5gECjRdS/fq3U5uhe5VMdLfbaBD/ttXpLYsa36n2 /e/tuiRDbcAS/IMFIJLTG0zreXpYvxQ== X-Spam-Status: No, hits=0.0 required=3.4 tests=AWL: 0.000, BAYES_00: -1.665, CUSTOM_RULE_FROM: ALLOW, TOTAL_SCORE: -1.665,autolearn=ham X-Spam-Level: X-Footer: bWV0cm90ZWsucnU= From: Ivan Bornyakov Cc: Ivan Bornyakov , system@metrotek.ru, andrew@lunn.ch, hkallweit1@gmail.com, linux@armlinux.org.uk, davem@davemloft.net, kuba@kernel.org, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 3/3] net: phy: marvell-88x2222: swap 1G/10G modes on autoneg Date: Tue, 13 Apr 2021 23:54:52 +0300 Message-Id: <8ae07fb62f1c81d3e6e016d16065f842912f40a0.1618347034.git.i.bornyakov@metrotek.ru> X-Mailer: git-send-email 2.26.3 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable To: unlisted-recipients:; (no To-header on input) Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-ZohoMail-DKIM: fail (Header signature does not verify) Content-Type: text/plain; charset="utf-8" Setting 10G without autonegotiation is invalid according to phy_ethtool_ksettings_set(). Thus, we need to set it during autonegotiation. If 1G autonegotiation can't complete for quite a time, but there is signal in line, switch line interface type to 10GBase-R, if supported, in hope for link to be established. And vice versa. If 10GBase-R link can't be established for quite a time, and autonegotiation is enabled, and there is signal in line, switch line interface type to appropriate 1G mode, i.e. 1000Base-X or SGMII, if supported. Signed-off-by: Ivan Bornyakov --- drivers/net/phy/marvell-88x2222.c | 117 +++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 28 deletions(-) diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88= x2222.c index 640b133f1371..9b9ac3ef735d 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -52,6 +52,8 @@ #define MV_1GBX_PHY_STAT_SPEED100 BIT(14) #define MV_1GBX_PHY_STAT_SPEED1000 BIT(15) =20 +#define AUTONEG_TIMEOUT 3 + struct mv2222_data { phy_interface_t line_interface; __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); @@ -173,6 +175,24 @@ static bool mv2222_is_1gbx_capable(struct phy_device *= phydev) priv->supported); } =20 +static bool mv2222_is_sgmii_capable(struct phy_device *phydev) +{ + struct mv2222_data *priv =3D phydev->priv; + + return (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, + priv->supported) || + linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, + priv->supported)); +} + static int mv2222_config_line(struct phy_device *phydev) { struct mv2222_data *priv =3D phydev->priv; @@ -192,7 +212,8 @@ static int mv2222_config_line(struct phy_device *phydev) } } =20 -static int mv2222_setup_forced(struct phy_device *phydev) +/* Switch between 1G (1000Base-X/SGMII) and 10G (10GBase-R) modes */ +static int mv2222_swap_line_type(struct phy_device *phydev) { struct mv2222_data *priv =3D phydev->priv; bool changed =3D false; @@ -200,25 +221,23 @@ static int mv2222_setup_forced(struct phy_device *phy= dev) =20 switch (priv->line_interface) { case PHY_INTERFACE_MODE_10GBASER: - if (phydev->speed =3D=3D SPEED_1000 && - mv2222_is_1gbx_capable(phydev)) { + if (mv2222_is_1gbx_capable(phydev)) { priv->line_interface =3D PHY_INTERFACE_MODE_1000BASEX; changed =3D true; } =20 - break; - case PHY_INTERFACE_MODE_1000BASEX: - if (phydev->speed =3D=3D SPEED_10000 && - mv2222_is_10g_capable(phydev)) { - priv->line_interface =3D PHY_INTERFACE_MODE_10GBASER; + if (mv2222_is_sgmii_capable(phydev)) { + priv->line_interface =3D PHY_INTERFACE_MODE_SGMII; changed =3D true; } =20 break; + case PHY_INTERFACE_MODE_1000BASEX: case PHY_INTERFACE_MODE_SGMII: - ret =3D mv2222_set_sgmii_speed(phydev); - if (ret < 0) - return ret; + if (mv2222_is_10g_capable(phydev)) { + priv->line_interface =3D PHY_INTERFACE_MODE_10GBASER; + changed =3D true; + } =20 break; default: @@ -231,6 +250,29 @@ static int mv2222_setup_forced(struct phy_device *phyd= ev) return ret; } =20 + return 0; +} + +static int mv2222_setup_forced(struct phy_device *phydev) +{ + struct mv2222_data *priv =3D phydev->priv; + int ret; + + if (priv->line_interface =3D=3D PHY_INTERFACE_MODE_10GBASER) { + if (phydev->speed < SPEED_10000 && + phydev->speed !=3D SPEED_UNKNOWN) { + ret =3D mv2222_swap_line_type(phydev); + if (ret < 0) + return ret; + } + } + + if (priv->line_interface =3D=3D PHY_INTERFACE_MODE_SGMII) { + ret =3D mv2222_set_sgmii_speed(phydev); + if (ret < 0) + return ret; + } + return mv2222_disable_aneg(phydev); } =20 @@ -244,17 +286,9 @@ static int mv2222_config_aneg(struct phy_device *phyde= v) return 0; =20 if (phydev->autoneg =3D=3D AUTONEG_DISABLE || - phydev->speed =3D=3D SPEED_10000) + priv->line_interface =3D=3D PHY_INTERFACE_MODE_10GBASER) return mv2222_setup_forced(phydev); =20 - if (priv->line_interface =3D=3D PHY_INTERFACE_MODE_10GBASER && - mv2222_is_1gbx_capable(phydev)) { - priv->line_interface =3D PHY_INTERFACE_MODE_1000BASEX; - ret =3D mv2222_config_line(phydev); - if (ret < 0) - return ret; - } - adv =3D linkmode_adv_to_mii_adv_x(priv->supported, ETHTOOL_LINK_MODE_1000baseX_Full_BIT); =20 @@ -291,6 +325,7 @@ static int mv2222_aneg_done(struct phy_device *phydev) /* Returns negative on error, 0 if link is down, 1 if link is up */ static int mv2222_read_status_10g(struct phy_device *phydev) { + static int timeout; int val, link =3D 0; =20 val =3D phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); @@ -304,6 +339,20 @@ static int mv2222_read_status_10g(struct phy_device *p= hydev) phydev->autoneg =3D AUTONEG_DISABLE; phydev->speed =3D SPEED_10000; phydev->duplex =3D DUPLEX_FULL; + } else { + if (phydev->autoneg =3D=3D AUTONEG_ENABLE) { + timeout++; + + if (timeout > AUTONEG_TIMEOUT) { + timeout =3D 0; + + val =3D mv2222_swap_line_type(phydev); + if (val < 0) + return val; + + return mv2222_config_aneg(phydev); + } + } } =20 return link; @@ -312,15 +361,31 @@ static int mv2222_read_status_10g(struct phy_device *= phydev) /* Returns negative on error, 0 if link is down, 1 if link is up */ static int mv2222_read_status_1g(struct phy_device *phydev) { + static int timeout; int val, link =3D 0; =20 val =3D phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT); if (val < 0) return val; =20 - if (!(val & BMSR_LSTATUS) || - (phydev->autoneg =3D=3D AUTONEG_ENABLE && - !(val & BMSR_ANEGCOMPLETE))) + if (phydev->autoneg =3D=3D AUTONEG_ENABLE && + !(val & BMSR_ANEGCOMPLETE)) { + timeout++; + + if (timeout > AUTONEG_TIMEOUT) { + timeout =3D 0; + + val =3D mv2222_swap_line_type(phydev); + if (val < 0) + return val; + + return mv2222_config_aneg(phydev); + } + + return 0; + } + + if (!(val & BMSR_LSTATUS)) return 0; =20 link =3D 1; @@ -447,11 +512,7 @@ static int mv2222_sfp_insert(void *upstream, const str= uct sfp_eeprom_id *id) return ret; =20 if (mutex_trylock(&phydev->lock)) { - if (priv->line_interface =3D=3D PHY_INTERFACE_MODE_10GBASER) - ret =3D mv2222_setup_forced(phydev); - else - ret =3D mv2222_config_aneg(phydev); - + ret =3D mv2222_config_aneg(phydev); mutex_unlock(&phydev->lock); } =20 --=20 2.26.3