Skip to content

Commit 139d3a2

Browse files
Russell Kingdavem330
authored andcommitted
net: sfp: allow modules with slow diagnostics to probe
When a module is inserted, we attempt to read read the ID from address 0x50. Once we are able to read the ID, we immediately attempt to initialise the hwmon support by reading from address 0x51. If this fails, then we fall into error state, and assume that the module is not usable. Modules such as the ALCATELLUCENT 3FE46541AA use a real EEPROM for I2C address 0x50, which responds immediately. However, address 0x51 is an emulated, which only becomes available once the on-board firmware has booted. This prompts us to fall into the error state. Since the module may be usable without diagnostics, arrange for the hwmon probe independent of the rest of the SFP itself, retrying every 5s for up to about 60s for the monitoring to become available, and print an error message if it doesn't become available. Signed-off-by: Russell King <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent e117be7 commit 139d3a2

File tree

1 file changed

+74
-22
lines changed

1 file changed

+74
-22
lines changed

drivers/net/phy/sfp.c

Lines changed: 74 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,8 @@ struct sfp {
218218

219219
#if IS_ENABLED(CONFIG_HWMON)
220220
struct sfp_diag diag;
221+
struct delayed_work hwmon_probe;
222+
unsigned int hwmon_tries;
221223
struct device *hwmon_dev;
222224
char *hwmon_name;
223225
#endif
@@ -1159,29 +1161,27 @@ static const struct hwmon_chip_info sfp_hwmon_chip_info = {
11591161
.info = sfp_hwmon_info,
11601162
};
11611163

1162-
static int sfp_hwmon_insert(struct sfp *sfp)
1164+
static void sfp_hwmon_probe(struct work_struct *work)
11631165
{
1166+
struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work);
11641167
int err, i;
11651168

1166-
if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE)
1167-
return 0;
1168-
1169-
if (!(sfp->id.ext.diagmon & SFP_DIAGMON_DDM))
1170-
return 0;
1171-
1172-
if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
1173-
/* This driver in general does not support address
1174-
* change.
1175-
*/
1176-
return 0;
1177-
11781169
err = sfp_read(sfp, true, 0, &sfp->diag, sizeof(sfp->diag));
1179-
if (err < 0)
1180-
return err;
1170+
if (err < 0) {
1171+
if (sfp->hwmon_tries--) {
1172+
mod_delayed_work(system_wq, &sfp->hwmon_probe,
1173+
T_PROBE_RETRY_SLOW);
1174+
} else {
1175+
dev_warn(sfp->dev, "hwmon probe failed: %d\n", err);
1176+
}
1177+
return;
1178+
}
11811179

11821180
sfp->hwmon_name = kstrdup(dev_name(sfp->dev), GFP_KERNEL);
1183-
if (!sfp->hwmon_name)
1184-
return -ENODEV;
1181+
if (!sfp->hwmon_name) {
1182+
dev_err(sfp->dev, "out of memory for hwmon name\n");
1183+
return;
1184+
}
11851185

11861186
for (i = 0; sfp->hwmon_name[i]; i++)
11871187
if (hwmon_is_bad_char(sfp->hwmon_name[i]))
@@ -1191,18 +1191,52 @@ static int sfp_hwmon_insert(struct sfp *sfp)
11911191
sfp->hwmon_name, sfp,
11921192
&sfp_hwmon_chip_info,
11931193
NULL);
1194+
if (IS_ERR(sfp->hwmon_dev))
1195+
dev_err(sfp->dev, "failed to register hwmon device: %ld\n",
1196+
PTR_ERR(sfp->hwmon_dev));
1197+
}
1198+
1199+
static int sfp_hwmon_insert(struct sfp *sfp)
1200+
{
1201+
if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE)
1202+
return 0;
11941203

