diff options
Diffstat (limited to 'drivers/mtd')
-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 |