this documentation.
 
 1. Optionally split the network driver's phylib update function into
-   three parts dealing with link-down, link-up and reconfiguring the
-   MAC settings. This can be done as a separate preparation commit.
+   two parts dealing with link-down and link-up. This can be done as
+   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::
 
    using. This is particularly important for in-band negotiation
    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
    requested state, and must avoid unnecessarily taking the link down
    when making changes to the MAC configuration.  This means the
 
        netif_tx_stop_all_queues(ndev);
 }
 
-static void macb_mac_link_up(struct phylink_config *config, unsigned int mode,
-                            phy_interface_t interface, struct phy_device *phy)
+static void macb_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)
 {
        struct net_device *ndev = to_net_dev(config->dev);
        struct macb *bp = netdev_priv(ndev);
 
                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,
-                             phy_interface_t interface, struct phy_device *phy)
+static void dpaa2_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)
 {
        struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config);
        struct dpmac_link_state *dpmac_state = &mac->state;
 
        mvneta_set_eee(pp, false);
 }
 
-static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode,
-                              phy_interface_t interface,
-                              struct phy_device *phy)
+static void mvneta_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)
 {
        struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
 
  */
 static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
                             const struct phylink_link_state *state);
-static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
-                             phy_interface_t interface, struct phy_device *phy);
+static void mvpp2_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);
 
 /* Queue modes */
 #define MVPP2_QDIST_SINGLE_MODE        0
                        .interface = port->phy_interface,
                };
                mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
-               mvpp2_mac_link_up(&port->phylink_config, MLO_AN_INBAND,
-                                 port->phy_interface, NULL);
+               mvpp2_mac_link_up(&port->phylink_config, NULL,
+                                 MLO_AN_INBAND, port->phy_interface,
+                                 SPEED_UNKNOWN, DUPLEX_UNKNOWN, false, false);
        }
 
        netif_tx_start_all_queues(port->dev);
        mvpp2_port_enable(port);
 }
 
-static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
-                             phy_interface_t interface, struct phy_device *phy)
+static void mvpp2_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)
 {
        struct net_device *dev = to_net_dev(config->dev);
        struct mvpp2_port *port = netdev_priv(dev);
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 }
 
-static void mtk_mac_link_up(struct phylink_config *config, unsigned int mode,
-                           phy_interface_t interface,
-                           struct phy_device *phy)
+static void mtk_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)
 {
        struct mtk_mac *mac = container_of(config, struct mtk_mac,
                                           phylink_config);
 
 }
 
 static void stmmac_mac_link_up(struct phylink_config *config,
+                              struct phy_device *phy,
                               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));
 
 
 }
 
 static void axienet_mac_link_up(struct phylink_config *config,
-                               unsigned int mode,
-                               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)
 {
        /* nothing meaningful to do */
 }
 
        struct net_device *ndev = pl->netdev;
 
        pl->cur_interface = link_state.interface;
-       pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode,
-                            pl->cur_interface, pl->phydev);
+       pl->ops->mac_link_up(pl->config, 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)
                netif_carrier_on(ndev);
                                link_state.pause = pl->phy_state.pause;
                                phylink_apply_manual_flow(pl, &link_state);
                                phylink_mac_config(pl, &link_state);
+                       } else {
+                               phylink_apply_manual_flow(pl, &link_state);
                        }
                        break;
                }
 
        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 phylink_config *config, unsigned int mode,
-                           phy_interface_t interface,
-                           struct phy_device *phy);
+       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);
 };
 
 #if 0 /* For kernel-doc purposes only. */
  * guaranteed to be correct, and so any mac_config() implementation must
  * 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
  * 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
  * The action performed depends on the currently selected mode:
  *
  * %MLO_AN_FIXED, %MLO_AN_PHY:
- *   Configure the specified @state->speed and @state->duplex over a link
- *   specified by @state->interface. @state->advertising may be used, but
- *   is not required. Pause modes as above. Other members of @state must
- *   be ignored.
+ *   Configure for non-inband negotiation mode, where the link settings
+ *   are completely communicated via mac_link_up().  The physical link
+ *   protocol from the MAC is specified by @state->interface.
+ *
+ *   @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().
  *
- *   Valid state members: interface, speed, duplex, pause, advertising.
+ *   Other members of @state must be ignored.
+ *
+ *   Valid state members: interface, advertising.
+ *   Deprecated state members: speed, duplex, pause.
  *
  * %MLO_AN_INBAND:
  *   place the link in an inband negotiation mode (such as 802.3z
 /**
  * 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
- * @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
- * phylink_autoneg_inband()), allow the link to come up. If @phy
- * is non-%NULL, configure Energy Efficient Ethernet by calling
+ * 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, unsigned int mode,
-                phy_interface_t interface,
-                struct phy_device *phy);
+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);
 #endif
 
 struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
 
 }
 
 static void dsa_port_phylink_mac_link_up(struct phylink_config *config,
+                                        struct phy_device *phydev,
                                         unsigned int mode,
                                         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_switch *ds = dp->ds;