diff options
Diffstat (limited to 'drivers/net')
| -rw-r--r-- | drivers/net/dsa/sja1105/sja1105_main.c | 11 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/mvneta.c | 36 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/mvpp2/mvpp2.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 43 | ||||
| -rw-r--r-- | drivers/net/phy/phy_device.c | 100 | ||||
| -rw-r--r-- | drivers/net/phy/phylink.c | 220 |
6 files changed, 269 insertions, 142 deletions
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 0663b78a2f6c..cfdefd9f1905 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -734,15 +734,16 @@ static int sja1105_adjust_port_config(struct sja1105_private *priv, int port, return sja1105_clocking_setup_port(priv, port); } -static void sja1105_adjust_link(struct dsa_switch *ds, int port, - struct phy_device *phydev) +static void sja1105_mac_config(struct dsa_switch *ds, int port, + unsigned int link_an_mode, + const struct phylink_link_state *state) { struct sja1105_private *priv = ds->priv; - if (!phydev->link) + if (!state->link) sja1105_adjust_port_config(priv, port, 0, false); else - sja1105_adjust_port_config(priv, port, phydev->speed, true); + sja1105_adjust_port_config(priv, port, state->speed, true); } static void sja1105_phylink_validate(struct dsa_switch *ds, int port, @@ -1515,9 +1516,9 @@ static int sja1105_set_ageing_time(struct dsa_switch *ds, static const struct dsa_switch_ops sja1105_switch_ops = { .get_tag_protocol = sja1105_get_tag_protocol, .setup = sja1105_setup, - .adjust_link = sja1105_adjust_link, .set_ageing_time = sja1105_set_ageing_time, .phylink_validate = sja1105_phylink_validate, + .phylink_mac_config = sja1105_mac_config, .get_strings = sja1105_get_strings, .get_ethtool_stats = sja1105_get_ethtool_stats, .get_sset_count = sja1105_get_sset_count, diff --git a/drivers/net/ethernet/marvell/mvneta.c b/drivers/net/ethernet/marvell/mvneta.c index e758650b2c26..adbbcdde73e6 100644 --- a/drivers/net/ethernet/marvell/mvneta.c +++ b/drivers/net/ethernet/marvell/mvneta.c @@ -437,6 +437,7 @@ struct mvneta_port { 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; @@ -3356,9 +3357,11 @@ static int mvneta_set_mac_addr(struct net_device *dev, void *addr) 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, }; @@ -3408,9 +3411,10 @@ static void mvneta_validate(struct net_device *ndev, unsigned long *supported, 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; @@ -3438,8 +3442,9 @@ static int mvneta_mac_link_state(struct net_device *ndev, 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); @@ -3449,9 +3454,10 @@ static void mvneta_mac_an_restart(struct net_device *ndev) 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); @@ -3581,9 +3587,10 @@ static void mvneta_set_eee(struct mvneta_port *pp, bool enable) 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; @@ -3600,10 +3607,11 @@ static void mvneta_mac_link_down(struct net_device *ndev, unsigned int mode, 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; @@ -4500,8 +4508,14 @@ static int mvneta_probe(struct platform_device *pdev) 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; @@ -4513,8 +4527,6 @@ static int mvneta_probe(struct platform_device *pdev) 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; diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h index 18ae8d06b692..d67c970f02e5 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2.h +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2.h @@ -915,6 +915,7 @@ struct mvpp2_port { phy_interface_t phy_interface; struct phylink *phylink; + struct phylink_config phylink_config; struct phy *comphy; struct mvpp2_bm_pool *pool_long; diff --git a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c index 3ed713b8dea5..757f8e31645e 100644 --- a/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c +++ b/drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c @@ -56,9 +56,9 @@ static struct { /* 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 */ @@ -3239,9 +3239,9 @@ static void mvpp2_start_dev(struct mvpp2_port *port) 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); @@ -4463,11 +4463,12 @@ static void mvpp2_port_copy_mac_addr(struct net_device *dev, struct mvpp2 *priv, 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 */ @@ -4591,10 +4592,11 @@ static void mvpp2_gmac_link_state(struct mvpp2_port *port, 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); @@ -4610,9 +4612,10 @@ static int mvpp2_phylink_mac_link_state(struct net_device *dev, 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, @@ -4797,9 +4800,10 @@ static void mvpp2_gmac_config(struct mvpp2_port *port, unsigned int mode, } } -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; @@ -4839,9 +4843,10 @@ static void mvpp2_mac_config(struct net_device *dev, unsigned int mode, 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; @@ -4866,9 +4871,10 @@ static void mvpp2_mac_link_up(struct net_device *dev, unsigned int mode, 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; @@ -5125,8 +5131,11 @@ static int mvpp2_port_probe(struct platform_device *pdev, /* 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; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 5d288da9a3b0..8b4fc3b4f269 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -948,6 +948,9 @@ int phy_connect_direct(struct net_device *dev, struct phy_device *phydev, { int rc; + if (!dev) + return -EINVAL; + rc = phy_attach_direct(dev, phydev, phydev->dev_flags, interface); if (rc) return rc; @@ -1133,6 +1136,44 @@ void phy_attached_print(struct phy_device *phydev, const char *fmt, ...) } EXPORT_SYMBOL(phy_attached_print); +static void phy_sysfs_create_links(struct phy_device *phydev) +{ + struct net_device *dev = phydev->attached_dev; + int err; + + if (!dev) + return; + + err = sysfs_create_link(&phydev->mdio.dev.kobj, &dev->dev.kobj, + "attached_dev"); + if (err) + return; + + err = sysfs_create_link_nowarn(&dev->dev.kobj, + &phydev->mdio.dev.kobj, + "phydev"); + if (err) { + dev_err(&dev->dev, "could not add device link to %s err %d\n", + kobject_name(&phydev->mdio.dev.kobj), + err); + /* non-fatal - some net drivers can use one netdevice + * with more then one phy + */ + } + + phydev->sysfs_links = true; +} + +static ssize_t +phy_standalone_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct phy_device *phydev = to_phy_device(dev); + + return sprintf(buf, "%d\n", !phydev->attached_dev); +} +static DEVICE_ATTR_RO(phy_standalone); + /** * phy_attach_direct - attach a network device to a given PHY device pointer * @dev: network device to attach @@ -1151,9 +1192,9 @@ EXPORT_SYMBOL(phy_attached_print); int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, u32 flags, phy_interface_t interface) { - struct module *ndev_owner = dev->dev.parent->driver->owner; struct mii_bus *bus = phydev->mdio.bus; struct device *d = &phydev->mdio.dev; + struct module *ndev_owner = NULL; bool using_genphy = false; int err; @@ -1162,8 +1203,10 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, * our own module->refcnt here, otherwise we would not be able to * unload later on. */ + if (dev) + ndev_owner = dev->dev.parent->driver->owner; if (ndev_owner != bus->owner && !try_module_get(bus->owner)) { - dev_err(&dev->dev, "failed to get the bus module\n"); + phydev_err(phydev, "failed to get the bus module\n"); return -EIO; } @@ -1182,7 +1225,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, } if (!try_module_get(d->driver->owner)) { - dev_err(&dev->dev, "failed to get the device driver module\n"); + phydev_err(phydev, "failed to get the device driver module\n"); err = -EIO; goto error_put_device; } @@ -1203,8 +1246,10 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, } phydev->phy_link_change = phy_link_change; - phydev->attached_dev = dev; - dev->phydev = phydev; + if (dev) { + phydev->attached_dev = dev; + dev->phydev = phydev; + } /* Some Ethernet drivers try to connect to a PHY device before * calling register_netdevice() -> netdev_register_kobject() and @@ -1216,22 +1261,13 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, */ phydev->sysfs_links = false; - err = sysfs_create_link(&phydev->mdio.dev.kobj, &dev->dev.kobj, - "attached_dev"); - if (!err) { - err = sysfs_create_link_nowarn(&dev->dev.kobj, - &phydev->mdio.dev.kobj, - "phydev"); - if (err) { - dev_err(&dev->dev, "could not add device link to %s err %d\n", - kobject_name(&phydev->mdio.dev.kobj), - err); - /* non-fatal - some net drivers can use one netdevice - * with more then one phy - */ - } + phy_sysfs_create_links(phydev); - phydev->sysfs_links = true; + if (!phydev->attached_dev) { + err = sysfs_create_file(&phydev->mdio.dev.kobj, + &dev_attr_phy_standalone.attr); + if (err) + phydev_err(phydev, "error creating 'phy_standalone' sysfs entry\n"); } phydev->dev_flags = flags; @@ -1243,7 +1279,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, /* Initial carrier state is off as the phy is about to be * (re)initialized. */ - netif_carrier_off(phydev->attached_dev); + if (dev) + netif_carrier_off(phydev->attached_dev); /* Do initial configuration here, now that * we have certain key parameters @@ -1290,6 +1327,9 @@ struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, struct device *d; int rc; + if (!dev) + return ERR_PTR(-EINVAL); + /* Search the list of PHY devices on the mdio bus for the * PHY with the requested name */ @@ -1349,16 +1389,24 @@ EXPORT_SYMBOL_GPL(phy_driver_is_genphy_10g); void phy_detach(struct phy_device *phydev) { struct net_device *dev = phydev->attached_dev; - struct module *ndev_owner = dev->dev.parent->driver->owner; + struct module *ndev_owner = NULL; struct mii_bus *bus; if (phydev->sysfs_links) { - sysfs_remove_link(&dev->dev.kobj, "phydev"); + if (dev) + sysfs_remove_link(&dev->dev.kobj, "phydev"); sysfs_remove_link(&phydev->mdio.dev.kobj, "attached_dev"); } + + if (!phydev->attached_dev) + sysfs_remove_file(&phydev->mdio.dev.kobj, + &dev_attr_phy_standalone.attr); + phy_suspend(phydev); - phydev->attached_dev->phydev = NULL; - phydev->attached_dev = NULL; + if (dev) { + phydev->attached_dev->phydev = NULL; + phydev->attached_dev = NULL; + } phydev->phylink = NULL; phy_led_triggers_unregister(phydev); @@ -1381,6 +1429,8 @@ void phy_detach(struct phy_device *phydev) bus = phydev->mdio.bus; put_device(&phydev->mdio.dev); + if (dev) + ndev_owner = dev->dev.parent->driver->owner; if (ndev_owner != bus->owner) module_put(bus->owner); diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 74983593834b..68d0a89c52be 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -41,6 +41,9 @@ struct phylink { /* private: */ 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; @@ -65,6 +68,23 @@ struct phylink { struct sfp_bus *sfp_bus; }; +#define phylink_printk(level, pl, fmt, ...) \ + do { \ + if ((pl)->config->type == PHYLINK_NETDEV) \ + netdev_printk(level, (pl)->netdev, fmt, ##__VA_ARGS__); \ + else if ((pl)->config->type == PHYLINK_DEV) \ + dev_printk(level, (pl)->dev, fmt, ##__VA_ARGS__); \ + } while (0) + +#define phylink_err(pl, fmt, ...) \ + phylink_printk(KERN_ERR, pl, fmt, ##__VA_ARGS__) +#define phylink_warn(pl, fmt, ...) \ + phylink_printk(KERN_WARNING, pl, fmt, ##__VA_ARGS__) +#define phylink_info(pl, fmt, ...) \ + phylink_printk(KERN_INFO, pl, fmt, ##__VA_ARGS__) +#define phylink_dbg(pl, fmt, ...) \ + phylink_printk(KERN_DEBUG, pl, fmt, ##__VA_ARGS__) + /** * phylink_set_port_modes() - set the port type modes in the ethtool mask * @mask: ethtool link mode mask @@ -111,7 +131,7 @@ static const char *phylink_an_mode_str(unsigned int mode) 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; } @@ -161,7 +181,7 @@ static int phylink_parse_fixedlink(struct phylink *pl, ret = fwnode_property_read_u32_array(fwnode, "fixed-link", NULL, 0); if (ret != ARRAY_SIZE(prop)) { - netdev_err(pl->netdev, "broken fixed-link?\n"); + phylink_err(pl, "broken fixed-link?\n"); return -EINVAL; } @@ -180,8 +200,8 @@ static int phylink_parse_fixedlink(struct phylink *pl, if (pl->link_config.speed > SPEED_1000 && pl->link_config.duplex != DUPLEX_FULL) - netdev_warn(pl->netdev, "fixed link specifies half duplex for %dMbps link?\n", - pl->link_config.speed); + phylink_warn(pl, "fixed link specifies half duplex for %dMbps link?\n", + pl->link_config.speed); bitmap_fill(pl->supported, __ETHTOOL_LINK_MODE_MASK_NBITS); linkmode_copy(pl->link_config.advertising, pl->supported); @@ -194,9 +214,9 @@ static int phylink_parse_fixedlink(struct phylink *pl, if (s) { __set_bit(s->bit, pl->supported); } else { - netdev_warn(pl->netdev, "fixed link %s duplex %dMbps not recognised\n", - pl->link_config.duplex == DUPLEX_FULL ? "full" : "half", - pl->link_config.speed); + phylink_warn(pl, "fixed link %s duplex %dMbps not recognised\n", + pl->link_config.duplex == DUPLEX_FULL ? "full" : "half", + pl->link_config.speed); } linkmode_and(pl->link_config.advertising, pl->link_config.advertising, @@ -221,8 +241,8 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) if (fwnode_property_read_string(fwnode, "managed", &managed) == 0 && strcmp(managed, "in-band-status") == 0) { if (pl->link_an_mode == MLO_AN_FIXED) { - netdev_err(pl->netdev, - "can't use both fixed-link and in-band-status\n"); + phylink_err(pl, + "can't use both fixed-link and in-band-status\n"); return -EINVAL; } @@ -269,17 +289,17 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) break; default: - netdev_err(pl->netdev, - "incorrect link mode %s for in-band status\n", - phy_modes(pl->link_config.interface)); + phylink_err(pl, + "incorrect link mode %s for in-band status\n", + phy_modes(pl->link_config.interface)); return -EINVAL; } linkmode_copy(pl->link_config.advertising, pl->supported); if (phylink_validate(pl, pl->supported, &pl->link_config)) { - netdev_err(pl->netdev, - "failed to validate link configuration for in-band status\n"); + phylink_err(pl, + "failed to validate link configuration for in-band status\n"); return -EINVAL; } } @@ -290,16 +310,16 @@ static int phylink_parse_mode(struct phylink *pl, struct fwnode_handle *fwnode) static void phylink_mac_config(struct phylink *pl, const struct phylink_link_state *state) { - netdev_dbg(pl->netdev, - "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", - __func__, phylink_an_mode_str(pl->link_an_mode), - phy_modes(state->interface), - phy_speed_to_str(state->speed), - phy_duplex_to_str(state->duplex), - __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); + phylink_dbg(pl, + "%s: mode=%s/%s/%s/%s adv=%*pb pause=%02x link=%u an=%u\n", + __func__, phylink_an_mode_str(pl->link_an_mode), + phy_modes(state->interface), + phy_speed_to_str(state->speed), + phy_duplex_to_str(state->duplex), + __ETHTOOL_LINK_MODE_MASK_NBITS, state->advertising, + state->pause, state->link, state->an_enabled); + + pl->ops->mac_config(pl->config, pl->link_an_mode, state); } static void phylink_mac_config_up(struct phylink *pl, @@ -313,12 +333,11 @@ static void phylink_mac_an_restart(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); @@ -330,7 +349,7 @@ static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state * 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, @@ -395,11 +414,42 @@ static const char *phylink_pause_to_str(int pause) } } +static void phylink_mac_link_up(struct phylink *pl, + struct phylink_link_state link_state) +{ + struct net_device *ndev = pl->netdev; + + pl->ops->mac_link_up(pl->config, pl->link_an_mode, + pl->phy_state.interface, + pl->phydev); + + if (ndev) + netif_carrier_on(ndev); + + phylink_info(pl, + "Link is Up - %s/%s - flow control %s\n", + phy_speed_to_str(link_state.speed), + phy_duplex_to_str(link_state.duplex), + phylink_pause_to_str(link_state.pause)); +} + +static void phylink_mac_link_down(struct phylink *pl) +{ + struct net_device *ndev = pl->netdev; + + if (ndev) + netif_carrier_off(ndev); + pl->ops->mac_link_down(pl->config, pl->link_an_mode, + pl->phy_state.interface); + phylink_info(pl, "Link is Down\n"); +} + 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) { @@ -442,25 +492,17 @@ static void phylink_resolve(struct work_struct *w) } } - if (link_state.link != netif_carrier_ok(ndev)) { - if (!link_state.link) { - netif_carrier_off(ndev); - pl->ops->mac_link_down(ndev, pl->link_an_mode, - pl->phy_state.interface); - netdev_info(ndev, "Link is Down\n"); - } else { - pl->ops->mac_link_up(ndev, pl->link_an_mode, - pl->phy_state.interface, - pl->phydev); - - netif_carrier_on(ndev); - - netdev_info(ndev, - "Link is Up - %s/%s - flow control %s\n", - phy_speed_to_str(link_state.speed), - phy_duplex_to_str(link_state.duplex), - phylink_pause_to_str(link_state.pause)); - } + 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 + phylink_mac_link_up(pl, link_state); } if (!link_state.link && pl->mac_link_dropped) { pl->mac_link_dropped = false; @@ -512,8 +554,8 @@ static int phylink_register_sfp(struct phylink *pl, if (ret == -ENOENT) return 0; - netdev_err(pl->netdev, "unable to parse \"sfp\" node: %d\n", - ret); + phylink_err(pl, "unable to parse \"sfp\" node: %d\n", + ret); return ret; } @@ -539,7 +581,7 @@ static int phylink_register_sfp(struct phylink *pl, * 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) @@ -553,7 +595,17 @@ struct phylink *phylink_create(struct net_device *ndev, 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 if (config->type == PHYLINK_DEV) { + pl->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) @@ -635,10 +687,10 @@ static void phylink_phy_change(struct phy_device *phydev, bool up, phylink_run_resolve(pl); - netdev_dbg(pl->netdev, "phy link %s %s/%s/%s\n", up ? "up" : "down", - phy_modes(phydev->interface), - phy_speed_to_str(phydev->speed), - phy_duplex_to_str(phydev->duplex)); + phylink_dbg(pl, "phy link %s %s/%s/%s\n", up ? "up" : "down", + phy_modes(phydev->interface), + phy_speed_to_str(phydev->speed), + phy_duplex_to_str(phydev->duplex)); } static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) @@ -671,9 +723,9 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) phy->phylink = pl; phy->phy_link_change = phylink_phy_change; - netdev_info(pl->netdev, - "PHY [%s] driver [%s]\n", dev_name(&phy->mdio.dev), - phy->drv->name); + phylink_info(pl, + "PHY [%s] driver [%s]\n", dev_name(&phy->mdio.dev), + phy->drv->name); mutex_lock(&phy->lock); mutex_lock(&pl->state_mutex); @@ -686,10 +738,10 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy) mutex_unlock(&pl->state_mutex); mutex_unlock(&phy->lock); - netdev_dbg(pl->netdev, - "phy: setting supported %*pb advertising %*pb\n", - __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, - __ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising); + phylink_dbg(pl, + "phy: setting supported %*pb advertising %*pb\n", + __ETHTOOL_LINK_MODE_MASK_NBITS, pl->supported, + __ETHTOOL_LINK_MODE_MASK_NBITS, phy->advertising); if (phy_interrupt_is_valid(phy)) phy_request_interrupt(phy); @@ -867,7 +919,7 @@ void phylink_mac_change(struct phylink *pl, bool up) if (!up) pl->mac_link_dropped = true; phylink_run_resolve(pl); - netdev_dbg(pl->netdev, "mac link %s\n", up ? "up" : "down"); + phylink_dbg(pl, "mac link %s\n", up ? "up" : "down"); } EXPORT_SYMBOL_GPL(phylink_mac_change); @@ -883,12 +935,13 @@ void phylink_start(struct phylink *pl) { ASSERT_RTNL(); - netdev_info(pl->netdev, "configuring for %s/%s link mode\n", - phylink_an_mode_str(pl->link_an_mode), - phy_modes(pl->link_config.interface)); + phylink_info(pl, "configuring for %s/%s link mode\n", + phylink_an_mode_str(pl->link_an_mode), + 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 @@ -1233,7 +1286,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; @@ -1594,33 +1648,33 @@ static int phylink_sfp_module_insert(void *upstream, /* Ignore errors if we're expecting a PHY to attach later */ ret = phylink_validate(pl, support, &config); if (ret) { - netdev_err(pl->netdev, "validation with support %*pb failed: %d\n", - __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); + phylink_err(pl, "validation with support %*pb failed: %d\n", + __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); return ret; } iface = sfp_select_interface(pl->sfp_bus, id, config.advertising); if (iface == PHY_INTERFACE_MODE_NA) { - netdev_err(pl->netdev, - "selection of interface failed, advertisement %*pb\n", - __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising); + phylink_err(pl, + "selection of interface failed, advertisement %*pb\n", + __ETHTOOL_LINK_MODE_MASK_NBITS, config.advertising); return -EINVAL; } config.interface = iface; ret = phylink_validate(pl, support, &config); if (ret) { - netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n", - phylink_an_mode_str(MLO_AN_INBAND), - phy_modes(config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); + phylink_err(pl, "validation of %s/%s with support %*pb failed: %d\n", + phylink_an_mode_str(MLO_AN_INBAND), + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, support, ret); return ret; } - netdev_dbg(pl->netdev, "requesting link mode %s/%s with support %*pb\n", - phylink_an_mode_str(MLO_AN_INBAND), - phy_modes(config.interface), - __ETHTOOL_LINK_MODE_MASK_NBITS, support); + phylink_dbg(pl, "requesting link mode %s/%s with support %*pb\n", + phylink_an_mode_str(MLO_AN_INBAND), + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, support); if (phy_interface_mode_is_8023z(iface) && pl->phydev) return -EINVAL; @@ -1639,9 +1693,9 @@ static int phylink_sfp_module_insert(void *upstream, changed = true; - netdev_info(pl->netdev, "switched to %s/%s link mode\n", - phylink_an_mode_str(MLO_AN_INBAND), - phy_modes(config.interface)); + phylink_info(pl, "switched to %s/%s link mode\n", + phylink_an_mode_str(MLO_AN_INBAND), + phy_modes(config.interface)); } pl->link_port = port; |
