4. Add::
 
        struct phylink *phylink;
+       struct phylink_config phylink_config;
 
    to the driver's private data structure.  We shall refer to the
    driver's private data pointer as ``priv`` below, and the driver's
    .. code-block:: c
 
        struct phylink *phylink;
+       priv->phylink_config.dev = &dev.dev;
+       priv->phylink_config.type = PHYLINK_NETDEV;
 
-       phylink = phylink_create(dev, node, phy_mode, &phylink_ops);
+       phylink = phylink_create(&priv->phylink_config, node, phy_mode, &phylink_ops);
        if (IS_ERR(phylink)) {
                err = PTR_ERR(phylink);
                fail probe;
 
        struct device_node *dn;
        unsigned int tx_csum_limit;
        struct phylink *phylink;
+       struct phylink_config phylink_config;
        struct phy *comphy;
 
        struct mvneta_bm *bm_priv;
        return 0;
 }
 
-static void mvneta_validate(struct net_device *ndev, unsigned long *supported,
+static void mvneta_validate(struct phylink_config *config,
+                           unsigned long *supported,
                            struct phylink_link_state *state)
 {
+       struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
        __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 
        phylink_helper_basex_speed(state);
 }
 
-static int mvneta_mac_link_state(struct net_device *ndev,
+static int mvneta_mac_link_state(struct phylink_config *config,
                                 struct phylink_link_state *state)
 {
+       struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
        u32 gmac_stat;
 
        return 1;
 }
 
-static void mvneta_mac_an_restart(struct net_device *ndev)
+static void mvneta_mac_an_restart(struct phylink_config *config)
 {
+       struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
        u32 gmac_an = mvreg_read(pp, MVNETA_GMAC_AUTONEG_CONFIG);
 
                    gmac_an & ~MVNETA_GMAC_INBAND_RESTART_AN);
 }
 
-static void mvneta_mac_config(struct net_device *ndev, unsigned int mode,
-       const struct phylink_link_state *state)
+static void mvneta_mac_config(struct phylink_config *config, unsigned int mode,
+                             const struct phylink_link_state *state)
 {
+       struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
        u32 new_ctrl0, gmac_ctrl0 = mvreg_read(pp, MVNETA_GMAC_CTRL_0);
        u32 new_ctrl2, gmac_ctrl2 = mvreg_read(pp, MVNETA_GMAC_CTRL_2);
        mvreg_write(pp, MVNETA_LPI_CTRL_1, lpi_ctl1);
 }
 
-static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode,
-                                phy_interface_t interface)
+static void mvneta_mac_link_down(struct phylink_config *config,
+                                unsigned int mode, phy_interface_t interface)
 {
+       struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
        u32 val;
 
        mvneta_set_eee(pp, false);
 }
 
