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  linux-hardening  linux-cve-announce  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]
Message-ID: <VI1PR0402MB280076275F4B8343B4E8BC2EE0EE0@VI1PR0402MB2800.eurprd04.prod.outlook.com>
Date:   Fri, 14 Jun 2019 16:34:59 +0000
From:   Ioana Ciornei <ioana.ciornei@....com>
To:     Russell King - ARM Linux admin <linux@...linux.org.uk>
CC:     "hkallweit1@...il.com" <hkallweit1@...il.com>,
        "f.fainelli@...il.com" <f.fainelli@...il.com>,
        "andrew@...n.ch" <andrew@...n.ch>,
        "davem@...emloft.net" <davem@...emloft.net>,
        "netdev@...r.kernel.org" <netdev@...r.kernel.org>,
        Alexandru Marginean <alexandru.marginean@....com>,
        Ioana Ciocoi Radulescu <ruxandra.radulescu@....com>
Subject: RE: [PATCH RFC 4/6] dpaa2-mac: add initial driver


> Subject: Re: [PATCH RFC 4/6] dpaa2-mac: add initial driver
> 
> On Fri, Jun 14, 2019 at 02:55:51AM +0300, Ioana Ciornei wrote:
> > The dpaa2-mac driver binds to DPAA2 DPMAC objects, dynamically
> > discovered on the fsl-mc bus. It acts as a proxy between the PHY
> > management layer and the MC firmware, delivering any configuration
> > changes to the firmware and also setting any new configuration
> > requested though PHYLINK.
> >
> > A in-depth view of the software architecture and the implementation
> > can be found in
> > 'Documentation/networking/device_drivers/freescale/dpaa2/dpmac-
> driver.rst'.
> >
> > Signed-off-by: Ioana Ciornei <ioana.ciornei@....com>
> > ---
> >  MAINTAINERS                                      |   7 +
> >  drivers/net/ethernet/freescale/dpaa2/Kconfig     |  13 +
> >  drivers/net/ethernet/freescale/dpaa2/Makefile    |   2 +
> >  drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c | 541
> > +++++++++++++++++++++++
> >  4 files changed, 563 insertions(+)
> >  create mode 100644 drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS index
> > dd247a059889..a024ab2b2548 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -4929,6 +4929,13 @@ S:	Maintained
> >  F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-ptp*
> >  F:	drivers/net/ethernet/freescale/dpaa2/dprtc*
> >
> > +DPAA2 MAC DRIVER
> > +M:	Ioana Ciornei <ioana.ciornei@....com>
> > +L:	netdev@...r.kernel.org
> > +S:	Maintained
> > +F:	drivers/net/ethernet/freescale/dpaa2/dpaa2-mac*
> > +F:	drivers/net/ethernet/freescale/dpaa2/dpmac*
> > +
> >  DPT_I2O SCSI RAID DRIVER
> >  M:	Adaptec OEM Raid Solutions <aacraid@...rosemi.com>
> >  L:	linux-scsi@...r.kernel.org
> > diff --git a/drivers/net/ethernet/freescale/dpaa2/Kconfig
> > b/drivers/net/ethernet/freescale/dpaa2/Kconfig
> > index 8bd384720f80..4ffa666c0a43 100644
> > --- a/drivers/net/ethernet/freescale/dpaa2/Kconfig
> > +++ b/drivers/net/ethernet/freescale/dpaa2/Kconfig
> > @@ -16,3 +16,16 @@ config FSL_DPAA2_PTP_CLOCK
> >  	help
> >  	  This driver adds support for using the DPAA2 1588 timer module
> >  	  as a PTP clock.
> > +
> > +config FSL_DPAA2_MAC
> > +	tristate "DPAA2 MAC / PHY proxy interface"
> > +	depends on FSL_MC_BUS
> > +	select MDIO_BUS_MUX_MMIOREG
> > +	select FSL_XGMAC_MDIO
> > +	select PHYLINK
> > +	help
> > +	  Prototype driver for DPAA2 MAC / PHY interface object.
> > +	  This driver works as a proxy between PHYLINK including phy drivers and
> > +	  the MC firmware.  It receives updates on link state changes from
> PHYLINK
> > +	  and forwards them to MC and receives interrupt from MC whenever a
> > +	  request is made to change the link state or configuration.
> > diff --git a/drivers/net/ethernet/freescale/dpaa2/Makefile
> > b/drivers/net/ethernet/freescale/dpaa2/Makefile
> > index d1e78cdd512f..e96386ab23ea 100644
> > --- a/drivers/net/ethernet/freescale/dpaa2/Makefile
> > +++ b/drivers/net/ethernet/freescale/dpaa2/Makefile
> > @@ -5,10 +5,12 @@
> >
> >  obj-$(CONFIG_FSL_DPAA2_ETH)		+= fsl-dpaa2-eth.o
> >  obj-$(CONFIG_FSL_DPAA2_PTP_CLOCK)	+= fsl-dpaa2-ptp.o
> > +obj-$(CONFIG_FSL_DPAA2_MAC)		+= fsl-dpaa2-mac.o
> >
> >  fsl-dpaa2-eth-objs	:= dpaa2-eth.o dpaa2-ethtool.o dpni.o
> >  fsl-dpaa2-eth-${CONFIG_DEBUG_FS} += dpaa2-eth-debugfs.o
> >  fsl-dpaa2-ptp-objs	:= dpaa2-ptp.o dprtc.o
> > +fsl-dpaa2-mac-objs	:= dpaa2-mac.o dpmac.o
> >
> >  # Needed by the tracing framework
> >  CFLAGS_dpaa2-eth.o := -I$(src)
> > diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> > b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> > new file mode 100644
> > index 000000000000..145ab4771788
> > --- /dev/null
> > +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-mac.c
> > @@ -0,0 +1,541 @@
> > +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
> > +/* Copyright 2015 Freescale Semiconductor Inc.
> > + * Copyright 2018-2019 NXP
> > + */
> > +#include <linux/module.h>
> > +#include <linux/netdevice.h>
> > +#include <linux/etherdevice.h>
> > +#include <linux/msi.h>
> > +#include <linux/rtnetlink.h>
> > +#include <linux/if_vlan.h>
> > +
> > +#include <net/netlink.h>
> > +#include <uapi/linux/if_bridge.h>
> > +
> > +#include <linux/of.h>
> > +#include <linux/of_mdio.h>
> > +#include <linux/of_net.h>
> > +#include <linux/phylink.h>
> > +#include <linux/notifier.h>
> > +
> > +#include <linux/fsl/mc.h>
> > +
> > +#include "dpmac.h"
> > +#include "dpmac-cmd.h"
> > +
> > +#define to_dpaa2_mac_priv(phylink_config) \
> > +	container_of(config, struct dpaa2_mac_priv, phylink_config)
> > +
> > +struct dpaa2_mac_priv {
> > +	struct fsl_mc_device *mc_dev;
> > +	struct dpmac_attr attr;
> > +	struct dpmac_link_state state;
> > +	u16 dpmac_ver_major;
> > +	u16 dpmac_ver_minor;
> > +
> > +	struct phylink *phylink;
> > +	struct phylink_config phylink_config;
> > +	struct ethtool_link_ksettings kset;
> > +};
> > +
> > +static phy_interface_t phy_mode(enum dpmac_eth_if eth_if) {
> > +	switch (eth_if) {
> > +	case DPMAC_ETH_IF_RGMII:
> > +		return PHY_INTERFACE_MODE_RGMII;
> > +	case DPMAC_ETH_IF_XFI:
> > +		return PHY_INTERFACE_MODE_10GKR;
> > +	case DPMAC_ETH_IF_USXGMII:
> > +		return PHY_INTERFACE_MODE_USXGMII;
> 
> No support for SGMII nor the 802.3z modes?

The Serdes has support for both of them but the driver does not at the moment.

> 
> > +	default:
> > +		return -EINVAL;
> > +	}
> > +}
> > +
> > +static int cmp_dpmac_ver(struct dpaa2_mac_priv *priv,
> > +			 u16 ver_major, u16 ver_minor)
> > +{
> > +	if (priv->dpmac_ver_major == ver_major)
> > +		return priv->dpmac_ver_minor - ver_minor;
> > +	return priv->dpmac_ver_major - ver_major; }
> > +
> > +struct dpaa2_mac_link_mode_map {
> > +	u64 dpmac_lm;
> > +	enum ethtool_link_mode_bit_indices ethtool_lm; };
> > +
> > +static const struct dpaa2_mac_link_mode_map dpaa2_mac_lm_map[] = {
> > +	{DPMAC_ADVERTISED_10BASET_FULL,
> ETHTOOL_LINK_MODE_10baseT_Full_BIT},
> > +	{DPMAC_ADVERTISED_100BASET_FULL,
> ETHTOOL_LINK_MODE_100baseT_Full_BIT},
> > +	{DPMAC_ADVERTISED_1000BASET_FULL,
> ETHTOOL_LINK_MODE_1000baseT_Full_BIT},
> > +	{DPMAC_ADVERTISED_10000BASET_FULL,
> > +ETHTOOL_LINK_MODE_10000baseT_Full_BIT},
> 
> No half-duplex support?

Yes, no half-duplex.

> 
> > +	{DPMAC_ADVERTISED_AUTONEG,
> ETHTOOL_LINK_MODE_Autoneg_BIT}, };
> > +
> > +static void link_mode_phydev2dpmac(unsigned long *phydev_lm,
> > +				   u64 *dpmac_lm)
> > +{
> > +	enum ethtool_link_mode_bit_indices link_mode;
> > +	int i;
> > +
> > +	*dpmac_lm = 0;
> > +	for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
> > +		link_mode = dpaa2_mac_lm_map[i].ethtool_lm;
> > +		if (linkmode_test_bit(link_mode, phydev_lm))
> > +			*dpmac_lm |= dpaa2_mac_lm_map[i].dpmac_lm;
> > +	}
> > +}
> > +
> > +static void dpaa2_mac_ksettings_change(struct dpaa2_mac_priv *priv) {
> > +	struct fsl_mc_device *mc_dev = priv->mc_dev;
> > +	struct dpmac_link_cfg link_cfg = { 0 };
> > +	int err, i;
> > +
> > +	err = dpmac_get_link_cfg(mc_dev->mc_io, 0,
> > +				 mc_dev->mc_handle,
> > +				 &link_cfg);
> > +
> > +	if (err) {
> > +		dev_err(&mc_dev->dev, "dpmac_get_link_cfg() = %d\n", err);
> > +		return;
> > +	}
> > +
> > +	phylink_ethtool_ksettings_get(priv->phylink, &priv->kset);
> > +
> > +	priv->kset.base.speed = link_cfg.rate;
> > +	priv->kset.base.duplex = !!(link_cfg.options &
> > +DPMAC_LINK_OPT_HALF_DUPLEX);
> 
> What's the point of setting duplex to anything other than true here - everything
> I've read in this driver apart from the above indicates that there is no support for
> half duplex.

Yep, that's another mishap on my part. That should have been removed.

> 
> > +
> > +	ethtool_link_ksettings_zero_link_mode(&priv->kset, advertising);
> > +	for (i = 0; i < ARRAY_SIZE(dpaa2_mac_lm_map); i++) {
> > +		if (link_cfg.advertising & dpaa2_mac_lm_map[i].dpmac_lm)
> > +			__set_bit(dpaa2_mac_lm_map[i].ethtool_lm,
> > +				  priv->kset.link_modes.advertising);
> > +	}
> > +
> > +	if (link_cfg.options & DPMAC_LINK_OPT_AUTONEG) {
> > +		priv->kset.base.autoneg = AUTONEG_ENABLE;
> > +		__set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
> > +			  priv->kset.link_modes.advertising);
> > +	} else {
> > +		priv->kset.base.autoneg = AUTONEG_DISABLE;
> > +		__clear_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
> > +			    priv->kset.link_modes.advertising);
> > +	}
> > +
> > +	phylink_ethtool_ksettings_set(priv->phylink, &priv->kset);
> 
> What if this returns an error?  There seems to be no way to communicate failure
> back through the firmware.

