Commit ccab371f authored by David S. Miller's avatar David S. Miller

Merge branch 'sfp-phylink-fixes'

Russell King says:

====================
SFP/phylink fixes

Here are four phylink fixes:
- the "options" is a big-endian value, we must test the bits taking the
  endian-ness into account.
- improve the handling of RX_LOS polarity, taking no RX_LOS polarity
  bits set to mean there is no RX_LOS functionality provided.
- do not report modules that require the address mode switching as
  supporting SFF8472.
- ensure that the mac_link_down() function is called when phylink_stop()
  is called.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents a0da456b 2012b7d6
...@@ -773,6 +773,7 @@ void phylink_stop(struct phylink *pl) ...@@ -773,6 +773,7 @@ void phylink_stop(struct phylink *pl)
sfp_upstream_stop(pl->sfp_bus); sfp_upstream_stop(pl->sfp_bus);
set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
queue_work(system_power_efficient_wq, &pl->resolve);
flush_work(&pl->resolve); flush_work(&pl->resolve);
} }
EXPORT_SYMBOL_GPL(phylink_stop); EXPORT_SYMBOL_GPL(phylink_stop);
......
...@@ -351,12 +351,13 @@ static void sfp_sm_link_check_los(struct sfp *sfp) ...@@ -351,12 +351,13 @@ static void sfp_sm_link_check_los(struct sfp *sfp)
{ {
unsigned int los = sfp->state & SFP_F_LOS; unsigned int los = sfp->state & SFP_F_LOS;
/* FIXME: what if neither SFP_OPTIONS_LOS_INVERTED nor /* If neither SFP_OPTIONS_LOS_INVERTED nor SFP_OPTIONS_LOS_NORMAL
* SFP_OPTIONS_LOS_NORMAL are set? For now, we assume * are set, we assume that no LOS signal is available.
* the same as SFP_OPTIONS_LOS_NORMAL set.
*/ */
if (sfp->id.ext.options & SFP_OPTIONS_LOS_INVERTED) if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED))
los ^= SFP_F_LOS; los ^= SFP_F_LOS;
else if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL)))
los = 0;
if (los) if (los)
sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0); sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0);
...@@ -364,6 +365,22 @@ static void sfp_sm_link_check_los(struct sfp *sfp) ...@@ -364,6 +365,22 @@ static void sfp_sm_link_check_los(struct sfp *sfp)
sfp_sm_link_up(sfp); sfp_sm_link_up(sfp);
} }
static bool sfp_los_event_active(struct sfp *sfp, unsigned int event)
{
return (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED) &&
event == SFP_E_LOS_LOW) ||
(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL) &&
event == SFP_E_LOS_HIGH);
}
static bool sfp_los_event_inactive(struct sfp *sfp, unsigned int event)
{
return (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED) &&
event == SFP_E_LOS_HIGH) ||
(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL) &&
event == SFP_E_LOS_LOW);
}
static void sfp_sm_fault(struct sfp *sfp, bool warn) static void sfp_sm_fault(struct sfp *sfp, bool warn)
{ {
if (sfp->sm_retries && !--sfp->sm_retries) { if (sfp->sm_retries && !--sfp->sm_retries) {
...@@ -470,6 +487,11 @@ static int sfp_sm_mod_probe(struct sfp *sfp) ...@@ -470,6 +487,11 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
return -EINVAL; return -EINVAL;
} }
/* If the module requires address swap mode, warn about it */
if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
dev_warn(sfp->dev,
"module address swap to access page 0xA2 is not supported.\n");
return sfp_module_insert(sfp->sfp_bus, &sfp->id); return sfp_module_insert(sfp->sfp_bus, &sfp->id);
} }
...@@ -581,9 +603,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event) ...@@ -581,9 +603,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
case SFP_S_WAIT_LOS: case SFP_S_WAIT_LOS:
if (event == SFP_E_TX_FAULT) if (event == SFP_E_TX_FAULT)
sfp_sm_fault(sfp, true); sfp_sm_fault(sfp, true);
else if (event == else if (sfp_los_event_inactive(sfp, event))
(sfp->id.ext.options & SFP_OPTIONS_LOS_INVERTED ?
SFP_E_LOS_HIGH : SFP_E_LOS_LOW))
sfp_sm_link_up(sfp); sfp_sm_link_up(sfp);
break; break;
...@@ -591,9 +611,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event) ...@@ -591,9 +611,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
if (event == SFP_E_TX_FAULT) { if (event == SFP_E_TX_FAULT) {
sfp_sm_link_down(sfp); sfp_sm_link_down(sfp);
sfp_sm_fault(sfp, true); sfp_sm_fault(sfp, true);
} else if (event == } else if (sfp_los_event_active(sfp, event)) {
(sfp->id.ext.options & SFP_OPTIONS_LOS_INVERTED ?
SFP_E_LOS_LOW : SFP_E_LOS_HIGH)) {
sfp_sm_link_down(sfp); sfp_sm_link_down(sfp);
sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0); sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0);
} }
...@@ -639,7 +657,8 @@ static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo) ...@@ -639,7 +657,8 @@ static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo)
{ {
/* locking... and check module is present */ /* locking... and check module is present */
if (sfp->id.ext.sff8472_compliance) { if (sfp->id.ext.sff8472_compliance &&
!(sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)) {
modinfo->type = ETH_MODULE_SFF_8472; modinfo->type = ETH_MODULE_SFF_8472;
modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
} else { } else {
......
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