Merge branch 'phylink-dsa-prep'

Florian Fainelli says:

====================
PHYLINK preparatory patches for DSA

In preparation for having DSA migrate to PHYLINK, I had to come up with a
number of preparatory patches:

- we need to be able to pass phy_flags from an external component calling
  phylink_of_phy_connect()
- DSA tries to connect through OF first, then fallsback using its own internal
  MDIO bus, in that case we would both show an error, but also not know what
  the correct phy_interface_t would be, instead use the PHY device/driver provided
  one
- Finally bcm_sf2 makes use of all possible PHYs out there: internal, external,
  fixed, and MoCA, the latter requires a bit of help to signal link notifications
  through a MMIO interrupt, as well a report a correct PORT type

Changes in v2:

- rebased against latest net-next/master
- added kernel doc documentation
- dropped error message in phylink_of_phy_connect() as suggested by Russell
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2017-12-13 15:55:02 -05:00
commit 824c2d672a
2 changed files with 52 additions and 9 deletions

View File

@ -54,6 +54,8 @@ struct phylink {
/* The link configuration settings */
struct phylink_link_state link_config;
struct gpio_desc *link_gpio;
void (*get_fixed_state)(struct net_device *dev,
struct phylink_link_state *s);
struct mutex state_mutex;
struct phylink_link_state phy_state;
@ -350,12 +352,14 @@ static int phylink_get_mac_state(struct phylink *pl, struct phylink_link_state *
}
/* The fixed state is... fixed except for the link state,
* which may be determined by a GPIO.
* which may be determined by a GPIO or a callback.
*/
static void phylink_get_fixed_state(struct phylink *pl, struct phylink_link_state *state)
{
*state = pl->link_config;
if (pl->link_gpio)
if (pl->get_fixed_state)
pl->get_fixed_state(pl->netdev, state);
else if (pl->link_gpio)
state->link = !!gpiod_get_value(pl->link_gpio);
}
@ -552,7 +556,10 @@ struct phylink *phylink_create(struct net_device *ndev,
pl->netdev = ndev;
pl->phy_state.interface = iface;
pl->link_interface = iface;
pl->link_port = PORT_MII;
if (iface == PHY_INTERFACE_MODE_MOCA)
pl->link_port = PORT_BNC;
else
pl->link_port = PORT_MII;
pl->link_config.interface = iface;
pl->link_config.pause = MLO_PAUSE_AN;
pl->link_config.speed = SPEED_UNKNOWN;
@ -715,6 +722,12 @@ int phylink_connect_phy(struct phylink *pl, struct phy_device *phy)
phy_interface_mode_is_8023z(pl->link_interface))))
return -EINVAL;
/* Use PHY device/driver interface */
if (pl->link_interface == PHY_INTERFACE_MODE_NA) {
pl->link_interface = phy->interface;
pl->link_config.interface = pl->link_interface;
}
ret = phy_attach_direct(pl->netdev, phy, 0, pl->link_interface);
if (ret)
return ret;
@ -731,6 +744,7 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
* phylink_of_phy_connect() - connect the PHY specified in the DT mode.
* @pl: a pointer to a &struct phylink returned from phylink_create()
* @dn: a pointer to a &struct device_node.
* @flags: PHY-specific flags to communicate to the PHY device driver
*
* Connect the phy specified in the device node @dn to the phylink instance
* specified by @pl. Actions specified in phylink_connect_phy() will be
@ -738,7 +752,8 @@ EXPORT_SYMBOL_GPL(phylink_connect_phy);
*
* Returns 0 on success or a negative errno.
*/
int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn,
u32 flags)
{
struct device_node *phy_node;
struct phy_device *phy_dev;
@ -757,14 +772,13 @@ int phylink_of_phy_connect(struct phylink *pl, struct device_node *dn)
phy_node = of_parse_phandle(dn, "phy-device", 0);
if (!phy_node) {
if (pl->link_an_mode == MLO_AN_PHY) {
netdev_err(pl->netdev, "unable to find PHY node\n");
if (pl->link_an_mode == MLO_AN_PHY)
return -ENODEV;
}
return 0;
}
phy_dev = of_phy_attach(pl->netdev, phy_node, 0, pl->link_interface);
phy_dev = of_phy_attach(pl->netdev, phy_node, flags,
pl->link_interface);
/* We're done with the phy_node handle */
of_node_put(phy_node);
@ -807,6 +821,32 @@ void phylink_disconnect_phy(struct phylink *pl)
}
EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
/**
* phylink_fixed_state_cb() - allow setting a fixed link callback
* @pl: a pointer to a &struct phylink returned from phylink_create()
* @cb: callback to execute to determine the fixed link state.
*
* The MAC driver should call this driver when the state of its link
* can be determined through e.g: an out of band MMIO register.
*/
int phylink_fixed_state_cb(struct phylink *pl,
void (*cb)(struct net_device *dev,
struct phylink_link_state *state))
{
/* It does not make sense to let the link be overriden unless we use
* MLO_AN_FIXED
*/
if (pl->link_an_mode != MLO_AN_FIXED)
return -EINVAL;
mutex_lock(&pl->state_mutex);
pl->get_fixed_state = cb;
mutex_unlock(&pl->state_mutex);
return 0;
}
EXPORT_SYMBOL_GPL(phylink_fixed_state_cb);
/**
* phylink_mac_change() - notify phylink of a change in MAC state
* @pl: a pointer to a &struct phylink returned from phylink_create()

View File

@ -188,8 +188,11 @@ struct phylink *phylink_create(struct net_device *, struct fwnode_handle *,
void phylink_destroy(struct phylink *);
int phylink_connect_phy(struct phylink *, struct phy_device *);
int phylink_of_phy_connect(struct phylink *, struct device_node *);
int phylink_of_phy_connect(struct phylink *, struct device_node *, u32 flags);
void phylink_disconnect_phy(struct phylink *);
int phylink_fixed_state_cb(struct phylink *,
void (*cb)(struct net_device *dev,
struct phylink_link_state *));
void phylink_mac_change(struct phylink *, bool up);