aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/devices/doc2001plus.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-28 21:26:58 -0400
committerThomas Gleixner <tglx@cruncher.tec.linutronix.de>2006-05-29 09:06:51 -0400
commit8593fbc68b0df1168995de76d1af38eb62fd6b62 (patch)
treedd244def53d2be4f1fbff9f74eac404fab8e240f /drivers/mtd/devices/doc2001plus.c
parentf4a43cfcecfcaeeaa40a9dbc1d1378298c22446e (diff)
[MTD] Rework the out of band handling completely
Hopefully the last iteration on this! The handling of out of band data on NAND was accompanied by tons of fruitless discussions and halfarsed patches to make it work for a particular problem. Sufficiently annoyed by I all those "I know it better" mails and the resonable amount of discarded "it solves my problem" patches, I finally decided to go for the big rework. After removing the _ecc variants of mtd read/write functions the solution to satisfy the various requirements was to refactor the read/write _oob functions in mtd. The major change is that read/write_oob now takes a pointer to an operation descriptor structure "struct mtd_oob_ops".instead of having a function with at least seven arguments. read/write_oob which should probably renamed to a more descriptive name, can do the following tasks: - read/write out of band data - read/write data content and out of band data - read/write raw data content and out of band data (ecc disabled) struct mtd_oob_ops has a mode field, which determines the oob handling mode. Aside of the MTD_OOB_RAW mode, which is intended to be especially for diagnostic purposes and some internal functions e.g. bad block table creation, the other two modes are for mtd clients: MTD_OOB_PLACE puts/gets the given oob data exactly to/from the place which is described by the ooboffs and ooblen fields of the mtd_oob_ops strcuture. It's up to the caller to make sure that the byte positions are not used by the ECC placement algorithms. MTD_OOB_AUTO puts/gets the given oob data automaticaly to/from the places in the out of band area which are described by the oobfree tuples in the ecclayout data structre which is associated to the devicee. The decision whether data plus oob or oob only handling is done depends on the setting of the datbuf member of the data structure. When datbuf == NULL then the internal read/write_oob functions are selected, otherwise the read/write data routines are invoked. Tested on a few platforms with all variants. Please be aware of possible regressions for your particular device / application scenario Disclaimer: Any whining will be ignored from those who just contributed "hot air blurb" and never sat down to tackle the underlying problem of the mess in the NAND driver grown over time and the big chunk of work to fix up the existing users. The problem was not the holiness of the existing MTD interfaces. The problems was the lack of time to go for the big overhaul. It's easy to add more mess to the existing one, but it takes alot of effort to go for a real solution. Improvements and bugfixes are welcome! Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'drivers/mtd/devices/doc2001plus.c')
-rw-r--r--drivers/mtd/devices/doc2001plus.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 1ee0c0dcb53b..66cb1e50469a 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -47,10 +47,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
47static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, 47static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
48 size_t *retlen, const u_char *buf, u_char *eccbuf, 48 size_t *retlen, const u_char *buf, u_char *eccbuf,
49 struct nand_oobinfo *oobsel); 49 struct nand_oobinfo *oobsel);
50static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, 50static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
51 size_t *retlen, u_char *buf); 51 struct mtd_oob_ops *ops);
52static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, 52static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
53 size_t *retlen, const u_char *buf); 53 struct mtd_oob_ops *ops);
54static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); 54static int doc_erase (struct mtd_info *mtd, struct erase_info *instr);
55 55
56static struct mtd_info *docmilpluslist = NULL; 56static struct mtd_info *docmilpluslist = NULL;
@@ -868,14 +868,20 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
868 return ret; 868 return ret;
869} 869}
870 870
871static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, 871static int doc_read_oob(struct mtd_info *mtd, loff_t ofs,
872 size_t *retlen, u_char *buf) 872 struct mtd_oob_ops *ops)
873{ 873{
874 loff_t fofs, base; 874 loff_t fofs, base;
875 struct DiskOnChip *this = mtd->priv; 875 struct DiskOnChip *this = mtd->priv;
876 void __iomem * docptr = this->virtadr; 876 void __iomem * docptr = this->virtadr;
877 struct Nand *mychip = &this->chips[ofs >> this->chipshift]; 877 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
878 size_t i, size, got, want; 878 size_t i, size, got, want;
879 uint8_t *buf = ops->oobbuf;
880 size_t len = ops->len;
881
882 BUG_ON(ops->mode != MTD_OOB_PLACE);
883
884 ofs += ops->ooboffs;
879 885
880 DoC_CheckASIC(docptr); 886 DoC_CheckASIC(docptr);
881 887
@@ -941,12 +947,12 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
941 /* Disable flash internally */ 947 /* Disable flash internally */
942 WriteDOC(0, docptr, Mplus_FlashSelect); 948 WriteDOC(0, docptr, Mplus_FlashSelect);
943 949
944 *retlen = len; 950 ops->retlen = len;
945 return 0; 951 return 0;
946} 952}
947 953
948static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, 954static int doc_write_oob(struct mtd_info *mtd, loff_t ofs,
949 size_t *retlen, const u_char *buf) 955 struct mtd_oob_ops *ops)
950{ 956{
951 volatile char dummy; 957 volatile char dummy;
952 loff_t fofs, base; 958 loff_t fofs, base;
@@ -955,6 +961,12 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
955 struct Nand *mychip = &this->chips[ofs >> this->chipshift]; 961 struct Nand *mychip = &this->chips[ofs >> this->chipshift];
956 size_t i, size, got, want; 962 size_t i, size, got, want;
957 int ret = 0; 963 int ret = 0;
964 uint8_t *buf = ops->oobbuf;
965 size_t len = ops->len;
966
967 BUG_ON(ops->mode != MTD_OOB_PLACE);
968
969 ofs += ops->ooboffs;
958 970
959 DoC_CheckASIC(docptr); 971 DoC_CheckASIC(docptr);
960 972
@@ -1030,7 +1042,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
1030 printk("MTD: Error 0x%x programming oob at 0x%x\n", 1042 printk("MTD: Error 0x%x programming oob at 0x%x\n",
1031 dummy, (int)ofs); 1043 dummy, (int)ofs);
1032 /* FIXME: implement Bad Block Replacement */ 1044 /* FIXME: implement Bad Block Replacement */
1033 *retlen = 0; 1045 ops->retlen = 0;
1034 ret = -EIO; 1046 ret = -EIO;
1035 } 1047 }
1036 dummy = ReadDOC(docptr, Mplus_LastDataRead); 1048 dummy = ReadDOC(docptr, Mplus_LastDataRead);
@@ -1043,7 +1055,7 @@ static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
1043 /* Disable flash internally */ 1055 /* Disable flash internally */
1044 WriteDOC(0, docptr, Mplus_FlashSelect); 1056 WriteDOC(0, docptr, Mplus_FlashSelect);
1045 1057
1046 *retlen = len; 1058 ops->retlen = len;
1047 return ret; 1059 return ret;
1048} 1060}
1049 1061