Message ID | 20230109211849.32530-7-jerry.ray@microchip.com |
---|---|
State | New |
Headers |
Return-Path: <linux-kernel-owner@vger.kernel.org> Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:4e01:0:0:0:0:0 with SMTP id p1csp2386786wrt; Mon, 9 Jan 2023 13:21:11 -0800 (PST) X-Google-Smtp-Source: AMrXdXugJYXuBvmdscJFp35pEscSP2R+roSs8WfJ+ThD+8XZp9CSmyFdl5NHwQ1zjoNfT18SA2sx X-Received: by 2002:a17:907:a0d6:b0:7d3:c516:6ef4 with SMTP id hw22-20020a170907a0d600b007d3c5166ef4mr74366551ejc.20.1673299271375; Mon, 09 Jan 2023 13:21:11 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1673299271; cv=none; d=google.com; s=arc-20160816; b=gWwAyHxce+LRUorqEwmSMgXOnQ8ao8nkWgsxN2Zi/ZzYCPaa1uBxwp3ACfqK+2WGhW k0MxqlbwkodiYp+ntvaiFN28/WOWE2ZTAbEebXvOuiCQo4nAfvJenzGE5d36aAjM7Fhy Rg1M0oM24Eunk3DwDo1mZ3SDCcaW8YFLt6eMV4QRyDcCfyi11cWXvM7EAHbuge5K9eo9 XCoZ1+HPS+JJiVcHRkwHT83SgESW5/xOImhFis8NjZa9XYL7gc5uTD1OM4+SjS6YoMIw 5QBhR7x6T+DaW6Ierc91J1RyzRAk9IJ7FjvRhziicV6Z7XqcxFLGeYpcrSpvmYukm5r0 hLEA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:mime-version:references:in-reply-to:message-id :date:subject:to:from:dkim-signature; bh=vMXpm/1M1AUHKgxamX5IcAw6KKXDUzr+9jNUjgAX3QA=; b=JiAFSjT4g/LdNEeDrFi4yztLn/vIWsSYtIxAVLkIsuKmK+bGKRMiUxsdnoo4K0kXzD yGnJW2Gc4XH/SZ1sR42KJVJVtfolzcZkZnvci3eiDAOa7XnVXbdt7p/GsStHRK7UT4C7 zYMPrMS9513PIcIdmIZq7SbB+EDR6Nqj1p3Cip8rJa4HQOYaStCwY94CpYHfQc/rQ1qJ pqmwHxPZxoLehYbCc5Ha6WyEOAIjZDsp9FYOJFKgz7MYawAWg1PVt6Xcv7pC8sky1c1T VxUrnmPmvBzX6yszk7i4UQJz+iZ6ra3o9WqZQKDsDsX5xYlaiqGszHZWu/MtoGDiOJBh St6Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@microchip.com header.s=mchp header.b=N859cFPK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=microchip.com Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id ne26-20020a1709077b9a00b0077d854aa10dsi11384295ejc.57.2023.01.09.13.20.47; Mon, 09 Jan 2023 13:21:11 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@microchip.com header.s=mchp header.b=N859cFPK; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=microchip.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237718AbjAIVUN (ORCPT <rfc822;syz17693488234@gmail.com> + 99 others); Mon, 9 Jan 2023 16:20:13 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:57182 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237709AbjAIVT2 (ORCPT <rfc822;linux-kernel@vger.kernel.org>); Mon, 9 Jan 2023 16:19:28 -0500 Received: from esa.microchip.iphmx.com (esa.microchip.iphmx.com [68.232.153.233]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id F0BAFEA0; Mon, 9 Jan 2023 13:19:10 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=microchip.com; i=@microchip.com; q=dns/txt; s=mchp; t=1673299152; x=1704835152; h=from:to:subject:date:message-id:in-reply-to:references: mime-version; bh=bF71XwdfkyXFfdauaOthhsM1+Sz7taE1BuvslIS1rog=; b=N859cFPKWrhNX/gvtgr60t7pb9k5ca1Ue24sqUGDTBac3ExkLZbbk+RT cli7BLymxjeUe5GsrJxcyyvU8j+Yfi4SuQN3I+QCntOGxe0HcNoawGve3 E3oVnjZgMlfvuCLIrMroh98LE0zg/7m15X/JodEyjGD3UnyhcJFIrz1Jb 28+2mFr8vaefihLgjw0c5kk197RWY17f2177SSsNM0re1veKocuNSI1VD 6LEcOyRba749TtDarPWX0kcQbZv70fKqb6Te7DlLaFu14UUA25maSfunb hl55rDjAhKAy3umFrQOqwhREQsnh8PtP8VnHM4NBlZi7spkaw36nOKwyH A==; X-IronPort-AV: E=Sophos;i="5.96,313,1665471600"; d="scan'208";a="196049306" Received: from unknown (HELO email.microchip.com) ([170.129.1.10]) by esa5.microchip.iphmx.com with ESMTP/TLS/AES256-SHA256; 09 Jan 2023 14:19:11 -0700 Received: from chn-vm-ex02.mchp-main.com (10.10.85.144) by chn-vm-ex03.mchp-main.com (10.10.85.151) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.16; Mon, 9 Jan 2023 14:19:09 -0700 Received: from AUS-LT-C33025.microchip.com (10.10.115.15) by chn-vm-ex02.mchp-main.com (10.10.85.144) with Microsoft SMTP Server id 15.1.2507.16 via Frontend Transport; Mon, 9 Jan 2023 14:19:07 -0700 From: Jerry Ray <jerry.ray@microchip.com> To: Andrew Lunn <andrew@lunn.ch>, Florian Fainelli <f.fainelli@gmail.com>, Vladimir Oltean <olteanv@gmail.com>, "David S. Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>, Jakub Kicinski <kuba@kernel.org>, "Paolo Abeni" <pabeni@redhat.com>, Russell King <linux@armlinux.org.uk>, <jbe@pengutronix.de>, <netdev@vger.kernel.org>, <linux-kernel@vger.kernel.org>, Jerry Ray <jerry.ray@microchip.com> Subject: [PATCH net-next v6 6/6] dsa: lan9303: Migrate to PHYLINK Date: Mon, 9 Jan 2023 15:18:49 -0600 Message-ID: <20230109211849.32530-7-jerry.ray@microchip.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20230109211849.32530-1-jerry.ray@microchip.com> References: <20230109211849.32530-1-jerry.ray@microchip.com> MIME-Version: 1.0 Content-Type: text/plain X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_DNSWL_MED, RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: <linux-kernel.vger.kernel.org> X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1754581456596160088?= X-GMAIL-MSGID: =?utf-8?q?1754581456596160088?= |
Series |
dsa: lan9303: Move to PHYLINK
|
|
Commit Message
Jerry Ray
Jan. 9, 2023, 9:18 p.m. UTC
This patch replaces the adjust_link api with the phylink apis that provide
equivalent functionality.
The remaining functionality from the adjust_link is now covered in the
phylink_mac_link_up api.
Removes:
.adjust_link
Adds:
.phylink_get_caps
.phylink_mac_link_up
Signed-off-by: Jerry Ray <jerry.ray@microchip.com>
---
v5->v6:
- Moved to using port number to identify xMII port for the LAN9303.
v4->v5:
- Added various prep patches to better show the movement of the logic.
v3->v4:
- Reworked the implementation to preserve the adjust_link functionality
by including it in the phylink_mac_link_up api.
v2->v3:
Added back in disabling Turbo Mode on the CPU MII interface.
Removed the unnecessary clearing of the phy supported interfaces.
---
drivers/net/dsa/lan9303-core.c | 101 ++++++++++++++++++++++-----------
1 file changed, 69 insertions(+), 32 deletions(-)
Comments
Hi Jerry, On Mon, 2023-01-09 at 15:18 -0600, Jerry Ray wrote: > > diff --git a/drivers/net/dsa/lan9303-core.c > b/drivers/net/dsa/lan9303-core.c > index 7be4c491e5d9..e514fff81af6 100644 > --- a/drivers/net/dsa/lan9303-core.c > +++ b/drivers/net/dsa/lan9303-core.c > @@ -1058,37 +1058,6 @@ static int lan9303_phy_write(struct dsa_switch > *ds, int phy, int regnum, > return chip->ops->phy_write(chip, phy, regnum, val); > } > > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int > port, > + struct phylink_config *config) > +{ > + struct lan9303 *chip = ds->priv; > + > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > + > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > + MAC_SYM_PAUSE; > + > + if (port == 0) { > + __set_bit(PHY_INTERFACE_MODE_RMII, > + config->supported_interfaces); > + __set_bit(PHY_INTERFACE_MODE_MII, > + config->supported_interfaces); > + } else { > + __set_bit(PHY_INTERFACE_MODE_INTERNAL, > + config->supported_interfaces); > + /* Compatibility for phylib's default interface type > when the > + * phy-mode property is absent > + */ > + __set_bit(PHY_INTERFACE_MODE_GMII, > + config->supported_interfaces); > + } > + > + /* This driver does not make use of the speed, duplex, pause or > the > + * advertisement in its mac_config, so it is safe to mark this > driver > + * as non-legacy. > + */ > + config->legacy_pre_march2020 = false; > +} > + > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int > port, > + unsigned int mode, > + phy_interface_t interface, > + struct phy_device *phydev, int > speed, > + int duplex, bool tx_pause, > + bool rx_pause) > +{ > + u32 ctl; > + > + /* On this device, we are only interested in doing something > here if > + * this is the xMII port. All other ports are 10/100 phys using > MDIO > + * to control there link settings. > + */ > + if (port != 0) > + return; > + > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > + > + ctl &= ~BMCR_ANENABLE; > + > + if (speed == SPEED_100) > + ctl |= BMCR_SPEED100; > + else if (speed == SPEED_10) > + ctl &= ~BMCR_SPEED100; > + else > + dev_err(ds->dev, "unsupported speed: %d\n", speed); I think, We will not reach in the error part, since in the phylink_get_caps we specified only 10 and 100 Mbps speed. Phylink layer will validate and if the value is beyond the speed supported, it will return back. > + > + if (duplex == DUPLEX_FULL) > + ctl |= BMCR_FULLDPLX; > + else > + ctl &= ~BMCR_FULLDPLX; > + > + lan9303_phy_write(ds, port, MII_BMCR, ctl); > +} > + >
On Mon, Jan 09, 2023 at 03:18:49PM -0600, Jerry Ray wrote: > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, > + struct phylink_config *config) > +{ > + struct lan9303 *chip = ds->priv; > + > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > + > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > + MAC_SYM_PAUSE; You indicate that pause modes are supported, but... > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, > + unsigned int mode, > + phy_interface_t interface, > + struct phy_device *phydev, int speed, > + int duplex, bool tx_pause, > + bool rx_pause) > +{ > + u32 ctl; > + > + /* On this device, we are only interested in doing something here if > + * this is the xMII port. All other ports are 10/100 phys using MDIO > + * to control there link settings. > + */ > + if (port != 0) > + return; > + > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > + > + ctl &= ~BMCR_ANENABLE; > + > + if (speed == SPEED_100) > + ctl |= BMCR_SPEED100; > + else if (speed == SPEED_10) > + ctl &= ~BMCR_SPEED100; > + else > + dev_err(ds->dev, "unsupported speed: %d\n", speed); > + > + if (duplex == DUPLEX_FULL) > + ctl |= BMCR_FULLDPLX; > + else > + ctl &= ~BMCR_FULLDPLX; > + > + lan9303_phy_write(ds, port, MII_BMCR, ctl); There is no code here to program the resolved pause modes. Is it handled internally within the switch? (Please add a comment to this effect either in get_caps or here.) Thanks.
> > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, > > + struct phylink_config *config) > > +{ > > + struct lan9303 *chip = ds->priv; > > + > > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > > + > > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > > + MAC_SYM_PAUSE; > > You indicate that pause modes are supported, but... > > > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, > > + unsigned int mode, > > + phy_interface_t interface, > > + struct phy_device *phydev, int speed, > > + int duplex, bool tx_pause, > > + bool rx_pause) > > +{ > > + u32 ctl; > > + > > + /* On this device, we are only interested in doing something here if > > + * this is the xMII port. All other ports are 10/100 phys using MDIO > > + * to control there link settings. > > + */ > > + if (port != 0) > > + return; > > + > > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > > + > > + ctl &= ~BMCR_ANENABLE; > > + > > + if (speed == SPEED_100) > > + ctl |= BMCR_SPEED100; > > + else if (speed == SPEED_10) > > + ctl &= ~BMCR_SPEED100; > > + else > > + dev_err(ds->dev, "unsupported speed: %d\n", speed); > > + > > + if (duplex == DUPLEX_FULL) > > + ctl |= BMCR_FULLDPLX; > > + else > > + ctl &= ~BMCR_FULLDPLX; > > + > > + lan9303_phy_write(ds, port, MII_BMCR, ctl); > > There is no code here to program the resolved pause modes. Is it handled > internally within the switch? (Please add a comment to this effect > either in get_caps or here.) > > Thanks. > As I look into this, the part does have control flags for advertising Symmetric and Asymmetric pause toward the link partner. The default is set by a configuration strap on power-up. I am having trouble mapping the rx and tx pause parameters into symmetric and asymmetric controls. Where can I find the proper definitions and mappings? ctl &= ~( ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_AYM); if(tx_pause) ctl |= ADVERTISE_PAUSE_CAP; if(rx_pause) ctl |= ADVERTISE_PAUSE_AYM; If I can pause my transmissions (receive pause requests), then advertise symmetric whether I ever sent pause requests or not. If I can send pause requests (using flow control on my receive side), then make sure asymmetric support is also advertised as rx_pause might have been clear. Not that if both rx and tx pause is supported, we can support either symmetric or asymmetric operating modes. If I receive a pause request, it affects my transmit data flow. So one could argue the rx_pause flag controls my ability to receive pause requests. I tend to overthink and almost always get these 50/50 propositions wrong. Regards, Jerry
> > diff --git a/drivers/net/dsa/lan9303-core.c > > b/drivers/net/dsa/lan9303-core.c > > index 7be4c491e5d9..e514fff81af6 100644 > > --- a/drivers/net/dsa/lan9303-core.c > > +++ b/drivers/net/dsa/lan9303-core.c > > @@ -1058,37 +1058,6 @@ static int lan9303_phy_write(struct dsa_switch > > *ds, int phy, int regnum, > > return chip->ops->phy_write(chip, phy, regnum, val); > > } > > > > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int > > port, > > + struct phylink_config *config) > > +{ > > + struct lan9303 *chip = ds->priv; > > + > > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > > + > > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > > + MAC_SYM_PAUSE; > > + > > + if (port == 0) { > > + __set_bit(PHY_INTERFACE_MODE_RMII, > > + config->supported_interfaces); > > + __set_bit(PHY_INTERFACE_MODE_MII, > > + config->supported_interfaces); > > + } else { > > + __set_bit(PHY_INTERFACE_MODE_INTERNAL, > > + config->supported_interfaces); > > + /* Compatibility for phylib's default interface type > > when the > > + * phy-mode property is absent > > + */ > > + __set_bit(PHY_INTERFACE_MODE_GMII, > > + config->supported_interfaces); > > + } > > + > > + /* This driver does not make use of the speed, duplex, pause or > > the > > + * advertisement in its mac_config, so it is safe to mark this > > driver > > + * as non-legacy. > > + */ > > + config->legacy_pre_march2020 = false; > > +} > > + > > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int > > port, > > + unsigned int mode, > > + phy_interface_t interface, > > + struct phy_device *phydev, int > > speed, > > + int duplex, bool tx_pause, > > + bool rx_pause) > > +{ > > + u32 ctl; > > + > > + /* On this device, we are only interested in doing something > > here if > > + * this is the xMII port. All other ports are 10/100 phys using > > MDIO > > + * to control there link settings. > > + */ > > + if (port != 0) > > + return; > > + > > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > > + > > + ctl &= ~BMCR_ANENABLE; > > + > > + if (speed == SPEED_100) > > + ctl |= BMCR_SPEED100; > > + else if (speed == SPEED_10) > > + ctl &= ~BMCR_SPEED100; > > + else > > + dev_err(ds->dev, "unsupported speed: %d\n", speed); > > I think, We will not reach in the error part, since in the > phylink_get_caps we specified only 10 and 100 Mbps speed. Phylink layer > will validate and if the value is beyond the speed supported, it will > return back. > I will remove the error check and will go with either 10 or 100. ctl &= ~BMCR_SPEED100; if ((speed == SPEED_100) ctl |= BMCR_SPEED100; Regards, Jerry. > > + > > + if (duplex == DUPLEX_FULL) > > + ctl |= BMCR_FULLDPLX; > > + else > > + ctl &= ~BMCR_FULLDPLX; > > + > > + lan9303_phy_write(ds, port, MII_BMCR, ctl); > > +} > > +
On Mon, Jan 16, 2023 at 05:22:05PM +0000, Jerry.Ray@microchip.com wrote: > > > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, > > > + struct phylink_config *config) > > > +{ > > > + struct lan9303 *chip = ds->priv; > > > + > > > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > > > + > > > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > > > + MAC_SYM_PAUSE; > > > > You indicate that pause modes are supported, but... > > > > > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, > > > + unsigned int mode, > > > + phy_interface_t interface, > > > + struct phy_device *phydev, int speed, > > > + int duplex, bool tx_pause, > > > + bool rx_pause) > > > +{ > > > + u32 ctl; > > > + > > > + /* On this device, we are only interested in doing something here if > > > + * this is the xMII port. All other ports are 10/100 phys using MDIO > > > + * to control there link settings. > > > + */ > > > + if (port != 0) > > > + return; > > > + > > > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > > > + > > > + ctl &= ~BMCR_ANENABLE; > > > + > > > + if (speed == SPEED_100) > > > + ctl |= BMCR_SPEED100; > > > + else if (speed == SPEED_10) > > > + ctl &= ~BMCR_SPEED100; > > > + else > > > + dev_err(ds->dev, "unsupported speed: %d\n", speed); > > > + > > > + if (duplex == DUPLEX_FULL) > > > + ctl |= BMCR_FULLDPLX; > > > + else > > > + ctl &= ~BMCR_FULLDPLX; > > > + > > > + lan9303_phy_write(ds, port, MII_BMCR, ctl); > > > > There is no code here to program the resolved pause modes. Is it handled > > internally within the switch? (Please add a comment to this effect > > either in get_caps or here.) > > > > Thanks. > > > > As I look into this, the part does have control flags for advertising > Symmetric and Asymmetric pause toward the link partner. The default is set > by a configuration strap on power-up. I am having trouble mapping the rx and > tx pause parameters into symmetric and asymmetric controls. Where can I find > the proper definitions and mappings? > > ctl &= ~( ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_AYM); > if(tx_pause) > ctl |= ADVERTISE_PAUSE_CAP; > if(rx_pause) > ctl |= ADVERTISE_PAUSE_AYM; lan9303_phylink_mac_link_up() has nothing to do with what might be advertised to the link partner - this is called when the link has been negotiated and established, and it's purpose is to program the results of the resolution into the MAC. That means programming the MAC to operate at the negotiated speed and duplex, and also permitting the MAC to generate pause frames when its receive side becomes full (tx_pause) and whether to act on pause frames received over the network (rx_pause). If there's nowhere to program the MAC to accept and/or generate pause frames, how are they controlled? Does the MAC always accept and/or generate them? Or does the MAC always ignore them and never generates them? If the latter, then that suggests pause frames are not supported, and thus MAC_SYM_PAUSE and MAC_ASYM_PAUSE should not be set in the get_caps method. This leads me on to another question - in the above quoted code, what device's BMCR is being accessed in lan9303_phylink_mac_link_up() ? Is it a PCS? If it is, please use the phylink_pcs support, as the pcs_config() method gives you what is necessary to program the PCS advertisement. Thanks.
> > > > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, > > > > + struct phylink_config *config) > > > > +{ > > > > + struct lan9303 *chip = ds->priv; > > > > + > > > > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > > > > + > > > > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > > > > + MAC_SYM_PAUSE; > > > > > > You indicate that pause modes are supported, but... > > > > > > > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, > > > > + unsigned int mode, > > > > + phy_interface_t interface, > > > > + struct phy_device *phydev, int speed, > > > > + int duplex, bool tx_pause, > > > > + bool rx_pause) > > > > +{ > > > > + u32 ctl; > > > > + > > > > + /* On this device, we are only interested in doing something here if > > > > + * this is the xMII port. All other ports are 10/100 phys using MDIO > > > > + * to control there link settings. > > > > + */ > > > > + if (port != 0) > > > > + return; > > > > + > > > > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > > > > + > > > > + ctl &= ~BMCR_ANENABLE; > > > > + > > > > + if (speed == SPEED_100) > > > > + ctl |= BMCR_SPEED100; > > > > + else if (speed == SPEED_10) > > > > + ctl &= ~BMCR_SPEED100; > > > > + else > > > > + dev_err(ds->dev, "unsupported speed: %d\n", speed); > > > > + > > > > + if (duplex == DUPLEX_FULL) > > > > + ctl |= BMCR_FULLDPLX; > > > > + else > > > > + ctl &= ~BMCR_FULLDPLX; > > > > + > > > > + lan9303_phy_write(ds, port, MII_BMCR, ctl); > > > > > > There is no code here to program the resolved pause modes. Is it handled > > > internally within the switch? (Please add a comment to this effect > > > either in get_caps or here.) > > > > > > Thanks. > > > > > > > As I look into this, the part does have control flags for advertising > > Symmetric and Asymmetric pause toward the link partner. The default is set > > by a configuration strap on power-up. I am having trouble mapping the rx and > > tx pause parameters into symmetric and asymmetric controls. Where can I find > > the proper definitions and mappings? > > > > ctl &= ~( ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_AYM); > > if(tx_pause) > > ctl |= ADVERTISE_PAUSE_CAP; > > if(rx_pause) > > ctl |= ADVERTISE_PAUSE_AYM; > > lan9303_phylink_mac_link_up() has nothing to do with what might be > advertised to the link partner - this is called when the link has been > negotiated and established, and it's purpose is to program the results > of the resolution into the MAC. > > That means programming the MAC to operate at the negotiated speed and > duplex, and also permitting the MAC to generate pause frames when its > receive side becomes full (tx_pause) and whether to act on pause frames > received over the network (rx_pause). > > If there's nowhere to program the MAC to accept and/or generate pause > frames, how are they controlled? Does the MAC always accept and/or > generate them? Or does the MAC always ignore them and never generates > them? > > If the latter, then that suggests pause frames are not supported, and > thus MAC_SYM_PAUSE and MAC_ASYM_PAUSE should not be set in the get_caps > method. > > This leads me on to another question - in the above quoted code, what > device's BMCR is being accessed in lan9303_phylink_mac_link_up() ? Is > it a PCS? If it is, please use the phylink_pcs support, as the > pcs_config() method gives you what is necessary to program the PCS > advertisement. > > Thanks. > > -- On this device, the XMII connection is the rev-xmii port connected to the CPU. This is the DSA port. This device 'emulates' a phy (virtual phy) allowing the CPU to use standard phy registers to set things up. Let me back up for a moment. The device supports half-duplex BackPressure as well as full-duplex Flow Control. The device has bootstrapping options that will configure the Settings for BP and FC. On port 0, these strapping options also affect the Virtual Phys Auto-Negotiation Link Partner Base Page Ability Register. If auto-negotiation is enabled, the flow control is enabled/disabled based on the Sym/Asym settings of the Advertised and Link Partner's capabilities registers. If Manual Flow Control is enabled, then flow control is programmed into the Manual_FC_0 register directly and the auto-neg registers are ignored. The device can be strapped to use (default to) the Manual FC register. So this is why I'm trying to reflect the flow control settings as provided in the mac_link_up hook api into the emulated phy's aneg settings. Question: In the get capabilities API, should I report the device's flow control capabilities independent of how the device is bootstrapped or should I reflect the bootstrapped settings? I consider the bootstrap setting to affect the register default rather than limit what the device is physically capable of supporting. Thanks for helping me get this right. Regards, Jerry.
On Mon, Jan 16, 2023 at 10:48:47PM +0000, Jerry.Ray@microchip.com wrote: > > > > > +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, > > > > > + struct phylink_config *config) > > > > > +{ > > > > > + struct lan9303 *chip = ds->priv; > > > > > + > > > > > + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); > > > > > + > > > > > + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | > > > > > + MAC_SYM_PAUSE; > > > > > > > > You indicate that pause modes are supported, but... > > > > > > > > > +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, > > > > > + unsigned int mode, > > > > > + phy_interface_t interface, > > > > > + struct phy_device *phydev, int speed, > > > > > + int duplex, bool tx_pause, > > > > > + bool rx_pause) > > > > > +{ > > > > > + u32 ctl; > > > > > + > > > > > + /* On this device, we are only interested in doing something here if > > > > > + * this is the xMII port. All other ports are 10/100 phys using MDIO > > > > > + * to control there link settings. > > > > > + */ > > > > > + if (port != 0) > > > > > + return; > > > > > + > > > > > + ctl = lan9303_phy_read(ds, port, MII_BMCR); > > > > > + > > > > > + ctl &= ~BMCR_ANENABLE; > > > > > + > > > > > + if (speed == SPEED_100) > > > > > + ctl |= BMCR_SPEED100; > > > > > + else if (speed == SPEED_10) > > > > > + ctl &= ~BMCR_SPEED100; > > > > > + else > > > > > + dev_err(ds->dev, "unsupported speed: %d\n", speed); > > > > > + > > > > > + if (duplex == DUPLEX_FULL) > > > > > + ctl |= BMCR_FULLDPLX; > > > > > + else > > > > > + ctl &= ~BMCR_FULLDPLX; > > > > > + > > > > > + lan9303_phy_write(ds, port, MII_BMCR, ctl); > > > > > > > > There is no code here to program the resolved pause modes. Is it handled > > > > internally within the switch? (Please add a comment to this effect > > > > either in get_caps or here.) > > > > > > > > Thanks. > > > > > > > > > > As I look into this, the part does have control flags for advertising > > > Symmetric and Asymmetric pause toward the link partner. The default is set > > > by a configuration strap on power-up. I am having trouble mapping the rx and > > > tx pause parameters into symmetric and asymmetric controls. Where can I find > > > the proper definitions and mappings? > > > > > > ctl &= ~( ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_AYM); > > > if(tx_pause) > > > ctl |= ADVERTISE_PAUSE_CAP; > > > if(rx_pause) > > > ctl |= ADVERTISE_PAUSE_AYM; > > > > lan9303_phylink_mac_link_up() has nothing to do with what might be > > advertised to the link partner - this is called when the link has been > > negotiated and established, and it's purpose is to program the results > > of the resolution into the MAC. > > > > That means programming the MAC to operate at the negotiated speed and > > duplex, and also permitting the MAC to generate pause frames when its > > receive side becomes full (tx_pause) and whether to act on pause frames > > received over the network (rx_pause). > > > > If there's nowhere to program the MAC to accept and/or generate pause > > frames, how are they controlled? Does the MAC always accept and/or > > generate them? Or does the MAC always ignore them and never generates > > them? > > > > If the latter, then that suggests pause frames are not supported, and > > thus MAC_SYM_PAUSE and MAC_ASYM_PAUSE should not be set in the get_caps > > method. > > > > This leads me on to another question - in the above quoted code, what > > device's BMCR is being accessed in lan9303_phylink_mac_link_up() ? Is > > it a PCS? If it is, please use the phylink_pcs support, as the > > pcs_config() method gives you what is necessary to program the PCS > > advertisement. > > > > Thanks. > > > > -- > > On this device, the XMII connection is the rev-xmii port connected to the CPU. > This is the DSA port. This device 'emulates' a phy (virtual phy) allowing the > CPU to use standard phy registers to set things up. > > Let me back up for a moment. > The device supports half-duplex BackPressure as well as full-duplex Flow > Control. > The device has bootstrapping options that will configure the Settings for > BP and FC. On port 0, these strapping options also affect the Virtual Phys > Auto-Negotiation Link Partner Base Page Ability Register. > If auto-negotiation is enabled, the flow control is enabled/disabled based > on the Sym/Asym settings of the Advertised and Link Partner's capabilities > registers. > If Manual Flow Control is enabled, then flow control is programmed into the > Manual_FC_0 register directly and the auto-neg registers are ignored. The > device can be strapped to use (default to) the Manual FC register. > > So this is why I'm trying to reflect the flow control settings as provided in > the mac_link_up hook api into the emulated phy's aneg settings. But it's wrong to be trying to do that. The advertisement (in other words _our_ capabilities) should be configured at one of the _config() stages - which includes the speed, duplex and pause capabilities. When the link partner wants to connect, the advertisement is exchanged between each ends, and these advertisements are then used to determine the final properties of the link. At this point, the link comes up, and the link_up() methods will be called. If, in the link_up() method, you want to change the advertisement, then you would need to program that, and _then_ trigger a renegotiation of the link, which would cause the link to go down. The above process would be repeated, and ultimately link_up() would be called again. You'd then reprogram the advertisement and trigger another renegotiation, and the link would go down, up, down, up, down, up indefinitely. > Question: In the get capabilities API, should I report the device's > flow control capabilities independent of how the device is bootstrapped or > should I reflect the bootstrapped settings? I consider the bootstrap setting > to affect the register default rather than limit what the device is physically > capable of supporting. I would suggest that the bootstrapping should in this case be reflected in the MAC_*_PAUSE settings passed to phylink, so phylink knows how that is configured and should end up with the same resolution as the hardware. Things can go wrong if ethtool is then used to force manual pause settings, but in such a case, you will be provided with the new advertisement using the standard algorithm for determining the ASYM and SYM bits that the kernel uses (which is not perfect, since it's ambiguous.)
diff --git a/drivers/net/dsa/lan9303-core.c b/drivers/net/dsa/lan9303-core.c index 7be4c491e5d9..e514fff81af6 100644 --- a/drivers/net/dsa/lan9303-core.c +++ b/drivers/net/dsa/lan9303-core.c @@ -1058,37 +1058,6 @@ static int lan9303_phy_write(struct dsa_switch *ds, int phy, int regnum, return chip->ops->phy_write(chip, phy, regnum, val); } -static void lan9303_adjust_link(struct dsa_switch *ds, int port, - struct phy_device *phydev) -{ - int ctl; - - /* On this device, we are only interested in doing something here if - * this is an xMII port. All other ports are 10/100 phys using MDIO - * to control there link settings. - */ - if (port != 0) - return; - - ctl = lan9303_phy_read(ds, port, MII_BMCR); - - ctl &= ~BMCR_ANENABLE; - - if (phydev->speed == SPEED_100) - ctl |= BMCR_SPEED100; - else if (phydev->speed == SPEED_10) - ctl &= ~BMCR_SPEED100; - else - dev_err(ds->dev, "unsupported speed: %d\n", phydev->speed); - - if (phydev->duplex == DUPLEX_FULL) - ctl |= BMCR_FULLDPLX; - else - ctl &= ~BMCR_FULLDPLX; - - lan9303_phy_write(ds, port, MII_BMCR, ctl); -} - static int lan9303_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) { @@ -1285,13 +1254,81 @@ static int lan9303_port_mdb_del(struct dsa_switch *ds, int port, return 0; } +static void lan9303_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + struct lan9303 *chip = ds->priv; + + dev_dbg(chip->dev, "%s(%d) entered.", __func__, port); + + config->mac_capabilities = MAC_10 | MAC_100 | MAC_ASYM_PAUSE | + MAC_SYM_PAUSE; + + if (port == 0) { + __set_bit(PHY_INTERFACE_MODE_RMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_MII, + config->supported_interfaces); + } else { + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + /* Compatibility for phylib's default interface type when the + * phy-mode property is absent + */ + __set_bit(PHY_INTERFACE_MODE_GMII, + config->supported_interfaces); + } + + /* This driver does not make use of the speed, duplex, pause or the + * advertisement in its mac_config, so it is safe to mark this driver + * as non-legacy. + */ + config->legacy_pre_march2020 = false; +} + +static void lan9303_phylink_mac_link_up(struct dsa_switch *ds, int port, + unsigned int mode, + phy_interface_t interface, + struct phy_device *phydev, int speed, + int duplex, bool tx_pause, + bool rx_pause) +{ + u32 ctl; + + /* On this device, we are only interested in doing something here if + * this is the xMII port. All other ports are 10/100 phys using MDIO + * to control there link settings. + */ + if (port != 0) + return; + + ctl = lan9303_phy_read(ds, port, MII_BMCR); + + ctl &= ~BMCR_ANENABLE; + + if (speed == SPEED_100) + ctl |= BMCR_SPEED100; + else if (speed == SPEED_10) + ctl &= ~BMCR_SPEED100; + else + dev_err(ds->dev, "unsupported speed: %d\n", speed); + + if (duplex == DUPLEX_FULL) + ctl |= BMCR_FULLDPLX; + else + ctl &= ~BMCR_FULLDPLX; + + lan9303_phy_write(ds, port, MII_BMCR, ctl); +} + static const struct dsa_switch_ops lan9303_switch_ops = { .get_tag_protocol = lan9303_get_tag_protocol, .setup = lan9303_setup, .get_strings = lan9303_get_strings, .phy_read = lan9303_phy_read, .phy_write = lan9303_phy_write, - .adjust_link = lan9303_adjust_link, + .phylink_get_caps = lan9303_phylink_get_caps, + .phylink_mac_link_up = lan9303_phylink_mac_link_up, .get_ethtool_stats = lan9303_get_ethtool_stats, .get_sset_count = lan9303_get_sset_count, .port_enable = lan9303_port_enable,