Example #1
0
static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
                                   int chunkInNAND,
                                   __u8 * data,
                                   yaffs_Spare * spare,
                                   yaffs_ECCResult * eccResult,
                                   int doErrorCorrection)
{
    int retVal;
    yaffs_Spare localSpare;

    dev->nPageReads++;

    if (!spare && data) {
        /* If we don't have a real spare, then we use a local one. */
        /* Need this for the calculation of the ecc */
        spare = &localSpare;
    }

    if (!dev->useNANDECC) {
        retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
        if (data && doErrorCorrection) {
            /* Do ECC correction */
            /* Todo handle any errors */
            int eccResult1, eccResult2;
            __u8 calcEcc[3];

            yaffs_ECCCalculate(data, calcEcc);
            eccResult1 =
                yaffs_ECCCorrect(data, spare->ecc1, calcEcc);
            yaffs_ECCCalculate(&data[256], calcEcc);
            eccResult2 =
                yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc);

            if (eccResult1 > 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>yaffs ecc error fix performed on chunk %d:0"
                    TENDSTR), chunkInNAND));
                dev->eccFixed++;
            } else if (eccResult1 < 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>yaffs ecc error unfixed on chunk %d:0"
                    TENDSTR), chunkInNAND));
                dev->eccUnfixed++;
            }

            if (eccResult2 > 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>yaffs ecc error fix performed on chunk %d:1"
                    TENDSTR), chunkInNAND));
                dev->eccFixed++;
            } else if (eccResult2 < 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>yaffs ecc error unfixed on chunk %d:1"
                    TENDSTR), chunkInNAND));
                dev->eccUnfixed++;
            }

            if (eccResult1 || eccResult2) {
                /* We had a data problem on this page */
                yaffs_HandleReadDataError(dev, chunkInNAND);
            }

            if (eccResult1 < 0 || eccResult2 < 0)
                *eccResult = YAFFS_ECC_RESULT_UNFIXED;
            else if (eccResult1 > 0 || eccResult2 > 0)
                *eccResult = YAFFS_ECC_RESULT_FIXED;
            else
                *eccResult = YAFFS_ECC_RESULT_NO_ERROR;
        }
    } else {
        /* Must allocate enough memory for spare+2*sizeof(int) */
        /* for ecc results from device. */
        struct yaffs_NANDSpare nspare;
        retVal =
            dev->readChunkFromNAND(dev, chunkInNAND, data,
                                   (yaffs_Spare *) & nspare);
        memcpy(spare, &nspare, sizeof(yaffs_Spare));
        if (data && doErrorCorrection) {
            if (nspare.eccres1 > 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>mtd ecc error fix performed on chunk %d:0"
                    TENDSTR), chunkInNAND));
            } else if (nspare.eccres1 < 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>mtd ecc error unfixed on chunk %d:0"
                    TENDSTR), chunkInNAND));
            }

            if (nspare.eccres2 > 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>mtd ecc error fix performed on chunk %d:1"
                    TENDSTR), chunkInNAND));
            } else if (nspare.eccres2 < 0) {
                T(YAFFS_TRACE_ERROR,
                  (TSTR
                   ("**>>mtd ecc error unfixed on chunk %d:1"
                    TENDSTR), chunkInNAND));
            }

            if (nspare.eccres1 || nspare.eccres2) {
                /* We had a data problem on this page */
                yaffs_HandleReadDataError(dev, chunkInNAND);
            }

            if (nspare.eccres1 < 0 || nspare.eccres2 < 0)
                *eccResult = YAFFS_ECC_RESULT_UNFIXED;
            else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)
                *eccResult = YAFFS_ECC_RESULT_FIXED;
            else
                *eccResult = YAFFS_ECC_RESULT_NO_ERROR;

        }
    }
    return retVal;
}
static int yaffs_ReadChunkFromNAND(struct yaffs_DeviceStruct *dev,
				   int chunkInNAND,
				   __u8 * data,
				   yaffs_Spare * spare,
				   yaffs_ECCResult * eccResult,
				   int doErrorCorrection)
{
	int retVal;
	yaffs_Spare localSpare;

	dev->nPageReads++;

	if (!spare && data) {
		
		
		spare = &localSpare;
	}

	if (!dev->useNANDECC) {
		retVal = dev->readChunkFromNAND(dev, chunkInNAND, data, spare);
		if (data && doErrorCorrection) {
			
			
			int eccResult1, eccResult2;
			__u8 calcEcc[3];

			yaffs_ECCCalculate(data, calcEcc);
			eccResult1 =
			    yaffs_ECCCorrect(data, spare->ecc1, calcEcc);
			yaffs_ECCCalculate(&data[256], calcEcc);
			eccResult2 =
			    yaffs_ECCCorrect(&data[256], spare->ecc2, calcEcc);

			if (eccResult1 > 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>yaffs ecc error fix performed on chunk %d:0"
				    TENDSTR), chunkInNAND));
				dev->eccFixed++;
			} else if (eccResult1 < 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>yaffs ecc error unfixed on chunk %d:0"
				    TENDSTR), chunkInNAND));
				dev->eccUnfixed++;
			}

			if (eccResult2 > 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>yaffs ecc error fix performed on chunk %d:1"
				    TENDSTR), chunkInNAND));
				dev->eccFixed++;
			} else if (eccResult2 < 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>yaffs ecc error unfixed on chunk %d:1"
				    TENDSTR), chunkInNAND));
				dev->eccUnfixed++;
			}

			if (eccResult1 || eccResult2) {
				
				yaffs_HandleReadDataError(dev, chunkInNAND);
			}

			if (eccResult1 < 0 || eccResult2 < 0)
				*eccResult = YAFFS_ECC_RESULT_UNFIXED;
			else if (eccResult1 > 0 || eccResult2 > 0)
				*eccResult = YAFFS_ECC_RESULT_FIXED;
			else
				*eccResult = YAFFS_ECC_RESULT_NO_ERROR;
		}
	} else {
		
		
		struct yaffs_NANDSpare nspare;
		retVal =
		    dev->readChunkFromNAND(dev, chunkInNAND, data,
					   (yaffs_Spare *) & nspare);
		memcpy(spare, &nspare, sizeof(yaffs_Spare));
		if (data && doErrorCorrection) {
			if (nspare.eccres1 > 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>mtd ecc error fix performed on chunk %d:0"
				    TENDSTR), chunkInNAND));
			} else if (nspare.eccres1 < 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>mtd ecc error unfixed on chunk %d:0"
				    TENDSTR), chunkInNAND));
			}

			if (nspare.eccres2 > 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>mtd ecc error fix performed on chunk %d:1"
				    TENDSTR), chunkInNAND));
			} else if (nspare.eccres2 < 0) {
				T(YAFFS_TRACE_ERROR,
				  (TSTR
				   ("**>>mtd ecc error unfixed on chunk %d:1"
				    TENDSTR), chunkInNAND));
			}

			if (nspare.eccres1 || nspare.eccres2) {
				
				yaffs_HandleReadDataError(dev, chunkInNAND);
			}

			if (nspare.eccres1 < 0 || nspare.eccres2 < 0)
				*eccResult = YAFFS_ECC_RESULT_UNFIXED;
			else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)
				*eccResult = YAFFS_ECC_RESULT_FIXED;
			else
				*eccResult = YAFFS_ECC_RESULT_NO_ERROR;

		}
	}
	return retVal;
}