diff options
author | David S. Miller <davem@davemloft.net> | 2017-12-01 15:18:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-12-01 15:18:42 -0500 |
commit | ccab371f746abca05a599d074cb3b95a549ef590 (patch) | |
tree | 885078df4b8d83aa0d8eb6f32e0852c6bbe01a76 | |
parent | a0da456bbf95d2a9294799bb05c61bfb24736bb7 (diff) | |
parent | 2012b7d6b2868c532f22d9172c8b24611637eb48 (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.c | 1 | ||||
-rw-r--r-- | drivers/net/phy/sfp.c | 41 |
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 | } |
778 | EXPORT_SYMBOL_GPL(phylink_stop); | 779 | EXPORT_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 | ||
368 | static 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 | |||
376 | static 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 | |||
367 | static void sfp_sm_fault(struct sfp *sfp, bool warn) | 384 | static 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 { |