aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2017-12-01 15:18:42 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-01 15:18:42 -0500
commitccab371f746abca05a599d074cb3b95a549ef590 (patch)
tree885078df4b8d83aa0d8eb6f32e0852c6bbe01a76
parenta0da456bbf95d2a9294799bb05c61bfb24736bb7 (diff)
parent2012b7d6b2868c532f22d9172c8b24611637eb48 (diff)
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: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/phy/phylink.c1
-rw-r--r--drivers/net/phy/sfp.c41
2 files changed, 31 insertions, 11 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index e3bbc70372d3..5dc9668dde34 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -773,6 +773,7 @@ void phylink_stop(struct phylink *pl)
773 sfp_upstream_stop(pl->sfp_bus); 773 sfp_upstream_stop(pl->sfp_bus);
774 774
775 set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state); 775 set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
776 queue_work(system_power_efficient_wq, &pl->resolve);
776 flush_work(&pl->resolve); 777 flush_work(&pl->resolve);
777} 778}
778EXPORT_SYMBOL_GPL(phylink_stop); 779EXPORT_SYMBOL_GPL(phylink_stop);
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index e381811e5f11..9dfc1c4c954f 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -351,12 +351,13 @@ static void sfp_sm_link_check_los(struct sfp *sfp)
351{ 351{
352 unsigned int los = sfp->state & SFP_F_LOS; 352 unsigned int los = sfp->state & SFP_F_LOS;
353 353
354 /* FIXME: what if neither SFP_OPTIONS_LOS_INVERTED nor 354 /* If neither SFP_OPTIONS_LOS_INVERTED nor SFP_OPTIONS_LOS_NORMAL
355 * SFP_OPTIONS_LOS_NORMAL are set? For now, we assume 355 * are set, we assume that no LOS signal is available.
356 * the same as SFP_OPTIONS_LOS_NORMAL set.
357 */ 356 */
358 if (sfp->id.ext.options & SFP_OPTIONS_LOS_INVERTED) 357 if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED))
359 los ^= SFP_F_LOS; 358 los ^= SFP_F_LOS;
359 else if (!(sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL)))
360 los = 0;
360 361
361 if (los) 362 if (los)
362 sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0); 363 sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0);
@@ -364,6 +365,22 @@ static void sfp_sm_link_check_los(struct sfp *sfp)
364 sfp_sm_link_up(sfp); 365 sfp_sm_link_up(sfp);
365} 366}
366 367
368static bool sfp_los_event_active(struct sfp *sfp, unsigned int event)
369{
370 return (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED) &&
371 event == SFP_E_LOS_LOW) ||
372 (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL) &&
373 event == SFP_E_LOS_HIGH);
374}
375
376static bool sfp_los_event_inactive(struct sfp *sfp, unsigned int event)
377{
378 return (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_INVERTED) &&
379 event == SFP_E_LOS_HIGH) ||
380 (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_LOS_NORMAL) &&
381 event == SFP_E_LOS_LOW);
382}
383
367static void sfp_sm_fault(struct sfp *sfp, bool warn) 384static void sfp_sm_fault(struct sfp *sfp, bool warn)
368{ 385{
369 if (sfp->sm_retries && !--sfp->sm_retries) { 386 if (sfp->sm_retries && !--sfp->sm_retries) {
@@ -470,6 +487,11 @@ static int sfp_sm_mod_probe(struct sfp *sfp)
470 return -EINVAL; 487 return -EINVAL;
471 } 488 }
472 489
490 /* If the module requires address swap mode, warn about it */
491 if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
492 dev_warn(sfp->dev,
493 "module address swap to access page 0xA2 is not supported.\n");
494
473 return sfp_module_insert(sfp->sfp_bus, &sfp->id); 495 return sfp_module_insert(sfp->sfp_bus, &sfp->id);
474} 496}
475 497
@@ -581,9 +603,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
581 case SFP_S_WAIT_LOS: 603 case SFP_S_WAIT_LOS:
582 if (event == SFP_E_TX_FAULT) 604 if (event == SFP_E_TX_FAULT)
583 sfp_sm_fault(sfp, true); 605 sfp_sm_fault(sfp, true);
584 else if (event == 606 else if (sfp_los_event_inactive(sfp, event))
585 (sfp->id.ext.options & SFP_OPTIONS_LOS_INVERTED ?
586 SFP_E_LOS_HIGH : SFP_E_LOS_LOW))
587 sfp_sm_link_up(sfp); 607 sfp_sm_link_up(sfp);
588 break; 608 break;
589 609
@@ -591,9 +611,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
591 if (event == SFP_E_TX_FAULT) { 611 if (event == SFP_E_TX_FAULT) {
592 sfp_sm_link_down(sfp); 612 sfp_sm_link_down(sfp);
593 sfp_sm_fault(sfp, true); 613 sfp_sm_fault(sfp, true);
594 } else if (event == 614 } else if (sfp_los_event_active(sfp, event)) {
595 (sfp->id.ext.options & SFP_OPTIONS_LOS_INVERTED ?
596 SFP_E_LOS_LOW : SFP_E_LOS_HIGH)) {
597 sfp_sm_link_down(sfp); 615 sfp_sm_link_down(sfp);
598 sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0); 616 sfp_sm_next(sfp, SFP_S_WAIT_LOS, 0);
599 } 617 }
@@ -639,7 +657,8 @@ static int sfp_module_info(struct sfp *sfp, struct ethtool_modinfo *modinfo)
639{ 657{
640 /* locking... and check module is present */ 658 /* locking... and check module is present */
641 659
642 if (sfp->id.ext.sff8472_compliance) { 660 if (sfp->id.ext.sff8472_compliance &&
661 !(sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)) {
643 modinfo->type = ETH_MODULE_SFF_8472; 662 modinfo->type = ETH_MODULE_SFF_8472;
644 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN; 663 modinfo->eeprom_len = ETH_MODULE_SFF_8472_LEN;
645 } else { 664 } else {