aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/mtdchar.c')
-rw-r--r--drivers/mtd/mtdchar.c203
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
54static loff_t mtd_lseek (struct file *file, loff_t offset, int orig) 54static 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
80static int mtd_open(struct inode *inode, struct file *file) 80static 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)
142out: 142out:
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
149static int mtd_close(struct inode *inode, struct file *file) 149static 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
187static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t *ppos) 187static 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
270static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count,loff_t *ppos) 273static 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)
361static int otp_select_filemode(struct mtd_file_info *mfi, int mode) 362static 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
390static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, 393static 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
439static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, 442static 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
533static int mtd_blkpg_ioctl(struct mtd_info *mtd, 531static 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
569static int mtd_write_ioctl(struct mtd_info *mtd, 567static 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
618static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) 616static 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
1036static long mtd_unlocked_ioctl(struct file *file, u_int cmd, u_long arg) 1015static 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
1058static long mtd_compat_ioctl(struct file *file, unsigned int cmd, 1037static 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
1114static unsigned long mtd_get_unmapped_area(struct file *file, 1093static 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 */
1147static int mtd_mmap(struct file *file, struct vm_area_struct *vma) 1122static 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
1186static const struct file_operations mtd_fops = { 1161static 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