yaffs_mtdif1.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. /*
  2. * YAFFS: Yet another FFS. A NAND-flash specific file system.
  3. *
  4. * Copyright (C) 2002-2010 Aleph One Ltd.
  5. * for Toby Churchill Ltd and Brightstar Engineering
  6. *
  7. * Created by Charles Manning <charles@aleph1.co.uk>
  8. *
  9. * This program is free software; you can redistribute it and/or modify
  10. * it under the terms of the GNU General Public License version 2 as
  11. * published by the Free Software Foundation.
  12. */
  13. /*
  14. * This module provides the interface between yaffs_nand.c and the
  15. * MTD API. This version is used when the MTD interface supports the
  16. * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
  17. * and we have small-page NAND device.
  18. *
  19. * These functions are invoked via function pointers in yaffs_nand.c.
  20. * This replaces functionality provided by functions in yaffs_mtdif.c
  21. * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are
  22. * called in yaffs_mtdif.c when the function pointers are NULL.
  23. * We assume the MTD layer is performing ECC (use_nand_ecc is true).
  24. */
  25. #include "yportenv.h"
  26. #include "yaffs_trace.h"
  27. #include "yaffs_guts.h"
  28. #include "yaffs_packedtags1.h"
  29. #include "yaffs_tagscompat.h" /* for yaffs_calc_tags_ecc */
  30. #include "yaffs_linux.h"
  31. #include "linux/kernel.h"
  32. #include "linux/version.h"
  33. #include "linux/types.h"
  34. #include "linux/mtd/mtd.h"
  35. #ifndef CONFIG_YAFFS_9BYTE_TAGS
  36. # define YTAG1_SIZE 8
  37. #else
  38. # define YTAG1_SIZE 9
  39. #endif
  40. /* Write a chunk (page) of data to NAND.
  41. *
  42. * Caller always provides ExtendedTags data which are converted to a more
  43. * compact (packed) form for storage in NAND. A mini-ECC runs over the
  44. * contents of the tags meta-data; used to valid the tags when read.
  45. *
  46. * - Pack ExtendedTags to packed_tags1 form
  47. * - Compute mini-ECC for packed_tags1
  48. * - Write data and packed tags to NAND.
  49. *
  50. * Note: Due to the use of the packed_tags1 meta-data which does not include
  51. * a full sequence number (as found in the larger packed_tags2 form) it is
  52. * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
  53. * discarded and dirty. This is not ideal: newer NAND parts are supposed
  54. * to be written just once. When Yaffs performs this operation, this
  55. * function is called with a NULL data pointer -- calling MTD write_oob
  56. * without data is valid usage (2.6.17).
  57. *
  58. * Any underlying MTD error results in YAFFS_FAIL.
  59. * Returns YAFFS_OK or YAFFS_FAIL.
  60. */
  61. int nandmtd1_write_chunk_tags(struct yaffs_dev *dev,
  62. int nand_chunk, const u8 * data,
  63. const struct yaffs_ext_tags *etags)
  64. {
  65. struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  66. int chunk_bytes = dev->data_bytes_per_chunk;
  67. loff_t addr = ((loff_t) nand_chunk) * chunk_bytes;
  68. struct mtd_oob_ops ops;
  69. struct yaffs_packed_tags1 pt1;
  70. int retval;
  71. /* we assume that packed_tags1 and struct yaffs_tags are compatible */
  72. compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
  73. compile_time_assertion(sizeof(struct yaffs_tags) == 8);
  74. yaffs_pack_tags1(&pt1, etags);
  75. yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
  76. /* When deleting a chunk, the upper layer provides only skeletal
  77. * etags, one with is_deleted set. However, we need to update the
  78. * tags, not erase them completely. So we use the NAND write property
  79. * that only zeroed-bits stick and set tag bytes to all-ones and
  80. * zero just the (not) deleted bit.
  81. */
  82. #ifndef CONFIG_YAFFS_9BYTE_TAGS
  83. if (etags->is_deleted) {
  84. memset(&pt1, 0xff, 8);
  85. /* clear delete status bit to indicate deleted */
  86. pt1.deleted = 0;
  87. }
  88. #else
  89. ((u8 *) & pt1)[8] = 0xff;
  90. if (etags->is_deleted) {
  91. memset(&pt1, 0xff, 8);
  92. /* zero page_status byte to indicate deleted */
  93. ((u8 *) & pt1)[8] = 0;
  94. }
  95. #endif
  96. memset(&ops, 0, sizeof(ops));
  97. ops.mode = MTD_OPS_AUTO_OOB;
  98. ops.len = (data) ? chunk_bytes : 0;
  99. ops.ooblen = YTAG1_SIZE;
  100. ops.datbuf = (u8 *) data;
  101. ops.oobbuf = (u8 *) & pt1;
  102. retval = mtd_write_oob(mtd, addr, &ops);
  103. if (retval) {
  104. yaffs_trace(YAFFS_TRACE_MTD,
  105. "write_oob failed, chunk %d, mtd error %d",
  106. nand_chunk, retval);
  107. }
  108. return retval ? YAFFS_FAIL : YAFFS_OK;
  109. }
  110. /* Return with empty ExtendedTags but add ecc_result.
  111. */
  112. static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval)
  113. {
  114. if (etags) {
  115. memset(etags, 0, sizeof(*etags));
  116. etags->ecc_result = ecc_result;
  117. }
  118. return retval;
  119. }
  120. /* Read a chunk (page) from NAND.
  121. *
  122. * Caller expects ExtendedTags data to be usable even on error; that is,
  123. * all members except ecc_result and block_bad are zeroed.
  124. *
  125. * - Check ECC results for data (if applicable)
  126. * - Check for blank/erased block (return empty ExtendedTags if blank)
  127. * - Check the packed_tags1 mini-ECC (correct if necessary/possible)
  128. * - Convert packed_tags1 to ExtendedTags
  129. * - Update ecc_result and block_bad members to refect state.
  130. *
  131. * Returns YAFFS_OK or YAFFS_FAIL.
  132. */
  133. int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
  134. int nand_chunk, u8 * data,
  135. struct yaffs_ext_tags *etags)
  136. {
  137. struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  138. int chunk_bytes = dev->data_bytes_per_chunk;
  139. loff_t addr = ((loff_t) nand_chunk) * chunk_bytes;
  140. int eccres = YAFFS_ECC_RESULT_NO_ERROR;
  141. struct mtd_oob_ops ops;
  142. struct yaffs_packed_tags1 pt1;
  143. int retval;
  144. int deleted;
  145. memset(&ops, 0, sizeof(ops));
  146. ops.mode = MTD_OPS_AUTO_OOB;
  147. ops.len = (data) ? chunk_bytes : 0;
  148. ops.ooblen = YTAG1_SIZE;
  149. ops.datbuf = data;
  150. ops.oobbuf = (u8 *) & pt1;
  151. /* Read page and oob using MTD.
  152. * Check status and determine ECC result.
  153. */
  154. retval = mtd_read_oob(mtd, addr, &ops);
  155. if (retval) {
  156. yaffs_trace(YAFFS_TRACE_MTD,
  157. "read_oob failed, chunk %d, mtd error %d",
  158. nand_chunk, retval);
  159. }
  160. switch (retval) {
  161. case 0:
  162. /* no error */
  163. break;
  164. case -EUCLEAN:
  165. /* MTD's ECC fixed the data */
  166. eccres = YAFFS_ECC_RESULT_FIXED;
  167. dev->n_ecc_fixed++;
  168. break;
  169. case -EBADMSG:
  170. /* MTD's ECC could not fix the data */
  171. dev->n_ecc_unfixed++;
  172. /* fall into... */
  173. default:
  174. rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
  175. etags->block_bad = mtd_block_isbad(mtd, addr);
  176. return YAFFS_FAIL;
  177. }
  178. /* Check for a blank/erased chunk.
  179. */
  180. if (yaffs_check_ff((u8 *) & pt1, 8)) {
  181. /* when blank, upper layers want ecc_result to be <= NO_ERROR */
  182. return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
  183. }
  184. #ifndef CONFIG_YAFFS_9BYTE_TAGS
  185. /* Read deleted status (bit) then return it to it's non-deleted
  186. * state before performing tags mini-ECC check. pt1.deleted is
  187. * inverted.
  188. */
  189. deleted = !pt1.deleted;
  190. pt1.deleted = 1;
  191. #else
  192. deleted = (yaffs_count_bits(((u8 *) & pt1)[8]) < 7);
  193. #endif
  194. /* Check the packed tags mini-ECC and correct if necessary/possible.
  195. */
  196. retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
  197. switch (retval) {
  198. case 0:
  199. /* no tags error, use MTD result */
  200. break;
  201. case 1:
  202. /* recovered tags-ECC error */
  203. dev->n_tags_ecc_fixed++;
  204. if (eccres == YAFFS_ECC_RESULT_NO_ERROR)
  205. eccres = YAFFS_ECC_RESULT_FIXED;
  206. break;
  207. default:
  208. /* unrecovered tags-ECC error */
  209. dev->n_tags_ecc_unfixed++;
  210. return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
  211. }
  212. /* Unpack the tags to extended form and set ECC result.
  213. * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
  214. */
  215. pt1.should_be_ff = 0xFFFFFFFF;
  216. yaffs_unpack_tags1(etags, &pt1);
  217. etags->ecc_result = eccres;
  218. /* Set deleted state */
  219. etags->is_deleted = deleted;
  220. return YAFFS_OK;
  221. }
  222. /* Mark a block bad.
  223. *
  224. * This is a persistant state.
  225. * Use of this function should be rare.
  226. *
  227. * Returns YAFFS_OK or YAFFS_FAIL.
  228. */
  229. int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no)
  230. {
  231. struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  232. int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
  233. int retval;
  234. yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
  235. "marking block %d bad", block_no);
  236. retval = mtd_block_markbad(mtd, (loff_t) blocksize * block_no);
  237. return (retval) ? YAFFS_FAIL : YAFFS_OK;
  238. }
  239. /* Check any MTD prerequists.
  240. *
  241. * Returns YAFFS_OK or YAFFS_FAIL.
  242. */
  243. static int nandmtd1_test_prerequists(struct mtd_info *mtd)
  244. {
  245. /* 2.6.18 has mtd->ecclayout->oobavail */
  246. /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
  247. int oobavail = mtd->ecclayout->oobavail;
  248. if (oobavail < YTAG1_SIZE) {
  249. yaffs_trace(YAFFS_TRACE_ERROR,
  250. "mtd device has only %d bytes for tags, need %d",
  251. oobavail, YTAG1_SIZE);
  252. return YAFFS_FAIL;
  253. }
  254. return YAFFS_OK;
  255. }
  256. /* Query for the current state of a specific block.
  257. *
  258. * Examine the tags of the first chunk of the block and return the state:
  259. * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
  260. * - YAFFS_BLOCK_STATE_NEEDS_SCANNING, the block is in use
  261. * - YAFFS_BLOCK_STATE_EMPTY, the block is clean
  262. *
  263. * Always returns YAFFS_OK.
  264. */
  265. int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
  266. enum yaffs_block_state *state_ptr, u32 * seq_ptr)
  267. {
  268. struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
  269. int chunk_num = block_no * dev->param.chunks_per_block;
  270. loff_t addr = (loff_t) chunk_num * dev->data_bytes_per_chunk;
  271. struct yaffs_ext_tags etags;
  272. int state = YAFFS_BLOCK_STATE_DEAD;
  273. int seqnum = 0;
  274. int retval;
  275. /* We don't yet have a good place to test for MTD config prerequists.
  276. * Do it here as we are called during the initial scan.
  277. */
  278. if (nandmtd1_test_prerequists(mtd) != YAFFS_OK)
  279. return YAFFS_FAIL;
  280. retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags);
  281. etags.block_bad = mtd_block_isbad(mtd, addr);
  282. if (etags.block_bad) {
  283. yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
  284. "block %d is marked bad", block_no);
  285. state = YAFFS_BLOCK_STATE_DEAD;
  286. } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
  287. /* bad tags, need to look more closely */
  288. state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
  289. } else if (etags.chunk_used) {
  290. state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
  291. seqnum = etags.seq_number;
  292. } else {
  293. state = YAFFS_BLOCK_STATE_EMPTY;
  294. }
  295. *state_ptr = state;
  296. *seq_ptr = seqnum;
  297. /* query always succeeds */
  298. return YAFFS_OK;
  299. }