lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 13 Jul 2020 19:38:19 +0300
From:   Vladimir Oltean <olteanv@...il.com>
To:     Michael Walle <michael@...le.cc>
Cc:     netdev@...r.kernel.org, linux-kernel@...r.kernel.org,
        "David S . Miller" <davem@...emloft.net>,
        Jakub Kicinski <kuba@...nel.org>, Andrew Lunn <andrew@...n.ch>,
        Alex Marginean <alexandru.marginean@....com>,
        Claudiu Manoil <claudiu.manoil@....com>,
        Heiko Thiery <heiko.thiery@...il.com>,
        Russell King - ARM Linux admin <linux@...linux.org.uk>,
        Ioana Ciornei <ioana.ciornei@....com>,
        Microchip Linux Driver Support <UNGLinuxDriver@...rochip.com>
Subject: Re: [PATCH net-next v6 3/4] net: enetc: Initialize SerDes for SGMII
 and USXGMII protocols

On Thu, Jul 09, 2020 at 11:35:25PM +0200, Michael Walle wrote:
> ENETC has ethernet MACs capable of SGMII, 2500BaseX and USXGMII. But in
> order to use these protocols some SerDes configurations need to be
> performed. The SerDes is configurable via an internal PCS PHY which is
> connected to an internal MDIO bus at address 0.
> 
> This patch basically removes the dependency on bootloader regarding
> SerDes initialization.
> 
> Signed-off-by: Michael Walle <michael@...le.cc>
> Reviewed-by: Claudiu Manoil <claudiu.manoil@....com>
> ---

As mentioned earlier, this works for SGMII. For USXGMII, it would also
need this patch to work (something which is also true of Felix):

https://patchwork.ozlabs.org/project/netdev/patch/20200712164815.1763532-1-olteanv@gmail.com/

Considering that patch as external to this series:

Tested-by: Vladimir Oltean <vladimir.oltean@....com>

