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: <2f59be00-5585-487a-9b1a-f5abdf4665c1@lunn.ch>
Date: Tue, 25 Jun 2024 19:05:18 +0200
From: Andrew Lunn <andrew@...n.ch>
To: Alexander Duyck <alexander.duyck@...il.com>
Cc: netdev@...r.kernel.org, Alexander Duyck <alexanderduyck@...com>,
	kuba@...nel.org, davem@...emloft.net, pabeni@...hat.com
Subject: Re: [net-next PATCH v2 11/15] eth: fbnic: Add link detection

On Tue, Jun 25, 2024 at 09:29:01AM -0700, Alexander Duyck wrote:
> On Tue, Jun 25, 2024 at 8:25 AM Andrew Lunn <andrew@...n.ch> wrote:
> >
> > > +     /* Tri-state value indicating state of link.
> > > +      *  0 - Up
> > > +      *  1 - Down
> > > +      *  2 - Event - Requires checking as link state may have changed
> > > +      */
> > > +     s8 link_state;
> >
> > Maybe add an enum?
> 
> Doesn't that default to a 32b size? The general thought was to just
> keep this small since it only needs to be a few bits.

I think you can do

enum __packed link_state_states {
	LINK_UP,
	LINK_DOWN,
	LINK_SIDEWAYS,
};

and it then should be a single byte. There appears to be one instance
of this already in the kernel:

drivers/accel/qaic/qaic.h:enum __packed dev_states {

> > > +static u32 __fbnic_mac_config_asic(struct fbnic_dev *fbd)
> > > +{
> > > +     /* Enable MAC Promiscuous mode and Tx padding */
> > > +     u32 command_config = FBNIC_MAC_COMMAND_CONFIG_TX_PAD_EN |
> > > +                          FBNIC_MAC_COMMAND_CONFIG_PROMISC_EN;
> > > +     struct fbnic_net *fbn = netdev_priv(fbd->netdev);
> > > +     u32 rxb_pause_ctrl;
> > > +
> > > +     /* Set class 0 Quanta and refresh */
> > > +     wr32(fbd, FBNIC_MAC_CL01_PAUSE_QUANTA, 0xffff);
> > > +     wr32(fbd, FBNIC_MAC_CL01_QUANTA_THRESH, 0x7fff);
> > > +
> > > +     /* Enable generation of pause frames if enabled */
> > > +     rxb_pause_ctrl = rd32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL);
> > > +     rxb_pause_ctrl &= ~FBNIC_RXB_PAUSE_DROP_CTRL_PAUSE_ENABLE;
> > > +     if (!fbn->tx_pause)
> > > +             command_config |= FBNIC_MAC_COMMAND_CONFIG_TX_PAUSE_DIS;
> > > +     else
> > > +             rxb_pause_ctrl |=
> > > +                     FIELD_PREP(FBNIC_RXB_PAUSE_DROP_CTRL_PAUSE_ENABLE,
> > > +                                FBNIC_PAUSE_EN_MASK);
> > > +     wr32(fbd, FBNIC_RXB_PAUSE_DROP_CTRL, rxb_pause_ctrl);
> > > +
> > > +     if (!fbn->rx_pause)
> > > +             command_config |= FBNIC_MAC_COMMAND_CONFIG_RX_PAUSE_DIS;
> >
> > Everybody gets pause wrong. To try to combat that it has mostly been
> > moved into phylink. When phylink calls your mac_config() callback it
> > passes const struct phylink_link_state *state. Within state is the
> > pause member. That tells you how to configure the hardware. phylink
> > will then deal with the differences between forced pause configuration
> > and negotiated pause configuration, etc. Your current mac_config() is
> > empty...
> >
> >         Andrew
> 
> So the pause setup for now is stored in fbn->[tr]x_pause. So if we
> were to configure it via the mac_config call and then likely call into
> this function. We end up having to reuse it in a few spots to avoid
> having to read/modify the MAC register and instead just set the data
> based on our stored config. Although I think we might be able to pare
> this down as the command_config is the only piece we really need to
> carry. The rest of this setup is essentially just a pause config which
> could be done once instead of on every link up/down transition. I will
> look at splitting this up.

Humm, actually, i got that wrong, sorry.

/**
 * mac_link_up() - allow the link to come up
 * @config: a pointer to a &struct phylink_config.
 * @phy: any attached phy
 * @mode: link autonegotiation mode
 * @interface: link &typedef phy_interface_t mode
 * @speed: link speed
 * @duplex: link duplex
 * @tx_pause: link transmit pause enablement status
 * @rx_pause: link receive pause enablement status
 *
 * Configure the MAC for an established link.
 *
 * @speed, @duplex, @tx_pause and @rx_pause indicate the finalised link
 * settings, and should be used to configure the MAC block appropriately
 * where these settings are not automatically conveyed from the PCS block,
 * or if in-band negotiation (as defined by phylink_autoneg_inband(@mode))
 * is disabled.
 *
 * Note that when 802.3z in-band negotiation is in use, it is possible
 * that the user wishes to override the pause settings, and this should
 * be allowed when considering the implementation of this method.
 *
 * If in-band negotiation mode is disabled, allow the link to come up. If
 * @phy is non-%NULL, configure Energy Efficient Ethernet by calling
 * phy_init_eee() and perform appropriate MAC configuration for EEE.
 * Interface type selection must be done in mac_config().
 */
void 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);

In your case, your pcs_config() should pass the pause settings which
is should advertise:

/**
 * pcs_config() - Configure the PCS mode and advertisement
 * @pcs: a pointer to a &struct phylink_pcs.
 * @neg_mode: link negotiation mode (see below)
 * @interface: interface mode to be used
 * @advertising: adertisement ethtool link mode mask
 * @permit_pause_to_mac: permit forwarding pause resolution to MAC
 *
 * Configure the PCS for the operating mode, the interface mode, and set
 * the advertisement mask. @permit_pause_to_mac indicates whether the
 * hardware may forward the pause mode resolution to the MAC.
 *
 * When operating in %MLO_AN_INBAND, inband should always be enabled,
 * otherwise inband should be disabled.
 *
 * For SGMII, there is no advertisement from the MAC side, the PCS should
 * be programmed to acknowledge the inband word from the PHY.
 *
 * For 1000BASE-X, the advertisement should be programmed into the PCS.
 *
 * For most 10GBASE-R, there is no advertisement.
 *
 * The %neg_mode argument should be tested via the phylink_mode_*() family of
 * functions, or for PCS that set pcs->neg_mode true, should be tested
 * against the PHYLINK_PCS_NEG_* definitions.
 */
int pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
	       phy_interface_t interface, const unsigned long *advertising,
	       bool permit_pause_to_mac);

and when the PCS has negotiated the link, you get the result with:

/**
 * pcs_get_state() - Read the current inband link state from the hardware
 * @pcs: a pointer to a &struct phylink_pcs.
 * @state: a pointer to a &struct phylink_link_state.
 *
 * Read the current inband link state from the MAC PCS, reporting the
 * current speed in @state->speed, duplex mode in @state->duplex, pause
 * mode in @state->pause using the %MLO_PAUSE_RX and %MLO_PAUSE_TX bits,
 * negotiation completion state in @state->an_complete, and link up state
 * in @state->link. If possible, @state->lp_advertising should also be
 * populated.
 */
void pcs_get_state(struct phylink_pcs *pcs,
		   struct phylink_link_state *state);

If however pause autoneg is off, and pause is being forced, the values
from pcs_get_state() are ignored, and mac_link_up() will give you the
forced values.

Once you have a fuller phylink implementation, you should Cc: Russell
King.

       Andrew

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