diff options
Diffstat (limited to 'drivers/mtd/ubi/ubi.h')
-rw-r--r-- | drivers/mtd/ubi/ubi.h | 128 |
1 files changed, 107 insertions, 21 deletions
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 754b3371d2..540f721e1b 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -43,17 +43,18 @@ /* Normal UBI messages */ #ifdef CONFIG_UBI_SILENCE_MSG -#define ubi_msg(fmt, ...) +#define ubi_msg(ubi, fmt, ...) #else -#define ubi_msg(fmt, ...) printk(KERN_NOTICE "UBI: " fmt "\n", ##__VA_ARGS__) +#define ubi_msg(ubi, fmt, ...) printk(UBI_NAME_STR "%d: " fmt "\n", \ + ubi->ubi_num, ##__VA_ARGS__) #endif /* UBI warning messages */ -#define ubi_warn(fmt, ...) pr_warn("UBI warning: %s: " fmt "\n", \ - __func__, ##__VA_ARGS__) +#define ubi_warn(ubi, fmt, ...) pr_warn(UBI_NAME_STR "%d warning: %s: " fmt "\n", \ + ubi->ubi_num, __func__, ##__VA_ARGS__) /* UBI error messages */ -#define ubi_err(fmt, ...) pr_err("UBI error: %s: " fmt "\n", \ - __func__, ##__VA_ARGS__) +#define ubi_err(ubi, fmt, ...) pr_err(UBI_NAME_STR "%d error: %s: " fmt "\n", \ + ubi->ubi_num, __func__, ##__VA_ARGS__) /* Background thread name pattern */ #define UBI_BGT_NAME_PATTERN "ubi_bgt%dd" @@ -147,6 +148,17 @@ enum { UBI_BAD_FASTMAP, }; +/* + * Flags for emulate_power_cut in ubi_debug_info + * + * POWER_CUT_EC_WRITE: Emulate a power cut when writing an EC header + * POWER_CUT_VID_WRITE: Emulate a power cut when writing a VID header + */ +enum { + POWER_CUT_EC_WRITE = 0x01, + POWER_CUT_VID_WRITE = 0x02, +}; + /** * struct ubi_wl_entry - wear-leveling entry. * @u.rb: link in the corresponding (free/used) RB-tree @@ -257,6 +269,7 @@ struct ubi_fm_pool { * @readers: number of users holding this volume in read-only mode * @writers: number of users holding this volume in read-write mode * @exclusive: whether somebody holds this volume in exclusive mode + * @metaonly: whether somebody is altering only meta data of this volume * * @reserved_pebs: how many physical eraseblocks are reserved for this volume * @vol_type: volume type (%UBI_DYNAMIC_VOLUME or %UBI_STATIC_VOLUME) @@ -305,6 +318,7 @@ struct ubi_volume { int readers; int writers; int exclusive; + int metaonly; int reserved_pebs; int vol_type; @@ -339,7 +353,8 @@ struct ubi_volume { /** * struct ubi_volume_desc - UBI volume descriptor returned when it is opened. * @vol: reference to the corresponding volume description object - * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, or %UBI_EXCLUSIVE) + * @mode: open mode (%UBI_READONLY, %UBI_READWRITE, %UBI_EXCLUSIVE + * or %UBI_METAONLY) */ struct ubi_volume_desc { struct ubi_volume *vol; @@ -353,30 +368,48 @@ struct ubi_wl_entry; * * @chk_gen: if UBI general extra checks are enabled * @chk_io: if UBI I/O extra checks are enabled + * @chk_fastmap: if UBI fastmap extra checks are enabled * @disable_bgt: disable the background task for testing purposes * @emulate_bitflips: emulate bit-flips for testing purposes * @emulate_io_failures: emulate write/erase failures for testing purposes + * @emulate_power_cut: emulate power cut for testing purposes + * @power_cut_counter: count down for writes left until emulated power cut + * @power_cut_min: minimum number of writes before emulating a power cut + * @power_cut_max: maximum number of writes until emulating a power cut * @dfs_dir_name: name of debugfs directory containing files of this UBI device * @dfs_dir: direntry object of the UBI device debugfs directory * @dfs_chk_gen: debugfs knob to enable UBI general extra checks * @dfs_chk_io: debugfs knob to enable UBI I/O extra checks + * @dfs_chk_fastmap: debugfs knob to enable UBI fastmap extra checks * @dfs_disable_bgt: debugfs knob to disable the background task * @dfs_emulate_bitflips: debugfs knob to emulate bit-flips * @dfs_emulate_io_failures: debugfs knob to emulate write/erase failures + * @dfs_emulate_power_cut: debugfs knob to emulate power cuts + * @dfs_power_cut_min: debugfs knob for minimum writes before power cut + * @dfs_power_cut_max: debugfs knob for maximum writes until power cut */ struct ubi_debug_info { unsigned int chk_gen:1; unsigned int chk_io:1; + unsigned int chk_fastmap:1; unsigned int disable_bgt:1; unsigned int emulate_bitflips:1; unsigned int emulate_io_failures:1; + unsigned int emulate_power_cut:2; + unsigned int power_cut_counter; + unsigned int power_cut_min; + unsigned int power_cut_max; char dfs_dir_name[UBI_DFS_DIR_LEN + 1]; struct dentry *dfs_dir; struct dentry *dfs_chk_gen; struct dentry *dfs_chk_io; + struct dentry *dfs_chk_fastmap; struct dentry *dfs_disable_bgt; struct dentry *dfs_emulate_bitflips; struct dentry *dfs_emulate_io_failures; + struct dentry *dfs_emulate_power_cut; + struct dentry *dfs_power_cut_min; + struct dentry *dfs_power_cut_max; }; /** @@ -390,7 +423,8 @@ struct ubi_debug_info { * @volumes_lock: protects @volumes, @rsvd_pebs, @avail_pebs, beb_rsvd_pebs, * @beb_rsvd_level, @bad_peb_count, @good_peb_count, @vol_count, * @vol->readers, @vol->writers, @vol->exclusive, - * @vol->ref_count, @vol->mapping and @vol->eba_tbl. + * @vol->metaonly, @vol->ref_count, @vol->mapping and + * @vol->eba_tbl. * @ref_count: count of references on the UBI device * @image_seq: image sequence number recorded on EC headers * @@ -422,11 +456,13 @@ struct ubi_debug_info { * @fm_pool: in-memory data structure of the fastmap pool * @fm_wl_pool: in-memory data structure of the fastmap pool used by the WL * sub-system - * @fm_mutex: serializes ubi_update_fastmap() and protects @fm_buf + * @fm_protect: serializes ubi_update_fastmap(), protects @fm_buf and makes sure + * that critical sections cannot be interrupted by ubi_update_fastmap() * @fm_buf: vmalloc()'d buffer which holds the raw fastmap * @fm_size: fastmap size in bytes - * @fm_sem: allows ubi_update_fastmap() to block EBA table changes + * @fm_eba_sem: allows ubi_update_fastmap() to block EBA table changes * @fm_work: fastmap work queue + * @fm_work_scheduled: non-zero if fastmap work was scheduled * * @used: RB-tree of used physical eraseblocks * @erroneous: RB-tree of erroneous used physical eraseblocks @@ -438,9 +474,11 @@ struct ubi_debug_info { * @pq_head: protection queue head * @wl_lock: protects the @used, @free, @pq, @pq_head, @lookuptbl, @move_from, * @move_to, @move_to_put @erase_pending, @wl_scheduled, @works, - * @erroneous, and @erroneous_peb_count fields + * @erroneous, @erroneous_peb_count, @fm_work_scheduled, @fm_pool, + * and @fm_wl_pool fields * @move_mutex: serializes eraseblock moves - * @work_sem: synchronizes the WL worker with use tasks + * @work_sem: used to wait for all the scheduled works to finish and prevent + * new works from being submitted * @wl_scheduled: non-zero if the wear-leveling was scheduled * @lookuptbl: a table to quickly find a &struct ubi_wl_entry object for any * physical eraseblock @@ -474,7 +512,7 @@ struct ubi_debug_info { * @vid_hdr_offset: starting offset of the volume identifier header (might be * unaligned) * @vid_hdr_aloffset: starting offset of the VID header aligned to - * @hdrs_min_io_size + * @hdrs_min_io_size * @vid_hdr_shift: contains @vid_hdr_offset - @vid_hdr_aloffset * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or * not @@ -527,13 +565,14 @@ struct ubi_device { struct ubi_fastmap_layout *fm; struct ubi_fm_pool fm_pool; struct ubi_fm_pool fm_wl_pool; - struct rw_semaphore fm_sem; - struct mutex fm_mutex; + struct rw_semaphore fm_eba_sem; + struct rw_semaphore fm_protect; void *fm_buf; size_t fm_size; #ifndef __UBOOT__ struct work_struct fm_work; #endif + int fm_work_scheduled; /* Wear-leveling sub-system's stuff */ struct rb_root used; @@ -716,14 +755,15 @@ struct ubi_attach_info { * @torture: if the physical eraseblock has to be tortured * @anchor: produce a anchor PEB to by used by fastmap * - * The @func pointer points to the worker function. If the @cancel argument is - * not zero, the worker has to free the resources and exit immediately. The - * worker has to return zero in case of success and a negative error code in + * The @func pointer points to the worker function. If the @shutdown argument is + * not zero, the worker has to free the resources and exit immediately as the + * WL sub-system is shutting down. + * The worker has to return zero in case of success and a negative error code in * case of failure. */ struct ubi_work { struct list_head list; - int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int cancel); + int (*func)(struct ubi_device *ubi, struct ubi_work *wrk, int shutdown); /* The below fields are only relevant to erasure works */ struct ubi_wl_entry *e; int vol_id; @@ -738,7 +778,7 @@ extern struct kmem_cache *ubi_wl_entry_slab; extern const struct file_operations ubi_ctrl_cdev_operations; extern const struct file_operations ubi_cdev_operations; extern const struct file_operations ubi_vol_cdev_operations; -extern struct class *ubi_class; +extern struct class ubi_class; extern struct mutex ubi_devices_mutex; extern struct blocking_notifier_head ubi_notifiers; @@ -807,6 +847,9 @@ int ubi_eba_unmap_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum); int ubi_eba_read_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, void *buf, int offset, int len, int check); +int ubi_eba_read_leb_sg(struct ubi_device *ubi, struct ubi_volume *vol, + struct ubi_sgl *sgl, int lnum, int offset, int len, + int check); int ubi_eba_write_leb(struct ubi_device *ubi, struct ubi_volume *vol, int lnum, const void *buf, int offset, int len); int ubi_eba_write_leb_st(struct ubi_device *ubi, struct ubi_volume *vol, @@ -877,10 +920,14 @@ int ubi_compare_lebs(struct ubi_device *ubi, const struct ubi_ainf_peb *aeb, int pnum, const struct ubi_vid_hdr *vid_hdr); /* fastmap.c */ +#ifdef CONFIG_MTD_UBI_FASTMAP size_t ubi_calc_fm_size(struct ubi_device *ubi); int ubi_update_fastmap(struct ubi_device *ubi); int ubi_scan_fastmap(struct ubi_device *ubi, struct ubi_attach_info *ai, int fm_anchor); +#else +static inline int ubi_update_fastmap(struct ubi_device *ubi) { return 0; } +#endif /* block.c */ #ifdef CONFIG_MTD_UBI_BLOCK @@ -901,6 +948,42 @@ static inline int ubiblock_remove(struct ubi_volume_info *vi) } #endif +/* + * ubi_for_each_free_peb - walk the UBI free RB tree. + * @ubi: UBI device description object + * @e: a pointer to a ubi_wl_entry to use as cursor + * @pos: a pointer to RB-tree entry type to use as a loop counter + */ +#define ubi_for_each_free_peb(ubi, e, tmp_rb) \ + ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->free, u.rb) + +/* + * ubi_for_each_used_peb - walk the UBI used RB tree. + * @ubi: UBI device description object + * @e: a pointer to a ubi_wl_entry to use as cursor + * @pos: a pointer to RB-tree entry type to use as a loop counter + */ +#define ubi_for_each_used_peb(ubi, e, tmp_rb) \ + ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->used, u.rb) + +/* + * ubi_for_each_scub_peb - walk the UBI scub RB tree. + * @ubi: UBI device description object + * @e: a pointer to a ubi_wl_entry to use as cursor + * @pos: a pointer to RB-tree entry type to use as a loop counter + */ +#define ubi_for_each_scrub_peb(ubi, e, tmp_rb) \ + ubi_rb_for_each_entry((tmp_rb), (e), &(ubi)->scrub, u.rb) + +/* + * ubi_for_each_protected_peb - walk the UBI protection queue. + * @ubi: UBI device description object + * @i: a integer used as counter + * @e: a pointer to a ubi_wl_entry to use as cursor + */ +#define ubi_for_each_protected_peb(ubi, i, e) \ + for ((i) = 0; (i) < UBI_PROT_QUEUE_LEN; (i)++) \ + list_for_each_entry((e), &(ubi->pq[(i)]), u.list) /* * ubi_rb_for_each_entry - walk an RB-tree. @@ -1004,7 +1087,7 @@ static inline void ubi_ro_mode(struct ubi_device *ubi) { if (!ubi->ro_mode) { ubi->ro_mode = 1; - ubi_warn("switch to read-only mode"); + ubi_warn(ubi, "switch to read-only mode"); dump_stack(); } } @@ -1035,4 +1118,7 @@ static inline int idx2vol_id(const struct ubi_device *ubi, int idx) return idx; } +#ifdef __UBOOT__ +int do_work(struct ubi_device *ubi); +#endif #endif /* !__UBI_UBI_H__ */ |