That's right, we do not have a way of signaling back the failure to the firmware.

> 
> > +static void dpaa2_mac_validate(struct phylink_config *config,
> > +			       unsigned long *supported,
> > +			       struct phylink_link_state *state) {
> > +	struct dpaa2_mac_priv *priv = to_dpaa2_mac_priv(phylink_config);
> > +	struct dpmac_link_state *dpmac_state = &priv->state;
> > +	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
> > +
> > +	phylink_set(mask, Autoneg);
> > +	phylink_set_port_modes(mask);
> > +
> > +	switch (state->interface) {
> > +	case PHY_INTERFACE_MODE_10GKR:
> > +		phylink_set(mask, 10baseT_Full);
> > +		phylink_set(mask, 100baseT_Full);
> > +		phylink_set(mask, 1000baseT_Full);
> > +		phylink_set(mask, 10000baseT_Full);
> > +		break;
> > +	case PHY_INTERFACE_MODE_QSGMII:
> > +	case PHY_INTERFACE_MODE_RGMII:
> > +	case PHY_INTERFACE_MODE_RGMII_ID:
> > +	case PHY_INTERFACE_MODE_RGMII_RXID:
> > +	case PHY_INTERFACE_MODE_RGMII_TXID:
> > +		phylink_set(mask, 10baseT_Full);
> > +		phylink_set(mask, 100baseT_Full);
> > +		phylink_set(mask, 1000baseT_Full);
> > +		break;
> > +	case PHY_INTERFACE_MODE_USXGMII:
> > +		phylink_set(mask, 10baseT_Full);
> > +		phylink_set(mask, 100baseT_Full);
> > +		phylink_set(mask, 1000baseT_Full);
> > +		phylink_set(mask, 10000baseT_Full);
> 
> Consider using the newer linkmode_set_bit() etc interfaces here.

Sure.

> 
> > +		break;
> > +	default:
> > +		goto empty_set;
> > +	}
> > +
> > +	bitmap_and(supported, supported, mask,
> __ETHTOOL_LINK_MODE_MASK_NBITS);
> > +	bitmap_and(state->advertising, state->advertising, mask,
> > +		   __ETHTOOL_LINK_MODE_MASK_NBITS);
> > +
> > +	link_mode_phydev2dpmac(supported, &dpmac_state->supported);
> > +	link_mode_phydev2dpmac(state->advertising,
> > +&dpmac_state->advertising);
> 
> This is not correct.  phylink will make calls to this function to enquire whether
> something is supported or not, it isn't strictly used to say "this is what we are
> going to use", so storing these does not reflect the current state.

We can update these only on a mac_config.
> 
> > +
> > +	return;
> > +
> > +empty_set:
> > +	bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS); }
> > +
> > +static void dpaa2_mac_config(struct phylink_config *config, unsigned int
> mode,
> > +			     const struct phylink_link_state *state) {
> > +	struct dpaa2_mac_priv *priv = to_dpaa2_mac_priv(phylink_config);
> > +	struct dpmac_link_state *dpmac_state = &priv->state;
> > +	struct device *dev = &priv->mc_dev->dev;
> > +	int err;
> > +
> > +	if (state->speed == SPEED_UNKNOWN && state->duplex ==
> DUPLEX_UNKNOWN)
> > +		return;
> > +
> > +	dpmac_state->up = !!state->link;
> > +	if (dpmac_state->up) {
> > +		dpmac_state->rate = state->speed;
> > +
> > +		if (!state->duplex)
> > +			dpmac_state->options |=
> DPMAC_LINK_OPT_HALF_DUPLEX;
> > +		else
> > +			dpmac_state->options &=
> ~DPMAC_LINK_OPT_HALF_DUPLEX;
> > +
> > +		if (state->an_enabled)
> > +			dpmac_state->options |=
> DPMAC_LINK_OPT_AUTONEG;
> > +		else
> > +			dpmac_state->options &=
> ~DPMAC_LINK_OPT_AUTONEG;
> > +	}
> 
> Apart from my comments for the above in reply to Andrew, you can store the
> "advertising" mask here.
> 
> However, what is the point of the "dpmac_state->up = !!state->link"
> stuff (despite it being wrong as previously described) when you set dpmac_state-
> >up in the mac_link_up/mac_link_down functions below.
> This makes no sense to me.

Ok, so keep the last known value of the link until a .mac_link_{up/down} is called and only them update it.
I'll change that.

> 
> > +
> > +	err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
> > +				   priv->mc_dev->mc_handle, dpmac_state);
> > +	if (err)
> > +		dev_err(dev, "dpmac_set_link_state() = %d\n", err); }
> > +
> > +static void dpaa2_mac_link_up(struct phylink_config *config, unsigned int
> mode,
> > +			      phy_interface_t interface, struct phy_device *phy) {
> > +	struct dpaa2_mac_priv *priv = to_dpaa2_mac_priv(phylink_config);
> > +	struct dpmac_link_state *dpmac_state = &priv->state;
> > +	struct device *dev = &priv->mc_dev->dev;
> > +	int err;
> > +
> > +	dpmac_state->up = 1;
> > +	err = dpmac_set_link_state(priv->mc_dev->mc_io, 0,
> > +				   priv->mc_dev->mc_handle, dpmac_state);
> > +	if (err)
> > +		dev_err(dev, "dpmac_set_link_state() = %d\n", err);
> 
> This is also very suspect - have you read the phylink documentation?
> The documentation details that there are some behavioural differences here
> depending on the negotiation mode, but your code doesn't even look at those.
> 
> Given that you're not handling those, I don't see how you expect SFP support to
> work.  In fact, given that the validate callback doesn't make any mention of
> SGMII, 1000BASEX, or 2500BASEX phy modes, I don't see how you expect this to
> work with SFP.  Given that, I really question why you want to use phylink rather
> than talking to phylib directly.

I am not handling the XFP/SFP+ support in this version of the driver since, as you noticed, I am not accepting BASEX modes.
Nonetheless, I am not ruling out adding support for SFP on top of this. This is one reason why we're using phylink. 

Also, using phylib is not straight-forward either. The dpaa2-mac should fabricate a net_device for each phy that it wants to connect to.
These net_device should be kept unregistered with the network core so that we don't see "MAC interfaces" in ifconfig.

> 
> I get the overall impression from what I've seen so far that phylink is entirely
> unsuited to the structure of this implementation.
> 
> phylinks purpose is to support hotpluggable PHYs on SFP modules where the
> MAC may be connected _directly_ to the SFP cage without an intervening PHY,
> or if there is an intervening PHY, the PHY is completely transparent.  For that to
> work, the interface modes that SFP modules support must be supported by the
> MAC.
> 
> I can't see a reason at the moment for you to use phylink.
> 

Well, a phylib solution isn't cleaner either. 

--
Ioana

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