ret = -EFAULT;
 
        kfree(ops.oobbuf);
+
+       /*
+        * NAND returns -EBADMSG on ECC errors, but it returns the OOB
+        * data. For our userspace tools it is important to dump areas
+        * with ECC errors!
+        * For kernel internal usage it also might return -EUCLEAN
+        * to signal the caller that a bitflip has occured and has
+        * been corrected by the ECC algorithm.
+        *
+        * Note: most NAND ECC algorithms do not calculate ECC
+        * for the OOB area.
+        */
+       if (ret == -EUCLEAN || ret == -EBADMSG)
+               return 0;
+
        return ret;
 }
 
 
 {
        int page, realpage, chipnr, sndcmd = 1;
        struct nand_chip *chip = mtd->priv;
+       struct mtd_ecc_stats stats;
        int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
        int readlen = ops->ooblen;
        int len;
        DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
                        __func__, (unsigned long long)from, readlen);
 
+       stats = mtd->ecc_stats;
+
        if (ops->mode == MTD_OOB_AUTO)
                len = chip->ecc.layout->oobavail;
        else
        }
 
        ops->oobretlen = ops->ooblen;
-       return 0;
+
+       if (mtd->ecc_stats.failed - stats.failed)
+               return -EBADMSG;
+
+       return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
 /**