>  .../net/ethernet/freescale/enetc/enetc_hw.h   |   3 +
>  .../net/ethernet/freescale/enetc/enetc_pf.c   | 135 ++++++++++++++++++
>  .../net/ethernet/freescale/enetc/enetc_pf.h   |   2 +
>  3 files changed, 140 insertions(+)
> 
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
> index fc357bc56835..135bf46354ea 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
> @@ -224,6 +224,9 @@ enum enetc_bdr_type {TX, RX};
>  #define ENETC_PM0_MAXFRM	0x8014
>  #define ENETC_SET_TX_MTU(val)	((val) << 16)
>  #define ENETC_SET_MAXFRM(val)	((val) & 0xffff)
> +
> +#define ENETC_PM_IMDIO_BASE	0x8030
> +
>  #define ENETC_PM0_IF_MODE	0x8300
>  #define ENETC_PMO_IFM_RG	BIT(2)
>  #define ENETC_PM0_IFM_RLP	(BIT(5) | BIT(11))
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
> index 4fac57dbb3c8..662740874841 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
> @@ -1,6 +1,7 @@
>  // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
>  /* Copyright 2017-2019 NXP */
>  
> +#include <linux/mdio.h>
>  #include <linux/module.h>
>  #include <linux/fsl/enetc_mdio.h>
>  #include <linux/of_mdio.h>
> @@ -833,6 +834,135 @@ static void enetc_of_put_phy(struct enetc_ndev_priv *priv)
>  		of_node_put(priv->phy_node);
>  }
>  
> +static int enetc_imdio_init(struct enetc_pf *pf, bool is_c45)
> +{
> +	struct device *dev = &pf->si->pdev->dev;
> +	struct enetc_mdio_priv *mdio_priv;
> +	struct phy_device *pcs;
> +	struct mii_bus *bus;
> +	int err;
> +
> +	bus = mdiobus_alloc_size(sizeof(*mdio_priv));
> +	if (!bus)
> +		return -ENOMEM;
> +
> +	bus->name = "Freescale ENETC internal MDIO Bus";
> +	bus->read = enetc_mdio_read;
> +	bus->write = enetc_mdio_write;
> +	bus->parent = dev;
> +	bus->phy_mask = ~0;
> +	mdio_priv = bus->priv;
> +	mdio_priv->hw = &pf->si->hw;
> +	mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE;
> +	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev));
> +
> +	err = mdiobus_register(bus);
> +	if (err) {
> +		dev_err(dev, "cannot register internal MDIO bus (%d)\n", err);
> +		goto free_mdio_bus;
> +	}
> +
> +	pcs = get_phy_device(bus, 0, is_c45);
> +	if (IS_ERR(pcs)) {
> +		err = PTR_ERR(pcs);
> +		dev_err(dev, "cannot get internal PCS PHY (%d)\n", err);
> +		goto unregister_mdiobus;
> +	}
> +
> +	pf->imdio = bus;
> +	pf->pcs = pcs;
> +
> +	return 0;
> +
> +unregister_mdiobus:
> +	mdiobus_unregister(bus);
> +free_mdio_bus:
> +	mdiobus_free(bus);
> +	return err;
> +}
> +
> +static void enetc_imdio_remove(struct enetc_pf *pf)
> +{
> +	if (pf->pcs)
> +		put_device(&pf->pcs->mdio.dev);
> +	if (pf->imdio) {
> +		mdiobus_unregister(pf->imdio);
> +		mdiobus_free(pf->imdio);
> +	}
> +}
> +
> +static void enetc_configure_sgmii(struct phy_device *pcs)
> +{
> +	/* SGMII spec requires tx_config_Reg[15:0] to be exactly 0x4001
> +	 * for the MAC PCS in order to acknowledge the AN.
> +	 */
> +	phy_write(pcs, MII_ADVERTISE, ADVERTISE_SGMII | ADVERTISE_LPACK);
> +
> +	phy_write(pcs, ENETC_PCS_IF_MODE,
> +		  ENETC_PCS_IF_MODE_SGMII_EN |
> +		  ENETC_PCS_IF_MODE_USE_SGMII_AN);
> +
> +	/* Adjust link timer for SGMII */
> +	phy_write(pcs, ENETC_PCS_LINK_TIMER1, ENETC_PCS_LINK_TIMER1_VAL);
> +	phy_write(pcs, ENETC_PCS_LINK_TIMER2, ENETC_PCS_LINK_TIMER2_VAL);
> +
> +	phy_write(pcs, MII_BMCR, BMCR_ANRESTART | BMCR_ANENABLE);
> +}
> +
> +static void enetc_configure_2500basex(struct phy_device *pcs)
> +{
> +	phy_write(pcs, ENETC_PCS_IF_MODE,
> +		  ENETC_PCS_IF_MODE_SGMII_EN |
> +		  ENETC_PCS_IF_MODE_SGMII_SPEED(ENETC_PCS_SPEED_2500));
> +
> +	phy_write(pcs, MII_BMCR, BMCR_SPEED1000 | BMCR_FULLDPLX | BMCR_RESET);
> +}
> +
> +static void enetc_configure_usxgmii(struct phy_device *pcs)
> +{
> +	/* Configure device ability for the USXGMII Replicator */
> +	phy_write_mmd(pcs, MDIO_MMD_VEND2, MII_ADVERTISE,
> +		      ADVERTISE_SGMII | ADVERTISE_LPACK |
> +		      MDIO_LPA_USXGMII_FULL_DUPLEX);
> +
> +	/* Restart PCS AN */
> +	phy_write_mmd(pcs, MDIO_MMD_VEND2, MII_BMCR,
> +		      BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
> +}
> +
> +static int enetc_configure_serdes(struct enetc_ndev_priv *priv)
> +{
> +	bool is_c45 = priv->if_mode == PHY_INTERFACE_MODE_USXGMII;
> +	struct enetc_pf *pf = enetc_si_priv(priv->si);
> +	int err;
> +
> +	if (priv->if_mode != PHY_INTERFACE_MODE_SGMII &&
> +	    priv->if_mode != PHY_INTERFACE_MODE_2500BASEX &&
> +	    priv->if_mode != PHY_INTERFACE_MODE_USXGMII)
> +		return 0;
> +
> +	err = enetc_imdio_init(pf, is_c45);
> +	if (err)
> +		return err;
> +
> +	switch (priv->if_mode) {
> +	case PHY_INTERFACE_MODE_SGMII:
> +		enetc_configure_sgmii(pf->pcs);
> +		break;
> +	case PHY_INTERFACE_MODE_2500BASEX:
> +		enetc_configure_2500basex(pf->pcs);
> +		break;
> +	case PHY_INTERFACE_MODE_USXGMII:
> +		enetc_configure_usxgmii(pf->pcs);
> +		break;
> +	default:
> +		dev_err(&pf->si->pdev->dev, "Unsupported link mode %s\n",
> +			phy_modes(priv->if_mode));
> +	}
> +
> +	return 0;
> +}
> +
>  static int enetc_pf_probe(struct pci_dev *pdev,
>  			  const struct pci_device_id *ent)
>  {
> @@ -897,6 +1027,10 @@ static int enetc_pf_probe(struct pci_dev *pdev,
>  	if (err)
>  		dev_warn(&pdev->dev, "Fallback to PHY-less operation\n");
>  
> +	err = enetc_configure_serdes(priv);
> +	if (err)
> +		dev_warn(&pdev->dev, "Attempted SerDes config but failed\n");
> +
>  	err = register_netdev(ndev);
>  	if (err)
>  		goto err_reg_netdev;
> @@ -932,6 +1066,7 @@ static void enetc_pf_remove(struct pci_dev *pdev)
>  	priv = netdev_priv(si->ndev);
>  	unregister_netdev(si->ndev);
>  
> +	enetc_imdio_remove(pf);
>  	enetc_mdio_remove(pf);
>  	enetc_of_put_phy(priv);
>  
> diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.h b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> index 59e65a6f6c3e..2cb922b59f46 100644
> --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.h
> @@ -44,6 +44,8 @@ struct enetc_pf {
>  	DECLARE_BITMAP(active_vlans, VLAN_N_VID);
>  
>  	struct mii_bus *mdio; /* saved for cleanup */
> +	struct mii_bus *imdio;
> +	struct phy_device *pcs;
>  };
>  
>  int enetc_msg_psi_init(struct enetc_pf *pf);
> -- 
> 2.20.1
> 

Powered by blists - more mailing lists