#if IS_ENABLED(CONFIG_HWMON)
        struct sfp_diag diag;
+       struct delayed_work hwmon_probe;
+       unsigned int hwmon_tries;
        struct device *hwmon_dev;
        char *hwmon_name;
 #endif
        .info = sfp_hwmon_info,
 };
 
-static int sfp_hwmon_insert(struct sfp *sfp)
+static void sfp_hwmon_probe(struct work_struct *work)
 {
+       struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work);
        int err, i;
 
-       if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE)
-               return 0;
-
-       if (!(sfp->id.ext.diagmon & SFP_DIAGMON_DDM))
-               return 0;
-
-       if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
-               /* This driver in general does not support address
-                * change.
-                */
-               return 0;
-
        err = sfp_read(sfp, true, 0, &sfp->diag, sizeof(sfp->diag));
-       if (err < 0)
-               return err;
+       if (err < 0) {
+               if (sfp->hwmon_tries--) {
+                       mod_delayed_work(system_wq, &sfp->hwmon_probe,
+                                        T_PROBE_RETRY_SLOW);
+               } else {
+                       dev_warn(sfp->dev, "hwmon probe failed: %d\n", err);
+               }
+               return;
+       }
 
        sfp->hwmon_name = kstrdup(dev_name(sfp->dev), GFP_KERNEL);
-       if (!sfp->hwmon_name)
-               return -ENODEV;
+       if (!sfp->hwmon_name) {
+               dev_err(sfp->dev, "out of memory for hwmon name\n");
+               return;
+       }
 
        for (i = 0; sfp->hwmon_name[i]; i++)
                if (hwmon_is_bad_char(sfp->hwmon_name[i]))
                                                         sfp->hwmon_name, sfp,
                                                         &sfp_hwmon_chip_info,
                                                         NULL);
+       if (IS_ERR(sfp->hwmon_dev))
+               dev_err(sfp->dev, "failed to register hwmon device: %ld\n",
+                       PTR_ERR(sfp->hwmon_dev));
+}
+
+static int sfp_hwmon_insert(struct sfp *sfp)
+{
+       if (sfp->id.ext.sff8472_compliance == SFP_SFF8472_COMPLIANCE_NONE)
+               return 0;
 
-       return PTR_ERR_OR_ZERO(sfp->hwmon_dev);
+       if (!(sfp->id.ext.diagmon & SFP_DIAGMON_DDM))
+               return 0;
+
+       if (sfp->id.ext.diagmon & SFP_DIAGMON_ADDRMODE)
+               /* This driver in general does not support address
+                * change.
+                */
+               return 0;
+
+       mod_delayed_work(system_wq, &sfp->hwmon_probe, 1);
+       sfp->hwmon_tries = R_PROBE_RETRY_SLOW;
+
+       return 0;
 }
 
 static void sfp_hwmon_remove(struct sfp *sfp)
 {
+       cancel_delayed_work_sync(&sfp->hwmon_probe);
        if (!IS_ERR_OR_NULL(sfp->hwmon_dev)) {
                hwmon_device_unregister(sfp->hwmon_dev);
                sfp->hwmon_dev = NULL;
                kfree(sfp->hwmon_name);
        }
 }
+
+static int sfp_hwmon_init(struct sfp *sfp)
+{
+       INIT_DELAYED_WORK(&sfp->hwmon_probe, sfp_hwmon_probe);
+
+       return 0;
+}
+
+static void sfp_hwmon_exit(struct sfp *sfp)
+{
+       cancel_delayed_work_sync(&sfp->hwmon_probe);
+}
 #else
 static int sfp_hwmon_insert(struct sfp *sfp)
 {
 static void sfp_hwmon_remove(struct sfp *sfp)
 {
 }
+
+static int sfp_hwmon_init(struct sfp *sfp)
+{
+       return 0;
+}
+
+static void sfp_hwmon_exit(struct sfp *sfp)
+{
+}
 #endif
 
 /* Helpers */
        if (ret < 0)
                return ret;
 
-       ret = sfp_hwmon_insert(sfp);
-       if (ret < 0)
-               return ret;
-
        return 0;
 }
 
        case SFP_MOD_ERROR:
                break;
        }
+
+#if IS_ENABLED(CONFIG_HWMON)
+       if (sfp->sm_mod_state >= SFP_MOD_WAITDEV &&
+           IS_ERR_OR_NULL(sfp->hwmon_dev)) {
+               err = sfp_hwmon_insert(sfp);
+               if (err)
+                       dev_warn(sfp->dev, "hwmon probe failed: %d\n", err);
+       }
+#endif
 }
 
 static void sfp_sm_main(struct sfp *sfp, unsigned int event)
        INIT_DELAYED_WORK(&sfp->poll, sfp_poll);
        INIT_DELAYED_WORK(&sfp->timeout, sfp_timeout);
 
+       sfp_hwmon_init(sfp);
+
        return sfp;
 }
 
 {
        struct sfp *sfp = data;
 
+       sfp_hwmon_exit(sfp);
+
        cancel_delayed_work_sync(&sfp->poll);
        cancel_delayed_work_sync(&sfp->timeout);
        if (sfp->i2c_mii) {