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

1 // SPDX-License-Identifier: GPL-2.0-or-later
6 * Copyright © 1999-2010 David Woodhouse <dwmw2@infradead.org>
24 #include <linux/backing-dev.h>
31 #include <linux/nvmem-provider.h>
33 #include <linux/error-injection.h>
95 dev_t index = MTD_DEVT(mtd->index); in mtd_release()
97 idr_remove(&mtd_idr, mtd->index); in mtd_release()
112 debugfs_remove_recursive(mtd->dbg.dfs_dir); in mtd_device_release()
115 nvmem_unregister(mtd->nvmem); in mtd_device_release()
117 device_unregister(&mtd->dev); in mtd_device_release()
120 * Clear dev so mtd can be safely re-registered later if desired. in mtd_device_release()
125 memset(&mtd->dev, 0, sizeof(mtd->dev)); in mtd_device_release()
142 switch (mtd->type) { in mtd_type_show()
165 type = "mlc-nand"; in mtd_type_show()
180 return sysfs_emit(buf, "0x%lx\n", (unsigned long)mtd->flags); in mtd_flags_show()
189 return sysfs_emit(buf, "%llu\n", (unsigned long long)mtd->size); in mtd_size_show()
198 return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->erasesize); in mtd_erasesize_show()
207 return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->writesize); in mtd_writesize_show()
215 unsigned int subpagesize = mtd->writesize >> mtd->subpage_sft; in mtd_subpagesize_show()
226 return sysfs_emit(buf, "%lu\n", (unsigned long)mtd->oobsize); in mtd_oobsize_show()
235 return sysfs_emit(buf, "%u\n", mtd->oobavail); in mtd_oobavail_show()
244 return sysfs_emit(buf, "%u\n", mtd->numeraseregions); in mtd_numeraseregions_show()
253 return sysfs_emit(buf, "%s\n", mtd->name); in mtd_name_show()
262 return sysfs_emit(buf, "%u\n", mtd->ecc_strength); in mtd_ecc_strength_show()
272 return sysfs_emit(buf, "%u\n", mtd->bitflip_threshold); in mtd_bitflip_threshold_show()
287 mtd->bitflip_threshold = bitflip_threshold; in mtd_bitflip_threshold_store()
297 return sysfs_emit(buf, "%u\n", mtd->ecc_step_size); in mtd_ecc_step_size_show()
306 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_corrected_bits_show()
308 return sysfs_emit(buf, "%u\n", ecc_stats->corrected); in mtd_corrected_bits_show()
310 MTD_DEVICE_ATTR_RO(corrected_bits); /* ecc stats corrected */
316 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_ecc_failures_show()
318 return sysfs_emit(buf, "%u\n", ecc_stats->failed); in mtd_ecc_failures_show()
320 MTD_DEVICE_ATTR_RO(ecc_failures); /* ecc stats errors */
326 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_bad_blocks_show()
328 return sysfs_emit(buf, "%u\n", ecc_stats->badblocks); in mtd_bad_blocks_show()
336 struct mtd_ecc_stats *ecc_stats = &mtd->ecc_stats; in mtd_bbt_blocks_show()
338 return sysfs_emit(buf, "%u\n", ecc_stats->bbtblocks); in mtd_bbt_blocks_show()
377 "This is only reserved for post-mortem forensics and debug purposes.\n" in mtd_check_expert_analysis_mode()
389 struct device *dev = &mtd->dev; in mtd_debugfs_populate()
394 mtd->dbg.dfs_dir = debugfs_create_dir(dev_name(dev), dfs_dir_mtd); in mtd_debugfs_populate()
400 switch (mtd->type) { in mtd_mmap_capabilities()
420 mtd->_reboot(mtd); in mtd_reboot_notifier()
426 * mtd_wunit_to_pairing_info - get pairing information of a wunit
435 * The notion of page is replaced by the term wunit (write-unit) to stay
436 * consistent with the ->writesize field.
454 struct mtd_info *master = mtd_get_master(mtd); in mtd_wunit_to_pairing_info() local
455 int npairs = mtd_wunit_per_eb(master) / mtd_pairing_groups(master); in mtd_wunit_to_pairing_info()
458 return -EINVAL; in mtd_wunit_to_pairing_info()
460 if (master->pairing && master->pairing->get_info) in mtd_wunit_to_pairing_info()
461 return master->pairing->get_info(master, wunit, info); in mtd_wunit_to_pairing_info()
463 info->group = 0; in mtd_wunit_to_pairing_info()
464 info->pair = wunit; in mtd_wunit_to_pairing_info()
471 * mtd_pairing_info_to_wunit - get wunit from pairing information
484 * software-emulated SLC mode:
491 * mtd->writesize, &retlen, buf + (i * mtd->writesize));
497 struct mtd_info *master = mtd_get_master(mtd); in mtd_pairing_info_to_wunit() local
498 int ngroups = mtd_pairing_groups(master); in mtd_pairing_info_to_wunit()
499 int npairs = mtd_wunit_per_eb(master) / ngroups; in mtd_pairing_info_to_wunit()
501 if (!info || info->pair < 0 || info->pair >= npairs || in mtd_pairing_info_to_wunit()
502 info->group < 0 || info->group >= ngroups) in mtd_pairing_info_to_wunit()
503 return -EINVAL; in mtd_pairing_info_to_wunit()
505 if (master->pairing && master->pairing->get_wunit) in mtd_pairing_info_to_wunit()
506 return mtd->pairing->get_wunit(master, info); in mtd_pairing_info_to_wunit()
508 return info->pair; in mtd_pairing_info_to_wunit()
513 * mtd_pairing_groups - get the number of pairing groups
524 struct mtd_info *master = mtd_get_master(mtd); in mtd_pairing_groups() local
526 if (!master->pairing || !master->pairing->ngroups) in mtd_pairing_groups()
529 return master->pairing->ngroups; in mtd_pairing_groups()
541 if (err && err != -EUCLEAN) in mtd_nvmem_reg_read()
544 return retlen == bytes ? 0 : -EIO; in mtd_nvmem_reg_read()
553 config.dev = &mtd->dev; in mtd_nvmem_add()
554 config.name = dev_name(&mtd->dev); in mtd_nvmem_add()
556 config.add_legacy_fixed_of_cells = of_device_is_compatible(node, "nvmem-cells"); in mtd_nvmem_add()
558 config.size = mtd->size; in mtd_nvmem_add()
566 mtd->nvmem = nvmem_register(&config); in mtd_nvmem_add()
567 if (IS_ERR(mtd->nvmem)) { in mtd_nvmem_add()
569 if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) in mtd_nvmem_add()
570 mtd->nvmem = NULL; in mtd_nvmem_add()
572 return dev_err_probe(&mtd->dev, PTR_ERR(mtd->nvmem), in mtd_nvmem_add()
582 const char *pname, *prefix = "partition-"; in mtd_check_of_node()
592 parent_dn = of_node_get(mtd_get_of_node(mtd->parent)); in mtd_check_of_node()
596 if (mtd_is_partition(mtd->parent)) in mtd_check_of_node()
604 mtd_name_len = strlen(mtd->name); in mtd_check_of_node()
616 pname = mtd_dn->name; in mtd_check_of_node()
620 plen = strlen(pname) - offset; in mtd_check_of_node()
622 !strncmp(mtd->name, pname + offset, plen)) { in mtd_check_of_node()
635 * add_mtd_device - register an MTD device
640 * zero on success or non-zero on failure.
646 struct mtd_info *master = mtd_get_master(mtd); in add_mtd_device() local
652 * mtd_device_parse_register() multiple times on the same master MTD, in add_mtd_device()
655 if (WARN_ONCE(mtd->dev.type, "MTD already registered\n")) in add_mtd_device()
656 return -EEXIST; in add_mtd_device()
658 BUG_ON(mtd->writesize == 0); in add_mtd_device()
661 * MTD drivers should implement ->_{write,read}() or in add_mtd_device()
662 * ->_{write,read}_oob(), but not both. in add_mtd_device()
664 if (WARN_ON((mtd->_write && mtd->_write_oob) || in add_mtd_device()
665 (mtd->_read && mtd->_read_oob))) in add_mtd_device()
666 return -EINVAL; in add_mtd_device()
668 if (WARN_ON((!mtd->erasesize || !master->_erase) && in add_mtd_device()
669 !(mtd->flags & MTD_NO_ERASE))) in add_mtd_device()
670 return -EINVAL; in add_mtd_device()
674 * master is an MLC NAND and has a proper pairing scheme defined. in add_mtd_device()
675 * We also reject masters that implement ->_writev() for now, because in add_mtd_device()
677 * SLC -> MLC address/length conversion to this path is useless if we in add_mtd_device()
680 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION && in add_mtd_device()
681 (!mtd_is_partition(mtd) || master->type != MTD_MLCNANDFLASH || in add_mtd_device()
682 !master->pairing || master->_writev)) in add_mtd_device()
683 return -EINVAL; in add_mtd_device()
687 ofidx = -1; in add_mtd_device()
699 mtd->index = i; in add_mtd_device()
700 kref_init(&mtd->refcnt); in add_mtd_device()
703 if (mtd->bitflip_threshold == 0) in add_mtd_device()
704 mtd->bitflip_threshold = mtd->ecc_strength; in add_mtd_device()
706 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in add_mtd_device()
707 int ngroups = mtd_pairing_groups(master); in add_mtd_device()
709 mtd->erasesize /= ngroups; in add_mtd_device()
710 mtd->size = (u64)mtd_div_by_eb(mtd->size, master) * in add_mtd_device()
711 mtd->erasesize; in add_mtd_device()
714 if (is_power_of_2(mtd->erasesize)) in add_mtd_device()
715 mtd->erasesize_shift = ffs(mtd->erasesize) - 1; in add_mtd_device()
717 mtd->erasesize_shift = 0; in add_mtd_device()
719 if (is_power_of_2(mtd->writesize)) in add_mtd_device()
720 mtd->writesize_shift = ffs(mtd->writesize) - 1; in add_mtd_device()
722 mtd->writesize_shift = 0; in add_mtd_device()
724 mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; in add_mtd_device()
725 mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; in add_mtd_device()
728 if ((mtd->flags & MTD_WRITEABLE) && (mtd->flags & MTD_POWERUP_LOCK)) { in add_mtd_device()
729 error = mtd_unlock(mtd, 0, mtd->size); in add_mtd_device()
730 if (error && error != -EOPNOTSUPP) in add_mtd_device()
733 mtd->name); in add_mtd_device()
741 mtd->dev.type = &mtd_devtype; in add_mtd_device()
742 mtd->dev.class = &mtd_class; in add_mtd_device()
743 mtd->dev.devt = MTD_DEVT(i); in add_mtd_device()
744 dev_set_name(&mtd->dev, "mtd%d", i); in add_mtd_device()
745 dev_set_drvdata(&mtd->dev, mtd); in add_mtd_device()
748 error = device_register(&mtd->dev); in add_mtd_device()
750 put_device(&mtd->dev); in add_mtd_device()
761 device_create(&mtd_class, mtd->dev.parent, MTD_DEVT(i) + 1, NULL, in add_mtd_device()
764 pr_debug("mtd: Giving out device %d to %s\n", i, mtd->name); in add_mtd_device()
768 not->add(mtd); in add_mtd_device()
774 pr_info("mtd: setting mtd%d (%s) as root device\n", mtd->index, mtd->name); in add_mtd_device()
775 ROOT_DEV = MKDEV(MTD_BLOCK_MAJOR, mtd->index); in add_mtd_device()
777 pr_warn("mtd: can't set mtd%d (%s) as root device - mtd must be builtin\n", in add_mtd_device()
778 mtd->index, mtd->name); in add_mtd_device()
790 device_unregister(&mtd->dev); in add_mtd_device()
800 * del_mtd_device - unregister an MTD device
816 if (idr_find(&mtd_idr, mtd->index) != mtd) { in del_mtd_device()
817 ret = -ENODEV; in del_mtd_device()
824 not->remove(mtd); in del_mtd_device()
826 kref_put(&mtd->refcnt, mtd_device_release); in del_mtd_device()
840 if (mtd->dev.parent) { in mtd_set_dev_defaults()
841 if (!mtd->owner && mtd->dev.parent->driver) in mtd_set_dev_defaults()
842 mtd->owner = mtd->dev.parent->driver->owner; in mtd_set_dev_defaults()
843 if (!mtd->name) in mtd_set_dev_defaults()
844 mtd->name = dev_name(mtd->dev.parent); in mtd_set_dev_defaults()
849 INIT_LIST_HEAD(&mtd->partitions); in mtd_set_dev_defaults()
850 mutex_init(&mtd->master.partitions_lock); in mtd_set_dev_defaults()
851 mutex_init(&mtd->master.chrdev_lock); in mtd_set_dev_defaults()
864 return -ENOMEM; in mtd_otp_size()
883 return ret == -ENODATA ? 0 : ret; in mtd_otp_size()
896 np = of_get_compatible_child(mtd->dev.of_node, compatible); in mtd_otp_nvmem_register()
899 config.dev = mtd->dev.parent; in mtd_otp_nvmem_register()
914 if (IS_ERR(nvmem) && PTR_ERR(nvmem) == -EOPNOTSUPP) in mtd_otp_nvmem_register()
933 return retlen == bytes ? 0 : -EIO; in mtd_nvmem_user_otp_reg_read()
947 return retlen == bytes ? 0 : -EIO; in mtd_nvmem_fact_otp_reg_read()
952 struct device *dev = mtd->dev.parent; in mtd_otp_nvmem_add()
957 if (mtd->_get_user_prot_info && mtd->_read_user_prot_reg) { in mtd_otp_nvmem_add()
965 nvmem = mtd_otp_nvmem_register(mtd, "user-otp", size, in mtd_otp_nvmem_add()
971 mtd->otp_user_nvmem = nvmem; in mtd_otp_nvmem_add()
975 if (mtd->_get_fact_prot_info && mtd->_read_fact_prot_reg) { in mtd_otp_nvmem_add()
992 err = -ENOMEM; in mtd_otp_nvmem_add()
1003 nvmem = mtd_otp_nvmem_register(mtd, "factory-otp", size, in mtd_otp_nvmem_add()
1009 mtd->otp_factory_nvmem = nvmem; in mtd_otp_nvmem_add()
1016 nvmem_unregister(mtd->otp_user_nvmem); in mtd_otp_nvmem_add()
1018 if (err == -EOPNOTSUPP) in mtd_otp_nvmem_add()
1024 * mtd_device_parse_register - parse partitions and register an MTD device.
1029 * @parser_data: MTD partition parser-specific data
1070 /* Prefer parsed partitions over driver-provided fallback */ in mtd_device_parse_register()
1072 if (ret == -EPROBE_DEFER) in mtd_device_parse_register()
1079 else if (!device_is_registered(&mtd->dev)) in mtd_device_parse_register()
1095 WARN_ONCE(mtd->_reboot && mtd->reboot_notifier.notifier_call, in mtd_device_parse_register()
1097 if (mtd->_reboot && !mtd->reboot_notifier.notifier_call) { in mtd_device_parse_register()
1098 mtd->reboot_notifier.notifier_call = mtd_reboot_notifier; in mtd_device_parse_register()
1099 register_reboot_notifier(&mtd->reboot_notifier); in mtd_device_parse_register()
1104 nvmem_unregister(mtd->otp_user_nvmem); in mtd_device_parse_register()
1105 nvmem_unregister(mtd->otp_factory_nvmem); in mtd_device_parse_register()
1108 if (ret && device_is_registered(&mtd->dev)) in mtd_device_parse_register()
1116 * mtd_device_unregister - unregister an existing MTD device.
1118 * @master: the MTD device to unregister. This will unregister both the master
1121 int mtd_device_unregister(struct mtd_info *master) in mtd_device_unregister() argument
1125 if (master->_reboot) { in mtd_device_unregister()
1126 unregister_reboot_notifier(&master->reboot_notifier); in mtd_device_unregister()
1127 memset(&master->reboot_notifier, 0, sizeof(master->reboot_notifier)); in mtd_device_unregister()
1130 nvmem_unregister(master->otp_user_nvmem); in mtd_device_unregister()
1131 nvmem_unregister(master->otp_factory_nvmem); in mtd_device_unregister()
1133 err = del_mtd_partitions(master); in mtd_device_unregister()
1137 if (!device_is_registered(&master->dev)) in mtd_device_unregister()
1140 return del_mtd_device(master); in mtd_device_unregister()
1145 * register_mtd_user - register a 'user' of MTD devices.
1158 list_add(&new->list, &mtd_notifiers); in register_mtd_user()
1163 new->add(mtd); in register_mtd_user()
1170 * unregister_mtd_user - unregister a 'user' of MTD devices.
1187 old->remove(mtd); in unregister_mtd_user()
1189 list_del(&old->list); in unregister_mtd_user()
1196 * get_mtd_device - obtain a validated handle for an MTD device
1201 * table, if any. Given an address and num == -1, search the device table
1209 int err = -ENODEV; in get_mtd_device()
1213 if (num == -1) { in get_mtd_device()
1243 struct mtd_info *master = mtd_get_master(mtd); in __get_mtd_device() local
1246 if (master->_get_device) { in __get_mtd_device()
1247 err = master->_get_device(mtd); in __get_mtd_device()
1252 if (!try_module_get(master->owner)) { in __get_mtd_device()
1253 if (master->_put_device) in __get_mtd_device()
1254 master->_put_device(master); in __get_mtd_device()
1255 return -ENODEV; in __get_mtd_device()
1259 if (mtd != master) in __get_mtd_device()
1260 kref_get(&mtd->refcnt); in __get_mtd_device()
1261 mtd = mtd->parent; in __get_mtd_device()
1265 kref_get(&master->refcnt); in __get_mtd_device()
1272 * of_get_mtd_device_by_node - obtain an MTD device associated with a given node
1284 err = -EPROBE_DEFER; in of_get_mtd_device_by_node()
1300 * get_mtd_device_nm - obtain a validated handle for an MTD device by
1309 int err = -ENODEV; in get_mtd_device_nm()
1315 if (!strcmp(name, other->name)) { in get_mtd_device_nm()
1348 struct mtd_info *master = mtd_get_master(mtd); in __put_mtd_device() local
1351 /* kref_put() can relese mtd, so keep a reference mtd->parent */ in __put_mtd_device()
1352 struct mtd_info *parent = mtd->parent; in __put_mtd_device()
1354 if (mtd != master) in __put_mtd_device()
1355 kref_put(&mtd->refcnt, mtd_device_release); in __put_mtd_device()
1360 kref_put(&master->refcnt, mtd_device_release); in __put_mtd_device()
1362 module_put(master->owner); in __put_mtd_device()
1364 /* must be the last as master can be freed in the _put_device */ in __put_mtd_device()
1365 if (master->_put_device) in __put_mtd_device()
1366 master->_put_device(master); in __put_mtd_device()
1372 * negative error code if the operation failed and update instr->fail_addr
1377 struct mtd_info *master = mtd_get_master(mtd); in mtd_erase() local
1382 instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; in mtd_erase()
1385 if (!mtd->erasesize || !master->_erase) in mtd_erase()
1386 return -ENOTSUPP; in mtd_erase()
1388 if (instr->addr >= mtd->size || instr->len > mtd->size - instr->addr) in mtd_erase()
1389 return -EINVAL; in mtd_erase()
1390 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_erase()
1391 return -EROFS; in mtd_erase()
1393 if (!instr->len) in mtd_erase()
1398 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_erase()
1399 adjinstr.addr = (loff_t)mtd_div_by_eb(instr->addr, mtd) * in mtd_erase()
1400 master->erasesize; in mtd_erase()
1401 adjinstr.len = ((u64)mtd_div_by_eb(instr->addr + instr->len, mtd) * in mtd_erase()
1402 master->erasesize) - in mtd_erase()
1408 ret = master->_erase(master, &adjinstr); in mtd_erase()
1411 instr->fail_addr = adjinstr.fail_addr - mst_ofs; in mtd_erase()
1412 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_erase()
1413 instr->fail_addr = mtd_div_by_eb(instr->fail_addr, in mtd_erase()
1414 master); in mtd_erase()
1415 instr->fail_addr *= mtd->erasesize; in mtd_erase()
1425 * This stuff for eXecute-In-Place. phys is optional and may be set to NULL.
1430 struct mtd_info *master = mtd_get_master(mtd); in mtd_point() local
1436 if (!master->_point) in mtd_point()
1437 return -EOPNOTSUPP; in mtd_point()
1438 if (from < 0 || from >= mtd->size || len > mtd->size - from) in mtd_point()
1439 return -EINVAL; in mtd_point()
1444 return master->_point(master, from, len, retlen, virt, phys); in mtd_point()
1451 struct mtd_info *master = mtd_get_master(mtd); in mtd_unpoint() local
1453 if (!master->_unpoint) in mtd_unpoint()
1454 return -EOPNOTSUPP; in mtd_unpoint()
1455 if (from < 0 || from >= mtd->size || len > mtd->size - from) in mtd_unpoint()
1456 return -EINVAL; in mtd_unpoint()
1459 return master->_unpoint(master, mtd_get_master_ofs(mtd, from), len); in mtd_unpoint()
1465 * - return the address to which the offset maps
1466 * - return -ENOSYS to indicate refusal to do the mapping
1480 return -ENOSYS; in mtd_get_unmapped_area()
1486 static void mtd_update_ecc_stats(struct mtd_info *mtd, struct mtd_info *master, in mtd_update_ecc_stats() argument
1491 if (master == mtd) in mtd_update_ecc_stats()
1494 diff = master->ecc_stats; in mtd_update_ecc_stats()
1495 diff.failed -= old_stats->failed; in mtd_update_ecc_stats()
1496 diff.corrected -= old_stats->corrected; in mtd_update_ecc_stats()
1498 while (mtd->parent) { in mtd_update_ecc_stats()
1499 mtd->ecc_stats.failed += diff.failed; in mtd_update_ecc_stats()
1500 mtd->ecc_stats.corrected += diff.corrected; in mtd_update_ecc_stats()
1501 mtd = mtd->parent; in mtd_update_ecc_stats()
1551 struct mtd_info *master = mtd_get_master(mtd); in mtd_panic_write() local
1554 if (!master->_panic_write) in mtd_panic_write()
1555 return -EOPNOTSUPP; in mtd_panic_write()
1556 if (to < 0 || to >= mtd->size || len > mtd->size - to) in mtd_panic_write()
1557 return -EINVAL; in mtd_panic_write()
1558 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_panic_write()
1559 return -EROFS; in mtd_panic_write()
1562 if (!master->oops_panic_write) in mtd_panic_write()
1563 master->oops_panic_write = true; in mtd_panic_write()
1565 return master->_panic_write(master, mtd_get_master_ofs(mtd, to), len, in mtd_panic_write()
1574 * Some users are setting ->datbuf or ->oobbuf to NULL, but are leaving in mtd_check_oob_ops()
1575 * ->len or ->ooblen uninitialized. Force ->len and ->ooblen to 0 in in mtd_check_oob_ops()
1578 if (!ops->datbuf) in mtd_check_oob_ops()
1579 ops->len = 0; in mtd_check_oob_ops()
1581 if (!ops->oobbuf) in mtd_check_oob_ops()
1582 ops->ooblen = 0; in mtd_check_oob_ops()
1584 if (offs < 0 || offs + ops->len > mtd->size) in mtd_check_oob_ops()
1585 return -EINVAL; in mtd_check_oob_ops()
1587 if (ops->ooblen) { in mtd_check_oob_ops()
1590 if (ops->ooboffs >= mtd_oobavail(mtd, ops)) in mtd_check_oob_ops()
1591 return -EINVAL; in mtd_check_oob_ops()
1593 maxooblen = ((size_t)(mtd_div_by_ws(mtd->size, mtd) - in mtd_check_oob_ops()
1595 mtd_oobavail(mtd, ops)) - ops->ooboffs; in mtd_check_oob_ops()
1596 if (ops->ooblen > maxooblen) in mtd_check_oob_ops()
1597 return -EINVAL; in mtd_check_oob_ops()
1606 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_oob_std() local
1610 if (master->_read_oob) in mtd_read_oob_std()
1611 ret = master->_read_oob(master, from, ops); in mtd_read_oob_std()
1613 ret = master->_read(master, from, ops->len, &ops->retlen, in mtd_read_oob_std()
1614 ops->datbuf); in mtd_read_oob_std()
1622 struct mtd_info *master = mtd_get_master(mtd); in mtd_write_oob_std() local
1626 if (master->_write_oob) in mtd_write_oob_std()
1627 ret = master->_write_oob(master, to, ops); in mtd_write_oob_std()
1629 ret = master->_write(master, to, ops->len, &ops->retlen, in mtd_write_oob_std()
1630 ops->datbuf); in mtd_write_oob_std()
1638 struct mtd_info *master = mtd_get_master(mtd); in mtd_io_emulated_slc() local
1639 int ngroups = mtd_pairing_groups(master); in mtd_io_emulated_slc()
1640 int npairs = mtd_wunit_per_eb(master) / ngroups; in mtd_io_emulated_slc()
1649 base = (loff_t)mtd_div_by_eb(start, mtd) * master->erasesize; in mtd_io_emulated_slc()
1655 while (ops->retlen < ops->len || ops->oobretlen < ops->ooblen) { in mtd_io_emulated_slc()
1660 base += master->erasesize; in mtd_io_emulated_slc()
1663 wunit = mtd_pairing_info_to_wunit(master, &info); in mtd_io_emulated_slc()
1666 adjops.len = ops->len - ops->retlen; in mtd_io_emulated_slc()
1667 if (adjops.len > mtd->writesize - pageofs) in mtd_io_emulated_slc()
1668 adjops.len = mtd->writesize - pageofs; in mtd_io_emulated_slc()
1670 adjops.ooblen = ops->ooblen - ops->oobretlen; in mtd_io_emulated_slc()
1671 if (adjops.ooblen > oobavail - adjops.ooboffs) in mtd_io_emulated_slc()
1672 adjops.ooblen = oobavail - adjops.ooboffs; in mtd_io_emulated_slc()
1686 ops->retlen += adjops.retlen; in mtd_io_emulated_slc()
1687 ops->oobretlen += adjops.oobretlen; in mtd_io_emulated_slc()
1700 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_oob() local
1701 struct mtd_ecc_stats old_stats = master->ecc_stats; in mtd_read_oob()
1704 ops->retlen = ops->oobretlen = 0; in mtd_read_oob()
1712 /* Check the validity of a potential fallback on mtd->_read */ in mtd_read_oob()
1713 if (!master->_read_oob && (!master->_read || ops->oobbuf)) in mtd_read_oob()
1714 return -EOPNOTSUPP; in mtd_read_oob()
1716 if (ops->stats) in mtd_read_oob()
1717 memset(ops->stats, 0, sizeof(*ops->stats)); in mtd_read_oob()
1719 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_read_oob()
1724 mtd_update_ecc_stats(mtd, master, &old_stats); in mtd_read_oob()
1727 * In cases where ops->datbuf != NULL, mtd->_read_oob() has semantics in mtd_read_oob()
1728 * similar to mtd->_read(), returning a non-negative integer in mtd_read_oob()
1729 * representing max bitflips. In other cases, mtd->_read_oob() may in mtd_read_oob()
1730 * return -EUCLEAN. In all cases, perform similar logic to mtd_read(). in mtd_read_oob()
1734 if (mtd->ecc_strength == 0) in mtd_read_oob()
1736 if (ops->stats) in mtd_read_oob()
1737 ops->stats->max_bitflips = ret_code; in mtd_read_oob()
1738 return ret_code >= mtd->bitflip_threshold ? -EUCLEAN : 0; in mtd_read_oob()
1745 struct mtd_info *master = mtd_get_master(mtd); in mtd_write_oob() local
1748 ops->retlen = ops->oobretlen = 0; in mtd_write_oob()
1750 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_write_oob()
1751 return -EROFS; in mtd_write_oob()
1759 /* Check the validity of a potential fallback on mtd->_write */ in mtd_write_oob()
1760 if (!master->_write_oob && (!master->_write || ops->oobbuf)) in mtd_write_oob()
1761 return -EOPNOTSUPP; in mtd_write_oob()
1763 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_write_oob()
1771 * mtd_ooblayout_ecc - Get the OOB region definition of a specific ECC section
1782 * mtd_ooblayout_ecc(mtd, section++, oobecc) until it returns -ERANGE.
1789 struct mtd_info *master = mtd_get_master(mtd); in mtd_ooblayout_ecc() local
1793 if (!master || section < 0) in mtd_ooblayout_ecc()
1794 return -EINVAL; in mtd_ooblayout_ecc()
1796 if (!master->ooblayout || !master->ooblayout->ecc) in mtd_ooblayout_ecc()
1797 return -ENOTSUPP; in mtd_ooblayout_ecc()
1799 return master->ooblayout->ecc(master, section, oobecc); in mtd_ooblayout_ecc()
1804 * mtd_ooblayout_free - Get the OOB region definition of a specific free
1816 * mtd_ooblayout_free(mtd, section++, oobfree) until it returns -ERANGE.
1823 struct mtd_info *master = mtd_get_master(mtd); in mtd_ooblayout_free() local
1827 if (!master || section < 0) in mtd_ooblayout_free()
1828 return -EINVAL; in mtd_ooblayout_free()
1830 if (!master->ooblayout || !master->ooblayout->free) in mtd_ooblayout_free()
1831 return -ENOTSUPP; in mtd_ooblayout_free()
1833 return master->ooblayout->free(master, section, oobfree); in mtd_ooblayout_free()
1838 * mtd_ooblayout_find_region - Find the region attached to a specific byte
1869 if (pos + oobregion->length > byte) in mtd_ooblayout_find_region()
1872 pos += oobregion->length; in mtd_ooblayout_find_region()
1880 oobregion->offset += byte - pos; in mtd_ooblayout_find_region()
1881 oobregion->length -= byte - pos; in mtd_ooblayout_find_region()
1888 * mtd_ooblayout_find_eccregion - Find the ECC region attached to a specific
1910 * mtd_ooblayout_get_bytes - Extract OOB bytes from the oob buffer
1941 nbytes -= cnt; in mtd_ooblayout_get_bytes()
1953 * mtd_ooblayout_set_bytes - put OOB bytes into the oob buffer
1984 nbytes -= cnt; in mtd_ooblayout_set_bytes()
1996 * mtd_ooblayout_count_bytes - count the number of bytes in a OOB category
2015 if (ret == -ERANGE) in mtd_ooblayout_count_bytes()
2027 * mtd_ooblayout_get_eccbytes - extract ECC bytes from the oob buffer
2047 * mtd_ooblayout_set_eccbytes - set ECC bytes into the oob buffer
2067 * mtd_ooblayout_get_databytes - extract data bytes from the oob buffer
2087 * mtd_ooblayout_set_databytes - set data bytes into the oob buffer
2107 * mtd_ooblayout_count_freebytes - count the number of free bytes in OOB
2121 * mtd_ooblayout_count_eccbytes - count the number of ECC bytes in OOB
2142 struct mtd_info *master = mtd_get_master(mtd); in mtd_get_fact_prot_info() local
2144 if (!master->_get_fact_prot_info) in mtd_get_fact_prot_info()
2145 return -EOPNOTSUPP; in mtd_get_fact_prot_info()
2148 return master->_get_fact_prot_info(master, len, retlen, buf); in mtd_get_fact_prot_info()
2155 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_fact_prot_reg() local
2158 if (!master->_read_fact_prot_reg) in mtd_read_fact_prot_reg()
2159 return -EOPNOTSUPP; in mtd_read_fact_prot_reg()
2162 return master->_read_fact_prot_reg(master, from, len, retlen, buf); in mtd_read_fact_prot_reg()
2169 struct mtd_info *master = mtd_get_master(mtd); in mtd_get_user_prot_info() local
2171 if (!master->_get_user_prot_info) in mtd_get_user_prot_info()
2172 return -EOPNOTSUPP; in mtd_get_user_prot_info()
2175 return master->_get_user_prot_info(master, len, retlen, buf); in mtd_get_user_prot_info()
2182 struct mtd_info *master = mtd_get_master(mtd); in mtd_read_user_prot_reg() local
2185 if (!master->_read_user_prot_reg) in mtd_read_user_prot_reg()
2186 return -EOPNOTSUPP; in mtd_read_user_prot_reg()
2189 return master->_read_user_prot_reg(master, from, len, retlen, buf); in mtd_read_user_prot_reg()
2196 struct mtd_info *master = mtd_get_master(mtd); in mtd_write_user_prot_reg() local
2200 if (!master->_write_user_prot_reg) in mtd_write_user_prot_reg()
2201 return -EOPNOTSUPP; in mtd_write_user_prot_reg()
2204 ret = master->_write_user_prot_reg(master, to, len, retlen, buf); in mtd_write_user_prot_reg()
2210 * must return -ENOSPC. in mtd_write_user_prot_reg()
2212 return (*retlen) ? 0 : -ENOSPC; in mtd_write_user_prot_reg()
2218 struct mtd_info *master = mtd_get_master(mtd); in mtd_lock_user_prot_reg() local
2220 if (!master->_lock_user_prot_reg) in mtd_lock_user_prot_reg()
2221 return -EOPNOTSUPP; in mtd_lock_user_prot_reg()
2224 return master->_lock_user_prot_reg(master, from, len); in mtd_lock_user_prot_reg()
2230 struct mtd_info *master = mtd_get_master(mtd); in mtd_erase_user_prot_reg() local
2232 if (!master->_erase_user_prot_reg) in mtd_erase_user_prot_reg()
2233 return -EOPNOTSUPP; in mtd_erase_user_prot_reg()
2236 return master->_erase_user_prot_reg(master, from, len); in mtd_erase_user_prot_reg()
2240 /* Chip-supported device locking */
2243 struct mtd_info *master = mtd_get_master(mtd); in mtd_lock() local
2245 if (!master->_lock) in mtd_lock()
2246 return -EOPNOTSUPP; in mtd_lock()
2247 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) in mtd_lock()
2248 return -EINVAL; in mtd_lock()
2252 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_lock()
2253 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_lock()
2254 len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize; in mtd_lock()
2257 return master->_lock(master, mtd_get_master_ofs(mtd, ofs), len); in mtd_lock()
2263 struct mtd_info *master = mtd_get_master(mtd); in mtd_unlock() local
2265 if (!master->_unlock) in mtd_unlock()
2266 return -EOPNOTSUPP; in mtd_unlock()
2267 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) in mtd_unlock()
2268 return -EINVAL; in mtd_unlock()
2272 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_unlock()
2273 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_unlock()
2274 len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize; in mtd_unlock()
2277 return master->_unlock(master, mtd_get_master_ofs(mtd, ofs), len); in mtd_unlock()
2283 struct mtd_info *master = mtd_get_master(mtd); in mtd_is_locked() local
2285 if (!master->_is_locked) in mtd_is_locked()
2286 return -EOPNOTSUPP; in mtd_is_locked()
2287 if (ofs < 0 || ofs >= mtd->size || len > mtd->size - ofs) in mtd_is_locked()
2288 return -EINVAL; in mtd_is_locked()
2292 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) { in mtd_is_locked()
2293 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_is_locked()
2294 len = (u64)mtd_div_by_eb(len, mtd) * master->erasesize; in mtd_is_locked()
2297 return master->_is_locked(master, mtd_get_master_ofs(mtd, ofs), len); in mtd_is_locked()
2303 struct mtd_info *master = mtd_get_master(mtd); in mtd_block_isreserved() local
2305 if (ofs < 0 || ofs >= mtd->size) in mtd_block_isreserved()
2306 return -EINVAL; in mtd_block_isreserved()
2307 if (!master->_block_isreserved) in mtd_block_isreserved()
2310 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_block_isreserved()
2311 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_block_isreserved()
2313 return master->_block_isreserved(master, mtd_get_master_ofs(mtd, ofs)); in mtd_block_isreserved()
2319 struct mtd_info *master = mtd_get_master(mtd); in mtd_block_isbad() local
2321 if (ofs < 0 || ofs >= mtd->size) in mtd_block_isbad()
2322 return -EINVAL; in mtd_block_isbad()
2323 if (!master->_block_isbad) in mtd_block_isbad()
2326 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_block_isbad()
2327 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_block_isbad()
2329 return master->_block_isbad(master, mtd_get_master_ofs(mtd, ofs)); in mtd_block_isbad()
2335 struct mtd_info *master = mtd_get_master(mtd); in mtd_block_markbad() local
2338 if (!master->_block_markbad) in mtd_block_markbad()
2339 return -EOPNOTSUPP; in mtd_block_markbad()
2340 if (ofs < 0 || ofs >= mtd->size) in mtd_block_markbad()
2341 return -EINVAL; in mtd_block_markbad()
2342 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_block_markbad()
2343 return -EROFS; in mtd_block_markbad()
2345 if (mtd->flags & MTD_SLC_ON_MLC_EMULATION) in mtd_block_markbad()
2346 ofs = (loff_t)mtd_div_by_eb(ofs, mtd) * master->erasesize; in mtd_block_markbad()
2348 ret = master->_block_markbad(master, mtd_get_master_ofs(mtd, ofs)); in mtd_block_markbad()
2352 while (mtd->parent) { in mtd_block_markbad()
2353 mtd->ecc_stats.badblocks++; in mtd_block_markbad()
2354 mtd = mtd->parent; in mtd_block_markbad()
2363 * default_mtd_writev - the default writev method
2395 * mtd_writev - the vector-based MTD write method
2408 struct mtd_info *master = mtd_get_master(mtd); in mtd_writev() local
2411 if (!(mtd->flags & MTD_WRITEABLE)) in mtd_writev()
2412 return -EROFS; in mtd_writev()
2414 if (!master->_writev) in mtd_writev()
2417 return master->_writev(master, vecs, count, in mtd_writev()
2423 * mtd_kmalloc_up_to - allocate a contiguous buffer up to the specified size
2433 * ask the memory allocator to avoid re-trying, swapping, writing back
2437 * the MTD device's min. I/O unit, i.e. the "mtd->writesize" value.
2440 * to handle smaller (i.e. degraded) buffer allocations under low- or
2441 * fragmented-memory situations where such reduced allocations, from a
2449 size_t min_alloc = max_t(size_t, mtd->writesize, PAGE_SIZE); in mtd_kmalloc_up_to()
2460 *size = ALIGN(*size, mtd->writesize); in mtd_kmalloc_up_to()
2465 * things (write-back, dropping caches, etc) by using GFP_KERNEL. in mtd_kmalloc_up_to()
2484 mtd->index, (unsigned long long)mtd->size, in mtd_proc_show()
2485 mtd->erasesize, mtd->name); in mtd_proc_show()
2502 return ERR_PTR(-ENOMEM); in mtd_bdi_init()
2503 bdi->ra_pages = 0; in mtd_bdi_init()
2504 bdi->io_pages = 0; in mtd_bdi_init()
2507 * We put '-0' suffix to the name to get the same name format as we in mtd_bdi_init()
2510 ret = bdi_register(bdi, "%.28s-0", name); in mtd_bdi_init()