size_t len)
 {
        struct i2c_msg msgs[2];
-       size_t block_size;
+       u8 bus_addr = a2 ? 0x51 : 0x50;
+       size_t block_size = sfp->i2c_block_size;
        size_t this_len;
-       u8 bus_addr;
        int ret;
 
-       if (a2) {
-               block_size = 16;
-               bus_addr = 0x51;
-       } else {
-               block_size = sfp->i2c_block_size;
-               bus_addr = 0x50;
-       }
-
        msgs[0].addr = bus_addr;
        msgs[0].flags = 0;
        msgs[0].len = 1;
        struct sfp *sfp = container_of(work, struct sfp, hwmon_probe.work);
        int err, i;
 
+       /* hwmon interface needs to access 16bit registers in atomic way to
+        * guarantee coherency of the diagnostic monitoring data. If it is not
+        * possible to guarantee coherency because EEPROM is broken in such way
+        * that does not support atomic 16bit read operation then we have to
+        * skip registration of hwmon device.
+        */
+       if (sfp->i2c_block_size < 2) {
+               dev_info(sfp->dev,
+                        "skipping hwmon device registration due to broken EEPROM\n");
+               dev_info(sfp->dev,
+                        "diagnostic EEPROM area cannot be read atomically to guarantee data coherency\n");
+               return;
+       }
+
        err = sfp_read(sfp, true, 0, &sfp->diag, sizeof(sfp->diag));
        if (err < 0) {
                if (sfp->hwmon_tries--) {
        return 0;
 }
 
-/* Some modules (Nokia 3FE46541AA) lock up if byte 0x51 is read as a
- * single read. Switch back to reading 16 byte blocks unless we have
- * a CarlitoxxPro module (rebranded VSOL V2801F). Even more annoyingly,
- * some VSOL V2801F have the vendor name changed to OEM.
+/* GPON modules based on Realtek RTL8672 and RTL9601C chips (e.g. V-SOL
+ * V2801F, CarlitoxxPro CPGOS03-0490, Ubiquiti U-Fiber Instant, ...) do
+ * not support multibyte reads from the EEPROM. Each multi-byte read
+ * operation returns just one byte of EEPROM followed by zeros. There is
+ * no way to identify which modules are using Realtek RTL8672 and RTL9601C
+ * chips. Moreover every OEM of V-SOL V2801F module puts its own vendor
+ * name and vendor id into EEPROM, so there is even no way to detect if
+ * module is V-SOL V2801F. Therefore check for those zeros in the read
+ * data and then based on check switch to reading EEPROM to one byte
+ * at a time.
  */
-static int sfp_quirk_i2c_block_size(const struct sfp_eeprom_base *base)
+static bool sfp_id_needs_byte_io(struct sfp *sfp, void *buf, size_t len)
 {
-       if (!memcmp(base->vendor_name, "VSOL            ", 16))
-               return 1;
-       if (!memcmp(base->vendor_name, "OEM             ", 16) &&
-           !memcmp(base->vendor_pn,   "V2801F          ", 16))
-               return 1;
+       size_t i, block_size = sfp->i2c_block_size;
 
-       /* Some modules can't cope with long reads */
-       return 16;
-}
+       /* Already using byte IO */
+       if (block_size == 1)
+               return false;
 
-static void sfp_quirks_base(struct sfp *sfp, const struct sfp_eeprom_base *base)
-{
-       sfp->i2c_block_size = sfp_quirk_i2c_block_size(base);
+       for (i = 1; i < len; i += block_size) {
+               if (memchr_inv(buf + i, '\0', min(block_size - 1, len - i)))
+                       return false;
+       }
+       return true;
 }
 
 static int sfp_cotsworks_fixup_check(struct sfp *sfp, struct sfp_eeprom_id *id)
        u8 check;
        int ret;
 
-       /* Some modules (CarlitoxxPro CPGOS03-0490) do not support multibyte
-        * reads from the EEPROM, so start by reading the base identifying
-        * information one byte at a time.
+       /* Some SFP modules and also some Linux I2C drivers do not like reads
+        * longer than 16 bytes, so read the EEPROM in chunks of 16 bytes at
+        * a time.
         */
-       sfp->i2c_block_size = 1;
+       sfp->i2c_block_size = 16;
 
        ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base));
        if (ret < 0) {
                return -EAGAIN;
        }
 
+       /* Some SFP modules (e.g. Nokia 3FE46541AA) lock up if read from
+        * address 0x51 is just one byte at a time. Also SFF-8472 requires
+        * that EEPROM supports atomic 16bit read operation for diagnostic
+        * fields, so do not switch to one byte reading at a time unless it
+        * is really required and we have no other option.
+        */
+       if (sfp_id_needs_byte_io(sfp, &id.base, sizeof(id.base))) {
+               dev_info(sfp->dev,
+                        "Detected broken RTL8672/RTL9601C emulated EEPROM\n");
+               dev_info(sfp->dev,
+                        "Switching to reading EEPROM to one byte at a time\n");
+               sfp->i2c_block_size = 1;
+
+               ret = sfp_read(sfp, false, 0, &id.base, sizeof(id.base));
+               if (ret < 0) {
+                       if (report)
+                               dev_err(sfp->dev, "failed to read EEPROM: %d\n",
+                                       ret);
+                       return -EAGAIN;
+               }
+
+               if (ret != sizeof(id.base)) {
+                       dev_err(sfp->dev, "EEPROM short read: %d\n", ret);
+                       return -EAGAIN;
+               }
+       }
+
        /* Cotsworks do not seem to update the checksums when they
         * do the final programming with the final module part number,
         * serial number and date code.
                }
        }
 
-       /* Apply any early module-specific quirks */
-       sfp_quirks_base(sfp, &id.base);
-
        ret = sfp_read(sfp, false, SFP_CC_BASE + 1, &id.ext, sizeof(id.ext));
        if (ret < 0) {
                if (report)