Commit 4d2af64b authored by David S. Miller's avatar David S. Miller

Merge branch 'phy-supported-interfaces-bitmap'

Russell King says:

====================
Introduce supported interfaces bitmap

This series introduces a new bitmap to allow us to indicate which
phy_interface_t modes are supported.

Currently, phylink will call ->validate with PHY_INTERFACE_MODE_NA to
request all link mode capabilities from the MAC driver before choosing
an interface to use. This leads in some cases to some rather hairly
code. This can be simplified if phylink is aware of the interface modes
that  the MAC supports, and it can instead walk those modes, calling
->validate for each one, and combining the results.

This series merely introduces the support; there is no change of
behaviour until MAC drivers populate their supported_interfaces bitmap.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 656bcd5d d25f3a74
...@@ -166,9 +166,45 @@ static const char *phylink_an_mode_str(unsigned int mode) ...@@ -166,9 +166,45 @@ static const char *phylink_an_mode_str(unsigned int mode)
return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown"; return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
} }
static int phylink_validate_any(struct phylink *pl, unsigned long *supported,
struct phylink_link_state *state)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, };
__ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, };
__ETHTOOL_DECLARE_LINK_MODE_MASK(s);
struct phylink_link_state t;
int intf;
for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) {
if (test_bit(intf, pl->config->supported_interfaces)) {
linkmode_copy(s, supported);
t = *state;
t.interface = intf;
pl->mac_ops->validate(pl->config, s, &t);
linkmode_or(all_s, all_s, s);
linkmode_or(all_adv, all_adv, t.advertising);
}
}
linkmode_copy(supported, all_s);
linkmode_copy(state->advertising, all_adv);
return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
}
static int phylink_validate(struct phylink *pl, unsigned long *supported, static int phylink_validate(struct phylink *pl, unsigned long *supported,
struct phylink_link_state *state) struct phylink_link_state *state)
{ {
if (!phy_interface_empty(pl->config->supported_interfaces)) {
if (state->interface == PHY_INTERFACE_MODE_NA)
return phylink_validate_any(pl, supported, state);
if (!test_bit(state->interface,
pl->config->supported_interfaces))
return -EINVAL;
}
pl->mac_ops->validate(pl->config, supported, state); pl->mac_ops->validate(pl->config, supported, state);
return phylink_is_empty_linkmode(supported) ? -EINVAL : 0; return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
......
...@@ -155,6 +155,40 @@ typedef enum { ...@@ -155,6 +155,40 @@ typedef enum {
PHY_INTERFACE_MODE_MAX, PHY_INTERFACE_MODE_MAX,
} phy_interface_t; } phy_interface_t;
/* PHY interface mode bitmap handling */
#define DECLARE_PHY_INTERFACE_MASK(name) \
DECLARE_BITMAP(name, PHY_INTERFACE_MODE_MAX)
static inline void phy_interface_zero(unsigned long *intf)
{
bitmap_zero(intf, PHY_INTERFACE_MODE_MAX);
}
static inline bool phy_interface_empty(const unsigned long *intf)
{
return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
}
static inline void phy_interface_and(unsigned long *dst, const unsigned long *a,
const unsigned long *b)
{
bitmap_and(dst, a, b, PHY_INTERFACE_MODE_MAX);
}
static inline void phy_interface_or(unsigned long *dst, const unsigned long *a,
const unsigned long *b)
{
bitmap_or(dst, a, b, PHY_INTERFACE_MODE_MAX);
}
static inline void phy_interface_set_rgmii(unsigned long *intf)
{
__set_bit(PHY_INTERFACE_MODE_RGMII, intf);
__set_bit(PHY_INTERFACE_MODE_RGMII_ID, intf);
__set_bit(PHY_INTERFACE_MODE_RGMII_RXID, intf);
__set_bit(PHY_INTERFACE_MODE_RGMII_TXID, intf);
}
/* /*
* phy_supported_speeds - return all speeds currently supported by a PHY device * phy_supported_speeds - return all speeds currently supported by a PHY device
*/ */
......
...@@ -67,6 +67,8 @@ enum phylink_op_type { ...@@ -67,6 +67,8 @@ enum phylink_op_type {
* @ovr_an_inband: if true, override PCS to MLO_AN_INBAND * @ovr_an_inband: if true, override PCS to MLO_AN_INBAND
* @get_fixed_state: callback to execute to determine the fixed link state, * @get_fixed_state: callback to execute to determine the fixed link state,
* if MAC link is at %MLO_AN_FIXED mode. * if MAC link is at %MLO_AN_FIXED mode.
* @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx
* are supported by the MAC/PCS.
*/ */
struct phylink_config { struct phylink_config {
struct device *dev; struct device *dev;
...@@ -76,6 +78,7 @@ struct phylink_config { ...@@ -76,6 +78,7 @@ struct phylink_config {
bool ovr_an_inband; bool ovr_an_inband;
void (*get_fixed_state)(struct phylink_config *config, void (*get_fixed_state)(struct phylink_config *config,
struct phylink_link_state *state); struct phylink_link_state *state);
DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
}; };
/** /**
...@@ -133,8 +136,14 @@ struct phylink_mac_ops { ...@@ -133,8 +136,14 @@ struct phylink_mac_ops {
* based on @state->advertising and/or @state->speed and update * based on @state->advertising and/or @state->speed and update
* @state->interface accordingly. See phylink_helper_basex_speed(). * @state->interface accordingly. See phylink_helper_basex_speed().
* *
* When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the * When @config->supported_interfaces has been set, phylink will iterate
* MAC driver to return all supported link modes. * over the supported interfaces to determine the full capability of the
* MAC. The validation function must not print errors if @state->interface
* is set to an unexpected value.
*
* When @config->supported_interfaces is empty, phylink will call this
* function with @state->interface set to %PHY_INTERFACE_MODE_NA, and
* expects the MAC driver to return all supported link modes.
* *
* If the @state->interface mode is not supported, then the @supported * If the @state->interface mode is not supported, then the @supported
* mask must be cleared. * mask must be cleared.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment