From 44cc27e43fa3b8977373915a8e7f515a9d263343 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 28 May 2019 20:38:12 +0300 Subject: net: phylink: Add struct phylink_config to PHYLINK API The phylink_config structure will encapsulate a pointer to a struct device and the operation type requested for this instance of PHYLINK. This patch does not make any functional changes, it just transitions the PHYLINK internals and all its users to the new API. A pointer to a phylink_config structure will be passed to phylink_create() instead of the net_device directly. Also, the same phylink_config pointer will be passed back to all phylink_mac_ops callbacks instead of the net_device. Using this mechanism, a PHYLINK user can get the original net_device using a structure such as 'to_net_dev(config->dev)' or directly the structure containing the phylink_config using a container_of call. At the moment, only the PHYLINK_NETDEV is defined as a valid operation type for PHYLINK. In this mode, a valid reference to a struct device linked to the original net_device should be passed to PHYLINK through the phylink_config structure. This API changes is mainly driven by the necessity of adding a new operation type in PHYLINK that disconnects the phy_device from the net_device and also works when the net_device is lacking. Signed-off-by: Ioana Ciornei Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Reviewed-by: Maxime Chevallier Tested-by: Maxime Chevallier Signed-off-by: David S. Miller --- include/linux/phylink.h | 56 +++++++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 20 deletions(-) (limited to 'include/linux/phylink.h') diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 6411c624f63a..67f35f07ac4b 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -54,6 +54,20 @@ struct phylink_link_state { unsigned int an_complete:1; }; +enum phylink_op_type { + PHYLINK_NETDEV = 0, +}; + +/** + * struct phylink_config - PHYLINK configuration structure + * @dev: a pointer to a struct device associated with the MAC + * @type: operation type of PHYLINK instance + */ +struct phylink_config { + struct device *dev; + enum phylink_op_type type; +}; + /** * struct phylink_mac_ops - MAC operations structure. * @validate: Validate and update the link configuration. @@ -66,16 +80,17 @@ struct phylink_link_state { * The individual methods are described more fully below. */ struct phylink_mac_ops { - void (*validate)(struct net_device *ndev, unsigned long *supported, + void (*validate)(struct phylink_config *config, + unsigned long *supported, struct phylink_link_state *state); - int (*mac_link_state)(struct net_device *ndev, + int (*mac_link_state)(struct phylink_config *config, struct phylink_link_state *state); - void (*mac_config)(struct net_device *ndev, unsigned int mode, + void (*mac_config)(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state); - void (*mac_an_restart)(struct net_device *ndev); - void (*mac_link_down)(struct net_device *ndev, unsigned int mode, + void (*mac_an_restart)(struct phylink_config *config); + void (*mac_link_down)(struct phylink_config *config, unsigned int mode, phy_interface_t interface); - void (*mac_link_up)(struct net_device *ndev, unsigned int mode, + void (*mac_link_up)(struct phylink_config *config, unsigned int mode, phy_interface_t interface, struct phy_device *phy); }; @@ -83,7 +98,7 @@ struct phylink_mac_ops { #if 0 /* For kernel-doc purposes only. */ /** * validate - Validate and update the link configuration - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @supported: ethtool bitmask for supported link modes. * @state: a pointer to a &struct phylink_link_state. * @@ -100,12 +115,12 @@ struct phylink_mac_ops { * based on @state->advertising and/or @state->speed and update * @state->interface accordingly. */ -void validate(struct net_device *ndev, unsigned long *supported, +void validate(struct phylink_config *config, unsigned long *supported, struct phylink_link_state *state); /** * mac_link_state() - Read the current link state from the hardware - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @state: a pointer to a &struct phylink_link_state. * * Read the current link state from the MAC, reporting the current @@ -114,12 +129,12 @@ void validate(struct net_device *ndev, unsigned long *supported, * negotiation completion state in @state->an_complete, and link * up state in @state->link. */ -int mac_link_state(struct net_device *ndev, +int mac_link_state(struct phylink_config *config, struct phylink_link_state *state); /** * mac_config() - configure the MAC for the selected mode and state - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. * @state: a pointer to a &struct phylink_link_state. * @@ -157,18 +172,18 @@ int mac_link_state(struct net_device *ndev, * down. This "update" behaviour is critical to avoid bouncing the * link up status. */ -void mac_config(struct net_device *ndev, unsigned int mode, +void mac_config(struct phylink_config *config, unsigned int mode, const struct phylink_link_state *state); /** * mac_an_restart() - restart 802.3z BaseX autonegotiation - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. */ -void mac_an_restart(struct net_device *ndev); +void mac_an_restart(struct phylink_config *config); /** * mac_link_down() - take the link down - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: link autonegotiation mode * @interface: link &typedef phy_interface_t mode * @@ -177,12 +192,12 @@ void mac_an_restart(struct net_device *ndev); * Energy Efficient Ethernet MAC configuration. Interface type * selection must be done in mac_config(). */ -void mac_link_down(struct net_device *ndev, unsigned int mode, +void mac_link_down(struct phylink_config *config, unsigned int mode, phy_interface_t interface); /** * mac_link_up() - allow the link to come up - * @ndev: a pointer to a &struct net_device for the MAC. + * @config: a pointer to a &struct phylink_config. * @mode: link autonegotiation mode * @interface: link &typedef phy_interface_t mode * @phy: any attached phy @@ -193,13 +208,14 @@ void mac_link_down(struct net_device *ndev, unsigned int mode, * phy_init_eee() and perform appropriate MAC configuration for EEE. * Interface type selection must be done in mac_config(). */ -void mac_link_up(struct net_device *ndev, unsigned int mode, +void mac_link_up(struct phylink_config *config, unsigned int mode, phy_interface_t interface, struct phy_device *phy); #endif -struct phylink *phylink_create(struct net_device *, struct fwnode_handle *, - phy_interface_t iface, const struct phylink_mac_ops *ops); +struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *, + phy_interface_t iface, + const struct phylink_mac_ops *ops); void phylink_destroy(struct phylink *); int phylink_connect_phy(struct phylink *, struct phy_device *); -- cgit v1.3-14-g43fede From 43de61959b999279bafb031c0c9bdf0f6cd1c501 Mon Sep 17 00:00:00 2001 From: Ioana Ciornei Date: Tue, 28 May 2019 20:38:13 +0300 Subject: net: phylink: Add PHYLINK_DEV operation type In the PHYLINK_DEV operation type, the PHYLINK infrastructure can work without an attached net_device. For printing usecases, instead, a struct device * should be passed to PHYLINK using the phylink_config structure. Also, netif_carrier_* calls ar guarded by the presence of a valid net_device. When using the PHYLINK_DEV operation type, we cannot check link status using the netif_carrier_ok() API so instead, keep an internal state of the MAC and call mac_link_{down,up} only when the link changed. Signed-off-by: Ioana Ciornei Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/phylink.c | 25 ++++++++++++++++++++----- include/linux/phylink.h | 1 + 2 files changed, 21 insertions(+), 5 deletions(-) (limited to 'include/linux/phylink.h') diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 5a283bf9d402..5f6120f3fa3f 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -42,6 +42,8 @@ struct phylink { struct net_device *netdev; const struct phylink_mac_ops *ops; struct phylink_config *config; + struct device *dev; + unsigned int old_link_state:1; unsigned long phylink_disable_state; /* bitmask of disables */ struct phy_device *phydev; @@ -404,7 +406,8 @@ static void phylink_mac_link_up(struct phylink *pl, pl->phy_state.interface, pl->phydev); - netif_carrier_on(ndev); + if (ndev) + netif_carrier_on(ndev); netdev_info(ndev, "Link is Up - %s/%s - flow control %s\n", @@ -417,7 +420,8 @@ static void phylink_mac_link_down(struct phylink *pl) { struct net_device *ndev = pl->netdev; - netif_carrier_off(ndev); + if (ndev) + netif_carrier_off(ndev); pl->ops->mac_link_down(pl->config, pl->link_an_mode, pl->phy_state.interface); netdev_info(ndev, "Link is Down\n"); @@ -428,6 +432,7 @@ static void phylink_resolve(struct work_struct *w) struct phylink *pl = container_of(w, struct phylink, resolve); struct phylink_link_state link_state; struct net_device *ndev = pl->netdev; + int link_changed; mutex_lock(&pl->state_mutex); if (pl->phylink_disable_state) { @@ -470,7 +475,13 @@ static void phylink_resolve(struct work_struct *w) } } - if (link_state.link != netif_carrier_ok(ndev)) { + if (pl->netdev) + link_changed = (link_state.link != netif_carrier_ok(ndev)); + else + link_changed = (link_state.link != pl->old_link_state); + + if (link_changed) { + pl->old_link_state = link_state.link; if (!link_state.link) phylink_mac_link_down(pl); else @@ -571,6 +582,8 @@ struct phylink *phylink_create(struct phylink_config *config, pl->config = config; if (config->type == PHYLINK_NETDEV) { pl->netdev = to_net_dev(config->dev); + } else if (config->type == PHYLINK_DEV) { + pl->dev = config->dev; } else { kfree(pl); return ERR_PTR(-EINVAL); @@ -910,7 +923,8 @@ void phylink_start(struct phylink *pl) phy_modes(pl->link_config.interface)); /* Always set the carrier off */ - netif_carrier_off(pl->netdev); + if (pl->netdev) + netif_carrier_off(pl->netdev); /* Apply the link configuration to the MAC when starting. This allows * a fixed-link to start with the correct parameters, and also @@ -1255,7 +1269,8 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl, switch (pl->link_an_mode) { case MLO_AN_PHY: /* Silently mark the carrier down, and then trigger a resolve */ - netif_carrier_off(pl->netdev); + if (pl->netdev) + netif_carrier_off(pl->netdev); phylink_run_resolve(pl); break; diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 67f35f07ac4b..0f6f65bb9d44 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -56,6 +56,7 @@ struct phylink_link_state { enum phylink_op_type { PHYLINK_NETDEV = 0, + PHYLINK_DEV, }; /** -- cgit v1.3-14-g43fede From 4add700968c7761acba88e70a0aa3f44e5ad359d Mon Sep 17 00:00:00 2001 From: Russell King - ARM Linux admin Date: Fri, 14 Jun 2019 11:37:49 +0100 Subject: net: phylink: further mac_config documentation improvements While reviewing the DPAA2 work, it has become apparent that we need better documentation about which members of the phylink link state structure are valid in the mac_config call. Improve this documentation. Signed-off-by: Russell King Signed-off-by: David S. Miller --- include/linux/phylink.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'include/linux/phylink.h') diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 6411c624f63a..2d2e55dfea94 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -123,11 +123,20 @@ int mac_link_state(struct net_device *ndev, * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND. * @state: a pointer to a &struct phylink_link_state. * + * Note - not all members of @state are valid. In particular, + * @state->lp_advertising, @state->link, @state->an_complete are never + * guaranteed to be correct, and so any mac_config() implementation must + * never reference these fields. + * * The action performed depends on the currently selected mode: * * %MLO_AN_FIXED, %MLO_AN_PHY: * Configure the specified @state->speed, @state->duplex and - * @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) mode. + * @state->pause (%MLO_PAUSE_TX / %MLO_PAUSE_RX) modes over a link + * specified by @state->interface. @state->advertising may be used, + * but is not required. Other members of @state must be ignored. + * + * Valid state members: interface, speed, duplex, pause, advertising. * * %MLO_AN_INBAND: * place the link in an inband negotiation mode (such as 802.3z @@ -150,6 +159,8 @@ int mac_link_state(struct net_device *ndev, * responsible for reading the configuration word and configuring * itself accordingly. * + * Valid state members: interface, an_enabled, pause, advertising. + * * Implementations are expected to update the MAC to reflect the * requested settings - i.o.w., if nothing has changed between two * calls, no action is expected. If only flow control settings have -- cgit v1.3-14-g43fede From 32e454efbb2279b0fa5874abb0944a9d42080ad1 Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 25 Jun 2019 10:44:33 +0100 Subject: net: phylink: further documentation clarifications Clarify the validate() behaviour in a few cases which weren't mentioned in the documentation, but which are necessary for users to get the correct behaviour. Signed-off-by: Russell King Reviewed-by: Andrew Lunn Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- include/linux/phylink.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'include/linux/phylink.h') diff --git a/include/linux/phylink.h b/include/linux/phylink.h index 2d2e55dfea94..5b130140fb8f 100644 --- a/include/linux/phylink.h +++ b/include/linux/phylink.h @@ -93,12 +93,19 @@ struct phylink_mac_ops { * Note that the PHY may be able to transform from one connection * technology to another, so, eg, don't clear 1000BaseX just * because the MAC is unable to BaseX mode. This is more about - * clearing unsupported speeds and duplex settings. + * clearing unsupported speeds and duplex settings. The port modes + * should not be cleared; phylink_set_port_modes() will help with this. * * If the @state->interface mode is %PHY_INTERFACE_MODE_1000BASEX * or %PHY_INTERFACE_MODE_2500BASEX, select the appropriate mode * based on @state->advertising and/or @state->speed and update - * @state->interface accordingly. + * @state->interface accordingly. See phylink_helper_basex_speed(). + * + * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the + * MAC driver to return all supported link modes. + * + * If the @state->interface mode is not supported, then the @supported + * mask must be cleared. */ void validate(struct net_device *ndev, unsigned long *supported, struct phylink_link_state *state); -- cgit v1.3-14-g43fede