netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Russell King (Oracle)" <linux@armlinux.org.uk>
To: Oleksandr Mazur <oleksandr.mazur@plvision.eu>
Cc: netdev@vger.kernel.org, "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
	open list <linux-kernel@vger.kernel.org>,
	Yevhen Orlov <yevhen.orlov@plvision.eu>,
	Taras Chornyi <taras.chornyi@plvision.eu>
Subject: Re: [PATCH net-next] net: marvell: prestera: add phylink support
Date: Fri, 8 Jul 2022 22:48:40 +0100	[thread overview]
Message-ID: <YsimODfLM3mu/KZM@shell.armlinux.org.uk> (raw)
In-Reply-To: <20220708170635.13190-1-oleksandr.mazur@plvision.eu>

On Fri, Jul 08, 2022 at 08:06:34PM +0300, Oleksandr Mazur wrote:
> For SFP port prestera driver will use kernel
> phylink infrastucture to configure port mode based on
> the module that has beed inserted
> 
> Co-developed-by: Yevhen Orlov <yevhen.orlov@plvision.eu>
> Signed-off-by: Yevhen Orlov <yevhen.orlov@plvision.eu>
> Co-developed-by: Taras Chornyi <taras.chornyi@plvision.eu>
> Signed-off-by: Taras Chornyi <taras.chornyi@plvision.eu>
> Signed-off-by: Oleksandr Mazur <oleksandr.mazur@plvision.eu>

First question which applies to everything in this patch is - why make
phylink conditional for this driver?

> +#ifdef CONFIG_PHYLINK
> +static void
> +prestera_port_mac_state_cache_read(struct prestera_port *port,
> +				   struct prestera_port_mac_state *state)
> +{
> +	read_lock(&port->state_mac_lock);
> +	*state = port->state_mac;
> +	read_unlock(&port->state_mac_lock);
> +}
> +
> +static void
> +prestera_port_mac_state_cache_write(struct prestera_port *port,
> +				    struct prestera_port_mac_state *state)
> +{
> +	write_lock(&port->state_mac_lock);
> +	port->state_mac = *state;
> +	write_unlock(&port->state_mac_lock);
> +}
> +
> +static void prestera_mac_pcs_get_state(struct phylink_config *config,
> +				       struct phylink_link_state *state)
> +{
> +	struct net_device *ndev = to_net_dev(config->dev);
> +	struct prestera_port *port = netdev_priv(ndev);
> +	struct prestera_port_mac_state smac;
> +
> +	prestera_port_mac_state_cache_read(port, &smac);
> +
> +	if (smac.valid) {
> +		state->link = smac.oper;
> +		state->pause = 0;
> +		/* AN is completed, when port is up */
> +		state->an_complete = smac.oper ? port->autoneg : false;
> +		state->speed = smac.speed;
> +		state->duplex = smac.duplex;
>  	} else {
> -		port->cfg_phy.admin = false;
> -		err = prestera_hw_port_phy_mode_set(port, false, port->autoneg,
> -						    port->cfg_phy.mode,
> -						    port->adver_link_modes,
> -						    port->cfg_phy.mdix);
> +		state->link = false;
> +		state->pause = 0;
> +		state->an_complete = false;
> +		state->speed = SPEED_UNKNOWN;
> +		state->duplex = DUPLEX_UNKNOWN;
> +	}
> +}

This function is obsolete, please delete it.

> +
> +static void prestera_mac_config(struct phylink_config *config,
> +				unsigned int an_mode,
> +				const struct phylink_link_state *state)
> +{
> +	struct net_device *ndev = to_net_dev(config->dev);
> +	struct prestera_port *port = netdev_priv(ndev);
> +	struct prestera_port_mac_config cfg_mac;
> +
> +	prestera_port_cfg_mac_read(port, &cfg_mac);
> +	cfg_mac.admin = true;
> +	cfg_mac.mode = PRESTERA_MAC_MODE_MAX;
> +	cfg_mac.inband = false;
> +	cfg_mac.speed = 0;
> +	cfg_mac.duplex = DUPLEX_UNKNOWN;
> +	cfg_mac.fec = PRESTERA_PORT_FEC_OFF;
> +
> +	/* See sfp_select_interface... fIt */
> +	switch (state->interface) {
> +	case PHY_INTERFACE_MODE_10GBASER:
> +		cfg_mac.mode = PRESTERA_MAC_MODE_SR_LR;
> +		cfg_mac.speed = SPEED_10000;
> +		if (state->speed == SPEED_1000) {
> +			cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X;
> +		} else if (state->speed == SPEED_2500) {
> +			cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;
> +			cfg_mac.inband = true;
> +			cfg_mac.speed = SPEED_2500;
> +			cfg_mac.duplex = DUPLEX_FULL;
> +		}

No no no no no no no. state->speed is _not_ defined here, as is stated
in the documentation. You can not test it here; the results are
meaningless. Also this looks really odd. If the interface is
10000base-R, then why are you switching the MAC mode to 1000base-X
or SGMII?

> +		break;
> +	case PHY_INTERFACE_MODE_2500BASEX:
> +	case PHY_INTERFACE_MODE_SGMII:
> +		/* But it seems to be not supported in HW */
> +		cfg_mac.mode = PRESTERA_MAC_MODE_SGMII;

SGMII mode for 2500base-X ?

> +		cfg_mac.inband = true;
> +		cfg_mac.speed = SPEED_2500;
> +		cfg_mac.duplex = DUPLEX_FULL;
> +		break;
> +	case PHY_INTERFACE_MODE_1000BASEX:
> +		cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X;
> +		cfg_mac.inband = state->an_enabled;
> +		cfg_mac.speed = SPEED_1000;
> +		cfg_mac.duplex = DUPLEX_UNKNOWN;
> +		break;
> +	default:
> +		cfg_mac.mode = PRESTERA_MAC_MODE_1000BASE_X;
> +	}
> +
> +	prestera_port_cfg_mac_write(port, &cfg_mac);
> +}
> +
> +int prestera_mac_finish(struct phylink_config *config, unsigned int mode,
> +			phy_interface_t iface)
> +{
> +	return 0;
> +}