-static void mvneta_mac_link_up(struct net_device *ndev, unsigned int mode,
+static void mvneta_mac_link_up(struct phylink_config *config, unsigned int mode,
                               phy_interface_t interface,
                               struct phy_device *phy)
 {
+       struct net_device *ndev = to_net_dev(config->dev);
        struct mvneta_port *pp = netdev_priv(ndev);
        u32 val;
 
                comphy = NULL;
        }
 
-       phylink = phylink_create(dev, pdev->dev.fwnode, phy_mode,
-                                &mvneta_phylink_ops);
+       pp = netdev_priv(dev);
+       spin_lock_init(&pp->lock);
+
+       pp->phylink_config.dev = &dev->dev;
+       pp->phylink_config.type = PHYLINK_NETDEV;
+
+       phylink = phylink_create(&pp->phylink_config, pdev->dev.fwnode,
+                                phy_mode, &mvneta_phylink_ops);
        if (IS_ERR(phylink)) {
                err = PTR_ERR(phylink);
                goto err_free_irq;
 
        dev->ethtool_ops = &mvneta_eth_tool_ops;
 
-       pp = netdev_priv(dev);
-       spin_lock_init(&pp->lock);
        pp->phylink = phylink;
        pp->comphy = comphy;
        pp->phy_interface = phy_mode;
 
 
        phy_interface_t phy_interface;
        struct phylink *phylink;
+       struct phylink_config phylink_config;
        struct phy *comphy;
 
        struct mvpp2_bm_pool *pool_long;
 
 /* The prototype is added here to be used in start_dev when using ACPI. This
  * will be removed once phylink is used for all modes (dt+ACPI).
  */
-static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,
+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 net_device *dev, unsigned int mode,
+static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
                              phy_interface_t interface, struct phy_device *phy);
 
 /* Queue modes */
                struct phylink_link_state state = {
                        .interface = port->phy_interface,
                };
-               mvpp2_mac_config(port->dev, MLO_AN_INBAND, &state);
-               mvpp2_mac_link_up(port->dev, MLO_AN_INBAND, port->phy_interface,
-                                 NULL);
+               mvpp2_mac_config(&port->phylink_config, MLO_AN_INBAND, &state);
+               mvpp2_mac_link_up(&port->phylink_config, MLO_AN_INBAND,
+                                 port->phy_interface, NULL);
        }
 
        netif_tx_start_all_queues(port->dev);
        eth_hw_addr_random(dev);
 }
 