1195-
return PTR_ERR_OR_ZERO(sfp->hwmon_dev);
1204+
if (!(sfp->id.ext.diagmon & SFP_DIAGMON_DDM))
1205+
return 0;
1206+
1207+
if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
1208+
/* This driver in general does not support address
1209+
* change.
1210+
*/
1211+
return 0;
1212+
1213+
mod_delayed_work(system_wq, &sfp->hwmon_probe, 1);
1214+
sfp->hwmon_tries = R_PROBE_RETRY_SLOW;
1215+
1216+
return 0;
11961217
}
11971218

11981219
static void sfp_hwmon_remove(struct sfp *sfp)
11991220
{
1221+
cancel_delayed_work_sync(&sfp->hwmon_probe);
12001222
if (!IS_ERR_OR_NULL(sfp->hwmon_dev)) {
12011223
hwmon_device_unregister(sfp->hwmon_dev);
12021224
sfp->hwmon_dev = NULL;
12031225
kfree(sfp->hwmon_name);
12041226
}
12051227
}
1228+
1229+
static int sfp_hwmon_init(struct sfp *sfp)
1230+
{
1231+
INIT_DELAYED_WORK(&sfp->hwmon_probe, sfp_hwmon_probe);
1232+
1233+
return 0;
1234+
}
1235+
1236+
static void sfp_hwmon_exit(struct sfp *sfp)
1237+
{
1238+
cancel_delayed_work_sync(&sfp->hwmon_probe);
1239+
}
12061240
#else
12071241
static int sfp_hwmon_insert(struct sfp *sfp)
12081242
{
@@ -1212,6 +1246,15 @@ static int sfp_hwmon_insert(struct sfp *sfp)
12121246
static void sfp_hwmon_remove(struct sfp *sfp)
12131247
{
12141248
}
1249+
1250+
static int sfp_hwmon_init(struct sfp *sfp)
1251+
{
1252+
return 0;
1253+
}
1254+
1255+
static void sfp_hwmon_exit(struct sfp *sfp)
1256+
{
1257+
}
12151258
#endif
12161259

12171260
/* Helpers */
@@ -1548,10 +1591,6 @@ static int sfp_sm_mod_probe(struct sfp *sfp, bool report)
15481591
if (ret < 0)
15491592
return ret;
15501593

1551-
ret = sfp_hwmon_insert(sfp);
1552-
if (ret < 0)
1553-
return ret;
1554-
15551594
return 0;
15561595
}
15571596

@@ -1700,6 +1739,15 @@ static void sfp_sm_module(struct sfp *sfp, unsigned int event)
17001739
case SFP_MOD_ERROR:
17011740
break;
17021741
}
1742+
1743+
#if IS_ENABLED(CONFIG_HWMON)
1744+
if (sfp->sm_mod_state >= SFP_MOD_WAITDEV &&
1745+
IS_ERR_OR_NULL(sfp->hwmon_dev)) {
1746+
err = sfp_hwmon_insert(sfp);
1747+
if (err)
1748+
dev_warn(sfp->dev, "hwmon probe failed: %d\n", err);
1749+
}
1750+
#endif
17031751
}
17041752

17051753
static void sfp_sm_main(struct sfp *sfp, unsigned int event)
@@ -2001,13 +2049,17 @@ static struct sfp *sfp_alloc(struct device *dev)
20012049
INIT_DELAYED_WORK(&sfp->poll, sfp_poll);
20022050
INIT_DELAYED_WORK(&sfp->timeout, sfp_timeout);
20032051

2052+
sfp_hwmon_init(sfp);
2053+
20042054
return sfp;
20052055
}
20062056

20072057
static void sfp_cleanup(void *data)
20082058
{
20092059
struct sfp *sfp = data;
20102060

2061+
sfp_hwmon_exit(sfp);
2062+
20112063
cancel_delayed_work_sync(&sfp->poll);
20122064
cancel_delayed_work_sync(&sfp->timeout);
20132065
if (sfp->i2c_mii) {

0 commit comments

Comments
 (0)