summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2021-12-04 12:38:24 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-01-18 10:17:26 +0000
commit4a6332d33f6a9eb1edfdeadb3707c898d0221b9b (patch)
treef32230a29c76f5b9e25319941c11f16727c6c9d2
parent45b4ec0637a3b5be7e7b27f94a567a349ed341f9 (diff)
net: sfp: fix high power modules without diag mode
Commit 7cfa9c92d0a3 ("net: sfp: avoid power switch on address-change modules") changed semantics for high power modules without diag mode. We repeatedly try to read the current power status from the non- existing 0x51 address, in the futile hope this failure is temporary: [ 8.856051] sfp sfp-eth3: module NTT 0000000000000000 rev 0000 sn 0000000000000000 dc 160408 [ 8.865843] mvpp2 f4000000.ethernet eth3: switched to inband/1000base-x link mode [ 8.873469] sfp sfp-eth3: Failed to read EEPROM: -5 [ 8.983251] sfp sfp-eth3: Failed to read EEPROM: -5 [ 9.103250] sfp sfp-eth3: Failed to read EEPROM: -5 Previously we assumed such modules were powered up in the correct mode, continuing without further configuration as long as the required power class was supported by the host. Restore this behaviour by detecting the lack of diagnostic address support prior to setting the module power or checking for the address change sequence. Fixes: 7cfa9c92d0a3 ("net: sfp: avoid power switch on address-change modules") Reported-by: 照山周一郎 <teruyama@springboard-inc.jp> Reported-by: Bjørn Mork <bjorn@mork.no> Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/phy/sfp.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/net/phy/sfp.c b/drivers/net/phy/sfp.c
index 51a1da50c608..4c900d063b19 100644
--- a/drivers/net/phy/sfp.c
+++ b/drivers/net/phy/sfp.c
@@ -1752,17 +1752,20 @@ static int sfp_sm_probe_for_phy(struct sfp *sfp)
static int sfp_module_parse_power(struct sfp *sfp)
{
u32 power_mW = 1000;
+ bool supports_a2;
if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_POWER_DECL))
power_mW = 1500;
if (sfp->id.ext.options & cpu_to_be16(SFP_OPTIONS_HIGH_POWER_LEVEL))
power_mW = 2000;
+ supports_a2 = sfp->id.ext.sff8472_compliance !=
+ SFP_SFF8472_COMPLIANCE_NONE ||
+ sfp->id.ext.diagmon & SFP_DIAGMON_DDM;
+
if (power_mW > sfp->max_power_mW) {
/* Module power specification exceeds the allowed maximum. */
- if (sfp->id.ext.sff8472_compliance ==
- SFP_SFF8472_COMPLIANCE_NONE &&
- !(sfp->id.ext.diagmon & SFP_DIAGMON_DDM)) {
+ if (!supports_a2) {
/* The module appears not to implement bus address
* 0xa2, so assume that the module powers up in the
* indicated mode.
@@ -1779,11 +1782,25 @@ static int sfp_module_parse_power(struct sfp *sfp)
}
}
+ if (power_mW <= 1000) {
+ /* Modules below 1W do not require a power change sequence */
+ sfp->module_power_mW = power_mW;
+ return 0;
+ }
+
+ if (!supports_a2) {
+ /* The module power level is below the host maximum and the
+ * module appears not to implement bus address 0xa2, so assume
+ * that the module powers up in the indicated mode.
+ */
+ return 0;
+ }
+
/* If the module requires a higher power mode, but also requires
* an address change sequence, warn the user that the module may
* not be functional.
*/
- if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE && power_mW > 1000) {
+ if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE) {
dev_warn(sfp->dev,
"Address Change Sequence not supported but module requires %u.%uW, module may not be functional\n",
power_mW / 1000, (power_mW / 100) % 10);