No need to implement this if its doing nothing.

> +
> +static void prestera_mac_an_restart(struct phylink_config *config)
> +{
> +	/* No need to restart autoneg as it is always with the same parameters,
> +	 * because e.g. as for 1000baseX FC isn't supported. And for 1000baseT
> +	 * autoneg provided by external tranciever
> +	 */
> +}

This function is obsolete, please delete it.

> +
> +static void prestera_mac_link_down(struct phylink_config *config,
> +				   unsigned int mode, phy_interface_t interface)
> +{
> +	struct net_device *ndev = to_net_dev(config->dev);
> +	struct prestera_port *port = netdev_priv(ndev);
> +	struct prestera_port_mac_state state_mac;
> +
> +	/* Invalidate. Parameters will update on next link event. */
> +	memset(&state_mac, 0, sizeof(state_mac));
> +	state_mac.valid = false;
> +	prestera_port_mac_state_cache_write(port, &state_mac);
> +}
> +
> +static void prestera_mac_link_up(struct phylink_config *config,
> +				 struct phy_device *phy,
> +				 unsigned int mode, phy_interface_t interface,
> +				 int speed, int duplex,
> +				 bool tx_pause, bool rx_pause)
> +{

This is the place that you get to learn about the link speed etc.

> +}
> +
> +static struct phylink_pcs *prestera_mac_select_pcs(struct phylink_config *config,
> +						   phy_interface_t interface)
> +{
> +	struct net_device *dev = to_net_dev(config->dev);
> +	struct prestera_port *port = netdev_priv(dev);
> +
> +	return &port->phylink_pcs;
> +}
> +
> +static void prestera_pcs_get_state(struct phylink_pcs *pcs,
> +				   struct phylink_link_state *state)
> +{
> +	struct prestera_port *port = container_of(pcs, struct prestera_port,
> +						  phylink_pcs);
> +	struct prestera_port_mac_state smac;
> +
> +	prestera_port_mac_state_cache_read(port, &smac);
> +
> +	if (smac.valid) {
> +		state->link = smac.oper;
> +		state->pause = 0;
> +		/* AN is completed, when port is up */
> +		state->an_complete = smac.oper ? port->autoneg : false;
> +		state->speed = smac.speed;
> +		state->duplex = smac.duplex;
> +	} else {
> +		state->link = false;

This isn't a boolean, it's a 1-bit field, so "state->link = 0;" is
appropriate here.

> +		state->pause = 0;

This will be set by phylink appropriately, there's no need to set
it if there is no link.

> +		state->an_complete = false;

an_complete is a 1-bit field as well, and is set to 0.

> +		state->speed = SPEED_UNKNOWN;
> +		state->duplex = DUPLEX_UNKNOWN;

These will be set to UNKNOWN if AN is disabled, otherwise to the
configured speed. There's no need to set these.

> +	}
> +}
> +
> +static int prestera_pcs_config(struct phylink_pcs *pcs,
> +			       unsigned int mode,
> +			       phy_interface_t interface,
> +			       const unsigned long *advertising,
> +			       bool permit_pause_to_mac)
> +{
> +	return 0;
> +}
> +
> +void prestera_pcs_an_restart(struct phylink_pcs *pcs)
> +{
> +}
> +
> +static const struct phylink_mac_ops prestera_mac_ops = {
> +	.validate = phylink_generic_validate,
> +	.mac_select_pcs = prestera_mac_select_pcs,
> +	.mac_pcs_get_state = prestera_mac_pcs_get_state,

Obsolete method.

> +	.mac_config = prestera_mac_config,
> +	.mac_finish = prestera_mac_finish,
> +	.mac_an_restart = prestera_mac_an_restart,

Obsolete method.

> +	.mac_link_down = prestera_mac_link_down,
> +	.mac_link_up = prestera_mac_link_up,
> +};

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 40Mbps down 10Mbps up. Decent connectivity at last!

      reply	other threads:[~2022-07-08 21:48 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-07-08 17:06 [PATCH net-next] net: marvell: prestera: add phylink support Oleksandr Mazur
2022-07-08 21:48 ` Russell King (Oracle) [this message]

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=YsimODfLM3mu/KZM@shell.armlinux.org.uk \
    --to=linux@armlinux.org.uk \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=netdev@vger.kernel.org \
    --cc=oleksandr.mazur@plvision.eu \
    --cc=pabeni@redhat.com \
    --cc=taras.chornyi@plvision.eu \
    --cc=yevhen.orlov@plvision.eu \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).