diff options
Diffstat (limited to 'drivers/mtd/mtdchar.c')
-rw-r--r-- | drivers/mtd/mtdchar.c | 203 |
1 files changed, 89 insertions, 114 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index e7dc732ddabc..50c6a1e7f675 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -51,7 +51,7 @@ struct mtd_file_info { | |||
51 | enum mtd_file_modes mode; | 51 | enum mtd_file_modes mode; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) | 54 | static loff_t mtdchar_lseek(struct file *file, loff_t offset, int orig) |
55 | { | 55 | { |
56 | struct mtd_file_info *mfi = file->private_data; | 56 | struct mtd_file_info *mfi = file->private_data; |
57 | struct mtd_info *mtd = mfi->mtd; | 57 | struct mtd_info *mtd = mfi->mtd; |
@@ -77,7 +77,7 @@ static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) | |||
77 | 77 | ||
78 | 78 | ||
79 | 79 | ||
80 | static int mtd_open(struct inode *inode, struct file *file) | 80 | static int mtdchar_open(struct inode *inode, struct file *file) |
81 | { | 81 | { |
82 | int minor = iminor(inode); | 82 | int minor = iminor(inode); |
83 | int devnum = minor >> 1; | 83 | int devnum = minor >> 1; |
@@ -142,11 +142,11 @@ static int mtd_open(struct inode *inode, struct file *file) | |||
142 | out: | 142 | out: |
143 | mutex_unlock(&mtd_mutex); | 143 | mutex_unlock(&mtd_mutex); |
144 | return ret; | 144 | return ret; |
145 | } /* mtd_open */ | 145 | } /* mtdchar_open */ |
146 | 146 | ||
147 | /*====================================================================*/ | 147 | /*====================================================================*/ |
148 | 148 | ||
149 | static int mtd_close(struct inode *inode, struct file *file) | 149 | static int mtdchar_close(struct inode *inode, struct file *file) |
150 | { | 150 | { |
151 | struct mtd_file_info *mfi = file->private_data; | 151 | struct mtd_file_info *mfi = file->private_data; |
152 | struct mtd_info *mtd = mfi->mtd; | 152 | struct mtd_info *mtd = mfi->mtd; |
@@ -154,8 +154,8 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
154 | pr_debug("MTD_close\n"); | 154 | pr_debug("MTD_close\n"); |
155 | 155 | ||
156 | /* Only sync if opened RW */ | 156 | /* Only sync if opened RW */ |
157 | if ((file->f_mode & FMODE_WRITE) && mtd->sync) | 157 | if ((file->f_mode & FMODE_WRITE)) |
158 | mtd->sync(mtd); | 158 | mtd_sync(mtd); |
159 | 159 | ||
160 | iput(mfi->ino); | 160 | iput(mfi->ino); |
161 | 161 | ||
@@ -164,7 +164,7 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
164 | kfree(mfi); | 164 | kfree(mfi); |
165 | 165 | ||
166 | return 0; | 166 | return 0; |
167 | } /* mtd_close */ | 167 | } /* mtdchar_close */ |
168 | 168 | ||
169 | /* Back in June 2001, dwmw2 wrote: | 169 | /* Back in June 2001, dwmw2 wrote: |
170 | * | 170 | * |
@@ -184,11 +184,12 @@ static int mtd_close(struct inode *inode, struct file *file) | |||
184 | * alignment requirements are not met in the NAND subdriver. | 184 | * alignment requirements are not met in the NAND subdriver. |
185 | */ | 185 | */ |
186 | 186 | ||
187 | static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) | 187 | static ssize_t mtdchar_read(struct file *file, char __user *buf, size_t count, |
188 | loff_t *ppos) | ||
188 | { | 189 | { |
189 | struct mtd_file_info *mfi = file->private_data; | 190 | struct mtd_file_info *mfi = file->private_data; |
190 | struct mtd_info *mtd = mfi->mtd; | 191 | struct mtd_info *mtd = mfi->mtd; |
191 | size_t retlen=0; | 192 | size_t retlen; |
192 | size_t total_retlen=0; | 193 | size_t total_retlen=0; |
193 | int ret=0; | 194 | int ret=0; |
194 | int len; | 195 | int len; |
@@ -212,10 +213,12 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
212 | 213 | ||
213 | switch (mfi->mode) { | 214 | switch (mfi->mode) { |
214 | case MTD_FILE_MODE_OTP_FACTORY: | 215 | case MTD_FILE_MODE_OTP_FACTORY: |
215 | ret = mtd->read_fact_prot_reg(mtd, *ppos, len, &retlen, kbuf); | 216 | ret = mtd_read_fact_prot_reg(mtd, *ppos, len, |
217 | &retlen, kbuf); | ||
216 | break; | 218 | break; |
217 | case MTD_FILE_MODE_OTP_USER: | 219 | case MTD_FILE_MODE_OTP_USER: |
218 | ret = mtd->read_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); | 220 | ret = mtd_read_user_prot_reg(mtd, *ppos, len, |
221 | &retlen, kbuf); | ||
219 | break; | 222 | break; |
220 | case MTD_FILE_MODE_RAW: | 223 | case MTD_FILE_MODE_RAW: |
221 | { | 224 | { |
@@ -226,12 +229,12 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
226 | ops.oobbuf = NULL; | 229 | ops.oobbuf = NULL; |
227 | ops.len = len; | 230 | ops.len = len; |
228 | 231 | ||
229 | ret = mtd->read_oob(mtd, *ppos, &ops); | 232 | ret = mtd_read_oob(mtd, *ppos, &ops); |
230 | retlen = ops.retlen; | 233 | retlen = ops.retlen; |
231 | break; | 234 | break; |
232 | } | 235 | } |
233 | default: | 236 | default: |
234 | ret = mtd->read(mtd, *ppos, len, &retlen, kbuf); | 237 | ret = mtd_read(mtd, *ppos, len, &retlen, kbuf); |
235 | } | 238 | } |
236 | /* Nand returns -EBADMSG on ECC errors, but it returns | 239 | /* Nand returns -EBADMSG on ECC errors, but it returns |
237 | * the data. For our userspace tools it is important | 240 | * the data. For our userspace tools it is important |
@@ -265,9 +268,10 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t | |||
265 | 268 | ||
266 | kfree(kbuf); | 269 | kfree(kbuf); |
267 | return total_retlen; | 270 | return total_retlen; |
268 | } /* mtd_read */ | 271 | } /* mtdchar_read */ |
269 | 272 | ||
270 | static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) | 273 | static ssize_t mtdchar_write(struct file *file, const char __user *buf, size_t count, |
274 | loff_t *ppos) | ||
271 | { | 275 | { |
272 | struct mtd_file_info *mfi = file->private_data; | 276 | struct mtd_file_info *mfi = file->private_data; |
273 | struct mtd_info *mtd = mfi->mtd; | 277 | struct mtd_info *mtd = mfi->mtd; |
@@ -306,11 +310,8 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
306 | ret = -EROFS; | 310 | ret = -EROFS; |
307 | break; | 311 | break; |
308 | case MTD_FILE_MODE_OTP_USER: | 312 | case MTD_FILE_MODE_OTP_USER: |
309 | if (!mtd->write_user_prot_reg) { | 313 | ret = mtd_write_user_prot_reg(mtd, *ppos, len, |
310 | ret = -EOPNOTSUPP; | 314 | &retlen, kbuf); |
311 | break; | ||
312 | } | ||
313 | ret = mtd->write_user_prot_reg(mtd, *ppos, len, &retlen, kbuf); | ||
314 | break; | 315 | break; |
315 | 316 | ||
316 | case MTD_FILE_MODE_RAW: | 317 | case MTD_FILE_MODE_RAW: |
@@ -323,13 +324,13 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
323 | ops.ooboffs = 0; | 324 | ops.ooboffs = 0; |
324 | ops.len = len; | 325 | ops.len = len; |
325 | 326 | ||
326 | ret = mtd->write_oob(mtd, *ppos, &ops); | 327 | ret = mtd_write_oob(mtd, *ppos, &ops); |
327 | retlen = ops.retlen; | 328 | retlen = ops.retlen; |
328 | break; | 329 | break; |
329 | } | 330 | } |
330 | 331 | ||
331 | default: | 332 | default: |
332 | ret = (*(mtd->write))(mtd, *ppos, len, &retlen, kbuf); | 333 | ret = mtd_write(mtd, *ppos, len, &retlen, kbuf); |
333 | } | 334 | } |
334 | if (!ret) { | 335 | if (!ret) { |
335 | *ppos += retlen; | 336 | *ppos += retlen; |
@@ -345,7 +346,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count | |||
345 | 346 | ||
346 | kfree(kbuf); | 347 | kfree(kbuf); |
347 | return total_retlen; | 348 | return total_retlen; |
348 | } /* mtd_write */ | 349 | } /* mtdchar_write */ |
349 | 350 | ||
350 | /*====================================================================== | 351 | /*====================================================================== |
351 | 352 | ||
@@ -361,20 +362,22 @@ static void mtdchar_erase_callback (struct erase_info *instr) | |||
361 | static int otp_select_filemode(struct mtd_file_info *mfi, int mode) | 362 | static int otp_select_filemode(struct mtd_file_info *mfi, int mode) |
362 | { | 363 | { |
363 | struct mtd_info *mtd = mfi->mtd; | 364 | struct mtd_info *mtd = mfi->mtd; |
365 | size_t retlen; | ||
364 | int ret = 0; | 366 | int ret = 0; |
365 | 367 | ||
368 | /* | ||
369 | * Make a fake call to mtd_read_fact_prot_reg() to check if OTP | ||
370 | * operations are supported. | ||
371 | */ | ||
372 | if (mtd_read_fact_prot_reg(mtd, -1, -1, &retlen, NULL) == -EOPNOTSUPP) | ||
373 | return -EOPNOTSUPP; | ||
374 | |||
366 | switch (mode) { | 375 | switch (mode) { |
367 | case MTD_OTP_FACTORY: | 376 | case MTD_OTP_FACTORY: |
368 | if (!mtd->read_fact_prot_reg) | 377 | mfi->mode = MTD_FILE_MODE_OTP_FACTORY; |
369 | ret = -EOPNOTSUPP; | ||
370 | else | ||
371 | mfi->mode = MTD_FILE_MODE_OTP_FACTORY; | ||
372 | break; | 378 | break; |
373 | case MTD_OTP_USER: | 379 | case MTD_OTP_USER: |
374 | if (!mtd->read_fact_prot_reg) | 380 | mfi->mode = MTD_FILE_MODE_OTP_USER; |
375 | ret = -EOPNOTSUPP; | ||
376 | else | ||
377 | mfi->mode = MTD_FILE_MODE_OTP_USER; | ||
378 | break; | 381 | break; |
379 | default: | 382 | default: |
380 | ret = -EINVAL; | 383 | ret = -EINVAL; |
@@ -387,7 +390,7 @@ static int otp_select_filemode(struct mtd_file_info *mfi, int mode) | |||
387 | # define otp_select_filemode(f,m) -EOPNOTSUPP | 390 | # define otp_select_filemode(f,m) -EOPNOTSUPP |
388 | #endif | 391 | #endif |
389 | 392 | ||
390 | static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | 393 | static int mtdchar_writeoob(struct file *file, struct mtd_info *mtd, |
391 | uint64_t start, uint32_t length, void __user *ptr, | 394 | uint64_t start, uint32_t length, void __user *ptr, |
392 | uint32_t __user *retp) | 395 | uint32_t __user *retp) |
393 | { | 396 | { |
@@ -424,7 +427,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | |||
424 | return PTR_ERR(ops.oobbuf); | 427 | return PTR_ERR(ops.oobbuf); |
425 | 428 | ||
426 | start &= ~((uint64_t)mtd->writesize - 1); | 429 | start &= ~((uint64_t)mtd->writesize - 1); |
427 | ret = mtd->write_oob(mtd, start, &ops); | 430 | ret = mtd_write_oob(mtd, start, &ops); |
428 | 431 | ||
429 | if (ops.oobretlen > 0xFFFFFFFFU) | 432 | if (ops.oobretlen > 0xFFFFFFFFU) |
430 | ret = -EOVERFLOW; | 433 | ret = -EOVERFLOW; |
@@ -436,7 +439,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, | |||
436 | return ret; | 439 | return ret; |
437 | } | 440 | } |
438 | 441 | ||
439 | static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, | 442 | static int mtdchar_readoob(struct file *file, struct mtd_info *mtd, |
440 | uint64_t start, uint32_t length, void __user *ptr, | 443 | uint64_t start, uint32_t length, void __user *ptr, |
441 | uint32_t __user *retp) | 444 | uint32_t __user *retp) |
442 | { | 445 | { |
@@ -447,13 +450,8 @@ static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, | |||
447 | if (length > 4096) | 450 | if (length > 4096) |
448 | return -EINVAL; | 451 | return -EINVAL; |
449 | 452 | ||
450 | if (!mtd->read_oob) | 453 | if (!access_ok(VERIFY_WRITE, ptr, length)) |
451 | ret = -EOPNOTSUPP; | 454 | return -EFAULT; |
452 | else | ||
453 | ret = access_ok(VERIFY_WRITE, ptr, | ||
454 | length) ? 0 : -EFAULT; | ||
455 | if (ret) | ||
456 | return ret; | ||
457 | 455 | ||
458 | ops.ooblen = length; | 456 | ops.ooblen = length; |
459 | ops.ooboffs = start & (mtd->writesize - 1); | 457 | ops.ooboffs = start & (mtd->writesize - 1); |
@@ -469,7 +467,7 @@ static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, | |||
469 | return -ENOMEM; | 467 | return -ENOMEM; |
470 | 468 | ||
471 | start &= ~((uint64_t)mtd->writesize - 1); | 469 | start &= ~((uint64_t)mtd->writesize - 1); |
472 | ret = mtd->read_oob(mtd, start, &ops); | 470 | ret = mtd_read_oob(mtd, start, &ops); |
473 | 471 | ||
474 | if (put_user(ops.oobretlen, retp)) | 472 | if (put_user(ops.oobretlen, retp)) |
475 | ret = -EFAULT; | 473 | ret = -EFAULT; |
@@ -530,7 +528,7 @@ static int shrink_ecclayout(const struct nand_ecclayout *from, | |||
530 | return 0; | 528 | return 0; |
531 | } | 529 | } |
532 | 530 | ||
533 | static int mtd_blkpg_ioctl(struct mtd_info *mtd, | 531 | static int mtdchar_blkpg_ioctl(struct mtd_info *mtd, |
534 | struct blkpg_ioctl_arg __user *arg) | 532 | struct blkpg_ioctl_arg __user *arg) |
535 | { | 533 | { |
536 | struct blkpg_ioctl_arg a; | 534 | struct blkpg_ioctl_arg a; |
@@ -566,7 +564,7 @@ static int mtd_blkpg_ioctl(struct mtd_info *mtd, | |||
566 | } | 564 | } |
567 | } | 565 | } |
568 | 566 | ||
569 | static int mtd_write_ioctl(struct mtd_info *mtd, | 567 | static int mtdchar_write_ioctl(struct mtd_info *mtd, |
570 | struct mtd_write_req __user *argp) | 568 | struct mtd_write_req __user *argp) |
571 | { | 569 | { |
572 | struct mtd_write_req req; | 570 | struct mtd_write_req req; |
@@ -607,7 +605,7 @@ static int mtd_write_ioctl(struct mtd_info *mtd, | |||
607 | ops.oobbuf = NULL; | 605 | ops.oobbuf = NULL; |
608 | } | 606 | } |
609 | 607 | ||
610 | ret = mtd->write_oob(mtd, (loff_t)req.start, &ops); | 608 | ret = mtd_write_oob(mtd, (loff_t)req.start, &ops); |
611 | 609 | ||
612 | kfree(ops.datbuf); | 610 | kfree(ops.datbuf); |
613 | kfree(ops.oobbuf); | 611 | kfree(ops.oobbuf); |
@@ -615,7 +613,7 @@ static int mtd_write_ioctl(struct mtd_info *mtd, | |||
615 | return ret; | 613 | return ret; |
616 | } | 614 | } |
617 | 615 | ||
618 | static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | 616 | static int mtdchar_ioctl(struct file *file, u_int cmd, u_long arg) |
619 | { | 617 | { |
620 | struct mtd_file_info *mfi = file->private_data; | 618 | struct mtd_file_info *mfi = file->private_data; |
621 | struct mtd_info *mtd = mfi->mtd; | 619 | struct mtd_info *mtd = mfi->mtd; |
@@ -729,7 +727,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
729 | wq_head is no longer there when the | 727 | wq_head is no longer there when the |
730 | callback routine tries to wake us up. | 728 | callback routine tries to wake us up. |
731 | */ | 729 | */ |
732 | ret = mtd->erase(mtd, erase); | 730 | ret = mtd_erase(mtd, erase); |
733 | if (!ret) { | 731 | if (!ret) { |
734 | set_current_state(TASK_UNINTERRUPTIBLE); | 732 | set_current_state(TASK_UNINTERRUPTIBLE); |
735 | add_wait_queue(&waitq, &wait); | 733 | add_wait_queue(&waitq, &wait); |
@@ -755,7 +753,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
755 | if (copy_from_user(&buf, argp, sizeof(buf))) | 753 | if (copy_from_user(&buf, argp, sizeof(buf))) |
756 | ret = -EFAULT; | 754 | ret = -EFAULT; |
757 | else | 755 | else |
758 | ret = mtd_do_writeoob(file, mtd, buf.start, buf.length, | 756 | ret = mtdchar_writeoob(file, mtd, buf.start, buf.length, |
759 | buf.ptr, &buf_user->length); | 757 | buf.ptr, &buf_user->length); |
760 | break; | 758 | break; |
761 | } | 759 | } |
@@ -769,7 +767,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
769 | if (copy_from_user(&buf, argp, sizeof(buf))) | 767 | if (copy_from_user(&buf, argp, sizeof(buf))) |
770 | ret = -EFAULT; | 768 | ret = -EFAULT; |
771 | else | 769 | else |
772 | ret = mtd_do_readoob(file, mtd, buf.start, buf.length, | 770 | ret = mtdchar_readoob(file, mtd, buf.start, buf.length, |
773 | buf.ptr, &buf_user->start); | 771 | buf.ptr, &buf_user->start); |
774 | break; | 772 | break; |
775 | } | 773 | } |
@@ -782,7 +780,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
782 | if (copy_from_user(&buf, argp, sizeof(buf))) | 780 | if (copy_from_user(&buf, argp, sizeof(buf))) |
783 | ret = -EFAULT; | 781 | ret = -EFAULT; |
784 | else | 782 | else |
785 | ret = mtd_do_writeoob(file, mtd, buf.start, buf.length, | 783 | ret = mtdchar_writeoob(file, mtd, buf.start, buf.length, |
786 | (void __user *)(uintptr_t)buf.usr_ptr, | 784 | (void __user *)(uintptr_t)buf.usr_ptr, |
787 | &buf_user->length); | 785 | &buf_user->length); |
788 | break; | 786 | break; |
@@ -796,7 +794,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
796 | if (copy_from_user(&buf, argp, sizeof(buf))) | 794 | if (copy_from_user(&buf, argp, sizeof(buf))) |
797 | ret = -EFAULT; | 795 | ret = -EFAULT; |
798 | else | 796 | else |
799 | ret = mtd_do_readoob(file, mtd, buf.start, buf.length, | 797 | ret = mtdchar_readoob(file, mtd, buf.start, buf.length, |
800 | (void __user *)(uintptr_t)buf.usr_ptr, | 798 | (void __user *)(uintptr_t)buf.usr_ptr, |
801 | &buf_user->length); | 799 | &buf_user->length); |
802 | break; | 800 | break; |
@@ -804,7 +802,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
804 | 802 | ||
805 | case MEMWRITE: | 803 | case MEMWRITE: |
806 | { | 804 | { |
807 | ret = mtd_write_ioctl(mtd, | 805 | ret = mtdchar_write_ioctl(mtd, |
808 | (struct mtd_write_req __user *)arg); | 806 | (struct mtd_write_req __user *)arg); |
809 | break; | 807 | break; |
810 | } | 808 | } |
@@ -816,10 +814,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
816 | if (copy_from_user(&einfo, argp, sizeof(einfo))) | 814 | if (copy_from_user(&einfo, argp, sizeof(einfo))) |
817 | return -EFAULT; | 815 | return -EFAULT; |
818 | 816 | ||
819 | if (!mtd->lock) | 817 | ret = mtd_lock(mtd, einfo.start, einfo.length); |
820 | ret = -EOPNOTSUPP; | ||
821 | else | ||
822 | ret = mtd->lock(mtd, einfo.start, einfo.length); | ||
823 | break; | 818 | break; |
824 | } | 819 | } |
825 | 820 | ||
@@ -830,10 +825,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
830 | if (copy_from_user(&einfo, argp, sizeof(einfo))) | 825 | if (copy_from_user(&einfo, argp, sizeof(einfo))) |
831 | return -EFAULT; | 826 | return -EFAULT; |
832 | 827 | ||
833 | if (!mtd->unlock) | 828 | ret = mtd_unlock(mtd, einfo.start, einfo.length); |
834 | ret = -EOPNOTSUPP; | ||
835 | else | ||
836 | ret = mtd->unlock(mtd, einfo.start, einfo.length); | ||
837 | break; | 829 | break; |
838 | } | 830 | } |
839 | 831 | ||
@@ -844,10 +836,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
844 | if (copy_from_user(&einfo, argp, sizeof(einfo))) | 836 | if (copy_from_user(&einfo, argp, sizeof(einfo))) |
845 | return -EFAULT; | 837 | return -EFAULT; |
846 | 838 | ||
847 | if (!mtd->is_locked) | 839 | ret = mtd_is_locked(mtd, einfo.start, einfo.length); |
848 | ret = -EOPNOTSUPP; | ||
849 | else | ||
850 | ret = mtd->is_locked(mtd, einfo.start, einfo.length); | ||
851 | break; | 840 | break; |
852 | } | 841 | } |
853 | 842 | ||
@@ -878,10 +867,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
878 | 867 | ||
879 | if (copy_from_user(&offs, argp, sizeof(loff_t))) | 868 | if (copy_from_user(&offs, argp, sizeof(loff_t))) |
880 | return -EFAULT; | 869 | return -EFAULT; |
881 | if (!mtd->block_isbad) | 870 | return mtd_block_isbad(mtd, offs); |
882 | ret = -EOPNOTSUPP; | ||
883 | else | ||
884 | return mtd->block_isbad(mtd, offs); | ||
885 | break; | 871 | break; |
886 | } | 872 | } |
887 | 873 | ||
@@ -891,10 +877,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
891 | 877 | ||
892 | if (copy_from_user(&offs, argp, sizeof(loff_t))) | 878 | if (copy_from_user(&offs, argp, sizeof(loff_t))) |
893 | return -EFAULT; | 879 | return -EFAULT; |
894 | if (!mtd->block_markbad) | 880 | return mtd_block_markbad(mtd, offs); |
895 | ret = -EOPNOTSUPP; | ||
896 | else | ||
897 | return mtd->block_markbad(mtd, offs); | ||
898 | break; | 881 | break; |
899 | } | 882 | } |
900 | 883 | ||
@@ -919,17 +902,15 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
919 | struct otp_info *buf = kmalloc(4096, GFP_KERNEL); | 902 | struct otp_info *buf = kmalloc(4096, GFP_KERNEL); |
920 | if (!buf) | 903 | if (!buf) |
921 | return -ENOMEM; | 904 | return -ENOMEM; |
922 | ret = -EOPNOTSUPP; | ||
923 | switch (mfi->mode) { | 905 | switch (mfi->mode) { |
924 | case MTD_FILE_MODE_OTP_FACTORY: | 906 | case MTD_FILE_MODE_OTP_FACTORY: |
925 | if (mtd->get_fact_prot_info) | 907 | ret = mtd_get_fact_prot_info(mtd, buf, 4096); |
926 | ret = mtd->get_fact_prot_info(mtd, buf, 4096); | ||
927 | break; | 908 | break; |
928 | case MTD_FILE_MODE_OTP_USER: | 909 | case MTD_FILE_MODE_OTP_USER: |
929 | if (mtd->get_user_prot_info) | 910 | ret = mtd_get_user_prot_info(mtd, buf, 4096); |
930 | ret = mtd->get_user_prot_info(mtd, buf, 4096); | ||
931 | break; | 911 | break; |
932 | default: | 912 | default: |
913 | ret = -EINVAL; | ||
933 | break; | 914 | break; |
934 | } | 915 | } |
935 | if (ret >= 0) { | 916 | if (ret >= 0) { |
@@ -953,9 +934,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
953 | return -EINVAL; | 934 | return -EINVAL; |
954 | if (copy_from_user(&oinfo, argp, sizeof(oinfo))) | 935 | if (copy_from_user(&oinfo, argp, sizeof(oinfo))) |
955 | return -EFAULT; | 936 | return -EFAULT; |
956 | if (!mtd->lock_user_prot_reg) | 937 | ret = mtd_lock_user_prot_reg(mtd, oinfo.start, oinfo.length); |
957 | return -EOPNOTSUPP; | ||
958 | ret = mtd->lock_user_prot_reg(mtd, oinfo.start, oinfo.length); | ||
959 | break; | 938 | break; |
960 | } | 939 | } |
961 | #endif | 940 | #endif |
@@ -999,7 +978,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
999 | break; | 978 | break; |
1000 | 979 | ||
1001 | case MTD_FILE_MODE_RAW: | 980 | case MTD_FILE_MODE_RAW: |
1002 | if (!mtd->read_oob || !mtd->write_oob) | 981 | if (!mtd_has_oob(mtd)) |
1003 | return -EOPNOTSUPP; | 982 | return -EOPNOTSUPP; |
1004 | mfi->mode = arg; | 983 | mfi->mode = arg; |
1005 | 984 | ||
@@ -1014,7 +993,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
1014 | 993 | ||
1015 | case BLKPG: | 994 | case BLKPG: |
1016 | { | 995 | { |
1017 | ret = mtd_blkpg_ioctl(mtd, | 996 | ret = mtdchar_blkpg_ioctl(mtd, |
1018 | (struct blkpg_ioctl_arg __user *)arg); | 997 | (struct blkpg_ioctl_arg __user *)arg); |
1019 | break; | 998 | break; |
1020 | } | 999 | } |
@@ -1033,12 +1012,12 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) | |||
1033 | return ret; | 1012 | return ret; |
1034 | } /* memory_ioctl */ | 1013 | } /* memory_ioctl */ |
1035 | 1014 | ||
1036 | static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) | 1015 | static long mtdchar_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) |
1037 | { | 1016 | { |
1038 | int ret; | 1017 | int ret; |
1039 | 1018 | ||
1040 | mutex_lock(&mtd_mutex); | 1019 | mutex_lock(&mtd_mutex); |
1041 | ret = mtd_ioctl(file, cmd, arg); | 1020 | ret = mtdchar_ioctl(file, cmd, arg); |
1042 | mutex_unlock(&mtd_mutex); | 1021 | mutex_unlock(&mtd_mutex); |
1043 | 1022 | ||
1044 | return ret; | 1023 | return ret; |
@@ -1055,7 +1034,7 @@ struct mtd_oob_buf32 { | |||
1055 | #define MEMWRITEOOB32 _IOWR('M', 3, struct mtd_oob_buf32) | 1034 | #define MEMWRITEOOB32 _IOWR('M', 3, struct mtd_oob_buf32) |
1056 | #define MEMREADOOB32 _IOWR('M', 4, struct mtd_oob_buf32) | 1035 | #define MEMREADOOB32 _IOWR('M', 4, struct mtd_oob_buf32) |
1057 | 1036 | ||
1058 | static long mtd_compat_ioctl(struct file *file, unsigned int cmd, | 1037 | static long mtdchar_compat_ioctl(struct file *file, unsigned int cmd, |
1059 | unsigned long arg) | 1038 | unsigned long arg) |
1060 | { | 1039 | { |
1061 | struct mtd_file_info *mfi = file->private_data; | 1040 | struct mtd_file_info *mfi = file->private_data; |
@@ -1074,7 +1053,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, | |||
1074 | if (copy_from_user(&buf, argp, sizeof(buf))) | 1053 | if (copy_from_user(&buf, argp, sizeof(buf))) |
1075 | ret = -EFAULT; | 1054 | ret = -EFAULT; |
1076 | else | 1055 | else |
1077 | ret = mtd_do_writeoob(file, mtd, buf.start, | 1056 | ret = mtdchar_writeoob(file, mtd, buf.start, |
1078 | buf.length, compat_ptr(buf.ptr), | 1057 | buf.length, compat_ptr(buf.ptr), |
1079 | &buf_user->length); | 1058 | &buf_user->length); |
1080 | break; | 1059 | break; |
@@ -1089,13 +1068,13 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, | |||
1089 | if (copy_from_user(&buf, argp, sizeof(buf))) | 1068 | if (copy_from_user(&buf, argp, sizeof(buf))) |
1090 | ret = -EFAULT; | 1069 | ret = -EFAULT; |
1091 | else | 1070 | else |
1092 | ret = mtd_do_readoob(file, mtd, buf.start, | 1071 | ret = mtdchar_readoob(file, mtd, buf.start, |
1093 | buf.length, compat_ptr(buf.ptr), | 1072 | buf.length, compat_ptr(buf.ptr), |
1094 | &buf_user->start); | 1073 | &buf_user->start); |
1095 | break; | 1074 | break; |
1096 | } | 1075 | } |
1097 | default: | 1076 | default: |
1098 | ret = mtd_ioctl(file, cmd, (unsigned long)argp); | 1077 | ret = mtdchar_ioctl(file, cmd, (unsigned long)argp); |
1099 | } | 1078 | } |
1100 | 1079 | ||
1101 | mutex_unlock(&mtd_mutex); | 1080 | mutex_unlock(&mtd_mutex); |
@@ -1111,7 +1090,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, | |||
1111 | * mappings) | 1090 | * mappings) |
1112 | */ | 1091 | */ |
1113 | #ifndef CONFIG_MMU | 1092 | #ifndef CONFIG_MMU |
1114 | static unsigned long mtd_get_unmapped_area(struct file *file, | 1093 | static unsigned long mtdchar_get_unmapped_area(struct file *file, |
1115 | unsigned long addr, | 1094 | unsigned long addr, |
1116 | unsigned long len, | 1095 | unsigned long len, |
1117 | unsigned long pgoff, | 1096 | unsigned long pgoff, |
@@ -1119,32 +1098,28 @@ static unsigned long mtd_get_unmapped_area(struct file *file, | |||
1119 | { | 1098 | { |
1120 | struct mtd_file_info *mfi = file->private_data; | 1099 | struct mtd_file_info *mfi = file->private_data; |
1121 | struct mtd_info *mtd = mfi->mtd; | 1100 | struct mtd_info *mtd = mfi->mtd; |
1101 | unsigned long offset; | ||
1102 | int ret; | ||
1122 | 1103 | ||
1123 | if (mtd->get_unmapped_area) { | 1104 | if (addr != 0) |
1124 | unsigned long offset; | 1105 | return (unsigned long) -EINVAL; |
1125 | |||
1126 | if (addr != 0) | ||
1127 | return (unsigned long) -EINVAL; | ||
1128 | |||
1129 | if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT)) | ||
1130 | return (unsigned long) -EINVAL; | ||
1131 | 1106 | ||
1132 | offset = pgoff << PAGE_SHIFT; | 1107 | if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT)) |
1133 | if (offset > mtd->size - len) | 1108 | return (unsigned long) -EINVAL; |
1134 | return (unsigned long) -EINVAL; | ||
1135 | 1109 | ||
1136 | return mtd->get_unmapped_area(mtd, len, offset, flags); | 1110 | offset = pgoff << PAGE_SHIFT; |
1137 | } | 1111 | if (offset > mtd->size - len) |
1112 | return (unsigned long) -EINVAL; | ||
1138 | 1113 | ||
1139 | /* can't map directly */ | 1114 | ret = mtd_get_unmapped_area(mtd, len, offset, flags); |
1140 | return (unsigned long) -ENOSYS; | 1115 | return ret == -EOPNOTSUPP ? -ENOSYS : ret; |
1141 | } | 1116 | } |
1142 | #endif | 1117 | #endif |
1143 | 1118 | ||
1144 | /* | 1119 | /* |
1145 | * set up a mapping for shared memory segments | 1120 | * set up a mapping for shared memory segments |
1146 | */ | 1121 | */ |
1147 | static int mtd_mmap(struct file *file, struct vm_area_struct *vma) | 1122 | static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma) |
1148 | { | 1123 | { |
1149 | #ifdef CONFIG_MMU | 1124 | #ifdef CONFIG_MMU |
1150 | struct mtd_file_info *mfi = file->private_data; | 1125 | struct mtd_file_info *mfi = file->private_data; |
@@ -1185,18 +1160,18 @@ static int mtd_mmap(struct file *file, struct vm_area_struct *vma) | |||
1185 | 1160 | ||
1186 | static const struct file_operations mtd_fops = { | 1161 | static const struct file_operations mtd_fops = { |
1187 | .owner = THIS_MODULE, | 1162 | .owner = THIS_MODULE, |
1188 | .llseek = mtd_lseek, | 1163 | .llseek = mtdchar_lseek, |
1189 | .read = mtd_read, | 1164 | .read = mtdchar_read, |
1190 | .write = mtd_write, | 1165 | .write = mtdchar_write, |
1191 | .unlocked_ioctl = mtd_unlocked_ioctl, | 1166 | .unlocked_ioctl = mtdchar_unlocked_ioctl, |
1192 | #ifdef CONFIG_COMPAT | 1167 | #ifdef CONFIG_COMPAT |
1193 | .compat_ioctl = mtd_compat_ioctl, | 1168 | .compat_ioctl = mtdchar_compat_ioctl, |
1194 | #endif | 1169 | #endif |
1195 | .open = mtd_open, | 1170 | .open = mtdchar_open, |
1196 | .release = mtd_close, | 1171 | .release = mtdchar_close, |
1197 | .mmap = mtd_mmap, | 1172 | .mmap = mtdchar_mmap, |
1198 | #ifndef CONFIG_MMU | 1173 | #ifndef CONFIG_MMU |
1199 | .get_unmapped_area = mtd_get_unmapped_area, | 1174 | .get_unmapped_area = mtdchar_get_unmapped_area, |
1200 | #endif | 1175 | #endif |
1201 | }; | 1176 | }; |
1202 | 1177 | ||