diff options
| -rw-r--r-- | drivers/mtd/ubi/debug.h | 4 | ||||
| -rw-r--r-- | drivers/mtd/ubi/io.c | 70 |
2 files changed, 74 insertions, 0 deletions
diff --git a/drivers/mtd/ubi/debug.h b/drivers/mtd/ubi/debug.h index f30bcb372c05..17a107129726 100644 --- a/drivers/mtd/ubi/debug.h +++ b/drivers/mtd/ubi/debug.h | |||
| @@ -96,8 +96,11 @@ void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len); | |||
| 96 | 96 | ||
| 97 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID | 97 | #ifdef CONFIG_MTD_UBI_DEBUG_PARANOID |
| 98 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); | 98 | int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len); |
| 99 | int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, | ||
| 100 | int offset, int len); | ||
| 99 | #else | 101 | #else |
| 100 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | 102 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 |
| 103 | #define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 | ||
| 101 | #endif | 104 | #endif |
| 102 | 105 | ||
| 103 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT | 106 | #ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT |
| @@ -176,6 +179,7 @@ static inline int ubi_dbg_is_erase_failure(void) | |||
| 176 | #define ubi_dbg_is_write_failure() 0 | 179 | #define ubi_dbg_is_write_failure() 0 |
| 177 | #define ubi_dbg_is_erase_failure() 0 | 180 | #define ubi_dbg_is_erase_failure() 0 |
| 178 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 | 181 | #define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0 |
| 182 | #define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0 | ||
| 179 | 183 | ||
| 180 | #endif /* !CONFIG_MTD_UBI_DEBUG */ | 184 | #endif /* !CONFIG_MTD_UBI_DEBUG */ |
| 181 | #endif /* !__UBI_DEBUG_H__ */ | 185 | #endif /* !__UBI_DEBUG_H__ */ |
diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index a2501299a67c..b4ecc84c7549 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c | |||
| @@ -273,6 +273,21 @@ int ubi_io_write(struct ubi_device *ubi, const void *buf, int pnum, int offset, | |||
| 273 | } else | 273 | } else |
| 274 | ubi_assert(written == len); | 274 | ubi_assert(written == len); |
| 275 | 275 | ||
| 276 | if (!err) { | ||
| 277 | err = ubi_dbg_check_write(ubi, buf, pnum, offset, len); | ||
| 278 | if (err) | ||
| 279 | return err; | ||
| 280 | |||
| 281 | /* | ||
| 282 | * Since we always write sequentially, the rest of the PEB has | ||
| 283 | * to contain only 0xFF bytes. | ||
| 284 | */ | ||
| 285 | offset += len; | ||
| 286 | len = ubi->peb_size - offset; | ||
| 287 | if (len) | ||
| 288 | err = ubi_dbg_check_all_ff(ubi, pnum, offset, len); | ||
| 289 | } | ||
| 290 | |||
| 276 | return err; | 291 | return err; |
| 277 | } | 292 | } |
| 278 | 293 | ||
| @@ -1282,6 +1297,61 @@ exit: | |||
| 1282 | } | 1297 | } |
| 1283 | 1298 | ||
| 1284 | /** | 1299 | /** |
| 1300 | * ubi_dbg_check_write - make sure write succeeded. | ||
| 1301 | * @ubi: UBI device description object | ||
| 1302 | * @buf: buffer with data which were written | ||
| 1303 | * @pnum: physical eraseblock number the data were written to | ||
| 1304 | * @offset: offset within the physical eraseblock the data were written to | ||
| 1305 | * @len: how many bytes were written | ||
| 1306 | * | ||
| 1307 | * This functions reads data which were recently written and compares it with | ||
| 1308 | * the original data buffer - the data have to match. Returns zero if the data | ||
| 1309 | * match and a negative error code if not or in case of failure. | ||
| 1310 | */ | ||
| 1311 | int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum, | ||
| 1312 | int offset, int len) | ||
| 1313 | { | ||
| 1314 | int err, i; | ||
| 1315 | |||
| 1316 | mutex_lock(&ubi->dbg_buf_mutex); | ||
| 1317 | err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len); | ||
| 1318 | if (err) | ||
| 1319 | goto out_unlock; | ||
| 1320 | |||
| 1321 | for (i = 0; i < len; i++) { | ||
| 1322 | uint8_t c = ((uint8_t *)buf)[i]; | ||
| 1323 | uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i]; | ||
| 1324 | int dump_len; | ||
| 1325 | |||
| 1326 | if (c == c1) | ||
| 1327 | continue; | ||
| 1328 | |||
| 1329 | ubi_err("paranoid check failed for PEB %d:%d, len %d", | ||
| 1330 | pnum, offset, len); | ||
| 1331 | ubi_msg("data differ at position %d", i); | ||
| 1332 | dump_len = max_t(int, 128, len - i); | ||
| 1333 | ubi_msg("hex dump of the original buffer from %d to %d", | ||
| 1334 | i, i + dump_len); | ||
| 1335 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
| 1336 | buf + i, dump_len, 1); | ||
| 1337 | ubi_msg("hex dump of the read buffer from %d to %d", | ||
| 1338 | i, i + dump_len); | ||
| 1339 | print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, | ||
| 1340 | ubi->dbg_peb_buf + i, dump_len, 1); | ||
| 1341 | ubi_dbg_dump_stack(); | ||
| 1342 | err = -EINVAL; | ||
| 1343 | goto out_unlock; | ||
| 1344 | } | ||
| 1345 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
| 1346 | |||
| 1347 | return 0; | ||
| 1348 | |||
| 1349 | out_unlock: | ||
| 1350 | mutex_unlock(&ubi->dbg_buf_mutex); | ||
| 1351 | return err; | ||
| 1352 | } | ||
| 1353 | |||
| 1354 | /** | ||
| 1285 | * ubi_dbg_check_all_ff - check that a region of flash is empty. | 1355 | * ubi_dbg_check_all_ff - check that a region of flash is empty. |
| 1286 | * @ubi: UBI device description object | 1356 | * @ubi: UBI device description object |
| 1287 | * @pnum: the physical eraseblock number to check | 1357 | * @pnum: the physical eraseblock number to check |
