123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173 |
- From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001
- From: "Russell King (Oracle)" <[email protected]>
- Date: Thu, 13 Jul 2023 09:42:07 +0100
- Subject: [PATCH] net: phylink: add pcs_enable()/pcs_disable() methods
- Add phylink PCS enable/disable callbacks that will allow us to place
- IEEE 802.3 register compliant PCS in power-down mode while not being
- used.
- Signed-off-by: Russell King (Oracle) <[email protected]>
- Signed-off-by: David S. Miller <[email protected]>
- ---
- drivers/net/phy/phylink.c | 48 +++++++++++++++++++++++++++++++--------
- include/linux/phylink.h | 16 +++++++++++++
- 2 files changed, 55 insertions(+), 9 deletions(-)
- --- a/drivers/net/phy/phylink.c
- +++ b/drivers/net/phy/phylink.c
- @@ -34,6 +34,10 @@ enum {
- PHYLINK_DISABLE_STOPPED,
- PHYLINK_DISABLE_LINK,
- PHYLINK_DISABLE_MAC_WOL,
- +
- + PCS_STATE_DOWN = 0,
- + PCS_STATE_STARTING,
- + PCS_STATE_STARTED,
- };
-
- /**
- @@ -72,6 +76,7 @@ struct phylink {
- struct phylink_link_state phy_state;
- struct work_struct resolve;
- unsigned int pcs_neg_mode;
- + unsigned int pcs_state;
-
- bool mac_link_dropped;
- bool using_mac_select_pcs;
- @@ -992,6 +997,22 @@ static void phylink_resolve_an_pause(str
- }
- }
-
- +static void phylink_pcs_disable(struct phylink_pcs *pcs)
- +{
- + if (pcs && pcs->ops->pcs_disable)
- + pcs->ops->pcs_disable(pcs);
- +}
- +
- +static int phylink_pcs_enable(struct phylink_pcs *pcs)
- +{
- + int err = 0;
- +
- + if (pcs && pcs->ops->pcs_enable)
- + err = pcs->ops->pcs_enable(pcs);
- +
- + return err;
- +}
- +
- static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
- const struct phylink_link_state *state,
- bool permit_pause_to_mac)
- @@ -1094,11 +1115,17 @@ static void phylink_major_config(struct
- /* If we have a new PCS, switch to the new PCS after preparing the MAC
- * for the change.
- */
- - if (pcs_changed)
- + if (pcs_changed) {
- + phylink_pcs_disable(pl->pcs);
- +
- pl->pcs = pcs;
- + }
-
- phylink_mac_config(pl, state);
-
- + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
- + phylink_pcs_enable(pl->pcs);
- +
- neg_mode = pl->cur_link_an_mode;
- if (pl->pcs && pl->pcs->neg_mode)
- neg_mode = pl->pcs_neg_mode;
- @@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct ph
- pl->link_config.pause = MLO_PAUSE_AN;
- pl->link_config.speed = SPEED_UNKNOWN;
- pl->link_config.duplex = DUPLEX_UNKNOWN;
- + pl->pcs_state = PCS_STATE_DOWN;
- pl->mac_ops = mac_ops;
- __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
- timer_setup(&pl->link_poll, phylink_fixed_poll, 0);
- @@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl)
- if (pl->netdev)
- netif_carrier_off(pl->netdev);
-
- + pl->pcs_state = PCS_STATE_STARTING;
- +
- /* Apply the link configuration to the MAC when starting. This allows
- * a fixed-link to start with the correct parameters, and also
- * ensures that we set the appropriate advertisement for Serdes links.
- @@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl)
- */
- phylink_mac_initial_config(pl, true);
-
- + pl->pcs_state = PCS_STATE_STARTED;
- +
- phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED);
-
- if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
- @@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl)
- poll = true;
- }
-
- - switch (pl->cfg_link_an_mode) {
- - case MLO_AN_FIXED:
- + if (pl->cfg_link_an_mode == MLO_AN_FIXED)
- poll |= pl->config->poll_fixed_state;
- - break;
- - case MLO_AN_INBAND:
- - if (pl->pcs)
- - poll |= pl->pcs->poll;
- - break;
- - }
- +
- if (poll)
- mod_timer(&pl->link_poll, jiffies + HZ);
- if (pl->phydev)
- @@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl)
- }
-
- phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
- +
- + pl->pcs_state = PCS_STATE_DOWN;
- +
- + phylink_pcs_disable(pl->pcs);
- }
- EXPORT_SYMBOL_GPL(phylink_stop);
-
- --- a/include/linux/phylink.h
- +++ b/include/linux/phylink.h
- @@ -533,6 +533,8 @@ struct phylink_pcs {
- /**
- * struct phylink_pcs_ops - MAC PCS operations structure.
- * @pcs_validate: validate the link configuration.
- + * @pcs_enable: enable the PCS.
- + * @pcs_disable: disable the PCS.
- * @pcs_get_state: read the current MAC PCS link state from the hardware.
- * @pcs_config: configure the MAC PCS for the selected mode and state.
- * @pcs_an_restart: restart 802.3z BaseX autonegotiation.
- @@ -542,6 +544,8 @@ struct phylink_pcs {
- struct phylink_pcs_ops {
- int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
- const struct phylink_link_state *state);
- + int (*pcs_enable)(struct phylink_pcs *pcs);
- + void (*pcs_disable)(struct phylink_pcs *pcs);
- void (*pcs_get_state)(struct phylink_pcs *pcs,
- struct phylink_link_state *state);
- int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode,
- @@ -572,6 +576,18 @@ int pcs_validate(struct phylink_pcs *pcs
- const struct phylink_link_state *state);
-
- /**
- + * pcs_enable() - enable the PCS.
- + * @pcs: a pointer to a &struct phylink_pcs.
- + */
- +int pcs_enable(struct phylink_pcs *pcs);
- +
- +/**
- + * pcs_disable() - disable the PCS.
- + * @pcs: a pointer to a &struct phylink_pcs.
- + */
- +void pcs_disable(struct phylink_pcs *pcs);
- +
- +/**
- * 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.
|