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

1 // SPDX-License-Identifier: GPL-2.0+
7 * Copyright © 2000-2010 David Woodhouse <dwmw2@infradead.org>
43 * kstrdup - allocate space for and copy an existing string
66 bool mtd_partitions_used(struct mtd_info *master) in mtd_partitions_used() argument
70 list_for_each_entry(slave, &master->partitions, node) { in mtd_partitions_used()
71 if (slave->usecount) in mtd_partitions_used()
79 * mtd_parse_partition - Parse @mtdparts partition definition, fill @partition
103 if (*mtdparts == '-') { in mtd_parse_partition()
105 partition->size = MTD_SIZE_REMAINING; in mtd_parse_partition()
108 partition->size = ustrtoull(mtdparts, (char **)&mtdparts, 0); in mtd_parse_partition()
109 if (partition->size < SZ_4K) { in mtd_parse_partition()
111 partition->size); in mtd_parse_partition()
112 return -EINVAL; in mtd_parse_partition()
117 partition->offset = MTD_OFFSET_NOT_SPECIFIED; in mtd_parse_partition()
120 partition->offset = ustrtoull(mtdparts, (char **)&mtdparts, 0); in mtd_parse_partition()
129 return -EINVAL; in mtd_parse_partition()
131 name_len = mtdparts - name + 1; in mtd_parse_partition()
132 if ((name_len - 1) == 0) { in mtd_parse_partition()
134 return -EINVAL; in mtd_parse_partition()
142 /* Check if the partition is read-only */ in mtd_parse_partition()
144 partition->mask_flags |= MTD_WRITEABLE; in mtd_parse_partition()
150 if (partition->size == MTD_SIZE_REMAINING) { in mtd_parse_partition()
151 printf("No partitions allowed after a fill-up\n"); in mtd_parse_partition()
152 return -EINVAL; in mtd_parse_partition()
159 return -EINVAL; in mtd_parse_partition()
164 * auto-generate it with the form 'size@offset'. in mtd_parse_partition()
168 return -ENOMEM; in mtd_parse_partition()
171 strncpy(buf, name, name_len - 1); in mtd_parse_partition()
174 partition->size, partition->offset); in mtd_parse_partition()
176 buf[name_len - 1] = '\0'; in mtd_parse_partition()
177 partition->name = buf; in mtd_parse_partition()
185 * mtd_parse_partitions - Create a partition array from an mtdparts definition
225 printf("Not enough space to save partitions meta-data\n"); in mtd_parse_partitions()
226 return -ENOMEM; in mtd_parse_partitions()
236 parts[idx].size = parent->size - cur_sz; in mtd_parse_partitions()
240 if (sz < parent->writesize || do_div(sz, parent->writesize)) { in mtd_parse_partitions()
242 parent->writesize); in mtd_parse_partitions()
243 return -EINVAL; in mtd_parse_partitions()
250 parts[idx].ecclayout = parent->ecclayout; in mtd_parse_partitions()
264 * mtd_free_parsed_partitions - Free dynamically allocated partitions
292 struct mtd_ecc_stats stats; in part_read() local
295 stats = mtd->parent->ecc_stats; in part_read()
296 res = mtd->parent->_read(mtd->parent, from + mtd->offset, len, in part_read()
299 mtd->ecc_stats.failed += in part_read()
300 mtd->parent->ecc_stats.failed - stats.failed; in part_read()
302 mtd->ecc_stats.corrected += in part_read()
303 mtd->parent->ecc_stats.corrected - stats.corrected; in part_read()
311 return mtd->parent->_point(mtd->parent, from + mtd->offset, len, in part_point()
317 return mtd->parent->_unpoint(mtd->parent, from + mtd->offset, len); in part_unpoint()
326 offset += mtd->offset; in part_get_unmapped_area()
327 return mtd->parent->_get_unmapped_area(mtd->parent, len, offset, flags); in part_get_unmapped_area()
335 if (from >= mtd->size) in part_read_oob()
336 return -EINVAL; in part_read_oob()
337 if (ops->datbuf && from + ops->len > mtd->size) in part_read_oob()
338 return -EINVAL; in part_read_oob()
344 if (ops->oobbuf) { in part_read_oob()
347 if (ops->mode == MTD_OPS_AUTO_OOB) in part_read_oob()
348 len = mtd->oobavail; in part_read_oob()
350 len = mtd->oobsize; in part_read_oob()
351 pages = mtd_div_by_ws(mtd->size, mtd); in part_read_oob()
352 pages -= mtd_div_by_ws(from, mtd); in part_read_oob()
353 if (ops->ooboffs + ops->ooblen > pages * len) in part_read_oob()
354 return -EINVAL; in part_read_oob()
357 res = mtd->parent->_read_oob(mtd->parent, from + mtd->offset, ops); in part_read_oob()
360 mtd->ecc_stats.corrected++; in part_read_oob()
362 mtd->ecc_stats.failed++; in part_read_oob()
370 return mtd->parent->_read_user_prot_reg(mtd->parent, from, len, in part_read_user_prot_reg()
377 return mtd->parent->_get_user_prot_info(mtd->parent, len, retlen, in part_get_user_prot_info()
384 return mtd->parent->_read_fact_prot_reg(mtd->parent, from, len, in part_read_fact_prot_reg()
391 return mtd->parent->_get_fact_prot_info(mtd->parent, len, retlen, in part_get_fact_prot_info()
398 return mtd->parent->_write(mtd->parent, to + mtd->offset, len, in part_write()
405 return mtd->parent->_panic_write(mtd->parent, to + mtd->offset, len, in part_panic_write()
412 if (to >= mtd->size) in part_write_oob()
413 return -EINVAL; in part_write_oob()
414 if (ops->datbuf && to + ops->len > mtd->size) in part_write_oob()
415 return -EINVAL; in part_write_oob()
416 return mtd->parent->_write_oob(mtd->parent, to + mtd->offset, ops); in part_write_oob()
422 return mtd->parent->_write_user_prot_reg(mtd->parent, from, len, in part_write_user_prot_reg()
429 return mtd->parent->_lock_user_prot_reg(mtd->parent, from, len); in part_lock_user_prot_reg()
436 return mtd->parent->_writev(mtd->parent, vecs, count, in part_writev()
437 to + mtd->offset, retlen); in part_writev()
445 instr->addr += mtd->offset; in part_erase()
446 ret = mtd->parent->_erase(mtd->parent, instr); in part_erase()
448 if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) in part_erase()
449 instr->fail_addr -= mtd->offset; in part_erase()
450 instr->addr -= mtd->offset; in part_erase()
457 if (instr->mtd->_erase == part_erase) { in mtd_erase_callback()
458 if (instr->fail_addr != MTD_FAIL_ADDR_UNKNOWN) in mtd_erase_callback()
459 instr->fail_addr -= instr->mtd->offset; in mtd_erase_callback()
460 instr->addr -= instr->mtd->offset; in mtd_erase_callback()
462 if (instr->callback) in mtd_erase_callback()
463 instr->callback(instr); in mtd_erase_callback()
469 return mtd->parent->_lock(mtd->parent, ofs + mtd->offset, len); in part_lock()
474 return mtd->parent->_unlock(mtd->parent, ofs + mtd->offset, len); in part_unlock()
479 return mtd->parent->_is_locked(mtd->parent, ofs + mtd->offset, len); in part_is_locked()
484 mtd->parent->_sync(mtd->parent); in part_sync()
490 return mtd->parent->_suspend(mtd->parent); in part_suspend()
495 mtd->parent->_resume(mtd->parent); in part_resume()
501 ofs += mtd->offset; in part_block_isreserved()
502 return mtd->parent->_block_isreserved(mtd->parent, ofs); in part_block_isreserved()
507 ofs += mtd->offset; in part_block_isbad()
508 return mtd->parent->_block_isbad(mtd->parent, ofs); in part_block_isbad()
515 ofs += mtd->offset; in part_block_markbad()
516 res = mtd->parent->_block_markbad(mtd->parent, ofs); in part_block_markbad()
518 mtd->ecc_stats.badblocks++; in part_block_markbad()
524 kfree(p->name); in free_partition()
530 * attached to the given master MTD object, recursively.
532 static int do_del_mtd_partitions(struct mtd_info *master) in do_del_mtd_partitions() argument
537 list_for_each_entry_safe(slave, next, &master->partitions, node) { in do_del_mtd_partitions()
541 debug("Deleting %s MTD partition\n", slave->name); in do_del_mtd_partitions()
545 slave->name, ret); in do_del_mtd_partitions()
550 list_del(&slave->node); in do_del_mtd_partitions()
557 int del_mtd_partitions(struct mtd_info *master) in del_mtd_partitions() argument
561 debug("Deleting MTD partitions on \"%s\":\n", master->name); in del_mtd_partitions()
564 ret = do_del_mtd_partitions(master); in del_mtd_partitions()
570 static struct mtd_info *allocate_partition(struct mtd_info *master, in allocate_partition() argument
579 name = kstrdup(part->name, GFP_KERNEL); in allocate_partition()
582 master->name); in allocate_partition()
585 return ERR_PTR(-ENOMEM); in allocate_partition()
589 slave->type = master->type; in allocate_partition()
590 slave->flags = master->flags & ~part->mask_flags; in allocate_partition()
591 slave->size = part->size; in allocate_partition()
592 slave->writesize = master->writesize; in allocate_partition()
593 slave->writebufsize = master->writebufsize; in allocate_partition()
594 slave->oobsize = master->oobsize; in allocate_partition()
595 slave->oobavail = master->oobavail; in allocate_partition()
596 slave->subpage_sft = master->subpage_sft; in allocate_partition()
598 slave->name = name; in allocate_partition()
599 slave->owner = master->owner; in allocate_partition()
601 slave->backing_dev_info = master->backing_dev_info; in allocate_partition()
603 /* NOTE: we don't arrange MTDs as a tree; it'd be error-prone in allocate_partition()
606 slave->dev.parent = master->dev.parent; in allocate_partition()
609 if (master->_read) in allocate_partition()
610 slave->_read = part_read; in allocate_partition()
611 if (master->_write) in allocate_partition()
612 slave->_write = part_write; in allocate_partition()
614 if (master->_panic_write) in allocate_partition()
615 slave->_panic_write = part_panic_write; in allocate_partition()
618 if (master->_point && master->_unpoint) { in allocate_partition()
619 slave->_point = part_point; in allocate_partition()
620 slave->_unpoint = part_unpoint; in allocate_partition()
624 if (master->_get_unmapped_area) in allocate_partition()
625 slave->_get_unmapped_area = part_get_unmapped_area; in allocate_partition()
626 if (master->_read_oob) in allocate_partition()
627 slave->_read_oob = part_read_oob; in allocate_partition()
628 if (master->_write_oob) in allocate_partition()
629 slave->_write_oob = part_write_oob; in allocate_partition()
630 if (master->_read_user_prot_reg) in allocate_partition()
631 slave->_read_user_prot_reg = part_read_user_prot_reg; in allocate_partition()
632 if (master->_read_fact_prot_reg) in allocate_partition()
633 slave->_read_fact_prot_reg = part_read_fact_prot_reg; in allocate_partition()
634 if (master->_write_user_prot_reg) in allocate_partition()
635 slave->_write_user_prot_reg = part_write_user_prot_reg; in allocate_partition()
636 if (master->_lock_user_prot_reg) in allocate_partition()
637 slave->_lock_user_prot_reg = part_lock_user_prot_reg; in allocate_partition()
638 if (master->_get_user_prot_info) in allocate_partition()
639 slave->_get_user_prot_info = part_get_user_prot_info; in allocate_partition()
640 if (master->_get_fact_prot_info) in allocate_partition()
641 slave->_get_fact_prot_info = part_get_fact_prot_info; in allocate_partition()
642 if (master->_sync) in allocate_partition()
643 slave->_sync = part_sync; in allocate_partition()
645 if (!partno && !master->dev.class && master->_suspend && in allocate_partition()
646 master->_resume) { in allocate_partition()
647 slave->_suspend = part_suspend; in allocate_partition()
648 slave->_resume = part_resume; in allocate_partition()
650 if (master->_writev) in allocate_partition()
651 slave->_writev = part_writev; in allocate_partition()
653 if (master->_lock) in allocate_partition()
654 slave->_lock = part_lock; in allocate_partition()
655 if (master->_unlock) in allocate_partition()
656 slave->_unlock = part_unlock; in allocate_partition()
657 if (master->_is_locked) in allocate_partition()
658 slave->_is_locked = part_is_locked; in allocate_partition()
659 if (master->_block_isreserved) in allocate_partition()
660 slave->_block_isreserved = part_block_isreserved; in allocate_partition()
661 if (master->_block_isbad) in allocate_partition()
662 slave->_block_isbad = part_block_isbad; in allocate_partition()
663 if (master->_block_markbad) in allocate_partition()
664 slave->_block_markbad = part_block_markbad; in allocate_partition()
665 slave->_erase = part_erase; in allocate_partition()
666 slave->parent = master; in allocate_partition()
667 slave->offset = part->offset; in allocate_partition()
668 INIT_LIST_HEAD(&slave->partitions); in allocate_partition()
669 INIT_LIST_HEAD(&slave->node); in allocate_partition()
671 if (slave->offset == MTDPART_OFS_APPEND) in allocate_partition()
672 slave->offset = cur_offset; in allocate_partition()
673 if (slave->offset == MTDPART_OFS_NXTBLK) { in allocate_partition()
674 slave->offset = cur_offset; in allocate_partition()
675 if (mtd_mod_by_eb(cur_offset, master) != 0) { in allocate_partition()
677 slave->offset = (mtd_div_by_eb(cur_offset, master) + 1) * master->erasesize; in allocate_partition()
679 "0x%012llx -> 0x%012llx\n", partno, in allocate_partition()
680 (unsigned long long)cur_offset, (unsigned long long)slave->offset); in allocate_partition()
683 if (slave->offset == MTDPART_OFS_RETAIN) { in allocate_partition()
684 slave->offset = cur_offset; in allocate_partition()
685 if (master->size - slave->offset >= slave->size) { in allocate_partition()
686 slave->size = master->size - slave->offset in allocate_partition()
687 - slave->size; in allocate_partition()
690 part->name, master->size - slave->offset, in allocate_partition()
691 slave->size); in allocate_partition()
696 if (slave->size == MTDPART_SIZ_FULL) in allocate_partition()
697 slave->size = master->size - slave->offset; in allocate_partition()
699 debug("0x%012llx-0x%012llx : \"%s\"\n", (unsigned long long)slave->offset, in allocate_partition()
700 (unsigned long long)(slave->offset + slave->size), slave->name); in allocate_partition()
703 if (slave->offset >= master->size) { in allocate_partition()
705 slave->offset = 0; in allocate_partition()
706 slave->size = 0; in allocate_partition()
707 printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n", in allocate_partition()
708 part->name); in allocate_partition()
711 if (slave->offset + slave->size > master->size) { in allocate_partition()
712 slave->size = master->size - slave->offset; in allocate_partition()
713 …printk(KERN_WARNING"mtd: partition \"%s\" extends beyond the end of device \"%s\" -- size truncate… in allocate_partition()
714 part->name, master->name, slave->size); in allocate_partition()
716 if (master->numeraseregions > 1) { in allocate_partition()
718 int i, max = master->numeraseregions; in allocate_partition()
719 u64 end = slave->offset + slave->size; in allocate_partition()
720 struct mtd_erase_region_info *regions = master->eraseregions; in allocate_partition()
724 for (i = 0; i < max && regions[i].offset <= slave->offset; i++) in allocate_partition()
728 i--; in allocate_partition()
732 if (slave->erasesize < regions[i].erasesize) in allocate_partition()
733 slave->erasesize = regions[i].erasesize; in allocate_partition()
735 WARN_ON(slave->erasesize == 0); in allocate_partition()
738 slave->erasesize = master->erasesize; in allocate_partition()
741 if ((slave->flags & MTD_WRITEABLE) && in allocate_partition()
742 mtd_mod_by_eb(slave->offset, slave)) { in allocate_partition()
746 slave->flags &= ~MTD_WRITEABLE; in allocate_partition()
747 …printk(KERN_WARNING"mtd: partition \"%s\" doesn't start on an erase block boundary -- force read-o… in allocate_partition()
748 part->name); in allocate_partition()
750 if ((slave->flags & MTD_WRITEABLE) && in allocate_partition()
751 mtd_mod_by_eb(slave->size, slave)) { in allocate_partition()
752 slave->flags &= ~MTD_WRITEABLE; in allocate_partition()
753 printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase block -- force read-only\n", in allocate_partition()
754 part->name); in allocate_partition()
757 slave->ecclayout = master->ecclayout; in allocate_partition()
758 slave->ecc_step_size = master->ecc_step_size; in allocate_partition()
759 slave->ecc_strength = master->ecc_strength; in allocate_partition()
760 slave->bitflip_threshold = master->bitflip_threshold; in allocate_partition()
762 if (master->_block_isbad) { in allocate_partition()
765 while (offs < slave->size) { in allocate_partition()
766 if (mtd_block_isbad(master, offs + slave->offset)) in allocate_partition()
767 slave->ecc_stats.badblocks++; in allocate_partition()
768 offs += slave->erasesize; in allocate_partition()
777 int mtd_add_partition(struct mtd_info *master, const char *name, in mtd_add_partition() argument
788 return -EINVAL; in mtd_add_partition()
791 length = master->size - offset; in mtd_add_partition()
794 return -EINVAL; in mtd_add_partition()
802 new = allocate_partition(master, &part, -1, offset); in mtd_add_partition()
810 list_for_each_entry(p, &master->partitions, node) { in mtd_add_partition()
811 if (start >= p->offset && in mtd_add_partition()
812 (start < (p->offset + p->size))) in mtd_add_partition()
815 if (end >= p->offset && in mtd_add_partition()
816 (end < (p->offset + p->size))) in mtd_add_partition()
820 list_add_tail(&new->node, &master->partitions); in mtd_add_partition()
829 return -EINVAL; in mtd_add_partition()
833 int mtd_del_partition(struct mtd_info *master, int partno) in mtd_del_partition() argument
836 int ret = -EINVAL; in mtd_del_partition()
839 list_for_each_entry_safe(slave, next, &master->partitions, node) in mtd_del_partition()
840 if (slave->index == partno) { in mtd_del_partition()
845 list_del(&slave->node); in mtd_del_partition()
857 * This function, given a master MTD object and a partition table, creates
858 * and registers slave MTD objects which are bound to the master according to
861 * We don't register the master, or expect the caller to have done so,
865 int add_mtd_partitions(struct mtd_info *master, in add_mtd_partitions() argument
873 debug("Creating %d MTD partitions on \"%s\":\n", nbparts, master->name); in add_mtd_partitions()
876 slave = allocate_partition(master, parts + i, i, cur_offset); in add_mtd_partitions()
881 list_add_tail(&slave->node, &master->partitions); in add_mtd_partitions()
886 cur_offset = slave->offset + slave->size; in add_mtd_partitions()
903 if (!strcmp(p->name, name) && try_module_get(p->owner)) { in get_partition_parser()
913 #define put_partition_parser(p) do { module_put((p)->owner); } while (0)
918 list_add(&p->list, &part_parsers); in register_mtd_parser()
926 list_del(&p->list); in deregister_mtd_parser()
942 * parse_mtd_partitions - parse MTD partitions
943 * @master: the master partition (describes whole MTD device)
946 * @data: MTD partition parser-specific data
948 * This function tries to find partition on MTD device @master. It uses MTD
961 int parse_mtd_partitions(struct mtd_info *master, const char *const *types, in parse_mtd_partitions() argument
977 ret = (*parser->parse_fn)(master, pparts, data); in parse_mtd_partitions()
981 ret, parser->name, master->name); in parse_mtd_partitions()
993 return mtd->parent->size; in mtd_get_device_size()
995 return mtd->size; in mtd_get_device_size()