diff options
Diffstat (limited to 'drivers/mtd/devices/doc2000.c')
-rw-r--r-- | drivers/mtd/devices/doc2000.c | 129 |
1 files changed, 29 insertions, 100 deletions
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c index 23e7a5c7d2c1..c54e40464d82 100644 --- a/drivers/mtd/devices/doc2000.c +++ b/drivers/mtd/devices/doc2000.c | |||
@@ -59,13 +59,10 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, | |||
59 | size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); | 59 | size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); |
60 | static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | 60 | static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, |
61 | size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); | 61 | size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); |
62 | static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, | 62 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, |
63 | unsigned long count, loff_t to, size_t *retlen, | 63 | struct mtd_oob_ops *ops); |
64 | u_char *eccbuf, struct nand_oobinfo *oobsel); | 64 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, |
65 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | 65 | struct mtd_oob_ops *ops); |
66 | size_t *retlen, u_char *buf); | ||
67 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | ||
68 | size_t *retlen, const u_char *buf); | ||
69 | static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, | 66 | static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, |
70 | size_t *retlen, const u_char *buf); | 67 | size_t *retlen, const u_char *buf); |
71 | static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); | 68 | static int doc_erase (struct mtd_info *mtd, struct erase_info *instr); |
@@ -517,16 +514,9 @@ static int DoC2k_is_alias(struct DiskOnChip *doc1, struct DiskOnChip *doc2) | |||
517 | return retval; | 514 | return retval; |
518 | } | 515 | } |
519 | 516 | ||
520 | static const char im_name[] = "DoC2k_init"; | 517 | /* This routine is found from the docprobe code by symbol_get(), |
521 | 518 | * which will bump the use count of this module. */ | |
522 | /* This routine is made available to other mtd code via | 519 | void DoC2k_init(struct mtd_info *mtd) |
523 | * inter_module_register. It must only be accessed through | ||
524 | * inter_module_get which will bump the use count of this module. The | ||
525 | * addresses passed back in mtd are valid as long as the use count of | ||
526 | * this module is non-zero, i.e. between inter_module_get and | ||
527 | * inter_module_put. Keith Owens <kaos@ocs.com.au> 29 Oct 2000. | ||
528 | */ | ||
529 | static void DoC2k_init(struct mtd_info *mtd) | ||
530 | { | 520 | { |
531 | struct DiskOnChip *this = mtd->priv; | 521 | struct DiskOnChip *this = mtd->priv; |
532 | struct DiskOnChip *old = NULL; | 522 | struct DiskOnChip *old = NULL; |
@@ -586,7 +576,7 @@ static void DoC2k_init(struct mtd_info *mtd) | |||
586 | mtd->ecctype = MTD_ECC_RS_DiskOnChip; | 576 | mtd->ecctype = MTD_ECC_RS_DiskOnChip; |
587 | mtd->size = 0; | 577 | mtd->size = 0; |
588 | mtd->erasesize = 0; | 578 | mtd->erasesize = 0; |
589 | mtd->oobblock = 512; | 579 | mtd->writesize = 512; |
590 | mtd->oobsize = 16; | 580 | mtd->oobsize = 16; |
591 | mtd->owner = THIS_MODULE; | 581 | mtd->owner = THIS_MODULE; |
592 | mtd->erase = doc_erase; | 582 | mtd->erase = doc_erase; |
@@ -594,9 +584,6 @@ static void DoC2k_init(struct mtd_info *mtd) | |||
594 | mtd->unpoint = NULL; | 584 | mtd->unpoint = NULL; |
595 | mtd->read = doc_read; | 585 | mtd->read = doc_read; |
596 | mtd->write = doc_write; | 586 | mtd->write = doc_write; |
597 | mtd->read_ecc = doc_read_ecc; | ||
598 | mtd->write_ecc = doc_write_ecc; | ||
599 | mtd->writev_ecc = doc_writev_ecc; | ||
600 | mtd->read_oob = doc_read_oob; | 587 | mtd->read_oob = doc_read_oob; |
601 | mtd->write_oob = doc_write_oob; | 588 | mtd->write_oob = doc_write_oob; |
602 | mtd->sync = NULL; | 589 | mtd->sync = NULL; |
@@ -623,6 +610,7 @@ static void DoC2k_init(struct mtd_info *mtd) | |||
623 | return; | 610 | return; |
624 | } | 611 | } |
625 | } | 612 | } |
613 | EXPORT_SYMBOL_GPL(DoC2k_init); | ||
626 | 614 | ||
627 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, | 615 | static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, |
628 | size_t * retlen, u_char * buf) | 616 | size_t * retlen, u_char * buf) |
@@ -971,72 +959,18 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, | |||
971 | return 0; | 959 | return 0; |
972 | } | 960 | } |
973 | 961 | ||
974 | static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs, | 962 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, |
975 | unsigned long count, loff_t to, size_t *retlen, | 963 | struct mtd_oob_ops *ops) |
976 | u_char *eccbuf, struct nand_oobinfo *oobsel) | ||
977 | { | ||
978 | static char static_buf[512]; | ||
979 | static DEFINE_MUTEX(writev_buf_mutex); | ||
980 | |||
981 | size_t totretlen = 0; | ||
982 | size_t thisvecofs = 0; | ||
983 | int ret= 0; | ||
984 | |||
985 | mutex_lock(&writev_buf_mutex); | ||
986 | |||
987 | while(count) { | ||
988 | size_t thislen, thisretlen; | ||
989 | unsigned char *buf; | ||
990 | |||
991 | buf = vecs->iov_base + thisvecofs; | ||
992 | thislen = vecs->iov_len - thisvecofs; | ||
993 | |||
994 | |||
995 | if (thislen >= 512) { | ||
996 | thislen = thislen & ~(512-1); | ||
997 | thisvecofs += thislen; | ||
998 | } else { | ||
999 | /* Not enough to fill a page. Copy into buf */ | ||
1000 | memcpy(static_buf, buf, thislen); | ||
1001 | buf = &static_buf[thislen]; | ||
1002 | |||
1003 | while(count && thislen < 512) { | ||
1004 | vecs++; | ||
1005 | count--; | ||
1006 | thisvecofs = min((512-thislen), vecs->iov_len); | ||
1007 | memcpy(buf, vecs->iov_base, thisvecofs); | ||
1008 | thislen += thisvecofs; | ||
1009 | buf += thisvecofs; | ||
1010 | } | ||
1011 | buf = static_buf; | ||
1012 | } | ||
1013 | if (count && thisvecofs == vecs->iov_len) { | ||
1014 | thisvecofs = 0; | ||
1015 | vecs++; | ||
1016 | count--; | ||
1017 | } | ||
1018 | ret = doc_write_ecc(mtd, to, thislen, &thisretlen, buf, eccbuf, oobsel); | ||
1019 | |||
1020 | totretlen += thisretlen; | ||
1021 | |||
1022 | if (ret || thisretlen != thislen) | ||
1023 | break; | ||
1024 | |||
1025 | to += thislen; | ||
1026 | } | ||
1027 | |||
1028 | mutex_unlock(&writev_buf_mutex); | ||
1029 | *retlen = totretlen; | ||
1030 | return ret; | ||
1031 | } | ||
1032 | |||
1033 | |||
1034 | static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | ||
1035 | size_t * retlen, u_char * buf) | ||
1036 | { | 964 | { |
1037 | struct DiskOnChip *this = mtd->priv; | 965 | struct DiskOnChip *this = mtd->priv; |
1038 | int len256 = 0, ret; | 966 | int len256 = 0, ret; |
1039 | struct Nand *mychip; | 967 | struct Nand *mychip; |
968 | uint8_t *buf = ops->oobbuf; | ||
969 | size_t len = ops->len; | ||
970 | |||
971 | BUG_ON(ops->mode != MTD_OOB_PLACE); | ||
972 | |||
973 | ofs += ops->ooboffs; | ||
1040 | 974 | ||
1041 | mutex_lock(&this->lock); | 975 | mutex_lock(&this->lock); |
1042 | 976 | ||
@@ -1077,7 +1011,7 @@ static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | |||
1077 | 1011 | ||
1078 | DoC_ReadBuf(this, &buf[len256], len - len256); | 1012 | DoC_ReadBuf(this, &buf[len256], len - len256); |
1079 | 1013 | ||
1080 | *retlen = len; | 1014 | ops->retlen = len; |
1081 | /* Reading the full OOB data drops us off of the end of the page, | 1015 | /* Reading the full OOB data drops us off of the end of the page, |
1082 | * causing the flash device to go into busy mode, so we need | 1016 | * causing the flash device to go into busy mode, so we need |
1083 | * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ | 1017 | * to wait until ready 11.4.1 and Toshiba TC58256FT docs */ |
@@ -1192,17 +1126,20 @@ static int doc_write_oob_nolock(struct mtd_info *mtd, loff_t ofs, size_t len, | |||
1192 | 1126 | ||
1193 | } | 1127 | } |
1194 | 1128 | ||
1195 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, | 1129 | static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, |
1196 | size_t * retlen, const u_char * buf) | 1130 | struct mtd_oob_ops *ops) |
1197 | { | 1131 | { |
1198 | struct DiskOnChip *this = mtd->priv; | 1132 | struct DiskOnChip *this = mtd->priv; |
1199 | int ret; | 1133 | int ret; |
1200 | 1134 | ||
1201 | mutex_lock(&this->lock); | 1135 | BUG_ON(ops->mode != MTD_OOB_PLACE); |
1202 | ret = doc_write_oob_nolock(mtd, ofs, len, retlen, buf); | 1136 | |
1137 | mutex_lock(&this->lock); | ||
1138 | ret = doc_write_oob_nolock(mtd, ofs + ops->ooboffs, ops->len, | ||
1139 | &ops->retlen, ops->oobbuf); | ||
1203 | 1140 | ||
1204 | mutex_unlock(&this->lock); | 1141 | mutex_unlock(&this->lock); |
1205 | return ret; | 1142 | return ret; |
1206 | } | 1143 | } |
1207 | 1144 | ||
1208 | static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) | 1145 | static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) |
@@ -1277,12 +1214,6 @@ static int doc_erase(struct mtd_info *mtd, struct erase_info *instr) | |||
1277 | * | 1214 | * |
1278 | ****************************************************************************/ | 1215 | ****************************************************************************/ |
1279 | 1216 | ||
1280 | static int __init init_doc2000(void) | ||
1281 | { | ||
1282 | inter_module_register(im_name, THIS_MODULE, &DoC2k_init); | ||
1283 | return 0; | ||
1284 | } | ||
1285 | |||
1286 | static void __exit cleanup_doc2000(void) | 1217 | static void __exit cleanup_doc2000(void) |
1287 | { | 1218 | { |
1288 | struct mtd_info *mtd; | 1219 | struct mtd_info *mtd; |
@@ -1298,11 +1229,9 @@ static void __exit cleanup_doc2000(void) | |||
1298 | kfree(this->chips); | 1229 | kfree(this->chips); |
1299 | kfree(mtd); | 1230 | kfree(mtd); |
1300 | } | 1231 | } |
1301 | inter_module_unregister(im_name); | ||
1302 | } | 1232 | } |
1303 | 1233 | ||
1304 | module_exit(cleanup_doc2000); | 1234 | module_exit(cleanup_doc2000); |
1305 | module_init(init_doc2000); | ||
1306 | 1235 | ||
1307 | MODULE_LICENSE("GPL"); | 1236 | MODULE_LICENSE("GPL"); |
1308 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al."); | 1237 | MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org> et al."); |