net: phylink: propagate resolved link config via mac_link_up()
Propagate the resolved link parameters via the mac_link_up() call for MACs that do not automatically track their PCS state. We propagate the link parameters via function arguments so that inappropriate members of struct phylink_link_state can't be accessed, and creating a new structure just for this adds needless complexity to the API. Tested-by: Andre Przywara <andre.przywara@arm.com> Tested-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Tested-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
2e6af0f304
commit
91a208f218
@ -74,10 +74,13 @@ phylib to the sfp/phylink support. Please send patches to improve
|
|||||||
this documentation.
|
this documentation.
|
||||||
|
|
||||||
1. Optionally split the network driver's phylib update function into
|
1. Optionally split the network driver's phylib update function into
|
||||||
three parts dealing with link-down, link-up and reconfiguring the
|
two parts dealing with link-down and link-up. This can be done as
|
||||||
MAC settings. This can be done as a separate preparation commit.
|
a separate preparation commit.
|
||||||
|
|
||||||
An example of this preparation can be found in git commit fc548b991fb0.
|
An older example of this preparation can be found in git commit
|
||||||
|
fc548b991fb0, although this was splitting into three parts; the
|
||||||
|
link-up part now includes configuring the MAC for the link settings.
|
||||||
|
Please see :c:func:`mac_link_up` for more information on this.
|
||||||
|
|
||||||
2. Replace::
|
2. Replace::
|
||||||
|
|
||||||
@ -207,6 +210,14 @@ this documentation.
|
|||||||
using. This is particularly important for in-band negotiation
|
using. This is particularly important for in-band negotiation
|
||||||
methods such as 1000base-X and SGMII.
|
methods such as 1000base-X and SGMII.
|
||||||
|
|
||||||
|
The :c:func:`mac_link_up` method is used to inform the MAC that the
|
||||||
|
link has come up. The call includes the negotiation mode and interface
|
||||||
|
for reference only. The finalised link parameters are also supplied
|
||||||
|
(speed, duplex and flow control/pause enablement settings) which
|
||||||
|
should be used to configure the MAC when the MAC and PCS are not
|
||||||
|
tightly integrated, or when the settings are not coming from in-band
|
||||||
|
negotiation.
|
||||||
|
|
||||||
The :c:func:`mac_config` method is used to update the MAC with the
|
The :c:func:`mac_config` method is used to update the MAC with the
|
||||||
requested state, and must avoid unnecessarily taking the link down
|
requested state, and must avoid unnecessarily taking the link down
|
||||||
when making changes to the MAC configuration. This means the
|
when making changes to the MAC configuration. This means the
|
||||||
|
@ -626,8 +626,11 @@ static void macb_mac_link_down(struct phylink_config *config, unsigned int mode,
|
|||||||
netif_tx_stop_all_queues(ndev);
|
netif_tx_stop_all_queues(ndev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void macb_mac_link_up(struct phylink_config *config, unsigned int mode,
|
static void macb_mac_link_up(struct phylink_config *config,
|
||||||
phy_interface_t interface, struct phy_device *phy)
|
struct phy_device *phy,
|
||||||
|
unsigned int mode, phy_interface_t interface,
|
||||||
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct net_device *ndev = to_net_dev(config->dev);
|
struct net_device *ndev = to_net_dev(config->dev);
|
||||||
struct macb *bp = netdev_priv(ndev);
|
struct macb *bp = netdev_priv(ndev);
|
||||||
|
@ -154,8 +154,11 @@ static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode,
|
|||||||
netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err);
|
netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dpaa2_mac_link_up(struct phylink_config *config, unsigned int mode,
|
static void dpaa2_mac_link_up(struct phylink_config *config,
|
||||||
phy_interface_t interface, struct phy_device *phy)
|
struct phy_device *phy,
|
||||||
|
unsigned int mode, phy_interface_t interface,
|
||||||
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
|
struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
|
||||||
struct dpmac_link_state *dpmac_state = &mac->state;
|
struct dpmac_link_state *dpmac_state = &mac->state;
|
||||||
|
@ -3965,9 +3965,11 @@ static void mvneta_mac_link_down(struct phylink_config *config,
|
|||||||
mvneta_set_eee(pp, false);
|
mvneta_set_eee(pp, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode,
|
static void mvneta_mac_link_up(struct phylink_config *config,
|
||||||
phy_interface_t interface,
|
struct phy_device *phy,
|
||||||
struct phy_device *phy)
|
unsigned int mode, phy_interface_t interface,
|
||||||
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct net_device *ndev = to_net_dev(config->dev);
|
struct net_device *ndev = to_net_dev(config->dev);
|
||||||
struct mvneta_port *pp = netdev_priv(ndev);
|
struct mvneta_port *pp = netdev_priv(ndev);
|
||||||
|
@ -58,8 +58,11 @@ static struct {
|
|||||||
*/
|
*/
|
||||||
static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
|
static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
|
||||||
const struct phylink_link_state *state);
|
const struct phylink_link_state *state);
|
||||||
static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
|
static void mvpp2_mac_link_up(struct phylink_config *config,
|
||||||
phy_interface_t interface, struct phy_device *phy);
|
struct phy_device *phy,
|
||||||
|
unsigned int mode, phy_interface_t interface,
|
||||||
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause);
|
||||||
|
|
||||||
/* Queue modes */
|
/* Queue modes */
|
||||||
#define MVPP2_QDIST_SINGLE_MODE 0
|
#define MVPP2_QDIST_SINGLE_MODE 0
|
||||||
@ -3473,8 +3476,9 @@ static void mvpp2_start_dev(struct mvpp2_port *port)
|
|||||||
.interface = port->phy_interface,
|
.interface = port->phy_interface,
|
||||||
};
|
};
|
||||||
mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
|
mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
|
||||||
mvpp2_mac_link_up(&port->phylink_config, MLO_AN_INBAND,
|
mvpp2_mac_link_up(&port->phylink_config, NULL,
|
||||||
port->phy_interface, NULL);
|
MLO_AN_INBAND, port->phy_interface,
|
||||||
|
SPEED_UNKNOWN, DUPLEX_UNKNOWN, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
netif_tx_start_all_queues(port->dev);
|
netif_tx_start_all_queues(port->dev);
|
||||||
@ -5141,8 +5145,11 @@ static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
|
|||||||
mvpp2_port_enable(port);
|
mvpp2_port_enable(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
|
static void mvpp2_mac_link_up(struct phylink_config *config,
|
||||||
phy_interface_t interface, struct phy_device *phy)
|
struct phy_device *phy,
|
||||||
|
unsigned int mode, phy_interface_t interface,
|
||||||
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct net_device *dev = to_net_dev(config->dev);
|
struct net_device *dev = to_net_dev(config->dev);
|
||||||
struct mvpp2_port *port = netdev_priv(dev);
|
struct mvpp2_port *port = netdev_priv(dev);
|
||||||
|
@ -412,9 +412,10 @@ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
|
|||||||
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode,
|
static void mtk_mac_link_up(struct phylink_config *config,
|
||||||
phy_interface_t interface,
|
struct phy_device *phy,
|
||||||
struct phy_device *phy)
|
unsigned int mode, phy_interface_t interface,
|
||||||
|
int speed, int duplex, bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct mtk_mac *mac = container_of(config, struct mtk_mac,
|
struct mtk_mac *mac = container_of(config, struct mtk_mac,
|
||||||
phylink_config);
|
phylink_config);
|
||||||
|
@ -950,8 +950,10 @@ static void stmmac_mac_link_down(struct phylink_config *config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void stmmac_mac_link_up(struct phylink_config *config,
|
static void stmmac_mac_link_up(struct phylink_config *config,
|
||||||
|
struct phy_device *phy,
|
||||||
unsigned int mode, phy_interface_t interface,
|
unsigned int mode, phy_interface_t interface,
|
||||||
struct phy_device *phy)
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||||
|
|
||||||
|
@ -1486,9 +1486,10 @@ static void axienet_mac_link_down(struct phylink_config *config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void axienet_mac_link_up(struct phylink_config *config,
|
static void axienet_mac_link_up(struct phylink_config *config,
|
||||||
unsigned int mode,
|
struct phy_device *phy,
|
||||||
phy_interface_t interface,
|
unsigned int mode, phy_interface_t interface,
|
||||||
struct phy_device *phy)
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
/* nothing meaningful to do */
|
/* nothing meaningful to do */
|
||||||
}
|
}
|
||||||
|
@ -480,8 +480,11 @@ static void phylink_mac_link_up(struct phylink *pl,
|
|||||||
struct net_device *ndev = pl->netdev;
|
struct net_device *ndev = pl->netdev;
|
||||||
|
|
||||||
pl->cur_interface = link_state.interface;
|
pl->cur_interface = link_state.interface;
|
||||||
pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode,
|
pl->ops->mac_link_up(pl->config, pl->phydev,
|
||||||
pl->cur_interface, pl->phydev);
|
pl->cur_link_an_mode, pl->cur_interface,
|
||||||
|
link_state.speed, link_state.duplex,
|
||||||
|
!!(link_state.pause & MLO_PAUSE_TX),
|
||||||
|
!!(link_state.pause & MLO_PAUSE_RX));
|
||||||
|
|
||||||
if (ndev)
|
if (ndev)
|
||||||
netif_carrier_on(ndev);
|
netif_carrier_on(ndev);
|
||||||
@ -547,6 +550,8 @@ static void phylink_resolve(struct work_struct *w)
|
|||||||
link_state.pause = pl->phy_state.pause;
|
link_state.pause = pl->phy_state.pause;
|
||||||
phylink_apply_manual_flow(pl, &link_state);
|
phylink_apply_manual_flow(pl, &link_state);
|
||||||
phylink_mac_config(pl, &link_state);
|
phylink_mac_config(pl, &link_state);
|
||||||
|
} else {
|
||||||
|
phylink_apply_manual_flow(pl, &link_state);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -91,9 +91,10 @@ struct phylink_mac_ops {
|
|||||||
void (*mac_an_restart)(struct phylink_config *config);
|
void (*mac_an_restart)(struct phylink_config *config);
|
||||||
void (*mac_link_down)(struct phylink_config *config, unsigned int mode,
|
void (*mac_link_down)(struct phylink_config *config, unsigned int mode,
|
||||||
phy_interface_t interface);
|
phy_interface_t interface);
|
||||||
void (*mac_link_up)(struct phylink_config *config, unsigned int mode,
|
void (*mac_link_up)(struct phylink_config *config,
|
||||||
phy_interface_t interface,
|
struct phy_device *phy, unsigned int mode,
|
||||||
struct phy_device *phy);
|
phy_interface_t interface, int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause);
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0 /* For kernel-doc purposes only. */
|
#if 0 /* For kernel-doc purposes only. */
|
||||||
@ -152,6 +153,9 @@ void mac_pcs_get_state(struct phylink_config *config,
|
|||||||
* guaranteed to be correct, and so any mac_config() implementation must
|
* guaranteed to be correct, and so any mac_config() implementation must
|
||||||
* never reference these fields.
|
* never reference these fields.
|
||||||
*
|
*
|
||||||
|
* (this requires a rewrite - please refer to mac_link_up() for situations
|
||||||
|
* where the PCS and MAC are not tightly integrated.)
|
||||||
|
*
|
||||||
* In all negotiation modes, as defined by @mode, @state->pause indicates the
|
* In all negotiation modes, as defined by @mode, @state->pause indicates the
|
||||||
* pause settings which should be applied as follows. If %MLO_PAUSE_AN is not
|
* pause settings which should be applied as follows. If %MLO_PAUSE_AN is not
|
||||||
* set, %MLO_PAUSE_TX and %MLO_PAUSE_RX indicate whether the MAC should send
|
* set, %MLO_PAUSE_TX and %MLO_PAUSE_RX indicate whether the MAC should send
|
||||||
@ -162,12 +166,20 @@ void mac_pcs_get_state(struct phylink_config *config,
|
|||||||
* The action performed depends on the currently selected mode:
|
* The action performed depends on the currently selected mode:
|
||||||
*
|
*
|
||||||
* %MLO_AN_FIXED, %MLO_AN_PHY:
|
* %MLO_AN_FIXED, %MLO_AN_PHY:
|
||||||
* Configure the specified @state->speed and @state->duplex over a link
|
* Configure for non-inband negotiation mode, where the link settings
|
||||||
* specified by @state->interface. @state->advertising may be used, but
|
* are completely communicated via mac_link_up(). The physical link
|
||||||
* is not required. Pause modes as above. Other members of @state must
|
* protocol from the MAC is specified by @state->interface.
|
||||||
* be ignored.
|
|
||||||
*
|
*
|
||||||
* Valid state members: interface, speed, duplex, pause, advertising.
|
* @state->advertising may be used, but is not required.
|
||||||
|
*
|
||||||
|
* Older drivers (prior to the mac_link_up() change) may use @state->speed,
|
||||||
|
* @state->duplex and @state->pause to configure the MAC, but this is
|
||||||
|
* deprecated; such drivers should be converted to use mac_link_up().
|
||||||
|
*
|
||||||
|
* Other members of @state must be ignored.
|
||||||
|
*
|
||||||
|
* Valid state members: interface, advertising.
|
||||||
|
* Deprecated state members: speed, duplex, pause.
|
||||||
*
|
*
|
||||||
* %MLO_AN_INBAND:
|
* %MLO_AN_INBAND:
|
||||||
* place the link in an inband negotiation mode (such as 802.3z
|
* place the link in an inband negotiation mode (such as 802.3z
|
||||||
@ -228,19 +240,34 @@ void mac_link_down(struct phylink_config *config, unsigned int mode,
|
|||||||
/**
|
/**
|
||||||
* mac_link_up() - allow the link to come up
|
* mac_link_up() - allow the link to come up
|
||||||
* @config: a pointer to a &struct phylink_config.
|
* @config: a pointer to a &struct phylink_config.
|
||||||
|
* @phy: any attached phy
|
||||||
* @mode: link autonegotiation mode
|
* @mode: link autonegotiation mode
|
||||||
* @interface: link &typedef phy_interface_t mode
|
* @interface: link &typedef phy_interface_t mode
|
||||||
* @phy: any attached phy
|
* @speed: link speed
|
||||||
|
* @duplex: link duplex
|
||||||
|
* @tx_pause: link transmit pause enablement status
|
||||||
|
* @rx_pause: link receive pause enablement status
|
||||||
*
|
*
|
||||||
* If @mode is not an in-band negotiation mode (as defined by
|
* Configure the MAC for an established link.
|
||||||
* phylink_autoneg_inband()), allow the link to come up. If @phy
|
*
|
||||||
* is non-%NULL, configure Energy Efficient Ethernet by calling
|
* @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.
|
* phy_init_eee() and perform appropriate MAC configuration for EEE.
|
||||||
* Interface type selection must be done in mac_config().
|
* Interface type selection must be done in mac_config().
|
||||||
*/
|
*/
|
||||||
void mac_link_up(struct phylink_config *config, unsigned int mode,
|
void mac_link_up(struct phylink_config *config, struct phy_device *phy,
|
||||||
phy_interface_t interface,
|
unsigned int mode, phy_interface_t interface,
|
||||||
struct phy_device *phy);
|
int speed, int duplex, bool tx_pause, bool rx_pause);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
|
struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
|
||||||
|
@ -489,9 +489,11 @@ static void dsa_port_phylink_mac_link_down(struct phylink_config *config,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void dsa_port_phylink_mac_link_up(struct phylink_config *config,
|
static void dsa_port_phylink_mac_link_up(struct phylink_config *config,
|
||||||
|
struct phy_device *phydev,
|
||||||
unsigned int mode,
|
unsigned int mode,
|
||||||
phy_interface_t interface,
|
phy_interface_t interface,
|
||||||
struct phy_device *phydev)
|
int speed, int duplex,
|
||||||
|
bool tx_pause, bool rx_pause)
|
||||||
{
|
{
|
||||||
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
|
||||||
struct dsa_switch *ds = dp->ds;
|
struct dsa_switch *ds = dp->ds;
|
||||||
|
Loading…
Reference in New Issue
Block a user