On Mon, Nov 3, 2008 at 6:01 AM, Magnus Lilja <[EMAIL PROTECTED]> wrote: > Dear Kyungmin Park, > > Some more comments after testing your patches. > > 2008/10/28 Kyungmin Park <[EMAIL PROTECTED]>: >> UBI (Latin: "where?") stands for "Unsorted Block Images". It is a volume >> management system for flash devices which manages multiple logical volumes >> on a single physical flash device and spreads the I/O load (i.e, >> wear-leveling) across the whole flash chip. >> >> In a sense, UBI may be compared to the Logical Volume Manager (LVM). Whereas >> LVM maps logical sectors to physical sectors, UBI maps logical eraseblocks >> to physical eraseblocks. But besides the mapping, UBI implements global >> wear-leveling and I/O errors handling. >> >> For more details, Please visit the following URL. >> http://www.linux-mtd.infradead.org/doc/ubi.html >> >> Signed-off-by: Kyungmin Park <[EMAIL PROTECTED]> >> --- >> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c >> new file mode 100644 >> index 0000000..b6f8699 >> --- /dev/null >> +++ b/drivers/mtd/ubi/build.c >> +static int io_init(struct ubi_device *ubi) >> +{ >> + if (ubi->mtd->numeraseregions != 0) { >> + /* >> + * Some flashes have several erase regions. Different regions >> + * may have different eraseblock size and other >> + * characteristics. It looks like mostly multi-region flashes >> + * have one "main" region and one or more small regions to >> + * store boot loader code or boot parameters or whatever. I >> + * guess we should just pick the largest region. But this is >> + * not implemented. >> + */ >> + ubi_err("multiple regions, not implemented"); >> + return -EINVAL; >> + } >> + >> + if (ubi->vid_hdr_offset < 0) >> + return -EINVAL; >> + >> + /* >> + * Note, in this implementation we support MTD devices with >> 0x7FFFFFFF >> + * physical eraseblocks maximum. >> + */ >> + >> + ubi->peb_size = ubi->mtd->erasesize; >> + ubi->peb_count = ubi->mtd->size / ubi->mtd->erasesize; >> + ubi->flash_size = ubi->mtd->size; >> + >> + if (ubi->mtd->block_isbad && ubi->mtd->block_markbad) >> + ubi->bad_allowed = 1; >> + >> + ubi->min_io_size = ubi->mtd->writesize; >> + ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; >> + >> + /* >> + * Make sure minimal I/O unit is power of 2. Note, there is no >> + * fundamental reason for this assumption. It is just an optimization >> + * which allows us to avoid costly division operations. >> + */ >> + if (!is_power_of_2(ubi->min_io_size)) { >> + ubi_err("min. I/O unit (%d) is not power of 2", >> + ubi->min_io_size); >> + return -EINVAL; >> + } >> + >> + ubi_assert(ubi->hdrs_min_io_size > 0); >> + ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size); >> + ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0); >> + >> + /* Calculate default aligned sizes of EC and VID headers */ >> + ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size); >> + ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size); >> + >> + dbg_msg("min_io_size %d", ubi->min_io_size); >> + dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size); >> + dbg_msg("ec_hdr_alsize %d", ubi->ec_hdr_alsize); >> + dbg_msg("vid_hdr_alsize %d", ubi->vid_hdr_alsize); >> + >> + if (ubi->vid_hdr_offset == 0) >> + /* Default offset */ >> + ubi->vid_hdr_offset = ubi->vid_hdr_aloffset = >> + ubi->ec_hdr_alsize; >> + else { >> + ubi->vid_hdr_aloffset = ubi->vid_hdr_offset & >> + ~(ubi->hdrs_min_io_size - 1); >> + ubi->vid_hdr_shift = ubi->vid_hdr_offset - >> + ubi->vid_hdr_aloffset; >> + } >> + >> + /* Similar for the data offset */ >> + ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE; >> + ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); >> + >> + dbg_msg("vid_hdr_offset %d", ubi->vid_hdr_offset); >> + dbg_msg("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset); >> + dbg_msg("vid_hdr_shift %d", ubi->vid_hdr_shift); >> + dbg_msg("leb_start %d", ubi->leb_start); >> + >> + /* The shift must be aligned to 32-bit boundary */ >> + if (ubi->vid_hdr_shift % 4) { >> + ubi_err("unaligned VID header shift %d", >> + ubi->vid_hdr_shift); >> + return -EINVAL; >> + } >> + >> + /* Check sanity */ >> + if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || >> + ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || >> + ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || >> + ubi->leb_start & (ubi->min_io_size - 1)) { >> + ubi_err("bad VID header (%d) or data offsets (%d)", >> + ubi->vid_hdr_offset, ubi->leb_start); >> + return -EINVAL; >> + } >> + >> + /* >> + * It may happen that EC and VID headers are situated in one minimal >> + * I/O unit. In this case we can only accept this UBI image in >> + * read-only mode. >> + */ >> + if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) >> { >> + ubi_warn("EC and VID headers are in the same minimal I/O >> unit, " >> + "switch to read-only mode"); >> + ubi->ro_mode = 1; >> + } >> + >> + ubi->leb_size = ubi->peb_size - ubi->leb_start; >> + >> + if (!(ubi->mtd->flags & MTD_WRITEABLE)) { >> + ubi_msg("MTD device %d is write-protected, attach in " >> + "read-only mode", ubi->mtd->index); >> + ubi->ro_mode = 1; >> + } >> + >> + ubi_msg("physical eraseblock size: %d bytes (%d KiB)", >> + ubi->peb_size, ubi->peb_size >> 10); >> + ubi_msg("logical eraseblock size: %d bytes", ubi->leb_size); >> + ubi_msg("smallest flash I/O unit: %d", ubi->min_io_size); >> + if (ubi->hdrs_min_io_size != ubi->min_io_size) >> + ubi_msg("sub-page size: %d", >> + ubi->hdrs_min_io_size); >> + ubi_msg("VID header offset: %d (aligned %d)", >> + ubi->vid_hdr_offset, ubi->vid_hdr_aloffset); >> + ubi_msg("data offset: %d", ubi->leb_start); > > I got these messages on my console, my suggestion is that (almost) all > of the standard info messages are off by default. > >> +int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, int >> vid_hdr_offset) >> +{ >> + struct ubi_device *ubi; >> + int i, err; >> + >> + /* >> + * Check if we already have the same MTD device attached. >> + * >> + * Note, this function assumes that UBI devices creations and >> deletions >> + * are serialized, so it does not take the &ubi_devices_lock. >> + */ >> + for (i = 0; i < UBI_MAX_DEVICES; i++) { >> + ubi = ubi_devices[i]; >> + if (ubi && mtd->index == ubi->mtd->index) { >> + dbg_err("mtd%d is already attached to ubi%d", >> + mtd->index, i); >> + return -EEXIST; >> + } >> + } >> + >> + /* >> + * Make sure this MTD device is not emulated on top of an UBI volume >> + * already. Well, generally this recursion works fine, but there are >> + * different problems like the UBI module takes a reference to itself >> + * by attaching (and thus, opening) the emulated MTD device. This >> + * results in inability to unload the module. And in general it makes >> + * no sense to attach emulated MTD devices, so we prohibit this. >> + */ >> + if (mtd->type == MTD_UBIVOLUME) { >> + ubi_err("refuse attaching mtd%d - it is already emulated on " >> + "top of UBI", mtd->index); >> + return -EINVAL; >> + } >> + >> + if (ubi_num == UBI_DEV_NUM_AUTO) { >> + /* Search for an empty slot in the @ubi_devices array */ >> + for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) >> + if (!ubi_devices[ubi_num]) >> + break; >> + if (ubi_num == UBI_MAX_DEVICES) { >> + dbg_err("only %d UBI devices may be created", >> UBI_MAX_DEVICES); >> + return -ENFILE; >> + } >> + } else { >> + if (ubi_num >= UBI_MAX_DEVICES) >> + return -EINVAL; >> + >> + /* Make sure ubi_num is not busy */ >> + if (ubi_devices[ubi_num]) { >> + dbg_err("ubi%d already exists", ubi_num); >> + return -EEXIST; >> + } >> + } >> + >> + ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL); >> + if (!ubi) >> + return -ENOMEM; >> + >> + ubi->mtd = mtd; >> + ubi->ubi_num = ubi_num; >> + ubi->vid_hdr_offset = vid_hdr_offset; >> + ubi->autoresize_vol_id = -1; >> + >> + mutex_init(&ubi->buf_mutex); >> + mutex_init(&ubi->ckvol_mutex); >> + mutex_init(&ubi->volumes_mutex); >> + spin_lock_init(&ubi->volumes_lock); >> + >> + ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num); >> + >> + err = io_init(ubi); >> + if (err) >> + goto out_free; >> + >> + ubi->peb_buf1 = vmalloc(ubi->peb_size); >> + if (!ubi->peb_buf1) >> + goto out_free; >> + >> + ubi->peb_buf2 = vmalloc(ubi->peb_size); >> + if (!ubi->peb_buf2) >> + goto out_free; >> + >> +#ifdef CONFIG_MTD_UBI_DEBUG >> + mutex_init(&ubi->dbg_buf_mutex); >> + ubi->dbg_peb_buf = vmalloc(ubi->peb_size); >> + if (!ubi->dbg_peb_buf) >> + goto out_free; >> +#endif >> + >> + err = attach_by_scanning(ubi); >> + if (err) { >> + dbg_err("failed to attach by scanning, error %d", err); >> + goto out_free; >> + } >> + >> + if (ubi->autoresize_vol_id != -1) { >> + err = autoresize(ubi, ubi->autoresize_vol_id); >> + if (err) >> + goto out_detach; >> + } >> + >> + err = uif_init(ubi); >> + if (err) >> + goto out_detach; >> + >> + ubi->bgt_thread = kthread_create(ubi_thread, ubi, ubi->bgt_name); >> + if (IS_ERR(ubi->bgt_thread)) { >> + err = PTR_ERR(ubi->bgt_thread); >> + ubi_err("cannot spawn \"%s\", error %d", ubi->bgt_name, >> + err); >> + goto out_uif; >> + } >> + >> + ubi_msg("attached mtd%d to ubi%d", mtd->index, ubi_num); >> + ubi_msg("MTD device name: \"%s\"", mtd->name); >> + ubi_msg("MTD device size: %llu MiB", ubi->flash_size >> >> 20); >> + ubi_msg("number of good PEBs: %d", ubi->good_peb_count); >> + ubi_msg("number of bad PEBs: %d", ubi->bad_peb_count); >> + ubi_msg("max. allowed volumes: %d", ubi->vtbl_slots); >> + ubi_msg("wear-leveling threshold: %d", >> CONFIG_MTD_UBI_WL_THRESHOLD); >> + ubi_msg("number of internal volumes: %d", UBI_INT_VOL_COUNT); >> + ubi_msg("number of user volumes: %d", >> + ubi->vol_count - UBI_INT_VOL_COUNT); >> + ubi_msg("available PEBs: %d", ubi->avail_pebs); >> + ubi_msg("total number of reserved PEBs: %d", ubi->rsvd_pebs); >> + ubi_msg("number of PEBs reserved for bad PEB handling: %d", >> + ubi->beb_rsvd_pebs); >> + ubi_msg("max/mean erase counter: %d/%d", ubi->max_ec, ubi->mean_ec); > > All these should also be off by default IMO.
These messages are default on kernel. If you want to off, we can add the another configuration to ubi_msg macro Thank you, Kyungmin Park _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot