Lines Matching +full:master +full:- +full:stats

1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
16 #include <linux/backing-dev.h>
41 struct mtd_file_info *mfi = file->private_data; in mtdchar_lseek()
42 return fixed_size_llseek(file, offset, orig, mfi->mtd->size); in mtdchar_lseek()
56 if ((file->f_mode & FMODE_WRITE) && (minor & 1)) in mtdchar_open()
57 return -EACCES; in mtdchar_open()
64 if (mtd->type == MTD_ABSENT) { in mtdchar_open()
65 ret = -ENODEV; in mtdchar_open()
70 if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { in mtdchar_open()
71 ret = -EACCES; in mtdchar_open()
77 ret = -ENOMEM; in mtdchar_open()
80 mfi->mtd = mtd; in mtdchar_open()
81 file->private_data = mfi; in mtdchar_open()
93 struct mtd_file_info *mfi = file->private_data; in mtdchar_close()
94 struct mtd_info *mtd = mfi->mtd; in mtdchar_close()
99 if ((file->f_mode & FMODE_WRITE)) in mtdchar_close()
103 file->private_data = NULL; in mtdchar_close()
115 * allocation failures when the system is under low-memory situations
119 * A more complex but more memory-efficient implementation based on
121 * longer-term goal, as intimated by dwmw2 above. However, for the
130 struct mtd_file_info *mfi = file->private_data; in mtdchar_read()
131 struct mtd_info *mtd = mfi->mtd; in mtdchar_read()
141 if (*ppos + count > mtd->size) { in mtdchar_read()
142 if (*ppos < mtd->size) in mtdchar_read()
143 count = mtd->size - *ppos; in mtdchar_read()
153 return -ENOMEM; in mtdchar_read()
158 switch (mfi->mode) { in mtdchar_read()
183 /* Nand returns -EBADMSG on ECC errors, but it returns in mtdchar_read()
186 * For kernel internal usage it also might return -EUCLEAN in mtdchar_read()
196 return -EFAULT; in mtdchar_read()
201 count -= retlen; in mtdchar_read()
220 struct mtd_file_info *mfi = file->private_data; in mtdchar_write()
221 struct mtd_info *mtd = mfi->mtd; in mtdchar_write()
231 if (*ppos >= mtd->size) in mtdchar_write()
232 return -ENOSPC; in mtdchar_write()
234 if (*ppos + count > mtd->size) in mtdchar_write()
235 count = mtd->size - *ppos; in mtdchar_write()
242 return -ENOMEM; in mtdchar_write()
249 return -EFAULT; in mtdchar_write()
252 switch (mfi->mode) { in mtdchar_write()
254 ret = -EROFS; in mtdchar_write()
281 * Return -ENOSPC only if no data could be written at all. in mtdchar_write()
285 if ((ret == -ENOSPC) && (total_retlen)) in mtdchar_write()
291 count -= retlen; in mtdchar_write()
312 struct mtd_info *mtd = mfi->mtd; in otp_select_filemode()
317 if (mtd_read_fact_prot_reg(mtd, -1, 0, &retlen, NULL) == in otp_select_filemode()
318 -EOPNOTSUPP) in otp_select_filemode()
319 return -EOPNOTSUPP; in otp_select_filemode()
321 mfi->mode = MTD_FILE_MODE_OTP_FACTORY; in otp_select_filemode()
324 if (mtd_read_user_prot_reg(mtd, -1, 0, &retlen, NULL) == in otp_select_filemode()
325 -EOPNOTSUPP) in otp_select_filemode()
326 return -EOPNOTSUPP; in otp_select_filemode()
328 mfi->mode = MTD_FILE_MODE_OTP_USER; in otp_select_filemode()
331 mfi->mode = MTD_FILE_MODE_NORMAL; in otp_select_filemode()
334 return -EINVAL; in otp_select_filemode()
344 struct mtd_info *master = mtd_get_master(mtd); in mtdchar_writeoob() local
345 struct mtd_file_info *mfi = file->private_data; in mtdchar_writeoob()
351 return -EINVAL; in mtdchar_writeoob()
353 if (!master->_write_oob) in mtdchar_writeoob()
354 return -EOPNOTSUPP; in mtdchar_writeoob()
357 ops.ooboffs = start & (mtd->writesize - 1); in mtdchar_writeoob()
359 ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW : in mtdchar_writeoob()
362 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) in mtdchar_writeoob()
363 return -EINVAL; in mtdchar_writeoob()
369 start &= ~((uint64_t)mtd->writesize - 1); in mtdchar_writeoob()
373 ret = -EOVERFLOW; in mtdchar_writeoob()
376 ret = -EFAULT; in mtdchar_writeoob()
386 struct mtd_file_info *mfi = file->private_data; in mtdchar_readoob()
391 return -EINVAL; in mtdchar_readoob()
394 ops.ooboffs = start & (mtd->writesize - 1); in mtdchar_readoob()
396 ops.mode = (mfi->mode == MTD_FILE_MODE_RAW) ? MTD_OPS_RAW : in mtdchar_readoob()
399 if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) in mtdchar_readoob()
400 return -EINVAL; in mtdchar_readoob()
404 return -ENOMEM; in mtdchar_readoob()
406 start &= ~((uint64_t)mtd->writesize - 1); in mtdchar_readoob()
410 ret = -EFAULT; in mtdchar_readoob()
413 ret = -EFAULT; in mtdchar_readoob()
418 * NAND returns -EBADMSG on ECC errors, but it returns the OOB in mtdchar_readoob()
421 * For kernel internal usage it also might return -EUCLEAN in mtdchar_readoob()
450 return -EINVAL; in shrink_ecclayout()
454 to->eccbytes = 0; in shrink_ecclayout()
460 if (ret != -ERANGE) in shrink_ecclayout()
469 to->eccpos[i] = eccpos++; in shrink_ecclayout()
470 to->eccbytes++; in shrink_ecclayout()
477 if (ret != -ERANGE) in shrink_ecclayout()
483 to->oobfree[i].offset = oobregion.offset; in shrink_ecclayout()
484 to->oobfree[i].length = oobregion.length; in shrink_ecclayout()
485 to->oobavail += to->oobfree[i].length; in shrink_ecclayout()
497 return -EINVAL; in get_oobinfo()
501 to->eccbytes = 0; in get_oobinfo()
502 for (i = 0; i < ARRAY_SIZE(to->eccpos);) { in get_oobinfo()
507 if (ret != -ERANGE) in get_oobinfo()
513 if (oobregion.length + i > ARRAY_SIZE(to->eccpos)) in get_oobinfo()
514 return -EINVAL; in get_oobinfo()
518 to->eccpos[i] = eccpos++; in get_oobinfo()
519 to->eccbytes++; in get_oobinfo()
526 if (ret != -ERANGE) in get_oobinfo()
532 to->oobfree[i][0] = oobregion.offset; in get_oobinfo()
533 to->oobfree[i][1] = oobregion.length; in get_oobinfo()
536 to->useecc = MTD_NANDECC_AUTOPLACE; in get_oobinfo()
547 return -EPERM; in mtdchar_blkpg_ioctl()
549 if (copy_from_user(&p, arg->data, sizeof(p))) in mtdchar_blkpg_ioctl()
550 return -EFAULT; in mtdchar_blkpg_ioctl()
552 switch (arg->op) { in mtdchar_blkpg_ioctl()
555 /* Only master mtd device must be used to add partitions */ in mtdchar_blkpg_ioctl()
557 return -EINVAL; in mtdchar_blkpg_ioctl()
560 p.devname[BLKPG_DEVNAMELTH - 1] = '\0'; in mtdchar_blkpg_ioctl()
567 return -EINVAL; in mtdchar_blkpg_ioctl()
572 return -EINVAL; in mtdchar_blkpg_ioctl()
582 if (ops->len == 0 || ops->ooblen == 0) in adjust_oob_length()
586 end_page = mtd_div_by_ws(start + ops->len - 1, mtd); in adjust_oob_length()
589 ops->ooblen = min_t(size_t, ops->ooblen, in adjust_oob_length()
590 (end_page - start_page + 1) * oob_per_page); in adjust_oob_length()
596 struct mtd_info *master = mtd_get_master(mtd); in mtdchar_write_ioctl() local
604 return -EFAULT; in mtdchar_write_ioctl()
609 if (!master->_write_oob) in mtdchar_write_ioctl()
610 return -EOPNOTSUPP; in mtdchar_write_ioctl()
621 if (req.start + req.len > mtd->size) in mtdchar_write_ioctl()
622 return -EINVAL; in mtdchar_write_ioctl()
624 datbuf_len = min_t(size_t, req.len, mtd->erasesize); in mtdchar_write_ioctl()
628 return -ENOMEM; in mtdchar_write_ioctl()
631 oobbuf_len = min_t(size_t, req.ooblen, mtd->erasesize); in mtdchar_write_ioctl()
636 return -ENOMEM; in mtdchar_write_ioctl()
650 * Shorten non-page-aligned, eraseblock-sized writes so that in mtdchar_write_ioctl()
652 * for adjust_oob_length() to properly handle non-page-aligned in mtdchar_write_ioctl()
655 if (ops.len == mtd->erasesize) in mtdchar_write_ioctl()
656 ops.len -= mtd_mod_by_ws(req.start + ops.len, mtd); in mtdchar_write_ioctl()
659 * For writes which are not OOB-only, adjust the amount of OOB in mtdchar_write_ioctl()
669 ret = -EFAULT; in mtdchar_write_ioctl()
678 req.len -= ops.retlen; in mtdchar_write_ioctl()
681 req.ooblen -= ops.oobretlen; in mtdchar_write_ioctl()
694 struct mtd_info *master = mtd_get_master(mtd); in mtdchar_read_ioctl() local
703 return -EFAULT; in mtdchar_read_ioctl()
711 if (!master->_read_oob) in mtdchar_read_ioctl()
712 return -EOPNOTSUPP; in mtdchar_read_ioctl()
727 if (req.start + req.len > mtd->size) { in mtdchar_read_ioctl()
728 ret = -EINVAL; in mtdchar_read_ioctl()
732 datbuf_len = min_t(size_t, req.len, mtd->erasesize); in mtdchar_read_ioctl()
736 ret = -ENOMEM; in mtdchar_read_ioctl()
741 oobbuf_len = min_t(size_t, req.ooblen, mtd->erasesize); in mtdchar_read_ioctl()
745 ret = -ENOMEM; in mtdchar_read_ioctl()
751 struct mtd_req_stats stats; in mtdchar_read_ioctl() local
758 .stats = &stats, in mtdchar_read_ioctl()
762 * Shorten non-page-aligned, eraseblock-sized reads so that the in mtdchar_read_ioctl()
765 * duplicated in the output of non-page-aligned reads requiring in mtdchar_read_ioctl()
768 if (ops.len == mtd->erasesize) in mtdchar_read_ioctl()
769 ops.len -= mtd_mod_by_ws(req.start + ops.len, mtd); in mtdchar_read_ioctl()
774 stats.uncorrectable_errors; in mtdchar_read_ioctl()
775 req.ecc_stats.corrected_bitflips += stats.corrected_bitflips; in mtdchar_read_ioctl()
777 max(req.ecc_stats.max_bitflips, stats.max_bitflips); in mtdchar_read_ioctl()
784 ret = -EFAULT; in mtdchar_read_ioctl()
789 req.len -= ops.retlen; in mtdchar_read_ioctl()
792 req.ooblen -= ops.oobretlen; in mtdchar_read_ioctl()
804 ret = -EBADMSG; in mtdchar_read_ioctl()
806 ret = -EUCLEAN; in mtdchar_read_ioctl()
810 req.len = orig_len - req.len; in mtdchar_read_ioctl()
811 req.ooblen = orig_ooblen - req.ooblen; in mtdchar_read_ioctl()
814 ret = -EFAULT; in mtdchar_read_ioctl()
824 struct mtd_file_info *mfi = file->private_data; in mtdchar_ioctl()
825 struct mtd_info *mtd = mfi->mtd; in mtdchar_ioctl()
826 struct mtd_info *master = mtd_get_master(mtd); in mtdchar_ioctl() local
869 if (!(file->f_mode & FMODE_WRITE)) in mtdchar_ioctl()
870 return -EPERM; in mtdchar_ioctl()
874 return -ENOTTY; in mtdchar_ioctl()
879 if (copy_to_user(argp, &(mtd->numeraseregions), sizeof(int))) in mtdchar_ioctl()
880 return -EFAULT; in mtdchar_ioctl()
889 if (get_user(ur_idx, &(ur->regionindex))) in mtdchar_ioctl()
890 return -EFAULT; in mtdchar_ioctl()
892 if (ur_idx >= mtd->numeraseregions) in mtdchar_ioctl()
893 return -EINVAL; in mtdchar_ioctl()
895 kr = &(mtd->eraseregions[ur_idx]); in mtdchar_ioctl()
897 if (put_user(kr->offset, &(ur->offset)) in mtdchar_ioctl()
898 || put_user(kr->erasesize, &(ur->erasesize)) in mtdchar_ioctl()
899 || put_user(kr->numblocks, &(ur->numblocks))) in mtdchar_ioctl()
900 return -EFAULT; in mtdchar_ioctl()
907 info.type = mtd->type; in mtdchar_ioctl()
908 info.flags = mtd->flags; in mtdchar_ioctl()
909 info.size = mtd->size; in mtdchar_ioctl()
910 info.erasesize = mtd->erasesize; in mtdchar_ioctl()
911 info.writesize = mtd->writesize; in mtdchar_ioctl()
912 info.oobsize = mtd->oobsize; in mtdchar_ioctl()
916 return -EFAULT; in mtdchar_ioctl()
926 ret = -ENOMEM; in mtdchar_ioctl()
934 return -EFAULT; in mtdchar_ioctl()
936 erase->addr = einfo64.start; in mtdchar_ioctl()
937 erase->len = einfo64.length; in mtdchar_ioctl()
944 return -EFAULT; in mtdchar_ioctl()
946 erase->addr = einfo32.start; in mtdchar_ioctl()
947 erase->len = einfo32.length; in mtdchar_ioctl()
961 /* NOTE: writes return length to buf_user->length */ in mtdchar_ioctl()
963 ret = -EFAULT; in mtdchar_ioctl()
966 buf.ptr, &buf_user->length); in mtdchar_ioctl()
975 /* NOTE: writes return length to buf_user->start */ in mtdchar_ioctl()
977 ret = -EFAULT; in mtdchar_ioctl()
980 buf.ptr, &buf_user->start); in mtdchar_ioctl()
990 ret = -EFAULT; in mtdchar_ioctl()
994 &buf_user->length); in mtdchar_ioctl()
1004 ret = -EFAULT; in mtdchar_ioctl()
1008 &buf_user->length); in mtdchar_ioctl()
1031 return -EFAULT; in mtdchar_ioctl()
1042 return -EFAULT; in mtdchar_ioctl()
1053 return -EFAULT; in mtdchar_ioctl()
1064 if (!master->ooblayout) in mtdchar_ioctl()
1065 return -EOPNOTSUPP; in mtdchar_ioctl()
1072 return -EFAULT; in mtdchar_ioctl()
1081 return -EFAULT; in mtdchar_ioctl()
1090 return -EFAULT; in mtdchar_ioctl()
1098 return -EFAULT; in mtdchar_ioctl()
1100 mfi->mode = MTD_FILE_MODE_NORMAL; in mtdchar_ioctl()
1104 file->f_pos = 0; in mtdchar_ioctl()
1114 return -ENOMEM; in mtdchar_ioctl()
1115 switch (mfi->mode) { in mtdchar_ioctl()
1123 ret = -EINVAL; in mtdchar_ioctl()
1133 ret = -EFAULT; in mtdchar_ioctl()
1144 if (mfi->mode != MTD_FILE_MODE_OTP_USER) in mtdchar_ioctl()
1145 return -EINVAL; in mtdchar_ioctl()
1147 return -EFAULT; in mtdchar_ioctl()
1155 /* This ioctl is being deprecated - it truncates the ECC layout */ in mtdchar_ioctl()
1160 if (!master->ooblayout) in mtdchar_ioctl()
1161 return -EOPNOTSUPP; in mtdchar_ioctl()
1165 return -ENOMEM; in mtdchar_ioctl()
1170 ret = -EFAULT; in mtdchar_ioctl()
1177 if (copy_to_user(argp, &mtd->ecc_stats, in mtdchar_ioctl()
1179 return -EFAULT; in mtdchar_ioctl()
1185 mfi->mode = 0; in mtdchar_ioctl()
1195 return -EOPNOTSUPP; in mtdchar_ioctl()
1196 mfi->mode = arg; in mtdchar_ioctl()
1202 ret = -EINVAL; in mtdchar_ioctl()
1204 file->f_pos = 0; in mtdchar_ioctl()
1214 ret = -EFAULT; in mtdchar_ioctl()
1233 struct mtd_file_info *mfi = file->private_data; in mtdchar_unlocked_ioctl()
1234 struct mtd_info *mtd = mfi->mtd; in mtdchar_unlocked_ioctl()
1235 struct mtd_info *master = mtd_get_master(mtd); in mtdchar_unlocked_ioctl() local
1238 mutex_lock(&master->master.chrdev_lock); in mtdchar_unlocked_ioctl()
1240 mutex_unlock(&master->master.chrdev_lock); in mtdchar_unlocked_ioctl()
1259 struct mtd_file_info *mfi = file->private_data; in mtdchar_compat_ioctl()
1260 struct mtd_info *mtd = mfi->mtd; in mtdchar_compat_ioctl()
1261 struct mtd_info *master = mtd_get_master(mtd); in mtdchar_compat_ioctl() local
1265 mutex_lock(&master->master.chrdev_lock); in mtdchar_compat_ioctl()
1273 if (!(file->f_mode & FMODE_WRITE)) { in mtdchar_compat_ioctl()
1274 ret = -EPERM; in mtdchar_compat_ioctl()
1279 ret = -EFAULT; in mtdchar_compat_ioctl()
1283 &buf_user->length); in mtdchar_compat_ioctl()
1292 /* NOTE: writes return length to buf->start */ in mtdchar_compat_ioctl()
1294 ret = -EFAULT; in mtdchar_compat_ioctl()
1298 &buf_user->start); in mtdchar_compat_ioctl()
1310 ret = -EFAULT; in mtdchar_compat_ioctl()
1328 mutex_unlock(&master->master.chrdev_lock); in mtdchar_compat_ioctl()
1337 * - only supported for NOMMU at the moment (MMU can't doesn't copy private
1347 struct mtd_file_info *mfi = file->private_data; in mtdchar_get_unmapped_area()
1348 struct mtd_info *mtd = mfi->mtd; in mtdchar_get_unmapped_area()
1353 return (unsigned long) -EINVAL; in mtdchar_get_unmapped_area()
1355 if (len > mtd->size || pgoff >= (mtd->size >> PAGE_SHIFT)) in mtdchar_get_unmapped_area()
1356 return (unsigned long) -EINVAL; in mtdchar_get_unmapped_area()
1359 if (offset > mtd->size - len) in mtdchar_get_unmapped_area()
1360 return (unsigned long) -EINVAL; in mtdchar_get_unmapped_area()
1363 return ret == -EOPNOTSUPP ? -ENODEV : ret; in mtdchar_get_unmapped_area()
1368 struct mtd_file_info *mfi = file->private_data; in mtdchar_mmap_capabilities()
1370 return mtd_mmap_capabilities(mfi->mtd); in mtdchar_mmap_capabilities()
1380 struct mtd_file_info *mfi = file->private_data; in mtdchar_mmap()
1381 struct mtd_info *mtd = mfi->mtd; in mtdchar_mmap()
1382 struct map_info *map = mtd->priv; in mtdchar_mmap()
1384 /* This is broken because it assumes the MTD device is map-based in mtdchar_mmap()
1385 and that mtd->priv is a valid struct map_info. It should be in mtdchar_mmap()
1388 if (0 /*mtd->type == MTD_RAM || mtd->type == MTD_ROM*/) { in mtdchar_mmap()
1390 if (file->f_flags & O_DSYNC || map->phys >= __pa(high_memory)) in mtdchar_mmap()
1391 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); in mtdchar_mmap()
1393 return vm_iomap_memory(vma, map->phys, map->size); in mtdchar_mmap()
1395 return -ENODEV; in mtdchar_mmap()
1397 return vma->vm_flags & VM_SHARED ? 0 : -EACCES; in mtdchar_mmap()