-static void mvpp2_phylink_validate(struct net_device *dev,
+static void mvpp2_phylink_validate(struct phylink_config *config,
                                   unsigned long *supported,
                                   struct phylink_link_state *state)
 {
-       struct mvpp2_port *port = netdev_priv(dev);
+       struct mvpp2_port *port = container_of(config, struct mvpp2_port,
+                                              phylink_config);
        __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
 
        /* Invalid combinations */
                state->pause |= MLO_PAUSE_TX;
 }
 
-static int mvpp2_phylink_mac_link_state(struct net_device *dev,
+static int mvpp2_phylink_mac_link_state(struct phylink_config *config,
                                        struct phylink_link_state *state)
 {
-       struct mvpp2_port *port = netdev_priv(dev);
+       struct mvpp2_port *port = container_of(config, struct mvpp2_port,
+                                              phylink_config);
 
        if (port->priv->hw_version == MVPP22 && port->gop_id == 0) {
                u32 mode = readl(port->base + MVPP22_XLG_CTRL3_REG);
        return 1;
 }
 
-static void mvpp2_mac_an_restart(struct net_device *dev)
+static void mvpp2_mac_an_restart(struct phylink_config *config)
 {
-       struct mvpp2_port *port = netdev_priv(dev);
+       struct mvpp2_port *port = container_of(config, struct mvpp2_port,
+                                              phylink_config);
        u32 val = readl(port->base + MVPP2_GMAC_AUTONEG_CONFIG);
 
        writel(val | MVPP2_GMAC_IN_BAND_RESTART_AN,
        }
 }
 
-static void mvpp2_mac_config(struct net_device *dev, unsigned int mode,
+static void mvpp2_mac_config(struct phylink_config *config, unsigned int mode,
                             const struct phylink_link_state *state)
 {
+       struct net_device *dev = to_net_dev(config->dev);
        struct mvpp2_port *port = netdev_priv(dev);
        bool change_interface = port->phy_interface != state->interface;
 
        mvpp2_port_enable(port);
 }
 
-static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode,
+static void mvpp2_mac_link_up(struct phylink_config *config, unsigned int mode,
                              phy_interface_t interface, struct phy_device *phy)
 {
+       struct net_device *dev = to_net_dev(config->dev);
        struct mvpp2_port *port = netdev_priv(dev);
        u32 val;
 
        netif_tx_wake_all_queues(dev);
 }
 
-static void mvpp2_mac_link_down(struct net_device *dev, unsigned int mode,
-                               phy_interface_t interface)
+static void mvpp2_mac_link_down(struct phylink_config *config,
+                               unsigned int mode, phy_interface_t interface)
 {
+       struct net_device *dev = to_net_dev(config->dev);
        struct mvpp2_port *port = netdev_priv(dev);
        u32 val;
 
 
        /* Phylink isn't used w/ ACPI as of now */
        if (port_node) {
-               phylink = phylink_create(dev, port_fwnode, phy_mode,
-                                        &mvpp2_phylink_ops);
+               port->phylink_config.dev = &dev->dev;
+               port->phylink_config.type = PHYLINK_NETDEV;
+
+               phylink = phylink_create(&port->phylink_config, port_fwnode,
+                                        phy_mode, &mvpp2_phylink_ops);
                if (IS_ERR(phylink)) {
                        err = PTR_ERR(phylink);
                        goto err_free_port_pcpu;
 
        /* private: */
        struct net_device *netdev;
        const struct phylink_mac_ops *ops;
+       struct phylink_config *config;
 
        unsigned long phylink_disable_state; /* bitmask of disables */
        struct phy_device *phydev;
 static int phylink_validate(struct phylink *pl, unsigned long *supported,
                            struct phylink_link_state *state)
 {
-       pl->ops->validate(pl->netdev, supported, state);
+       pl->ops->validate(pl->config, supported, state);
 
        return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
 }
                   __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising,
                   state->pause, state->link, state->an_enabled);
 
-       pl->ops->mac_config(pl->netdev, pl->link_an_mode, state);
+       pl->ops->mac_config(pl->config, pl->link_an_mode, state);
 }
 
 static void phylink_mac_config_up(struct phylink *pl,
 {
        if (pl->link_config.an_enabled &&
            phy_interface_mode_is_8023z(pl->link_config.interface))
-               pl->ops->mac_an_restart(pl->netdev);
+               pl->ops->mac_an_restart(pl->config);
 }
 
 static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state *state)
 {
-       struct net_device *ndev = pl->netdev;
 
        linkmode_copy(state->advertising, pl->link_config.advertising);
        linkmode_zero(state->lp_advertising);
        state->an_complete = 0;
        state->link = 1;
 
-       return pl->ops->mac_link_state(ndev, state);
+       return pl->ops->mac_link_state(pl->config, state);
 }
 
 /* The fixed state is... fixed except for the link state,
 {
        struct net_device *ndev = pl->netdev;
 
-       pl->ops->mac_link_up(ndev, pl->link_an_mode,
+       pl->ops->mac_link_up(pl->config, pl->link_an_mode,
                             pl->phy_state.interface,
                             pl->phydev);
 
        struct net_device *ndev = pl->netdev;
 
        netif_carrier_off(ndev);
-       pl->ops->mac_link_down(ndev, pl->link_an_mode,
+       pl->ops->mac_link_down(pl->config, pl->link_an_mode,
                               pl->phy_state.interface);
        netdev_info(ndev, "Link is Down\n");
 }
  * Returns a pointer to a &struct phylink, or an error-pointer value. Users
  * must use IS_ERR() to check for errors from this function.
  */
-struct phylink *phylink_create(struct net_device *ndev,
+struct phylink *phylink_create(struct phylink_config *config,
                               struct fwnode_handle *fwnode,
                               phy_interface_t iface,
                               const struct phylink_mac_ops *ops)
 
        mutex_init(&pl->state_mutex);
        INIT_WORK(&pl->resolve, phylink_resolve);
-       pl->netdev = ndev;
+
+       pl->config = config;
+       if (config->type == PHYLINK_NETDEV) {
+               pl->netdev = to_net_dev(config->dev);
+       } else {
+               kfree(pl);
+               return ERR_PTR(-EINVAL);
+       }
+
        pl->phy_state.interface = iface;
        pl->link_interface = iface;
        if (iface == PHY_INTERFACE_MODE_MOCA)
 
        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.
  * 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);
 };
 #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.
  *
  * 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
  * 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.
  *
  * 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
  *
  * 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
  * 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 *);
 
 #include <linux/net_tstamp.h>
 #include <linux/phy.h>
 #include <linux/platform_data/dsa.h>
+#include <linux/phylink.h>
 #include <net/devlink.h>
 #include <net/switchdev.h>
 
        struct net_device       *bridge_dev;
        struct devlink_port     devlink_port;
        struct phylink          *pl;
+       struct phylink_config   pl_config;
 
        struct work_struct      xmit_work;
        struct sk_buff_head     xmit_queue;
 
        .name   = "dsa",
 };
 
-static void dsa_slave_phylink_validate(struct net_device *dev,
+static void dsa_slave_phylink_validate(struct phylink_config *config,
                                       unsigned long *supported,
                                       struct phylink_link_state *state)
 {
-       struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
        struct dsa_switch *ds = dp->ds;
 
        if (!ds->ops->phylink_validate)
        ds->ops->phylink_validate(ds, dp->index, supported, state);
 }
 
-static int dsa_slave_phylink_mac_link_state(struct net_device *dev,
+static int dsa_slave_phylink_mac_link_state(struct phylink_config *config,
                                            struct phylink_link_state *state)
 {
-       struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
        struct dsa_switch *ds = dp->ds;
 
        /* Only called for SGMII and 802.3z */
        return ds->ops->phylink_mac_link_state(ds, dp->index, state);
 }
 
-static void dsa_slave_phylink_mac_config(struct net_device *dev,
+static void dsa_slave_phylink_mac_config(struct phylink_config *config,
                                         unsigned int mode,
                                         const struct phylink_link_state *state)
 {
-       struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
        struct dsa_switch *ds = dp->ds;
 
        if (!ds->ops->phylink_mac_config)
        ds->ops->phylink_mac_config(ds, dp->index, mode, state);
 }
 
-static void dsa_slave_phylink_mac_an_restart(struct net_device *dev)
+static void dsa_slave_phylink_mac_an_restart(struct phylink_config *config)
 {
-       struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
        struct dsa_switch *ds = dp->ds;
 
        if (!ds->ops->phylink_mac_an_restart)
        ds->ops->phylink_mac_an_restart(ds, dp->index);
 }
 
-static void dsa_slave_phylink_mac_link_down(struct net_device *dev,
+static void dsa_slave_phylink_mac_link_down(struct phylink_config *config,
                                            unsigned int mode,
                                            phy_interface_t interface)
 {
-       struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+       struct net_device *dev = dp->slave;
        struct dsa_switch *ds = dp->ds;
 
        if (!ds->ops->phylink_mac_link_down) {
        ds->ops->phylink_mac_link_down(ds, dp->index, mode, interface);
 }
 
-static void dsa_slave_phylink_mac_link_up(struct net_device *dev,
+static void dsa_slave_phylink_mac_link_up(struct phylink_config *config,
                                          unsigned int mode,
                                          phy_interface_t interface,
                                          struct phy_device *phydev)
 {
-       struct dsa_port *dp = dsa_slave_to_port(dev);
+       struct dsa_port *dp = container_of(config, struct dsa_port, pl_config);
+       struct net_device *dev = dp->slave;
        struct dsa_switch *ds = dp->ds;
 
        if (!ds->ops->phylink_mac_link_up) {
        if (mode < 0)
                mode = PHY_INTERFACE_MODE_NA;
 
-       dp->pl = phylink_create(slave_dev, of_fwnode_handle(port_dn), mode,
+       dp->pl_config.dev = &slave_dev->dev;
+       dp->pl_config.type = PHYLINK_NETDEV;
+
+       dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode,
                                &dsa_slave_phylink_mac_ops);
        if (IS_ERR(dp->pl)) {
                netdev_err(slave_dev,