From Artem.Bityutskiy at nokia.com Mon May 3 06:13:02 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Mon, 3 May 2010 13:13:02 +0300 Subject: [PATCH 4/4] UBI: improve corrupted flash handling In-Reply-To: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> Message-ID: <1272881582-17196-5-git-send-email-Artem.Bityutskiy@nokia.com> This patch improves the way UBI handles corrupted flash, or flash containing garbage or non-UBI data, which is the same from UBI POW. Namely, we do the following: * if 5% or more PEBs are corrupted, refuse the flash * if less than 5% PEBs are corrupted, do not refuse the flash and format these PEBs * if less than 8 PEBs are corrupted, format them silently, otherwise print a warning message. Reported-by: Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 103 +++++++++++++++++++++++++++++++++++++++--------- 1 files changed, 84 insertions(+), 19 deletions(-) diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index dc5e061..c326f5b 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -760,8 +760,6 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, bitflips = 1; } - si->is_empty = 0; - if (!ec_corr) { int image_seq; @@ -892,6 +890,87 @@ adjust_mean_ec: } /** + * check_what_we_have - check what PEB were found by scanning. + * @ubi: UBI device description object + * @si: scanning information + * + * This is a helper function which takes a look what PEBs were found by + * scanning, and decides whether the flash is empty and should be formatted and + * whether there are too many corrupted PEBs and we should not attach this + * MTD device. Returns zero if we should proceed with attaching the MTD device, + * and %-EINVAL if we should not. + */ +static int check_what_we_have(const struct ubi_device *ubi, + struct ubi_scan_info *si) +{ + struct ubi_scan_leb *seb; + int max_corr; + + max_corr = ubi->peb_count - si->bad_peb_count - si->alien_peb_count; + max_corr = max_corr / 20 ?: 8; + + /* + * Few corrupted PEBs are not a problem and may be just a result of + * unclean reboots. However, many of them may indicate some problems + * with the flash HW or driver. + */ + if (si->corr_peb_count >= 8) { + int cnt; + + ubi_warn("%d PEBs are corrupted", si->corr_peb_count); + printk(KERN_WARNING "corrupted PEBs are:"); + list_for_each_entry(seb, &si->corr, u.list) + printk(KERN_CONT " %d", seb->pnum); + printk(KERN_CONT "\n"); + + /* + * If too many PEBs are corrupted, we refuse attaching, + * otherwise, only print a warning. + */ + if (si->corr_peb_count >= max_corr) { + ubi_err("too many corrupted PEBs, refusing this device"); + return -EINVAL; + } + } + + if (si->free_peb_count + si->used_peb_count + + si->alien_peb_count == 0) { + /* No UBI-formatted eraseblocks were found */ + if (si->corr_peb_count == si->read_err_count && + si->corr_peb_count < 8) { + /* No or just few corrupted PEBs, and all of them had a + * read error. We assume that those are bad PEBs, which + * were just not marked as bad so far. + * + * This piece of code basically tries to distinguish + * between the following 2 situations: + * + * 1. Flash is empty, but there are few bad PEBs, which + * are not marked as bad so far, and which were read + * with error. We want to go ahead and format this + * flash. While formating, the faulty PEBs will + * probably be marked as bad. + * + * 2. Flash contains probably contain non-UBI data + * and we do not want to format it and destroy + * possibly needed data (e.g., the bootloader MTD + * partition was accidentally fed to UBI). + */ + si->is_empty = 1; + ubi_msg("empty MTD device detected"); + } else { + ubi_err("MTD device possibly contains non-UBI data, " + "refusing it"); + return -EINVAL; + } + } + + if (si->corr_peb_count >= 0) + ubi_msg("corrupted PEBs will be formatted"); + return 0; +} + +/** * ubi_scan - scan an MTD device. * @ubi: UBI device description object * @@ -915,7 +994,6 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) INIT_LIST_HEAD(&si->erase); INIT_LIST_HEAD(&si->alien); si->volumes = RB_ROOT; - si->is_empty = 1; err = -ENOMEM; ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL); @@ -941,22 +1019,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) if (si->ec_count) si->mean_ec = div_u64(si->ec_sum, si->ec_count); - if (si->is_empty) - ubi_msg("empty MTD device detected"); - - /* - * Few corrupted PEBs are not a problem and may be just a result of - * unclean reboots. However, many of them may indicate some problems - * with the flash HW or driver. Print a warning in this case. - */ - if (si->corr_peb_count >= 8 || - si->corr_peb_count >= ubi->peb_count / 4) { - ubi_warn("%d PEBs are corrupted", si->corr_peb_count); - printk(KERN_WARNING "corrupted PEBs are:"); - list_for_each_entry(seb, &si->corr, u.list) - printk(KERN_CONT " %d", seb->pnum); - printk(KERN_CONT "\n"); - } + err = check_what_we_have(ubi, si); + if (err) + goto out_vidh; /* * In case of unknown erase counter we use the mean erase counter -- 1.6.6.1 From Artem.Bityutskiy at nokia.com Mon May 3 06:13:00 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Mon, 3 May 2010 13:13:00 +0300 Subject: [PATCH 2/4] UBI: introduce a new IO return code In-Reply-To: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> Message-ID: <1272881582-17196-3-git-send-email-Artem.Bityutskiy@nokia.com> This patch introduces the %UBI_IO_BAD_HDR_READ return code for the I/O level function. We will use this code in order to distinguish between "corrupted header possibly because this is non-ubi data" and "corrupted header possibly because of real data corruption and ECC error". So far this patch does not introduce any functional change, just a preparation. This patch is pased on a patch from Sebastian Andrzej Siewior Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/eba.c | 5 +++-- drivers/mtd/ubi/io.c | 42 +++++++++++++++++++++++------------------- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/ubi.h | 3 +++ 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 8e82267..b582671 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -418,7 +418,8 @@ retry: * may try to recover data. FIXME: but this is * not implemented. */ - if (err == UBI_IO_BAD_HDR) { + if (err == UBI_IO_BAD_HDR_READ || + err == UBI_IO_BAD_HDR) { ubi_warn("corrupted VID header at PEB " "%d, LEB %d:%d", pnum, vol_id, lnum); @@ -962,7 +963,7 @@ write_error: static int is_error_sane(int err) { if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR || - err == -ETIMEDOUT) + err == UBI_IO_BAD_HDR_READ || err == -ETIMEDOUT) return 0; return 1; } diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 6f5b087..abae9af 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -515,7 +515,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) * In this case we probably anyway have garbage in this PEB. */ err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); - if (err1 == UBI_IO_BAD_HDR) + if (err1 == UBI_IO_BAD_HDR_READ || err1 == UBI_IO_BAD_HDR) /* * The VID header is corrupted, so we can safely erase this * PEB and not afraid that it will be treated as a valid PEB in @@ -736,23 +736,21 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, * header is still OK, we just report this as there was a * bit-flip. */ - read_err = err; + if (err == -EBADMSG) + read_err = UBI_IO_BAD_HDR_READ; } magic = be32_to_cpu(ec_hdr->magic); if (magic != UBI_EC_HDR_MAGIC) { + if (read_err) + return read_err; + /* * The magic field is wrong. Let's check if we have read all * 0xFF. If yes, this physical eraseblock is assumed to be * empty. - * - * But if there was a read error, we do not test it for all - * 0xFFs. Even if it does contain all 0xFFs, this error - * indicates that something is still wrong with this physical - * eraseblock and we anyway cannot treat it as empty. */ - if (read_err != -EBADMSG && - check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { + if (check_pattern(ec_hdr, 0xFF, UBI_EC_HDR_SIZE)) { /* The physical eraseblock is supposedly empty */ if (verbose) ubi_warn("no EC header found at PEB %d, " @@ -788,7 +786,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad EC header CRC at PEB %d, calculated " "%#08x, read %#08x", pnum, crc, hdr_crc); - return UBI_IO_BAD_HDR; + return read_err ?: UBI_IO_BAD_HDR; } /* And of course validate what has just been read from the media */ @@ -798,6 +796,10 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, return -EINVAL; } + /* + * If there was %-EBADMSG, but the header CRC is still OK, report about + * a bit-flip to force scrubbing on this PEB. + */ return read_err ? UBI_IO_BITFLIPS : 0; } @@ -1008,22 +1010,20 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, * CRC check-sum and we will identify this. If the VID header is * still OK, we just report this as there was a bit-flip. */ - read_err = err; + if (err == -EBADMSG) + read_err = UBI_IO_BAD_HDR_READ; } magic = be32_to_cpu(vid_hdr->magic); if (magic != UBI_VID_HDR_MAGIC) { + if (read_err) + return read_err; + /* * If we have read all 0xFF bytes, the VID header probably does * not exist and the physical eraseblock is assumed to be free. - * - * But if there was a read error, we do not test the data for - * 0xFFs. Even if it does contain all 0xFFs, this error - * indicates that something is still wrong with this physical - * eraseblock and it cannot be regarded as free. */ - if (read_err != -EBADMSG && - check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { + if (check_pattern(vid_hdr, 0xFF, UBI_VID_HDR_SIZE)) { /* The physical eraseblock is supposedly free */ if (verbose) ubi_warn("no VID header found at PEB %d, " @@ -1059,7 +1059,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); - return UBI_IO_BAD_HDR; + return read_err ?: UBI_IO_BAD_HDR; } /* Validate the VID header that we have just read */ @@ -1069,6 +1069,10 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, return -EINVAL; } + /* + * If there was a read error (%-EBADMSG), but the header CRC is still + * OK, report about a bit-flip to force scrubbing on this PEB. + */ return read_err ? UBI_IO_BITFLIPS : 0; } diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index f52adca..65d03b5 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -745,7 +745,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, bitflips = 1; else if (err == UBI_IO_PEB_EMPTY) return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); - else if (err == UBI_IO_BAD_HDR) { + else if (err = UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { /* * We have to also look at the VID header, possibly it is not * corrupted. Set %bitflips flag in order to make this PEB be @@ -813,7 +813,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, return err; else if (err == UBI_IO_BITFLIPS) bitflips = 1; - else if (err == UBI_IO_BAD_HDR || + else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR || (err == UBI_IO_PEB_FREE && ec_corr)) { /* VID header is corrupted */ err = add_to_list(si, pnum, ec, &si->corr); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index 539b3f6..0359e0c 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -90,12 +90,15 @@ * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a * valid erase counter header, and the rest are %0xFF bytes * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) + * UBI_IO_BAD_HDR_READ: the same as %UBI_IO_BAD_HDR, but also there was a read + * error reported by the flash driver * UBI_IO_BITFLIPS: bit-flips were detected and corrected */ enum { UBI_IO_PEB_EMPTY = 1, UBI_IO_PEB_FREE, UBI_IO_BAD_HDR, + UBI_IO_BAD_HDR_READ, UBI_IO_BITFLIPS }; -- 1.6.6.1 From Artem.Bityutskiy at nokia.com Mon May 3 06:12:58 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Mon, 3 May 2010 13:12:58 +0300 Subject: [PATCH 0/4] UBI: improve empty flash handling Message-ID: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> Hi Sebastian, I've removed your 'UBI: recognize empty flash with errors as empty' patch from the ubi-2.6.git tree, because it solves one problem, but introduces another, and needs more work, as you yourself pointed. This is a series of patches which is intended to fix your problem. Basically, the idea is that during scanning, we just remember the information about which eraseblocks we found. Then at the end, we look at them and decide what to do. We do the following: 1. If there are more than 8 corrupted eraseblocks, we print a warning. This functionality was there before. This is just a warning, nothing else. 2. If more than 5% or eraseblocks are corrupted, we refuse. This logic was not there, I've just added it. 3. If now UBI-formatted eraseblocks were found, then we start checking whether this is empty device and we should format it. Otherwise, we go forward and try to attach the device. 3.1 If there are not corrupted eraseblocks -> empty, format 3.2 If there are few corrupted eraseblocks, all of them had read error -> empty, format. This is the place where we handle the "empty flash with few bad eraseblocks not marked yet as such" 3.3 If there is a corrupted eraseblock, and there was not read error, or if there are many corrupted eraseblocks (>= 8), then we refuse. Please, review and test the following series. P.S. I gave it only a very quick try Artem. From Artem.Bityutskiy at nokia.com Mon May 3 06:13:01 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Mon, 3 May 2010 13:13:01 +0300 Subject: [PATCH 3/4] UBI: introduce eraseblock counter variables In-Reply-To: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> Message-ID: <1272881582-17196-4-git-send-email-Artem.Bityutskiy@nokia.com> This is just a preparation patch which introduces several 'struct ubi_scan_info' fields which count eraseblocks of different types. This will be used later on to decide whether it is safe to format the flash or not. No functional changes so far. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/scan.c | 29 ++++++++++++++++++----------- drivers/mtd/ubi/scan.h | 19 ++++++++++++++----- 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 65d03b5..dc5e061 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -72,16 +72,19 @@ static int add_to_list(struct ubi_scan_info *si, int pnum, int ec, { struct ubi_scan_leb *seb; - if (list == &si->free) + if (list == &si->free) { dbg_bld("add to free: PEB %d, EC %d", pnum, ec); - else if (list == &si->erase) + si->free_peb_count += 1; + } else if (list == &si->erase) { dbg_bld("add to erase: PEB %d, EC %d", pnum, ec); - else if (list == &si->corr) { + si->erase_peb_count += 1; + } else if (list == &si->corr) { dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec); - si->corr_count += 1; - } else if (list == &si->alien) + si->corr_peb_count += 1; + } else if (list == &si->alien) { dbg_bld("add to alien: PEB %d, EC %d", pnum, ec); - else + si->alien_peb_count += 1; + } else BUG(); seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL); @@ -517,6 +520,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, sv->leb_count += 1; rb_link_node(&seb->u.rb, parent, p); rb_insert_color(&seb->u.rb, &sv->root); + si->used_peb_count += 1; return 0; } @@ -745,13 +749,13 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, bitflips = 1; else if (err == UBI_IO_PEB_EMPTY) return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); - else if (err = UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { + else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { /* * We have to also look at the VID header, possibly it is not * corrupted. Set %bitflips flag in order to make this PEB be * moved and EC be re-created. */ - ec_corr = 1; + ec_corr = err; ec = UBI_SCAN_UNKNOWN_EC; bitflips = 1; } @@ -816,6 +820,9 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, else if (err == UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR || (err == UBI_IO_PEB_FREE && ec_corr)) { /* VID header is corrupted */ + if (err == UBI_IO_BAD_HDR_READ || + ec_corr == UBI_IO_BAD_HDR_READ) + si->read_err_count += 1; err = add_to_list(si, pnum, ec, &si->corr); if (err) return err; @@ -855,7 +862,6 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, err = add_to_list(si, pnum, ec, &si->alien); if (err) return err; - si->alien_peb_count += 1; return 0; case UBI_COMPAT_REJECT: @@ -943,8 +949,9 @@ struct ubi_scan_info *ubi_scan(struct ubi_device *ubi) * unclean reboots. However, many of them may indicate some problems * with the flash HW or driver. Print a warning in this case. */ - if (si->corr_count >= 8 || si->corr_count >= ubi->peb_count / 4) { - ubi_warn("%d PEBs are corrupted", si->corr_count); + if (si->corr_peb_count >= 8 || + si->corr_peb_count >= ubi->peb_count / 4) { + ubi_warn("%d PEBs are corrupted", si->corr_peb_count); printk(KERN_WARNING "corrupted PEBs are:"); list_for_each_entry(seb, &si->corr, u.list) printk(KERN_CONT " %d", seb->pnum); diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h index ff179ad..2576a8d 100644 --- a/drivers/mtd/ubi/scan.h +++ b/drivers/mtd/ubi/scan.h @@ -91,10 +91,16 @@ struct ubi_scan_volume { * @erase: list of physical eraseblocks which have to be erased * @alien: list of physical eraseblocks which should not be used by UBI (e.g., * those belonging to "preserve"-compatible internal volumes) + * @used_peb_count: count of used PEBs + * @corr_peb_count: count of PEBs in the @corr list + * @read_err_count: count of PEBs read with error (%UBI_IO_BAD_HDR_READ was + * returned) + * @free_peb_count: count of PEBs in the @free list + * @erase_peb_count: count of PEBs in the @erase list + * @alien_peb_count: count of PEBs in the @alien list * @bad_peb_count: count of bad physical eraseblocks * @vols_found: number of volumes found during scanning * @highest_vol_id: highest volume ID - * @alien_peb_count: count of physical eraseblocks in the @alien list * @is_empty: flag indicating whether the MTD device is empty or not * @min_ec: lowest erase counter value * @max_ec: highest erase counter value @@ -102,7 +108,6 @@ struct ubi_scan_volume { * @mean_ec: mean erase counter value * @ec_sum: a temporary variable used when calculating @mean_ec * @ec_count: a temporary variable used when calculating @mean_ec - * @corr_count: count of corrupted PEBs * * This data structure contains the result of scanning and may be used by other * UBI sub-systems to build final UBI data structures, further error-recovery @@ -114,10 +119,15 @@ struct ubi_scan_info { struct list_head free; struct list_head erase; struct list_head alien; + int used_peb_count; + int corr_peb_count; + int read_err_count; + int free_peb_count; + int erase_peb_count; + int alien_peb_count; int bad_peb_count; int vols_found; int highest_vol_id; - int alien_peb_count; int is_empty; int min_ec; int max_ec; @@ -125,7 +135,6 @@ struct ubi_scan_info { int mean_ec; uint64_t ec_sum; int ec_count; - int corr_count; }; struct ubi_device; @@ -135,7 +144,7 @@ struct ubi_vid_hdr; * ubi_scan_move_to_list - move a PEB from the volume tree to a list. * * @sv: volume scanning information - * @seb: scanning eraseblock infprmation + * @seb: scanning eraseblock information * @list: the list to move to */ static inline void ubi_scan_move_to_list(struct ubi_scan_volume *sv, -- 1.6.6.1 From Artem.Bityutskiy at nokia.com Mon May 3 06:12:59 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Mon, 3 May 2010 13:12:59 +0300 Subject: [PATCH 1/4] UBI: simplify IO error codes - part 1 In-Reply-To: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> Message-ID: <1272881582-17196-2-git-send-email-Artem.Bityutskiy@nokia.com> We do not really need 2 separate error codes for indicating bad VID and bad EC headers (UBI_IO_BAD_EC_HDR, UBI_IO_BAD_VID_HDR), it is enough to have only one UBI_IO_BAD_HDR return code. This patch does not introduce any functional change, only some code simplification. Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/eba.c | 4 ++-- drivers/mtd/ubi/io.c | 14 +++++++------- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/ubi.h | 7 ++----- 4 files changed, 13 insertions(+), 16 deletions(-) diff --git a/drivers/mtd/ubi/eba.c b/drivers/mtd/ubi/eba.c index 9f87c99..8e82267 100644 --- a/drivers/mtd/ubi/eba.c +++ b/drivers/mtd/ubi/eba.c @@ -418,7 +418,7 @@ retry: * may try to recover data. FIXME: but this is * not implemented. */ - if (err == UBI_IO_BAD_VID_HDR) { + if (err == UBI_IO_BAD_HDR) { ubi_warn("corrupted VID header at PEB " "%d, LEB %d:%d", pnum, vol_id, lnum); @@ -961,7 +961,7 @@ write_error: */ static int is_error_sane(int err) { - if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_VID_HDR || + if (err == -EIO || err == -ENOMEM || err == UBI_IO_BAD_HDR || err == -ETIMEDOUT) return 0; return 1; diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 533b1a4..6f5b087 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -515,7 +515,7 @@ static int nor_erase_prepare(struct ubi_device *ubi, int pnum) * In this case we probably anyway have garbage in this PEB. */ err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0); - if (err1 == UBI_IO_BAD_VID_HDR) + if (err1 == UBI_IO_BAD_HDR) /* * The VID header is corrupted, so we can safely erase this * PEB and not afraid that it will be treated as a valid PEB in @@ -709,7 +709,7 @@ bad: * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected * and corrected by the flash driver; this is harmless but may indicate that * this eraseblock may become bad soon (but may be not); - * o %UBI_IO_BAD_EC_HDR if the erase counter header is corrupted (a CRC error); + * o %UBI_IO_BAD_HDR if the erase counter header is corrupted (a CRC error); * o %UBI_IO_PEB_EMPTY if the physical eraseblock is empty; * o a negative error code in case of failure. */ @@ -774,7 +774,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_EC_HDR_MAGIC); - return UBI_IO_BAD_EC_HDR; + return UBI_IO_BAD_HDR; } crc = crc32(UBI_CRC32_INIT, ec_hdr, UBI_EC_HDR_SIZE_CRC); @@ -788,7 +788,7 @@ int ubi_io_read_ec_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad EC header CRC at PEB %d, calculated " "%#08x, read %#08x", pnum, crc, hdr_crc); - return UBI_IO_BAD_EC_HDR; + return UBI_IO_BAD_HDR; } /* And of course validate what has just been read from the media */ @@ -977,7 +977,7 @@ bad: * o %UBI_IO_BITFLIPS if the CRC is correct, but bit-flips were detected * and corrected by the flash driver; this is harmless but may indicate that * this eraseblock may become bad soon; - * o %UBI_IO_BAD_VID_HDR if the volume identifier header is corrupted (a CRC + * o %UBI_IO_BAD_HDR if the volume identifier header is corrupted (a CRC * error detected); * o %UBI_IO_PEB_FREE if the physical eraseblock is free (i.e., there is no VID * header there); @@ -1045,7 +1045,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad magic number at PEB %d: %08x instead of " "%08x", pnum, magic, UBI_VID_HDR_MAGIC); - return UBI_IO_BAD_VID_HDR; + return UBI_IO_BAD_HDR; } crc = crc32(UBI_CRC32_INIT, vid_hdr, UBI_VID_HDR_SIZE_CRC); @@ -1059,7 +1059,7 @@ int ubi_io_read_vid_hdr(struct ubi_device *ubi, int pnum, } else if (UBI_IO_DEBUG) dbg_msg("bad CRC at PEB %d, calculated %#08x, " "read %#08x", pnum, crc, hdr_crc); - return UBI_IO_BAD_VID_HDR; + return UBI_IO_BAD_HDR; } /* Validate the VID header that we have just read */ diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index dc5f688..f52adca 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -745,7 +745,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, bitflips = 1; else if (err == UBI_IO_PEB_EMPTY) return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); - else if (err == UBI_IO_BAD_EC_HDR) { + else if (err == UBI_IO_BAD_HDR) { /* * We have to also look at the VID header, possibly it is not * corrupted. Set %bitflips flag in order to make this PEB be @@ -813,7 +813,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, return err; else if (err == UBI_IO_BITFLIPS) bitflips = 1; - else if (err == UBI_IO_BAD_VID_HDR || + else if (err == UBI_IO_BAD_HDR || (err == UBI_IO_PEB_FREE && ec_corr)) { /* VID header is corrupted */ err = add_to_list(si, pnum, ec, &si->corr); diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h index a637f02..539b3f6 100644 --- a/drivers/mtd/ubi/ubi.h +++ b/drivers/mtd/ubi/ubi.h @@ -89,16 +89,13 @@ * %0xFF bytes * UBI_IO_PEB_FREE: the physical eraseblock is free, i.e. it contains only a * valid erase counter header, and the rest are %0xFF bytes - * UBI_IO_BAD_EC_HDR: the erase counter header is corrupted (bad magic or CRC) - * UBI_IO_BAD_VID_HDR: the volume identifier header is corrupted (bad magic or - * CRC) + * UBI_IO_BAD_HDR: the EC or VID header is corrupted (bad magic or CRC) * UBI_IO_BITFLIPS: bit-flips were detected and corrected */ enum { UBI_IO_PEB_EMPTY = 1, UBI_IO_PEB_FREE, - UBI_IO_BAD_EC_HDR, - UBI_IO_BAD_VID_HDR, + UBI_IO_BAD_HDR, UBI_IO_BITFLIPS }; -- 1.6.6.1 From okpalin at gmail.com Mon May 3 07:54:16 2010 From: okpalin at gmail.com (=?Big5?B?qkykX65t?=) Date: Mon, 3 May 2010 19:54:16 +0800 Subject: Can not mount UBIFS In-Reply-To: <1270544458.6754.15.camel@localhost> References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> Message-ID: Dear all, Thank you for your support. I can mount UBIFS now after fixing mtd read function. However, if I enable the "extra checks" of UBI and UBIFS, then I can not mount UBIFS. What's the different after enable "extra checks" of UBI and UBIFS. Thank you, Best regards, 2010/4/6 Artem Bityutskiy : > On Tue, 2010-03-16 at 16:13 +0800, ??? wrote: >> Dear all, >> >> I try to sync /driver/mtd/ubi/*, /fs/ubifs/*, and >> /include/linux/mtd/ubi.h with >> git://git.infradead.org/~dedekind/ubifs-v2.6.29.git >> But mount still fail. >> I will try nandsim latter. >> >> To get more information, I enable UBI and UBIFS debugging message, >> described below.. >> I enable UBI debugging: UBI debugging messages, Extra self-check, and >> all Aditional UBI debugging messages. >> I also enable UBIFS: Enable debugging with message level 3 and Enable >> extra checks. >> >> Below are my entered command and debug message get from "adb logcat" >> >> My entered command: >> # cat /proc/mtd >> cat /proc/mtd >> dev: size erasesize name >> mtd0: 00500000 00020000 "recovery" >> mtd1: 00800000 00020000 "boot" >> mtd2: 077a0000 00020000 "system" >> mtd3: 02000000 00020000 "cache" >> mtd4: 14b00000 00020000 "userdata" >> >> # flash_eraseall /dev/mtd/mtd3 >> flash_eraseall /dev/mtd/mtd3 >> Erasing 128 Kibyte @ 2000000 -- 100 % complete. >> >> # ubiattach /dev/ubi_ctrl -m 3 >> ubiattach /dev/ubi_ctrl -m 3 >> UBI device number 0, total 256 LEBs (32505856 bytes, 31.0 MiB), >> available 250 LEBs (31744000 bytes, 30.3 MiB), LEB size 126976 bytes >> (124.0 KiB) >> >> # ubinfo >> ubinfo >> UBI version: 1 >> Count of UBI devices: 1 >> UBI control device major/minor: 10:57 >> Present UBI devices: ubi0 >> >> # ubimkvol /dev/ubi0 -N rootfs -s 10MiB >> ubimkvol /dev/ubi0 -N rootfs -s 10MiB >> Volume ID 0, size 83 LEBs (10539008 bytes, 10.1 MiB), LEB size >> 126976 bytes (124.0 KiB), dynamic, name "rootfs", alignment 1 >> >> # ubinfo -a >> ubinfo -a >> UBI version: 1 >> Count of UBI devices: 1 >> UBI control device major/minor: 10:57 >> Present UBI devices: ubi0 >> >> ubi0 >> Volumes count: 1 >> Logical eraseblock size: 126976 bytes, 124.0 KiB >> Total amount of logical eraseblocks: 256 (32505856 bytes, 31.0 MiB) >> Amount of available logical eraseblocks: 167 (21204992 bytes, 20.2 MiB) >> Maximum count of volumes 128 >> Count of bad physical eraseblocks: 0 >> Count of reserved physical eraseblocks: 2 >> Current maximum erase counter value: 2 >> Minimum input/output unit size: 2048 bytes >> Character device major/minor: 249:0 >> Present volumes: 0 >> >> Volume ID: 0 (on ubi0) >> Type: dynamic >> Alignment: 1 >> Size: 83 LEBs (10539008 bytes, 10.1 MiB) >> State: OK >> Name: rootfs >> Character device major/minor: 249:1 >> >> # mount -t ubifs ubi0_0 /cache >> mount -t ubifs ubi0_0 /cache >> mount: Invalid argument >> >> # mount -t ubifs ubi0:rootfs /cache >> mount -t ubifs ubi0:rootfs /cache >> mount: Invalid argument >> >> Debug message from "adb logcat": >> <7>UBIFS DBG (pid 1378): ubifs_get_sb: name ubi0:rootfs, flags 0x8000 >> <7>UBI DBG (pid 1378): ubi_open_volume_path: open volume ubi0:rootfs, mode 1 >> <7>UBI DBG (pid 1378): ubi_open_volume_nm: open device 0, volume rootfs, mode 1 >> <7>UBI DBG (pid 1378): ubi_open_volume: open device 0, volume 0, mode 1 >> <7>UBIFS DBG (pid 1378): ubifs_get_sb: opened ubi0_0 >> <7>UBI DBG (pid 1378): ubi_open_volume: open device 0, volume 0, mode 2 >> <7>UBI DBG (pid 1378): ubi_is_mapped: test LEB 0:0 >> <7>UBIFS DBG (pid 1378): ubifs_read_node: LEB 0:0, superblock node, length 4096 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 4096 bytes from LEB 0:0:0 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 4096 bytes from offset 0 >> of LEB 0:0, PEB 1 >> <7>UBI DBG (pid 1378): ubi_io_read: read 4096 bytes from PEB 1:4096 >> <7>UBIFS DBG (pid 1378): ubifs_start_scan: scan LEB 1:0 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 126976 bytes from LEB 0:1:0 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 126976 bytes from offset >> 0 of LEB 0:1, PEB 129 >> <7>UBI DBG (pid 1378): ubi_io_read: read 126976 bytes from PEB 129:4096 >> <7>UBIFS DBG (pid 1380): ubifs_bg_thread: background thread >> "ubifs_bgt0_0" started, PID 1380 >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 1:0 (126976 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning master node >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 1:512 (126464 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning padding node >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: 1508 bytes padded, offset now 2048 >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 1:2048 (124928 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning master node >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 1:2560 (124416 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning padding node >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: 1508 bytes padded, offset now 4096 >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 1:4096 (122880 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: hit empty space >> <7>UBIFS DBG (pid 1378): ubifs_end_scan: stop scanning LEB 1 at offset 4096 >> <7>UBIFS DBG (pid 1378): ubifs_start_scan: scan LEB 2:0 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 126976 bytes from LEB 0:2:0 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 126976 bytes from offset >> 0 of LEB 0:2, PEB 130 >> <7>UBI DBG (pid 1378): ubi_io_read: read 126976 bytes from PEB 130:4096 >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 2:0 (126976 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning master node >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 2:512 (126464 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning padding node >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: 1508 bytes padded, offset now 2048 >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 2:2048 (124928 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning master node >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 2:2560 (124416 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: scanning padding node >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: 1508 bytes padded, offset now 4096 >> <7>UBIFS DBG (pid 1378): ubifs_scan: look at LEB 2:4096 (122880 bytes left) >> <7>UBIFS DBG (pid 1378): ubifs_scan_a_node: hit empty space >> <7>UBIFS DBG (pid 1378): ubifs_end_scan: stop scanning LEB 2 at offset 4096 >> <7>UBIFS DBG (pid 1378): ubifs_read_node: LEB 10:0, indexing node, length 48 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 48 bytes from LEB 0:10:0 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 48 bytes from offset 0 >> of LEB 0:10, PEB 131 >> <7>UBI DBG (pid 1378): ubi_io_read: read 48 bytes from PEB 131:4096 >> <5>UBIFS: recovery needed >> <7>UBIFS DBG (pid 1378): ubifs_recover_inl_heads: checking index head at 10:2048 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 2048 bytes from LEB 0:10:2048 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 2048 bytes from offset >> 2048 of LEB 0:10, PEB 131 >> <7>UBI DBG (pid 1378): ubi_io_read: read 2048 bytes from PEB 131:6144 >> <7>UBIFS DBG (pid 1378): ubifs_recover_inl_heads: checking LPT head at 6:2048 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 2048 bytes from LEB 0:6:2048 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 2048 bytes from offset >> 2048 of LEB 0:6, PEB 2 >> <7>UBI DBG (pid 1378): ubi_io_read: read 2048 bytes from PEB 2:6144 >> <7>UBI DBG (pid 1378): ubi_leb_read: read 11 bytes from LEB 0:6:419 >> <7>UBI DBG (pid 1378): ubi_eba_read_leb: read 11 bytes from offset 419 >> of LEB 0:6, PEB 2 >> <7>UBI DBG (pid 1378): ubi_io_read: read 11 bytes from PEB 2:4515 >> <3>UBIFS error (pid 1378): check_lpt_type: invalid type (0) in LPT node type 2 > > Looks like your drive has problems with reading 11 bytes. Please, > validate it. > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > > From dedekind1 at gmail.com Mon May 3 08:08:32 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 03 May 2010 15:08:32 +0300 Subject: Can not mount UBIFS In-Reply-To: References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> Message-ID: <1272888512.27729.46.camel@localhost> On Mon, 2010-05-03 at 19:54 +0800, ??? wrote: > Dear all, > > Thank you for your support. > I can mount UBIFS now after fixing mtd read function. > > However, if I enable the "extra checks" of UBI and UBIFS, then I can > not mount UBIFS. > What's the different after enable "extra checks" of UBI and UBIFS. Well, these are various self-checks. There are many of them and they are different. E.g., in UBI some of them read flash before every writing and make sure the area contains all 0xFF bytes. In UBIFS this can be walking through the whole index tree and checks it. There are many of them and they are different. If things stop working for you when you enable all checks, this either means a bug in the debugging code or a real problem. Please, post your error report. Use this guide: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_how_send_bugreport -- Best Regards, Artem Bityutskiy (????? ????????) From muehlfelder at enertex.de Mon May 3 09:05:18 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Mon, 3 May 2010 15:05:18 +0200 Subject: Some questions on bit-flips and JFFS2 Message-ID: <201005031505.18604.muehlfelder@enertex.de> Hi there, I'm experiencing some problems with bit-flips on devices using NAND and JFFS2: NAND device: Manufacturer ID: 0x2c, Chip ID: 0xdc (Micron NAND 512MiB 3,3V 8-bit) Creating 2 MTD partitions on "NAND 512MiB 3,3V 8-bit": 0x00000000-0x00a00000 : "Bootloader Area" 0x00a00000-0x20000000 : "User Area" In rare cases 1 or 2 bits in the bootloader area (kernel) flip, so that the system won't boot anymore (kernel checksum error). As the bootloader image is not mounted at all I wonder if this may be caused by these read disturbs I've heard of. I've found some statements from different people about it here on the ML: > We use JFFS2. As known JFFS2 detects and corrects single bit-flips > (per 256 byte subpage) but it doesn't physically correct them > on the NAND device itself. and: > AFAIK, jffs2 doesn't handle correctly bit flip on read: it won't try to > copy the data on another block while the data can still be recovered > by ecc. For me this means that data still is read correctly because of ECC but it won't get moved to a new block if a bit-flip happens? And what happens if this occours on the kernel partition? Furthermore: > > How about detection of ECC errors in read only partitions? > > ECC should be done on both rw and read-only partitions. Sometimes NAND gets > read disturbs which would impact on read-only partitions. Also, write > disturbs from writes to one partition can still corrupt a read-only > partition on the same chip. So writing to my root partition may harm my kernel partition, too? PS: I could not reproduce the bit-flip problem. It just happens in rare cases. Furthermore some of my devices are using Samsung NAND instead of the Micron NAND and did not show any problems yet. So perhaps my problem are just some bad NAND chip? But still I have to find a solution for the problem. From psanchez at fosstel.com Mon May 3 10:48:06 2010 From: psanchez at fosstel.com (Pedro I. Sanchez) Date: Mon, 03 May 2010 10:48:06 -0400 Subject: UBIFS and MLC NAND Flash In-Reply-To: <4BCCECC7.8000006@fosstel.com> References: <4BA7A183.7040206@fosstel.com> <1270714961.6754.107.camel@localhost> <4BCCECC7.8000006@fosstel.com> Message-ID: <4BDEE226.80205@fosstel.com> Pedro I. Sanchez wrote: > twebb wrote: >>>> 2. I have several boards with MLC NAND flash running the Linux kernel >>>> 2.6.29 and UBIFS. I am seeing a fairly large rate of file "corruption" >>>> errors, files that all of a sudden become unreadable. Curiously enough, >>>> they have been read-only files in all cases, program executables and >>>> shared libraries. >>> Hmm. Do you do unclean power cuts? >>> >>>> Would upgrading to a more recent kernel, or back porting the latest >>>> UBIFS code, help? Shall I expect better support for MLC NAND flash in >>>> the latest UBIFS code? >>> You did not specify whether you pulled the ubifs-v2.6.29.git tree. If >>> you did this, then your UBI/UBIFS should be the same as in the latest >>> kernels. Please, do this, although this will probably not solve your >>> corruption problems, but you'll have other bug-fixes we have made since >>> 2.6.29 times. >>> >>> >> >> Pedro, >> I'm seeing very similar issues with MLC+UBIFS, though not only with >> read-only files. Have you made any progress in your investigation or >> while trying Artem's suggestions? I'm about to start digging into >> this and would be interested to hear about any issues you may have >> come across. Do you have any opinion on whether this "corruption" is >> related to the information posted on the linux-mtd site at... >> http://www.linux-mtd.infradead.org/faq/ubifs.html#L_ubifs_mlc ? >> >> A few notes: >> - I do occasionally have power cuts, but my understanding was that >> UBI/UBIFS was very tolerant of that condition. >> - I use CONFIG_MTD_UBI_WL_THRESHOLD=256 >> - I'm using linux-2.6.29 >> >> Thanks, >> twebb > > I haven't had the opportunity to use 2.6.29 with the ubifs backport yet. > However, I run my devices over an extended operational test and couldn't > reproduce the errors. In this test I avoided any power cuts on purpose > because I wanted to verify that the boards' software was not at fault > during normal conditions. > > I still see the errors in the deployed boards and these ones are subject > to random power cuts. After analyzing the logs I conclude that there is > a strong correlation between the power cuts and the corruption errors. > The typical scenario is a board running fine for two months without > interruption, then a power cut, and then upon reboot a myriad of UBIFS > error messages show up (see sample following my signature) > > I'm almost convinced now that power cuts are the culprit. I will be > conducting test in the next few days to fully verify this. I'll post my > results. > > Thanks, > My tests are done. I arrived to the following conclusions: 1. All errors, zero-size files and random corruption, are related to power outages. 2. I was not able to reproduce any corruption errors under stable conditions (no sudden power cuts). We are now making some hardware mods to better handle power outages, basically holding the processor's reset line until power is stable. Item 2 above speaks well of the UBIFS layer anyway. Even though we have MLC flash I couldn't replicate any corruption problems. However, we are moving to SLC flash for our next round of boards anyway, just to be safe (or safer!). Thanks, -- Pedro From kirill at shutemov.name Mon May 3 12:56:07 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Mon, 3 May 2010 19:56:07 +0300 Subject: [PATCH] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1271934535.11751.1550.camel@macbook.infradead.org> References: <1271934535.11751.1550.camel@macbook.infradead.org> Message-ID: <1272905767-4317-1-git-send-email-kirill@shutemov.name> We cannot modify file->f_mapping->backing_dev_info, because it will corrupt backing device of device node inode, since file->f_mapping is equal to inode->i_mapping (see __dentry_open() in fs/open.c). Let's introduce separate inode for MTD device with appropriate backing device. Signed-off-by: Kirill A. Shutemov --- drivers/mtd/mtdchar.c | 70 +++++++++++++++++++++++++++++++++++++++++----- drivers/mtd/mtdcore.c | 3 ++ include/linux/mtd/mtd.h | 3 ++ 3 files changed, 68 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 5b081cb..24ea34f 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include +#define MTD_INODE_FS_MAGIC 0x11307854 +static struct vfsmount *mtd_inode_mnt __read_mostly; /* * Data structure to hold the pointer to the mtd device as well @@ -88,8 +91,21 @@ static int mtd_open(struct inode *inode, struct file *file) goto out; } - if (mtd->backing_dev_info) - file->f_mapping->backing_dev_info = mtd->backing_dev_info; + if (!mtd->inode) { + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); + mtd->inode->i_mode = S_IFCHR; + mtd->inode->i_rdev = inode->i_rdev; + if (mtd->backing_dev_info) { + mtd->inode->i_data.backing_dev_info = + mtd->backing_dev_info; + } + } + + spin_lock(&inode_lock); + __iget(mtd->inode); + spin_unlock(&inode_lock); + + file->f_mapping = mtd->inode->i_mapping; /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { @@ -125,6 +141,8 @@ static int mtd_close(struct inode *inode, struct file *file) if ((file->f_mode & FMODE_WRITE) && mtd->sync) mtd->sync(mtd); + iput(mtd->inode); + put_mtd_device(mtd); file->private_data = NULL; kfree(mfi); @@ -954,21 +972,57 @@ static const struct file_operations mtd_fops = { #endif }; +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, + mnt); +} + +static struct file_system_type mtd_inodefs_type = { + .name = "mtd_inodefs", + .get_sb = mtd_inodefs_get_sb, + .kill_sb = kill_anon_super, +}; + static int __init init_mtdchar(void) { - int status; + int ret; - status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); - if (status < 0) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); + ret = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); + if (ret < 0) { + pr_notice("Can't allocate major number %d for " + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); + return ret; + } + + ret = register_filesystem(&mtd_inodefs_type); + if (ret) { + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_chdev; + } + + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); + if (IS_ERR(mtd_inode_mnt)) { + ret = PTR_ERR(mtd_inode_mnt); + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_filesystem; } - return status; + return ret; + +err_unregister_chdev: + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); +err_unregister_filesystem: + unregister_filesystem(&mtd_inodefs_type); + return ret; } static void __exit cleanup_mtdchar(void) { + mntput(mtd_inode_mnt); + unregister_filesystem(&mtd_inodefs_type); unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index b177e75..980919e 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -383,6 +383,9 @@ int del_mtd_device (struct mtd_info *mtd) } else { struct mtd_notifier *not; + if (mtd->inode) + iput(mtd->inode); + device_unregister(&mtd->dev); /* No need to get a refcount on the module containing diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 0f32a9b..0589632 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,8 @@ struct mtd_info { */ struct backing_dev_info *backing_dev_info; + /* inode for mtd device */ + struct inode *inode; int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -- 1.7.0.4 From jack at suse.cz Mon May 3 14:54:21 2010 From: jack at suse.cz (Jan Kara) Date: Mon, 3 May 2010 20:54:21 +0200 Subject: [PATCH] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1272905767-4317-1-git-send-email-kirill@shutemov.name> References: <1271934535.11751.1550.camel@macbook.infradead.org> <1272905767-4317-1-git-send-email-kirill@shutemov.name> Message-ID: <20100503185421.GF3470@quack.suse.cz> On Mon 03-05-10 19:56:07, Kirill A. Shutemov wrote: > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > backing device of device node inode, since file->f_mapping is equal to > inode->i_mapping (see __dentry_open() in fs/open.c). > > Let's introduce separate inode for MTD device with appropriate backing > device. Now the patch looks much cleaner. Thanks! Having a separate fstype for a single inode seems like a bit of an overkill but I agree there doesn't seem to be a suitable filesystem where an inode could live, so it's probably OK. Two minor comments are below. > Signed-off-by: Kirill A. Shutemov > --- > drivers/mtd/mtdchar.c | 70 +++++++++++++++++++++++++++++++++++++++++----- > drivers/mtd/mtdcore.c | 3 ++ > include/linux/mtd/mtd.h | 3 ++ > 3 files changed, 68 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c > index 5b081cb..24ea34f 100644 > --- a/drivers/mtd/mtdchar.c > +++ b/drivers/mtd/mtdchar.c > @@ -88,8 +91,21 @@ static int mtd_open(struct inode *inode, struct file *file) > goto out; > } > > - if (mtd->backing_dev_info) > - file->f_mapping->backing_dev_info = mtd->backing_dev_info; > + if (!mtd->inode) { > + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); This can fail so you should check whether mtd->inode is != NULL. ... > static int __init init_mtdchar(void) > { > - int status; > + int ret; > > - status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); > - if (status < 0) { > - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", > - MTD_CHAR_MAJOR); > + ret = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); > + if (ret < 0) { > + pr_notice("Can't allocate major number %d for " > + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); > + return ret; > + } > + > + ret = register_filesystem(&mtd_inodefs_type); > + if (ret) { > + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); > + goto err_unregister_chdev; > + } > + > + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); > + if (IS_ERR(mtd_inode_mnt)) { > + ret = PTR_ERR(mtd_inode_mnt); > + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); > + goto err_unregister_filesystem; > } > > - return status; > + return ret; > + > +err_unregister_chdev: > + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); > +err_unregister_filesystem: > + unregister_filesystem(&mtd_inodefs_type); > + return ret; I think you should swap unregister_chrdev and unregister_filesystem blocks... Honza -- Jan Kara SUSE Labs, CR From kirill at shutemov.name Mon May 3 17:32:48 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Tue, 4 May 2010 00:32:48 +0300 Subject: [PATCH v2] mtd: Do not corrupt backing device of device node inode Message-ID: <1272922368-18517-1-git-send-email-kirill@shutemov.name> We cannot modify file->f_mapping->backing_dev_info, because it will corrupt backing device of device node inode, since file->f_mapping is equal to inode->i_mapping (see __dentry_open() in fs/open.c). Let's introduce separate inode for MTD device with appropriate backing device. Signed-off-by: Kirill A. Shutemov --- Changelog v1 -> v2: - Fix error handling based on comments by Jan Kara. --- drivers/mtd/mtdchar.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- drivers/mtd/mtdcore.c | 3 ++ include/linux/mtd/mtd.h | 3 ++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 5b081cb..11d7c4a 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include +#define MTD_INODE_FS_MAGIC 0x11307854 +static struct vfsmount *mtd_inode_mnt __read_mostly; /* * Data structure to hold the pointer to the mtd device as well @@ -88,11 +91,30 @@ static int mtd_open(struct inode *inode, struct file *file) goto out; } - if (mtd->backing_dev_info) - file->f_mapping->backing_dev_info = mtd->backing_dev_info; + if (!mtd->inode) { + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); + if (!mtd->inode) { + put_mtd_device(mtd); + ret = -ENOMEM; + goto out; + } + mtd->inode->i_mode = S_IFCHR; + mtd->inode->i_rdev = inode->i_rdev; + if (mtd->backing_dev_info) { + mtd->inode->i_data.backing_dev_info = + mtd->backing_dev_info; + } + } + + spin_lock(&inode_lock); + __iget(mtd->inode); + spin_unlock(&inode_lock); + + file->f_mapping = mtd->inode->i_mapping; /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { + iput(mtd->inode); put_mtd_device(mtd); ret = -EACCES; goto out; @@ -100,6 +122,7 @@ static int mtd_open(struct inode *inode, struct file *file) mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); if (!mfi) { + iput(mtd->inode); put_mtd_device(mtd); ret = -ENOMEM; goto out; @@ -125,6 +148,8 @@ static int mtd_close(struct inode *inode, struct file *file) if ((file->f_mode & FMODE_WRITE) && mtd->sync) mtd->sync(mtd); + iput(mtd->inode); + put_mtd_device(mtd); file->private_data = NULL; kfree(mfi); @@ -954,21 +979,57 @@ static const struct file_operations mtd_fops = { #endif }; +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, + mnt); +} + +static struct file_system_type mtd_inodefs_type = { + .name = "mtd_inodefs", + .get_sb = mtd_inodefs_get_sb, + .kill_sb = kill_anon_super, +}; + static int __init init_mtdchar(void) { - int status; + int ret; + + ret = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); + if (ret < 0) { + pr_notice("Can't allocate major number %d for " + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); + return ret; + } + + ret = register_filesystem(&mtd_inodefs_type); + if (ret) { + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_chdev; + } - status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); - if (status < 0) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); + if (IS_ERR(mtd_inode_mnt)) { + ret = PTR_ERR(mtd_inode_mnt); + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_filesystem; } - return status; + return ret; + +err_unregister_filesystem: + unregister_filesystem(&mtd_inodefs_type); +err_unregister_chdev: + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); + return ret; } static void __exit cleanup_mtdchar(void) { + mntput(mtd_inode_mnt); + unregister_filesystem(&mtd_inodefs_type); unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index b177e75..980919e 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -383,6 +383,9 @@ int del_mtd_device (struct mtd_info *mtd) } else { struct mtd_notifier *not; + if (mtd->inode) + iput(mtd->inode); + device_unregister(&mtd->dev); /* No need to get a refcount on the module containing diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 0f32a9b..0589632 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -177,6 +178,8 @@ struct mtd_info { */ struct backing_dev_info *backing_dev_info; + /* inode for mtd device */ + struct inode *inode; int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -- 1.7.0.4 From vaurora at redhat.com Mon May 3 19:12:14 2010 From: vaurora at redhat.com (Valerie Aurora) Date: Mon, 3 May 2010 16:12:14 -0700 Subject: [PATCH 15/39] fallthru: jffs2 fallthru support In-Reply-To: <1272928358-20854-1-git-send-email-vaurora@redhat.com> References: <1272928358-20854-1-git-send-email-vaurora@redhat.com> Message-ID: <1272928358-20854-16-git-send-email-vaurora@redhat.com> From: Felix Fietkau Add support for fallthru dentries to jffs2. Cc: David Woodhouse Cc: linux-mtd at lists.infradead.org Signed-off-by: Felix Fietkau Signed-off-by: Valerie Aurora --- fs/jffs2/dir.c | 36 +++++++++++++++++++++++++++++++++--- include/linux/jffs2.h | 6 ++++++ 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index c259193..98397b3 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -35,6 +35,7 @@ static int jffs2_rename (struct inode *, struct dentry *, struct inode *, struct dentry *); static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *); +static int jffs2_fallthru (struct inode *, struct dentry *); const struct file_operations jffs2_dir_operations = { @@ -59,6 +60,7 @@ const struct inode_operations jffs2_dir_inode_operations = .rename = jffs2_rename, .check_acl = jffs2_check_acl, .whiteout = jffs2_whiteout, + .fallthru = jffs2_fallthru, .setattr = jffs2_setattr, .setxattr = jffs2_setxattr, .getxattr = jffs2_getxattr, @@ -103,10 +105,14 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, } if (fd) { spin_lock(&target->d_lock); - if (fd->type == DT_WHT) + switch (fd->type) { + case DT_WHT: target->d_flags |= DCACHE_WHITEOUT; - else + case JFFS2_DT_FALLTHRU: + target->d_flags |= DCACHE_FALLTHRU; + default: ino = fd->ino; + } spin_unlock(&target->d_lock); } mutex_unlock(&dir_f->sem); @@ -164,7 +170,10 @@ static int jffs2_readdir(struct file *filp, void *dirent, filldir_t filldir) fd->name, fd->ino, fd->type, curofs, offset)); continue; } - if (!fd->ino) { + if (fd->type == JFFS2_DT_FALLTHRU) + /* XXX Should really do a lookup for the real inode number here */ + fd->ino = 100; + else if (!fd->ino && (fd->type != DT_WHT)) { D2(printk(KERN_DEBUG "Skipping deletion dirent \"%s\"\n", fd->name)); offset++; continue; @@ -793,6 +802,26 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de return 0; } +static int jffs2_fallthru (struct inode *dir, struct dentry *dentry) +{ + struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb); + uint32_t now; + int ret; + + now = get_seconds(); + ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_UNKNOWN, + dentry->d_name.name, dentry->d_name.len, now); + if (ret) + return ret; + + d_instantiate(dentry, NULL); + spin_lock(&dentry->d_lock); + dentry->d_flags |= DCACHE_FALLTHRU; + spin_unlock(&dentry->d_lock); + + return 0; +} + static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry, struct dentry *new_dentry) { @@ -825,6 +854,7 @@ static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry, return ret; spin_lock(&new_dentry->d_lock); + new_dentry->d_flags &= ~DCACHE_FALLTHRU; new_dentry->d_flags |= DCACHE_WHITEOUT; spin_unlock(&new_dentry->d_lock); d_add(new_dentry, NULL); diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 65533bb..dbe8c93 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -114,6 +114,12 @@ struct jffs2_unknown_node jint32_t hdr_crc; }; +/* + * Non-standard directory entry type(s), for on-disk use + */ + +#define JFFS2_DT_FALLTHRU (DT_WHT + 1) + struct jffs2_raw_dirent { jint16_t magic; -- 1.6.3.3 From vaurora at redhat.com Mon May 3 19:12:11 2010 From: vaurora at redhat.com (Valerie Aurora) Date: Mon, 3 May 2010 16:12:11 -0700 Subject: [PATCH 12/39] whiteout: jffs2 whiteout support In-Reply-To: <1272928358-20854-1-git-send-email-vaurora@redhat.com> References: <1272928358-20854-1-git-send-email-vaurora@redhat.com> Message-ID: <1272928358-20854-13-git-send-email-vaurora@redhat.com> From: Felix Fietkau Add support for whiteout dentries to jffs2. Signed-off-by: Felix Fietkau Signed-off-by: Valerie Aurora Cc: David Woodhouse Cc: linux-mtd at lists.infradead.org --- fs/jffs2/dir.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++- fs/jffs2/fs.c | 4 +++ fs/jffs2/super.c | 2 +- include/linux/jffs2.h | 2 + 4 files changed, 77 insertions(+), 3 deletions(-) diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 7aa4417..c259193 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c @@ -34,6 +34,8 @@ static int jffs2_mknod (struct inode *,struct dentry *,int,dev_t); static int jffs2_rename (struct inode *, struct dentry *, struct inode *, struct dentry *); +static int jffs2_whiteout (struct inode *, struct dentry *, struct dentry *); + const struct file_operations jffs2_dir_operations = { .read = generic_read_dir, @@ -56,6 +58,7 @@ const struct inode_operations jffs2_dir_inode_operations = .mknod = jffs2_mknod, .rename = jffs2_rename, .check_acl = jffs2_check_acl, + .whiteout = jffs2_whiteout, .setattr = jffs2_setattr, .setxattr = jffs2_setxattr, .getxattr = jffs2_getxattr, @@ -98,8 +101,14 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, fd = fd_list; } } - if (fd) - ino = fd->ino; + if (fd) { + spin_lock(&target->d_lock); + if (fd->type == DT_WHT) + target->d_flags |= DCACHE_WHITEOUT; + else + ino = fd->ino; + spin_unlock(&target->d_lock); + } mutex_unlock(&dir_f->sem); if (ino) { inode = jffs2_iget(dir_i->i_sb, ino); @@ -498,6 +507,11 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) return PTR_ERR(inode); } + if (dentry->d_flags & DCACHE_WHITEOUT) { + inode->i_flags |= S_OPAQUE; + ri->flags = cpu_to_je16(JFFS2_INO_FLAG_OPAQUE); + } + inode->i_op = &jffs2_dir_inode_operations; inode->i_fop = &jffs2_dir_operations; @@ -779,6 +793,60 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de return 0; } +static int jffs2_whiteout (struct inode *dir, struct dentry *old_dentry, + struct dentry *new_dentry) +{ + struct jffs2_sb_info *c = JFFS2_SB_INFO(dir->i_sb); + struct jffs2_inode_info *victim_f = NULL; + uint32_t now; + int ret; + + /* If it's a directory, then check whether it is really empty */ + if (new_dentry->d_inode) { + victim_f = JFFS2_INODE_INFO(old_dentry->d_inode); + if (S_ISDIR(old_dentry->d_inode->i_mode)) { + struct jffs2_full_dirent *fd; + + mutex_lock(&victim_f->sem); + for (fd = victim_f->dents; fd; fd = fd->next) { + if (fd->ino) { + mutex_unlock(&victim_f->sem); + return -ENOTEMPTY; + } + } + mutex_unlock(&victim_f->sem); + } + } + + now = get_seconds(); + ret = jffs2_do_link(c, JFFS2_INODE_INFO(dir), 0, DT_WHT, + new_dentry->d_name.name, new_dentry->d_name.len, now); + if (ret) + return ret; + + spin_lock(&new_dentry->d_lock); + new_dentry->d_flags |= DCACHE_WHITEOUT; + spin_unlock(&new_dentry->d_lock); + d_add(new_dentry, NULL); + + if (victim_f) { + /* There was a victim. Kill it off nicely */ + drop_nlink(old_dentry->d_inode); + /* Don't oops if the victim was a dirent pointing to an + inode which didn't exist. */ + if (victim_f->inocache) { + mutex_lock(&victim_f->sem); + if (S_ISDIR(old_dentry->d_inode->i_mode)) + victim_f->inocache->pino_nlink = 0; + else + victim_f->inocache->pino_nlink--; + mutex_unlock(&victim_f->sem); + } + } + + return 0; +} + static int jffs2_rename (struct inode *old_dir_i, struct dentry *old_dentry, struct inode *new_dir_i, struct dentry *new_dentry) { diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 3451a81..c1e333c 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c @@ -301,6 +301,10 @@ struct inode *jffs2_iget(struct super_block *sb, unsigned long ino) inode->i_op = &jffs2_dir_inode_operations; inode->i_fop = &jffs2_dir_operations; + + if (je16_to_cpu(latest_node.flags) & JFFS2_INO_FLAG_OPAQUE) + inode->i_flags |= S_OPAQUE; + break; } case S_IFREG: diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9a80e8e..c12cd1c 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -172,7 +172,7 @@ static int jffs2_fill_super(struct super_block *sb, void *data, int silent) sb->s_op = &jffs2_super_operations; sb->s_export_op = &jffs2_export_ops; - sb->s_flags = sb->s_flags | MS_NOATIME; + sb->s_flags = sb->s_flags | MS_NOATIME | MS_WHITEOUT; sb->s_xattr = jffs2_xattr_handlers; #ifdef CONFIG_JFFS2_FS_POSIX_ACL sb->s_flags |= MS_POSIXACL; diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h index 2b32d63..65533bb 100644 --- a/include/linux/jffs2.h +++ b/include/linux/jffs2.h @@ -87,6 +87,8 @@ #define JFFS2_INO_FLAG_USERCOMPR 2 /* User has requested a specific compression type */ +#define JFFS2_INO_FLAG_OPAQUE 4 /* Directory is opaque (for union mounts) */ + /* These can go once we've made sure we've caught all uses without byteswapping */ -- 1.6.3.3 From cernekee at gmail.com Mon May 3 20:46:12 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Mon, 3 May 2010 17:46:12 -0700 Subject: [PATCH] mtd: nand_base: Extend NAND flash detection to new MLC chips Message-ID: <430ce15d6a65533b5c3677b02498e5ff2e41c78c@localhost.localdomain> Some of the newer MLC devices have a 6-byte ID sequence in which several field definitions differ from older chips in a manner that is not backward compatible. For instance: Samsung K9GAG08U0M (5-byte sequence): ec d5 14 b6 74 4th byte, bits 1:0 encode the page size: 0=1KiB, 1=2KiB, 2=4KiB, 3=8KiB 4th byte, bits 5:4 encode the block size: 0=64KiB, 1=128KiB, ... 4th byte, bit 6 encodes the OOB size: 0=8B/512B, 1=16B/512B Samsung K9GAG08U0D (6-byte sequence): ec d5 94 29 34 41 4th byte, bits 1:0 encode the page size: 0=2KiB, 1=4KiB, 3=8KiB, 4=rsvd 4th byte, bits 7;5:4 encode the block size: 0=128KiB, 1=256KiB, ... 4th byte, bits 6;3:2 encode the OOB size: 1=128B/page, 2=218B/page This patch uses the new 6-byte scheme if the ID code wraps around exactly at byte 6, and falls back to the old scheme otherwise. Signed-off-by: Kevin Cernekee --- drivers/mtd/nand/nand_base.c | 60 ++++++++++++++++++++++++++++-------------- 1 files changed, 40 insertions(+), 20 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b9dc65c..2537ceb 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2774,8 +2774,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, int busw, int *maf_id, struct nand_flash_dev *type) { - int dev_id, maf_idx; - int tmp_id, tmp_manf; + int dev_id, maf_idx, i; + u8 id_data[8]; /* Select the device */ chip->select_chip(mtd, 0); @@ -2801,15 +2801,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - /* Read manufacturer and device IDs */ + /* Read entire ID string */ - tmp_manf = chip->read_byte(mtd); - tmp_id = chip->read_byte(mtd); + for (i = 0; i < 8; i++) + id_data[i] = chip->read_byte(mtd); - if (tmp_manf != *maf_id || tmp_id != dev_id) { + if (id_data[0] != *maf_id || id_data[1] != dev_id) { printk(KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n", __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, dev_id, id_data[0], id_data[1]); return ERR_PTR(-ENODEV); } @@ -2832,21 +2832,41 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (!type->pagesize) { int extid; /* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = chip->read_byte(mtd); + chip->cellinfo = id_data[2]; /* The 4th id byte is the important one */ - extid = chip->read_byte(mtd); - /* Calc pagesize */ - mtd->writesize = 1024 << (extid & 0x3); - extid >>= 2; - /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); - extid >>= 2; - /* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 * 1024) << (extid & 0x03); - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + extid = id_data[3]; + /* + * Field definitions are in the following datasheets: + * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) + * New style (6 byte ID): Samsung K9GAG08U0D (p.40) + * Check for wraparound at byte 6 to decide what to do. + */ + if (id_data[0] == id_data[6] && id_data[1] == id_data[7]) { + /* Calc pagesize */ + mtd->writesize = 2048 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; + extid >>= 2; + /* Calc blocksize */ + mtd->erasesize = (128 * 1024) << + (((extid >> 1) & 0x04) | (extid & 0x03)); + busw = 0; + } else { + /* Calc pagesize */ + mtd->writesize = 1024 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * + (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + } } else { /* * Old devices have chip data hardcoded in the device id table -- 1.6.3.1 From okpalin at gmail.com Mon May 3 23:20:43 2010 From: okpalin at gmail.com (=?Big5?B?qkykX65t?=) Date: Tue, 4 May 2010 11:20:43 +0800 Subject: Can not mount UBIFS In-Reply-To: <1272888512.27729.46.camel@localhost> References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> <1272888512.27729.46.camel@localhost> Message-ID: Dear all, I find the root cause: bootloader UBI image, written by bootloader, could not be mount. UBI image, written by ubiformat command, could be mount correctly. I guess that bootloader may not write ubi image correctly. I will port ubiformat in bootloader. Thank you, Best regards, 2010/5/3 Artem Bityutskiy : > On Mon, 2010-05-03 at 19:54 +0800, ??? wrote: >> Dear all, >> >> Thank you for your support. >> I can mount UBIFS now after fixing mtd read function. >> >> However, if I enable the "extra checks" of UBI and UBIFS, then I can >> not mount UBIFS. >> What's the different after enable "extra checks" of UBI and UBIFS. > > Well, these are various self-checks. There are many of them and they are > different. E.g., in UBI some of them read flash before every writing and > make sure the area contains all 0xFF bytes. In UBIFS this can be walking > through the whole index tree and checks it. There are many of them and > they are different. > > If things stop working for you when you enable all checks, this either > means a bug in the debugging code or a real problem. Please, post your > error report. Use this guide: > > http://www.linux-mtd.infradead.org/doc/ubifs.html#L_how_send_bugreport > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > > From cernekee at gmail.com Tue May 4 00:20:04 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Mon, 3 May 2010 21:20:04 -0700 Subject: [PATCH] mtd: Increase NAND_MAX_OOBSIZE from 128 to 256 Message-ID: NAND_MAX_OOBSIZE needs to be increased to support newer parts with 218 or 224 byte spare areas. Tested with Samsung K9GAG08U0D. Signed-off-by: Kevin Cernekee --- include/linux/mtd/nand.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 8bdacb8..50f3aa0 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -53,7 +53,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); * is supported now. If you add a chip with bigger oobsize/page * adjust this accordingly. */ -#define NAND_MAX_OOBSIZE 128 +#define NAND_MAX_OOBSIZE 256 #define NAND_MAX_PAGESIZE 4096 /* -- 1.6.3.1 From cernekee at gmail.com Tue May 4 00:14:39 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Mon, 3 May 2010 21:14:39 -0700 Subject: [PATCH] nanddump: Support 4096+218 and 4096+224 page sizes Message-ID: Tested with Samsung K9GAG08U0D. Signed-off-by: Kevin Cernekee --- nanddump.c | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/nanddump.c b/nanddump.c index 678d684..ae0e425 100644 --- a/nanddump.c +++ b/nanddump.c @@ -209,7 +209,9 @@ int main(int argc, char * const argv[]) } /* Make sure device page sizes are valid */ - if (!(meminfo.oobsize == 128 && meminfo.writesize == 4096) && + if (!(meminfo.oobsize == 224 && meminfo.writesize == 4096) && + !(meminfo.oobsize == 218 && meminfo.writesize == 4096) && + !(meminfo.oobsize == 128 && meminfo.writesize == 4096) && !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && !(meminfo.oobsize == 32 && meminfo.writesize == 1024) && !(meminfo.oobsize == 16 && meminfo.writesize == 512) && -- 1.6.3.1 From cernekee at gmail.com Tue May 4 01:10:41 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Mon, 3 May 2010 22:10:41 -0700 Subject: [PATCHv2] nanddump: Support 4096+218 and 4096+224 page sizes Message-ID: <947e853e5d1ba35a67546703267b0fabe59af110@localhost.localdomain> Tested with Samsung K9GAG08U0D (4096+218). This fixes three additional problems found after the initial patch submission: 1) oobbuf was only 128B. Needs to be 256B now. 2) Random OOB data is output when nanddump hits a bad block, because the code was initializing readbuf instead. 3) When using "-p", random data is displayed for bytes 218-223 since the OOB does not end on a 16B boundary. Signed-off-by: Kevin Cernekee --- nanddump.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-) diff --git a/nanddump.c b/nanddump.c index 678d684..4c0a094 100644 --- a/nanddump.c +++ b/nanddump.c @@ -174,8 +174,11 @@ static void process_options (int argc, char * const argv[]) /* * Buffers for reading data from flash */ + +#define NAND_MAX_OOBSIZE 256 + static unsigned char readbuf[4096]; -static unsigned char oobbuf[128]; +static unsigned char oobbuf[NAND_MAX_OOBSIZE]; /* * Main program @@ -209,7 +212,9 @@ int main(int argc, char * const argv[]) } /* Make sure device page sizes are valid */ - if (!(meminfo.oobsize == 128 && meminfo.writesize == 4096) && + if (!(meminfo.oobsize == 224 && meminfo.writesize == 4096) && + !(meminfo.oobsize == 218 && meminfo.writesize == 4096) && + !(meminfo.oobsize == 128 && meminfo.writesize == 4096) && !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && !(meminfo.oobsize == 32 && meminfo.writesize == 1024) && !(meminfo.oobsize == 16 && meminfo.writesize == 512) && @@ -354,9 +359,8 @@ int main(int argc, char * const argv[]) if (omitoob) continue; - if (badblock) { - memset (readbuf, 0xff, meminfo.oobsize); - } else { + memset (oobbuf, 0xff, NAND_MAX_OOBSIZE); + if (!badblock) { /* Read OOB data and exit on failure */ oob.start = ofs; if (ioctl(fd, MEMREADOOB, &oob) != 0) { -- 1.6.3.1 From shiraz.hashim at st.com Tue May 4 01:36:31 2010 From: shiraz.hashim at st.com (Shiraz HASHIM) Date: Tue, 04 May 2010 11:06:31 +0530 Subject: [Query] Serial Memory Interface Controller interface Message-ID: <4BDFB25F.8050305@st.com> Hi, I am working on ST's SMI controller for Serial NOR flashes. This controller is a special controller build specifically for serial memories (spi based). It has certain features directly catering to serial memories such as mapping of memory directly on the bus so that it can be directly accessed/addressed. Now the problem is that this controller cannot be exactly mapped in to SPI framework due to its features. What should be the best approach 1. To write serial nor flash drivers accessing smi controller (instead of SPI framework APIs) 2. To use some tricks and fit SMI controller into SPI framework itself. thanks for help regards Shiraz From nvbolhuis at aimvalley.nl Tue May 4 05:28:54 2010 From: nvbolhuis at aimvalley.nl (Norbert van Bolhuis) Date: Tue, 04 May 2010 11:28:54 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <201005031505.18604.muehlfelder@enertex.de> References: <201005031505.18604.muehlfelder@enertex.de> Message-ID: <4BDFE8D6.1050704@aimvalley.nl> Thorsten M?hlfelder wrote: > Hi there, > > I'm experiencing some problems with bit-flips on devices using NAND and JFFS2: > NAND device: Manufacturer ID: 0x2c, Chip ID: 0xdc (Micron NAND 512MiB 3,3V > 8-bit) > Creating 2 MTD partitions on "NAND 512MiB 3,3V 8-bit": > 0x00000000-0x00a00000 : "Bootloader Area" > 0x00a00000-0x20000000 : "User Area" > > In rare cases 1 or 2 bits in the bootloader area (kernel) flip, so that the > system won't boot anymore (kernel checksum error). > As the bootloader image is not mounted at all I wonder if this may be caused > by these read disturbs I've heard of. > This may very well be the case. > I've found some statements from different people about it here on the ML: > >> We use JFFS2. As known JFFS2 detects and corrects single bit-flips >> (per 256 byte subpage) but it doesn't physically correct them >> on the NAND device itself. > > and: > >> AFAIK, jffs2 doesn't handle correctly bit flip on read: it won't try to >> copy the data on another block while the data can still be recovered >> by ecc. > > For me this means that data still is read correctly because of ECC but it > won't get moved to a new block if a bit-flip happens? And what happens if > this occours on the kernel partition? > True. ECC is taken care of by the low-level MTD/NAND code (e.g. drivers/mtd/nand/nand_base.c). These routines do indicate errors but jffs2 doesn't really handle them (see jffs2_flash_read) The kernel partition is a bare MTD(BLOCK) partition so the block won't be moved or handled for sure. This means the same (=nothing) will happen. > Furthermore: >>> How about detection of ECC errors in read only partitions? >> ECC should be done on both rw and read-only partitions. Sometimes NAND gets >> read disturbs which would impact on read-only partitions. Also, write >> disturbs from writes to one partition can still corrupt a read-only >> partition on the same chip. > > So writing to my root partition may harm my kernel partition, too? > I don't know. Check/ask your hardware supplier. Micron may have some details/documents about this. > PS: I could not reproduce the bit-flip problem. It just happens in rare cases. > Furthermore some of my devices are using Samsung NAND instead of the Micron > NAND and did not show any problems yet. So perhaps my problem are just some > bad NAND chip? But still I have to find a solution for the problem. > Maybe, as said check/ask your hardware supplier. Maybe "refreshing" the block helps (that is saving the data, erasing the block(s) and reprogramming all data). You could try this. The best solution is of course UBIFS. UBI/UBIFS will handle bad blocks and read/write disturbs. Include your kernel partition into the (big) flash filesystem partition and start using UBIFS (i.s.o. JFFS2). hth, Norbert van Bolhuis. From jack at suse.cz Tue May 4 07:19:48 2010 From: jack at suse.cz (Jan Kara) Date: Tue, 4 May 2010 13:19:48 +0200 Subject: [PATCH v2] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1272922368-18517-1-git-send-email-kirill@shutemov.name> References: <1272922368-18517-1-git-send-email-kirill@shutemov.name> Message-ID: <20100504111947.GB3398@quack.suse.cz> On Tue 04-05-10 00:32:48, Kirill A. Shutemov wrote: > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > backing device of device node inode, since file->f_mapping is equal to > inode->i_mapping (see __dentry_open() in fs/open.c). > > Let's introduce separate inode for MTD device with appropriate backing > device. > > Signed-off-by: Kirill A. Shutemov The patch now looks correct to me. Acked-by: Jan Kara Honza > > --- > Changelog v1 -> v2: > - Fix error handling based on comments by Jan Kara. > > --- > drivers/mtd/mtdchar.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- > drivers/mtd/mtdcore.c | 3 ++ > include/linux/mtd/mtd.h | 3 ++ > 3 files changed, 75 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c > index 5b081cb..11d7c4a 100644 > --- a/drivers/mtd/mtdchar.c > +++ b/drivers/mtd/mtdchar.c > @@ -15,12 +15,15 @@ > #include > #include > #include > +#include > > #include > #include > > #include > > +#define MTD_INODE_FS_MAGIC 0x11307854 > +static struct vfsmount *mtd_inode_mnt __read_mostly; > > /* > * Data structure to hold the pointer to the mtd device as well > @@ -88,11 +91,30 @@ static int mtd_open(struct inode *inode, struct file *file) > goto out; > } > > - if (mtd->backing_dev_info) > - file->f_mapping->backing_dev_info = mtd->backing_dev_info; > + if (!mtd->inode) { > + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); > + if (!mtd->inode) { > + put_mtd_device(mtd); > + ret = -ENOMEM; > + goto out; > + } > + mtd->inode->i_mode = S_IFCHR; > + mtd->inode->i_rdev = inode->i_rdev; > + if (mtd->backing_dev_info) { > + mtd->inode->i_data.backing_dev_info = > + mtd->backing_dev_info; > + } > + } > + > + spin_lock(&inode_lock); > + __iget(mtd->inode); > + spin_unlock(&inode_lock); > + > + file->f_mapping = mtd->inode->i_mapping; > > /* You can't open it RW if it's not a writeable device */ > if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { > + iput(mtd->inode); > put_mtd_device(mtd); > ret = -EACCES; > goto out; > @@ -100,6 +122,7 @@ static int mtd_open(struct inode *inode, struct file *file) > > mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); > if (!mfi) { > + iput(mtd->inode); > put_mtd_device(mtd); > ret = -ENOMEM; > goto out; > @@ -125,6 +148,8 @@ static int mtd_close(struct inode *inode, struct file *file) > if ((file->f_mode & FMODE_WRITE) && mtd->sync) > mtd->sync(mtd); > > + iput(mtd->inode); > + > put_mtd_device(mtd); > file->private_data = NULL; > kfree(mfi); > @@ -954,21 +979,57 @@ static const struct file_operations mtd_fops = { > #endif > }; > > +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, > + const char *dev_name, void *data, > + struct vfsmount *mnt) > +{ > + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, > + mnt); > +} > + > +static struct file_system_type mtd_inodefs_type = { > + .name = "mtd_inodefs", > + .get_sb = mtd_inodefs_get_sb, > + .kill_sb = kill_anon_super, > +}; > + > static int __init init_mtdchar(void) > { > - int status; > + int ret; > + > + ret = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); > + if (ret < 0) { > + pr_notice("Can't allocate major number %d for " > + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); > + return ret; > + } > + > + ret = register_filesystem(&mtd_inodefs_type); > + if (ret) { > + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); > + goto err_unregister_chdev; > + } > > - status = register_chrdev(MTD_CHAR_MAJOR, "mtd", &mtd_fops); > - if (status < 0) { > - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", > - MTD_CHAR_MAJOR); > + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); > + if (IS_ERR(mtd_inode_mnt)) { > + ret = PTR_ERR(mtd_inode_mnt); > + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); > + goto err_unregister_filesystem; > } > > - return status; > + return ret; > + > +err_unregister_filesystem: > + unregister_filesystem(&mtd_inodefs_type); > +err_unregister_chdev: > + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); > + return ret; > } > > static void __exit cleanup_mtdchar(void) > { > + mntput(mtd_inode_mnt); > + unregister_filesystem(&mtd_inodefs_type); > unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); > } > > diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c > index b177e75..980919e 100644 > --- a/drivers/mtd/mtdcore.c > +++ b/drivers/mtd/mtdcore.c > @@ -383,6 +383,9 @@ int del_mtd_device (struct mtd_info *mtd) > } else { > struct mtd_notifier *not; > > + if (mtd->inode) > + iput(mtd->inode); > + > device_unregister(&mtd->dev); > > /* No need to get a refcount on the module containing > diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h > index 0f32a9b..0589632 100644 > --- a/include/linux/mtd/mtd.h > +++ b/include/linux/mtd/mtd.h > @@ -12,6 +12,7 @@ > #include > #include > #include > +#include > > #include > #include > @@ -177,6 +178,8 @@ struct mtd_info { > */ > struct backing_dev_info *backing_dev_info; > > + /* inode for mtd device */ > + struct inode *inode; > > int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); > int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); > -- > 1.7.0.4 > -- Jan Kara SUSE Labs, CR From nalajala.murali at gmail.com Tue May 4 07:39:57 2010 From: nalajala.murali at gmail.com (Murali N) Date: Tue, 4 May 2010 17:09:57 +0530 Subject: unable to run "flash_eraseall" on ARM target!!! Message-ID: Hi, i have compiled the mtd-utils for android using arm-eabi-4.4.0 tool chain. I tried erasing the flash using "flash_eraseall" on target but i am getting the below errors!!! # sh ./flash_eraseall sh ./flash_eraseall ./flash_eraseall: 1: Syntax error: word unexpected (expecting ")") # ./flash_eraseall ./flash_eraseall ./flash_eraseall: not found # sh /data/flash_eraseall sh /data/flash_eraseall /data/flash_eraseall: 1: Syntax error: word unexpected (expecting ")") # Why "flash_eraseall" was not found? i am running from the same directory where i have copied. Thanks for your help. From ricard.wanderlof at axis.com Tue May 4 07:44:35 2010 From: ricard.wanderlof at axis.com (Ricard Wanderlof) Date: Tue, 4 May 2010 13:44:35 +0200 (CEST) Subject: unable to run "flash_eraseall" on ARM target!!! In-Reply-To: References: Message-ID: On Tue, 4 May 2010, Murali N wrote: > Hi, > i have compiled the mtd-utils for android using arm-eabi-4.4.0 tool chain. > I tried erasing the flash using "flash_eraseall" on target but i am > getting the below errors!!! > > # sh ./flash_eraseall > sh ./flash_eraseall > ./flash_eraseall: 1: Syntax error: word unexpected (expecting ")") > # ./flash_eraseall > ./flash_eraseall > ./flash_eraseall: not found > # sh /data/flash_eraseall > sh /data/flash_eraseall > /data/flash_eraseall: 1: Syntax error: word unexpected (expecting ")") > # > > Why "flash_eraseall" was not found? i am running from the same > directory where i have copied. Have you made flash_eraseall executable? Looks like you've just copied it without doing chmod +x flash_eraseall afterwards. /Ricard -- Ricard Wolf Wanderl?f ricardw(at)axis.com Axis Communications AB, Lund, Sweden www.axis.com Phone +46 46 272 2016 Fax +46 46 13 61 30 From nalajala.murali at gmail.com Tue May 4 08:28:58 2010 From: nalajala.murali at gmail.com (Murali N) Date: Tue, 4 May 2010 17:58:58 +0530 Subject: unable to run "flash_eraseall" on ARM target!!! In-Reply-To: References: Message-ID: yes, permissions are clearly set. -rwxrwxrwx root root 17189 2010-05-04 11:03 flash_eraseall On Tue, May 4, 2010 at 5:14 PM, Ricard Wanderlof wrote: > > On Tue, 4 May 2010, Murali N wrote: > >> Hi, >> i have compiled the mtd-utils for android using arm-eabi-4.4.0 tool chain. >> I tried erasing the flash using "flash_eraseall" on target but i am >> getting the below errors!!! >> >> # sh ./flash_eraseall >> ? ?sh ./flash_eraseall >> ? ?./flash_eraseall: 1: Syntax error: word unexpected (expecting ")") >> # ./flash_eraseall >> ? ./flash_eraseall >> ? ./flash_eraseall: not found >> # sh /data/flash_eraseall >> ? sh /data/flash_eraseall >> ? /data/flash_eraseall: 1: Syntax error: word unexpected (expecting ")") >> # >> >> Why "flash_eraseall" was not found? i am running from the same >> directory where i have copied. > > Have you made flash_eraseall executable? Looks like you've just copied it > without doing ? chmod +x flash_eraseall ?afterwards. > > /Ricard > -- > Ricard Wolf Wanderl?f ? ? ? ? ? ? ? ? ? ? ? ? ? ricardw(at)axis.com > Axis Communications AB, Lund, Sweden ? ? ? ? ? ?www.axis.com > Phone +46 46 272 2016 ? ? ? ? ? ? ? ? ? ? ? ? ? Fax +46 46 13 61 30 > -- Regards, Murali N From dedekind1 at gmail.com Tue May 4 09:04:32 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 16:04:32 +0300 Subject: [PATCHv2] MTD: Suppress warnings in inline_map_read() In-Reply-To: <1272354388.26036.4.camel@localhost> References: <1270891582.4704.102.camel@macbook.infradead.org> <1272354388.26036.4.camel@localhost> Message-ID: <1272978272.3702.5.camel@localhost> On Tue, 2010-04-27 at 10:46 +0300, Artem Bityutskiy wrote: > On Sat, 2010-04-10 at 11:18 -0700, Kevin Cernekee wrote: > > With gcc 4.4.3 -O2 on MIPS32: > > > > drivers/mtd/chips/cfi_util.c: In function 'cfi_qry_present': > > include/linux/mtd/map.h:390: warning: 'r' may be used uninitialized in this function > > include/linux/mtd/map.h:375: note: 'r' was declared here > > include/linux/mtd/map.h:390: warning: 'r' may be used uninitialized in this function > > include/linux/mtd/map.h:375: note: 'r' was declared here > > > > Signed-off-by: Kevin Cernekee > > Pushed to l2-mtd-2.6 / dunno Removed from my tree because this breaks compilation: [dedekind at eru l2-mtd-2.6]$ make ARCH=arm O=/home/dedekind/tmp/l2-mtd-2.6-arm/ Using /home/dedekind/git/l2-mtd-2.6 as source for kernel GEN /home/dedekind/tmp/l2-mtd-2.6-arm/Makefile CHK include/linux/version.h CHK include/generated/utsrelease.h make[2]: `include/generated/mach-types.h' is up to date. CALL /home/dedekind/git/l2-mtd-2.6/scripts/checksyscalls.sh CHK include/generated/compile.h CC [M] drivers/mtd/lpddr/lpddr_cmds.o In file included from /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/qinfo.h:4, from /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/pfow.h:7, from /home/dedekind/git/l2-mtd-2.6/drivers/mtd/lpddr/lpddr_cmds.c:27: /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/map.h: In function 'inline_map_read': /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/map.h:390: error: implicit declaration of function 'BUG' make[4]: *** [drivers/mtd/lpddr/lpddr_cmds.o] Error 1 make[3]: *** [drivers/mtd/lpddr] Error 2 make[2]: *** [drivers/mtd] Error 2 make[1]: *** [drivers] Error 2 make: *** [sub-make] Error 2 [dedekind at eru l2-mtd-2.6]$ git revert ae60e258dda8a9c575fcbd68f05ca034ad043a36^C [dedekind at eru l2-mtd-2.6]$ git log -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Tue May 4 09:11:13 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 16:11:13 +0300 Subject: [PATCH 1/2] mtd/chips: add SST39WF160x NOR-flashes In-Reply-To: <1272334774-17019-1-git-send-email-w.sang@pengutronix.de> References: <1272334774-17019-1-git-send-email-w.sang@pengutronix.de> Message-ID: <1272978673.3702.6.camel@localhost> On Tue, 2010-04-27 at 04:19 +0200, Wolfram Sang wrote: > Due to a broken CFI, they have to be added to jedec_probe. > > Signed-off-by: Wolfram Sang > Cc: Artem Bityutskiy > Cc: David Woodhouse > --- > > Sadly, those two cannot be detected using Guillaume's SST-patchset. > > drivers/mtd/chips/jedec_probe.c | 30 ++++++++++++++++++++++++++++++ > 1 files changed, 30 insertions(+), 0 deletions(-) Pushed both to my l2-mtd-2.6 / dunno -- Best Regards, Artem Bityutskiy (????? ????????) From chohnstaedt at innominate.com Tue May 4 09:28:24 2010 From: chohnstaedt at innominate.com (Christian Hohnstaedt) Date: Tue, 4 May 2010 15:28:24 +0200 Subject: unable to run "flash_eraseall" on ARM target!!! In-Reply-To: References: Message-ID: <20100504132824.GM20932@elara.bln.innominate.local> Hi, On Tue, May 04, 2010 at 05:09:57PM +0530, Murali N wrote: > Hi, > i have compiled the mtd-utils for android using arm-eabi-4.4.0 tool chain. > I tried erasing the flash using "flash_eraseall" on target but i am > getting the below errors!!! > > # ./flash_eraseall > ./flash_eraseall > ./flash_eraseall: not found This looks like a missing library loader. Did you link dynamically ? Do you have ld-linux.so (glibc) or ld-uClibc.so (ulibc) in /lib ? Christian -- Christian Hohnstaedt / Project Manager Hardware and Manufacturing Innominate Security Technologies AG / protecting industrial networks tel: +49.30.921028.208 / fax: +49.30.921028.020 Rudower Chaussee 13, D-12489 Berlin / http://www.innominate.com Register Court: AG Charlottenburg, HR B 81603 Management Board: Dirk Seewald Chairman of the Supervisory Board: Volker Bibelhausen From dedekind1 at gmail.com Tue May 4 09:21:41 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 16:21:41 +0300 Subject: [PATCH v2] Add support for Samsung SoC OneNAND controllers In-Reply-To: <1272469609-21876-1-git-send-email-m.szyprowski@samsung.com> References: <1272469609-21876-1-git-send-email-m.szyprowski@samsung.com> Message-ID: <1272979301.3702.8.camel@localhost> On Wed, 2010-04-28 at 17:46 +0200, Marek Szyprowski wrote: > This patch series add support for Samsung SoC OneNAND controllers found > on S3C64xx, S5PC100 and S5PC110 chips. A few extensions to OneNAND core > were required to make the driver working properly on all supported SoCs. > > The required platform setup code has been posted to relevant mailing > list (ARM Kernel: "[PATCH] ARM: Samsung: Add platform support code for > OneNAND controller" thread). > > Changes since v1: > * addressed all coding style issues reported by Ben Dooks > * moved all resource definitions to platform device resources > * moved all resource definitions for different SoCs from regs-onenand.h to > arch/arm/mach-{s3c64xx,s5pc100,s5pv210}/include/mach/map.h > * moved all #ifdef conditional code to separate functions > > This patch series includes: > > [PATCH 1/5] drivers: mtd: onenand: add support for chips with 4KB page size > [PATCH 2/5] drivers: mtd: onenand: allocate verify buffer in the core > [PATCH 3/5] drivers: mtd: onenand: add new callback for bufferram read > [PATCH 4/5] drivers: mtd: onenand: add workaround for SYNC_WRITE mode > [PATCH 5/5] drivers: mtd: add Samsung SoC OneNAND driver Pushed this series to my l2-mtd-2.6.git / dunno -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Tue May 4 09:45:55 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 16:45:55 +0300 Subject: [PATCH v2] mtdchar: allow mmap() on MTD RAM/ROM char devices In-Reply-To: <20100429161320.3b179f6c@wker> References: <1272461518.7750.31.camel@localhost> <1272471640-27073-1-git-send-email-agust@denx.de> <20100429161320.3b179f6c@wker> Message-ID: <1272980755.3702.9.camel@localhost> On Thu, 2010-04-29 at 16:13 +0200, Anatolij Gustschin wrote: > Hi Artem, > > On Wed, 28 Apr 2010 18:20:40 +0200 > Anatolij Gustschin wrote: > > > Signed-off-by: Anatolij Gustschin > > --- > > v1 -> v2: > > - Fixed compilation breakage on x86_64 while compiling > > as module, since on x86_64 phys_mem_access_prot() is > > not exported. Sorry for the breakage. > > > > drivers/mtd/mtdchar.c | 30 +++++++++++++++++++++++++++++- > > 1 files changed, 29 insertions(+), 1 deletions(-) > > Is this patch ok now? Not sure, I did not really review it, but it compiles now and I've pushed it to my l2-mtd-2.6 / dunno tree. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Tue May 4 09:47:43 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 16:47:43 +0300 Subject: [PATCH] mpc5121_nfc: Changed SVR check to allow MPC5123. In-Reply-To: <181804936ABC2349BE503168465576460E95836C@exchserver.basler.com> References: <181804936ABC2349BE503168465576460E95836C@exchserver.basler.com> Message-ID: <1272980863.3702.10.camel@localhost> On Wed, 2010-04-28 at 17:33 -0500, Steve Deiters wrote: > The revision in SVR for MPC5123 is 3. The NFC is the same as MPC5121 > revision 2. > > --- > drivers/mtd/nand/mpc5121_nfc.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > Please, add your Signed-off-by and re-send. -- Best Regards, Artem Bityutskiy (????? ????????) From nalajala.murali at gmail.com Tue May 4 10:21:43 2010 From: nalajala.murali at gmail.com (Murali N) Date: Tue, 4 May 2010 19:51:43 +0530 Subject: unable to run "flash_eraseall" on ARM target!!! In-Reply-To: <20100504132824.GM20932@elara.bln.innominate.local> References: <20100504132824.GM20932@elara.bln.innominate.local> Message-ID: file flash_eraseall produce flash_eraseall: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), not stripped. It is linked against bionic libc (android specific) library. Aslo i am able to see the libc.so under /system/lib/ On Tue, May 4, 2010 at 6:58 PM, Christian Hohnstaedt wrote: > Hi, > > On Tue, May 04, 2010 at 05:09:57PM +0530, Murali N wrote: >> Hi, >> i have compiled the mtd-utils for android using arm-eabi-4.4.0 tool chain. >> I tried erasing the flash using "flash_eraseall" on target but i am >> getting the below errors!!! >> >> # ./flash_eraseall >> ? ? ./flash_eraseall >> ? ? ./flash_eraseall: not found > > This looks like a missing library loader. > Did you link dynamically ? > Do you have ld-linux.so (glibc) or ld-uClibc.so (ulibc) in /lib ? > > > Christian > > -- > Christian Hohnstaedt / Project Manager Hardware and Manufacturing > > Innominate Security Technologies AG / protecting industrial networks > tel: +49.30.921028.208 / fax: +49.30.921028.020 > Rudower Chaussee 13, D-12489 Berlin / http://www.innominate.com > > Register Court: AG Charlottenburg, HR B 81603 > Management Board: Dirk Seewald > Chairman of the Supervisory Board: Volker Bibelhausen > -- Regards, Murali N From dedekind1 at gmail.com Tue May 4 10:17:07 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 17:17:07 +0300 Subject: UBIFS and MLC NAND Flash In-Reply-To: <4BDEE226.80205@fosstel.com> References: <4BA7A183.7040206@fosstel.com> <1270714961.6754.107.camel@localhost> <4BCCECC7.8000006@fosstel.com> <4BDEE226.80205@fosstel.com> Message-ID: <1272982627.3702.15.camel@localhost> On Mon, 2010-05-03 at 10:48 -0400, Pedro I. Sanchez wrote: > Pedro I. Sanchez wrote: > > twebb wrote: > >>>> 2. I have several boards with MLC NAND flash running the Linux kernel > >>>> 2.6.29 and UBIFS. I am seeing a fairly large rate of file "corruption" > >>>> errors, files that all of a sudden become unreadable. Curiously enough, > >>>> they have been read-only files in all cases, program executables and > >>>> shared libraries. > >>> Hmm. Do you do unclean power cuts? > >>> > >>>> Would upgrading to a more recent kernel, or back porting the latest > >>>> UBIFS code, help? Shall I expect better support for MLC NAND flash in > >>>> the latest UBIFS code? > >>> You did not specify whether you pulled the ubifs-v2.6.29.git tree. If > >>> you did this, then your UBI/UBIFS should be the same as in the latest > >>> kernels. Please, do this, although this will probably not solve your > >>> corruption problems, but you'll have other bug-fixes we have made since > >>> 2.6.29 times. > >>> > >>> > >> > >> Pedro, > >> I'm seeing very similar issues with MLC+UBIFS, though not only with > >> read-only files. Have you made any progress in your investigation or > >> while trying Artem's suggestions? I'm about to start digging into > >> this and would be interested to hear about any issues you may have > >> come across. Do you have any opinion on whether this "corruption" is > >> related to the information posted on the linux-mtd site at... > >> http://www.linux-mtd.infradead.org/faq/ubifs.html#L_ubifs_mlc ? > >> > >> A few notes: > >> - I do occasionally have power cuts, but my understanding was that > >> UBI/UBIFS was very tolerant of that condition. > >> - I use CONFIG_MTD_UBI_WL_THRESHOLD=256 > >> - I'm using linux-2.6.29 > >> > >> Thanks, > >> twebb > > > > I haven't had the opportunity to use 2.6.29 with the ubifs backport yet. > > However, I run my devices over an extended operational test and couldn't > > reproduce the errors. In this test I avoided any power cuts on purpose > > because I wanted to verify that the boards' software was not at fault > > during normal conditions. > > > > I still see the errors in the deployed boards and these ones are subject > > to random power cuts. After analyzing the logs I conclude that there is > > a strong correlation between the power cuts and the corruption errors. > > The typical scenario is a board running fine for two months without > > interruption, then a power cut, and then upon reboot a myriad of UBIFS > > error messages show up (see sample following my signature) > > > > I'm almost convinced now that power cuts are the culprit. I will be > > conducting test in the next few days to fully verify this. I'll post my > > results. > > > > Thanks, > > > My tests are done. I arrived to the following conclusions: > > 1. All errors, zero-size files and random corruption, are related to > power outages. Well, on SLC we did huge amount of power-cut tests and were always able to mount the FS. Zero-files and zeroes in files are possible, and this is described here: http://www.linux-mtd.infradead.org/faq/ubifs.html#L_empty_file http://www.linux-mtd.infradead.org/faq/ubifs.html#L_end_hole Not sure what you mean by random corruption, but this is probably something which should not happen. But a better description would be interesting. Anyway, if you have problems, they are probably MLC-specific, and of course it would be nice if someone with the real HW would investigate and fix them... -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Tue May 4 10:19:17 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 04 May 2010 17:19:17 +0300 Subject: [PATCH v2] mtd: Do not corrupt backing device of device node inode In-Reply-To: <20100504111947.GB3398@quack.suse.cz> References: <1272922368-18517-1-git-send-email-kirill@shutemov.name> <20100504111947.GB3398@quack.suse.cz> Message-ID: <1272982757.3702.16.camel@localhost> On Tue, 2010-05-04 at 13:19 +0200, Jan Kara wrote: > On Tue 04-05-10 00:32:48, Kirill A. Shutemov wrote: > > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > > backing device of device node inode, since file->f_mapping is equal to > > inode->i_mapping (see __dentry_open() in fs/open.c). > > > > Let's introduce separate inode for MTD device with appropriate backing > > device. > > > > Signed-off-by: Kirill A. Shutemov > The patch now looks correct to me. Acked-by: Jan Kara > Is this -stable material? -- Best Regards, Artem Bityutskiy (????? ????????) From muehlfelder at enertex.de Tue May 4 10:59:26 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Tue, 4 May 2010 16:59:26 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <4BDFE8D6.1050704@aimvalley.nl> References: <201005031505.18604.muehlfelder@enertex.de> <4BDFE8D6.1050704@aimvalley.nl> Message-ID: <201005041659.26262.muehlfelder@enertex.de> Am Tuesday 04 May 2010 11:28:54 schrieb Norbert van Bolhuis: > Thorsten M?hlfelder wrote: > > Hi there, > > > > I'm experiencing some problems with bit-flips on devices using NAND and > > JFFS2: NAND device: Manufacturer ID: 0x2c, Chip ID: 0xdc (Micron NAND > > 512MiB 3,3V 8-bit) > > Creating 2 MTD partitions on "NAND 512MiB 3,3V 8-bit": > > 0x00000000-0x00a00000 : "Bootloader Area" > > 0x00a00000-0x20000000 : "User Area" > > > > In rare cases 1 or 2 bits in the bootloader area (kernel) flip, so that > > the system won't boot anymore (kernel checksum error). > > As the bootloader image is not mounted at all I wonder if this may be > > caused by these read disturbs I've heard of. ... > > PS: I could not reproduce the bit-flip problem. It just happens in rare > > cases. Furthermore some of my devices are using Samsung NAND instead of > > the Micron NAND and did not show any problems yet. So perhaps my problem > > are just some bad NAND chip? But still I have to find a solution for the > > problem. > > Maybe, as said check/ask your hardware supplier. > Maybe "refreshing" the block helps (that is saving the data, erasing the > block(s) and reprogramming all data). You could try this. I've already thought about something like this: 1. After first succesful bootup dump a mtd0 image and calculate a md5sum of it: nanddump -o -b -f mtd0.img /dev/mtd0 2. Before each shutdown dump the image again and check if the md5sum has changed. 3. If it has changed write the initial dump back: flash_eraseall /dev/mtd0 nandwrite -p /dev/mtd0 mtd0.img Would this be the right method? > The best solution is of course UBIFS. UBI/UBIFS will handle bad blocks and > read/write disturbs. Include your kernel partition into the (big) flash > filesystem partition and start using UBIFS (i.s.o. JFFS2). Is there any How-To for U-Boot? Greetings Thorsten From arno.steffen at googlemail.com Tue May 4 11:03:29 2010 From: arno.steffen at googlemail.com (Arno Steffen) Date: Tue, 4 May 2010 17:03:29 +0200 Subject: strange flash effects - ask for help Message-ID: you probably sick and tired of question to messages like "Empty flash at 0x009cf28c ends at 0x009cf800" But I coudn't found enough information about that. To finally clear that stuff - may I ask some question? Please help! 1) Is this a jffs2 message? So in other words - is it an absolute flash address of with offset to a mounted jffs partion? In case of an offset and I would have more than one jffs partion - where do I know from which has a problem? 2) From what I read is this message caused by a mismatch of erasesize of flash-IC / settings for linux ( which can be seen in /proc/mtd) and building the jffs-fs whith mkfs.jffs2 ( -e parameter). I did used the 1.6 version of mkfs.jffs2 (recent 1.3.1 mtdutil) and with both 128 and 131072 (kB and B) size. Both resulting jffs files are same (that has been different in 1.5) 3) cat /proc/mtd dev: size erasesize name mtd0: 00020000 00020000 "X-Loader" mtd1: 00080000 00020000 "U-Boot" mtd2: 00020000 00020000 "U-Boot Environment" mtd3: 00400000 00020000 "Kernel(1)" mtd4: 00400000 00020000 "Kernel(2)" mtd5: 02800000 00020000 "system(1)" mtd6: 02800000 00020000 "system(2)" mtd7: 02740000 00020000 "extra" looks fine for the 128kByte / 131072 byte setting. "mkfs.jffs2 -lqnp -e 128 -r /opt/rootfs -o /mnt/hgfs/share/rootfs.jffs2" Nevertheless I get this message "empty flash .." while booting after I changed something in the filesystem (even with a clean "halt"). As this is just a part of my flash-fs problems, I need to know, whats going wrong here. 4) After a while of power cycles I get messages like uncorrectable error : <3>uncorrectable error : <3>uncorrectable error : <3>uncorrectable error : <3>uncorrectable error : <3>uncorrectable error : <3>uncorrectable error : <3>uncorrectable error : <4>mtd->read(0x1fa14 bytes from 0x1c05ec) returned ECC error jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x001cc504: 0xadd7 instead jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x001cc508: 0xc179 instead jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x001cc50c: 0xcbae instead and JFFS2 notice: (1) jffs2_get_inode_nodes: Node header CRC failed at 0x1cc594. {e99d,d185,2da85850,efc64922} although I don't believe to write anything into flash) What does this <3> and <4> and this messages mean and how to prevent them? ------------- The filesystem has been flashed in uboot with "nandecc sw; nand write.i 0x81600000 8c0000 2800000" (of course cleaning the RAM with ff and loading the jffs2) I do have 2 badblocks inside, but they are not in the area of the message above. uboot: 0x1400000 / flash_eraseall: 0xb40000 uboot: 0x1600000 / flash_eraseall: 0xd40000 (I guess linux message is relative to its /dev/mtd5) boot message: Creating 8 MTD partitions on "omap2-nand.0": 0x00000000-0x00020000 : "X-Loader" 0x00020000-0x000a0000 : "U-Boot" 0x000a0000-0x000c0000 : "U-Boot Environment" 0x000c0000-0x004c0000 : "Kernel(1)" 0x004c0000-0x008c0000 : "Kernel(2)" 0x008c0000-0x030c0000 : "system(1)" 0x030c0000-0x058c0000 : "system(2)" 0x058c0000-0x08000000 : "extra" 5) How can I come closer to repair or inspect it? Thanks! Arno From cernekee at gmail.com Tue May 4 15:51:34 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Tue, 4 May 2010 12:51:34 -0700 Subject: [PATCH] mtd: map.h: add missing bug.h include Message-ID: Signed-off-by: Kevin Cernekee --- include/linux/mtd/map.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h index b981b87..01703d4 100644 --- a/include/linux/mtd/map.h +++ b/include/linux/mtd/map.h @@ -7,6 +7,7 @@ #include #include #include +#include #include -- 1.6.3.1 From cernekee at gmail.com Tue May 4 16:06:51 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Tue, 4 May 2010 13:06:51 -0700 Subject: [PATCHv2] MTD: Suppress warnings in inline_map_read() In-Reply-To: <1272978272.3702.5.camel@localhost> References: <1270891582.4704.102.camel@macbook.infradead.org> <1272354388.26036.4.camel@localhost> <1272978272.3702.5.camel@localhost> Message-ID: On Tue, May 4, 2010 at 6:04 AM, Artem Bityutskiy wrote: > /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/map.h: In function 'inline_map_read': > /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/map.h:390: error: implicit declaration of function 'BUG' I did test my patch, but it didn't generate any warnings or errors on MIPS... Could you please apply this patch and retry: http://lists.infradead.org/pipermail/linux-mtd/2010-May/029904.html should probably be added anyway since there are two other BUG statements in that file. Thanks. From tony at atomide.com Tue May 4 18:08:03 2010 From: tony at atomide.com (Tony Lindgren) Date: Tue, 4 May 2010 15:08:03 -0700 Subject: Upcoming merge window and omap NAND patches Message-ID: <20100504220803.GN29604@atomide.com> Hi all, There are several omap NAND patches pending, but some basic things should be fixed first. 1. The NAND driver needs to stop tinkering with the GPMC registers The omap General Purpose Memory Controller (GPMC) registers are omap specific, and not driver specific. Tinkering with these registers can cause issues with the other devices on the GPMC. To find out what needs to disappear fomr the NAND driver, just do: $ grep baseaddr drivers/mtd/nand/omap2.c Any GPMC register tinkering needs to happen in arch/arm/mach-omap2/gpmc.c. If there are not currently GPMC functions to do something in gpmc.c, then let's add the necessary support there. 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files Passing hardcoded GPMC virtual addressess is sure way to mess up things. This should all become unnecessary once the NAND drivers stops messing with the GPMC registers directly. So, as a result, I'm not planning on pushing any omap NAND related patches until these basic issues are fixed. I'll mark these patches as "Changes requested" in patchwork.kernel.org even if these patches don't have anything else wrong with them. Let's fix the basic things for good, and put the other patches on hold for a while. Sorry if this causes problems! Cheers, Tony From linux_vpn at yahoo.com Tue May 4 18:34:45 2010 From: linux_vpn at yahoo.com (Zhiwei Yu) Date: Tue, 4 May 2010 15:34:45 -0700 (PDT) Subject: jacqueline wehrlen Message-ID: <907239.53332.qm@web55001.mail.re4.yahoo.com> http://mariebedouet.com/home.php From haojian.zhuang at gmail.com Tue May 4 23:33:41 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Tue, 4 May 2010 23:33:41 -0400 Subject: failue on compiling mtd tree Message-ID: Hi all, I fetched latest code from mtd-2.6 tree. Now I met an issue in below. AS arch/arm/boot/compressed/lib1funcs.o AS arch/arm/boot/compressed/piggy.gzip.o LD arch/arm/boot/compressed/vmlinux `.LANCHOR0' referenced in section `.text' of arch/arm/boot/compressed/misc.o: defined in discarded section `.data' of arch/arm/boot/compressed/misc.o `.LANCHOR0' referenced in section `.text' of arch/arm/boot/compressed/misc.o: defined in discarded section `.data' of arch/arm/boot/compressed/misc.o make[2]: *** [arch/arm/boot/compressed/vmlinux] Error 1 make[1]: *** [arch/arm/boot/compressed/vmlinux] Error 2 make: *** [zImage] Error 2 I remember this issue is fixed in arm tree. Could mtd-2.6 tree be synced with latest code? Thanks Haojian From cernekee at gmail.com Tue May 4 23:58:00 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Tue, 4 May 2010 20:58:00 -0700 Subject: [PATCHv2 0/2] mtd: nand: Extend MLC support Message-ID: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> Part 1/2 is an improved version of my previous submission. Additional checks were added to ensure that certain "5-byte" Micron and Samsung parts are not falsely detected as having 6-byte IDs. I also rolled in the 256B NAND_MAX_OOBSIZE change. Part 2/2 is a resubmission/rebase of Reuben Dowle's 2009/02/03 patch: http://lists.infradead.org/pipermail/linux-mtd/2009-February/024473.html I am trying to compile a table of NAND IDs to make sure the detection algorithm correctly handles all known cases. If you could send me the following information for any NAND chips you have access to (via private email), it would be appreciated: 1) Part number 2) ID code (please read 8 bytes so I can see where it wraps around) 3) Device size, block size, page size, OOB bytes per page, bus width, and bad block marker location 4) Datasheet, if available Thanks. From cernekee at gmail.com Tue May 4 23:58:03 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Tue, 4 May 2010 20:58:03 -0700 Subject: [PATCHv2 1/2] mtd: nand: Extend NAND flash detection to new MLC chips In-Reply-To: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> References: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> Message-ID: <10137ab89de6e6d229798d6f397688b0807024da@localhost.localdomain> Some of the newer MLC devices have a 6-byte ID sequence in which several field definitions differ from older chips in a manner that is not backward compatible. For instance: Samsung K9GAG08U0M (5-byte sequence): ec d5 14 b6 74 4th byte, bits 1:0 encode the page size: 0=1KiB, 1=2KiB, 2=4KiB, 3=8KiB 4th byte, bits 5:4 encode the block size: 0=64KiB, 1=128KiB, ... 4th byte, bit 6 encodes the OOB size: 0=8B/512B, 1=16B/512B Samsung K9GAG08U0D (6-byte sequence): ec d5 94 29 34 41 4th byte, bits 1:0 encode the page size: 0=2KiB, 1=4KiB, 3=8KiB, 4=rsvd 4th byte, bits 7;5:4 encode the block size: 0=128KiB, 1=256KiB, ... 4th byte, bits 6;3:2 encode the OOB size: 1=128B/page, 2=218B/page This patch uses the new 6-byte scheme if the following conditions are all true: 1) The ID code wraps around after exactly 6 bytes 2) Manufacturer is Samsung 3) 6th byte is zero The patch also extends the maximum OOB size from 128B to 256B. Signed-off-by: Kevin Cernekee --- drivers/mtd/nand/nand_base.c | 64 ++++++++++++++++++++++++++++------------- include/linux/mtd/nand.h | 2 +- 2 files changed, 45 insertions(+), 21 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b9dc65c..85891dc 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -2774,8 +2774,8 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, int busw, int *maf_id, struct nand_flash_dev *type) { - int dev_id, maf_idx; - int tmp_id, tmp_manf; + int i, dev_id, maf_idx; + u8 id_data[8]; /* Select the device */ chip->select_chip(mtd, 0); @@ -2801,15 +2801,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1); - /* Read manufacturer and device IDs */ + /* Read entire ID string */ - tmp_manf = chip->read_byte(mtd); - tmp_id = chip->read_byte(mtd); + for (i = 0; i < 8; i++) + id_data[i] = chip->read_byte(mtd); - if (tmp_manf != *maf_id || tmp_id != dev_id) { + if (id_data[0] != *maf_id || id_data[1] != dev_id) { printk(KERN_INFO "%s: second ID read did not match " "%02x,%02x against %02x,%02x\n", __func__, - *maf_id, dev_id, tmp_manf, tmp_id); + *maf_id, dev_id, id_data[0], id_data[1]); return ERR_PTR(-ENODEV); } @@ -2832,21 +2832,45 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (!type->pagesize) { int extid; /* The 3rd id byte holds MLC / multichip data */ - chip->cellinfo = chip->read_byte(mtd); + chip->cellinfo = id_data[2]; /* The 4th id byte is the important one */ - extid = chip->read_byte(mtd); - /* Calc pagesize */ - mtd->writesize = 1024 << (extid & 0x3); - extid >>= 2; - /* Calc oobsize */ - mtd->oobsize = (8 << (extid & 0x01)) * (mtd->writesize >> 9); - extid >>= 2; - /* Calc blocksize. Blocksize is multiples of 64KiB */ - mtd->erasesize = (64 * 1024) << (extid & 0x03); - extid >>= 2; - /* Get buswidth information */ - busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + extid = id_data[3]; + /* + * Field definitions are in the following datasheets: + * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) + * New style (6 byte ID): Samsung K9GAG08U0D (p.40) + * + * Check for wraparound + Samsung ID + nonzero 6th byte + * to decide what to do. + */ + if (id_data[0] == id_data[6] && id_data[1] == id_data[7] && + id_data[0] == NAND_MFR_SAMSUNG && + id_data[5] != 0x00) { + /* Calc pagesize */ + mtd->writesize = 2048 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (extid & 0x03) == 0x01 ? 128 : 218; + extid >>= 2; + /* Calc blocksize */ + mtd->erasesize = (128 * 1024) << + (((extid >> 1) & 0x04) | (extid & 0x03)); + busw = 0; + } else { + /* Calc pagesize */ + mtd->writesize = 1024 << (extid & 0x03); + extid >>= 2; + /* Calc oobsize */ + mtd->oobsize = (8 << (extid & 0x01)) * + (mtd->writesize >> 9); + extid >>= 2; + /* Calc blocksize. Blocksize is multiples of 64KiB */ + mtd->erasesize = (64 * 1024) << (extid & 0x03); + extid >>= 2; + /* Get buswidth information */ + busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; + } } else { /* * Old devices have chip data hardcoded in the device id table diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 8bdacb8..50f3aa0 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -53,7 +53,7 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); * is supported now. If you add a chip with bigger oobsize/page * adjust this accordingly. */ -#define NAND_MAX_OOBSIZE 128 +#define NAND_MAX_OOBSIZE 256 #define NAND_MAX_PAGESIZE 4096 /* -- 1.6.5 From cernekee at gmail.com Tue May 4 23:58:10 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Tue, 4 May 2010 20:58:10 -0700 Subject: [PATCHv2 2/2] mtd: nand: Support alternate BB marker locations on MLC In-Reply-To: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> References: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> Message-ID: <73903cdde20c6be375703e18849282bd3f2a2ff1@localhost.localdomain> This is a slightly modified version of a patch submitted last year by Reuben Dowle . His original comments follow: This patch adds support for some MLC NAND flashes that place the BB marker in the LAST page of the bad block rather than the FIRST page used for SLC NAND and other types of MLC nand. Lifted from Samsung datasheet for K9LG8G08U0A (1Gbyte MLC NAND): " Identifying Initial Invalid Block(s) All device locations are erased(FFh) except locations where the initial invalid block(s) information is written prior to shipping. The initial invalid block(s) status is defined by the 1st byte in the spare area. Samsung makes sure that the last page of every initial invalid block has non-FFh data at the column address of 2,048. ... " As far as I can tell, this is the same for all Samsung MLC nand, and in fact the samsung bsp for the processor used in our project (s3c6410) actually contained a hack similar to this patch but less portable to enable use of their NAND parts. I discovered this problem when trying to use a Micron NAND which does not used this layout - I wish samsung would put their stuff in main-line to avoid this type of problem. Currently this patch causes all MLC nand with manufacturer codes from Samsung and ST(Numonyx) to use this alternative location, since these are the manufactures that I know of that use this layout. Signed-off-by: Kevin Cernekee --- drivers/mtd/nand/nand_base.c | 15 +++++++++++++++ drivers/mtd/nand/nand_bbt.c | 3 +++ include/linux/mtd/nand.h | 2 ++ 3 files changed, 20 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 85891dc..4a7b864 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -347,6 +347,9 @@ static int nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) struct nand_chip *chip = mtd->priv; u16 bad; + if (chip->options & NAND_BB_LAST_PAGE) + ofs += mtd->erasesize - mtd->writesize; + page = (int)(ofs >> chip->page_shift) & chip->pagemask; if (getchip) { @@ -396,6 +399,9 @@ static int nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) uint8_t buf[2] = { 0, 0 }; int block, ret; + if (chip->options & NAND_BB_LAST_PAGE) + ofs += mtd->erasesize - mtd->writesize; + /* Get block number */ block = (int)(ofs >> chip->bbt_erase_shift); if (chip->bbt) @@ -2933,6 +2939,15 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd, if (*maf_id != NAND_MFR_SAMSUNG && !type->pagesize) chip->options &= ~NAND_SAMSUNG_LP_OPTIONS; + /* + * Bad block marker is stored in the last page of each block + * on Samsung and Hynix MLC devices + */ + if ((chip->cellinfo & NAND_CI_CELLTYPE_MSK) && + (*maf_id == NAND_MFR_SAMSUNG || + *maf_id == NAND_MFR_HYNIX)) + chip->options |= NAND_BB_LAST_PAGE; + /* Check for AND chips with 4 page planes */ if (chip->options & NAND_4PAGE_ARRAY) chip->erase_cmd = multi_erase_cmd; diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c index 387c45c..ad97c0c 100644 --- a/drivers/mtd/nand/nand_bbt.c +++ b/drivers/mtd/nand/nand_bbt.c @@ -432,6 +432,9 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf, from = (loff_t)startblock << (this->bbt_erase_shift - 1); } + if (this->options & NAND_BB_LAST_PAGE) + from += mtd->erasesize - (mtd->writesize * len); + for (i = startblock; i < numblocks;) { int ret; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 50f3aa0..a81b185 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -181,6 +181,8 @@ typedef enum { #define NAND_NO_READRDY 0x00000100 /* Chip does not allow subpage writes */ #define NAND_NO_SUBPAGE_WRITE 0x00000200 +/* Chip stores bad block marker on the last page of the eraseblock */ +#define NAND_BB_LAST_PAGE 0x00000400 /* Device is one of 'new' xD cards that expose fake nand command set */ #define NAND_BROKEN_XD 0x00000400 -- 1.6.5 From Artem.Bityutskiy at nokia.com Wed May 5 00:49:03 2010 From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy) Date: Wed, 05 May 2010 07:49:03 +0300 Subject: Upcoming merge window and omap NAND patches In-Reply-To: <20100504220803.GN29604@atomide.com> References: <20100504220803.GN29604@atomide.com> Message-ID: <1273034943.3702.19.camel@localhost> On Wed, 2010-05-05 at 00:08 +0200, ext Tony Lindgren wrote: > Hi all, > > There are several omap NAND patches pending, but some basic things > should be fixed first. > > 1. The NAND driver needs to stop tinkering with the GPMC registers > > The omap General Purpose Memory Controller (GPMC) registers are omap > specific, and not driver specific. Tinkering with these registers > can cause issues with the other devices on the GPMC. > > To find out what needs to disappear fomr the NAND driver, just do: > > $ grep baseaddr drivers/mtd/nand/omap2.c > > Any GPMC register tinkering needs to happen in arch/arm/mach-omap2/gpmc.c. > If there are not currently GPMC functions to do something in gpmc.c, then > let's add the necessary support there. > > 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files > > Passing hardcoded GPMC virtual addressess is sure way to mess up > things. This should all become unnecessary once the NAND drivers > stops messing with the GPMC registers directly. > > So, as a result, I'm not planning on pushing any omap NAND related > patches until these basic issues are fixed. I'll mark these patches > as "Changes requested" in patchwork.kernel.org even if these patches > don't have anything else wrong with them. > > Let's fix the basic things for good, and put the other patches on > hold for a while. Sorry if this causes problems! Hi, fair enough. I guess Vimal should address this, as he seems to be the TI mr. NAND, right? :-) -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:12:39 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:12:39 +0300 Subject: [PATCH] ubi: init even if mtd device cannot be attached, if built into kernel In-Reply-To: <1272537664-21603-1-git-send-email-mkl@pengutronix.de> References: <1272537664-21603-1-git-send-email-mkl@pengutronix.de> Message-ID: <1273036359.3702.35.camel@localhost> On Thu, 2010-04-29 at 12:41 +0200, Marc Kleine-Budde wrote: > Ubi can be built into the kernel or be compiled as a kernel module. > Further on the command line one can specify mtd devices to be attach to > ubi while loading. In the current implementation the ubi driver refuses > to load if one of the mtd devices cannot be attached. > > Consider: > 1) ubi compiled into the kernel and > 2) a mtd device specified on the command line and > 3) this mtd device contains bogus data (for whatever reason). > > During init ubi tries to attach the mtd device is this fails the whole > ubi subsystem isn't initialized. Later the userspace cannot attach any > mtd to ubi because ubi isn't loaded. > > This patch keeps the current behaviour: if ubi is compiled as a module > and a mtd device cannot be attached the ubi module cannot be loaded, > but changes it for the ubi-is-built-into-the-kernel usecase. > > If ubi is builtin, a not attachable mtd device doen't stop ubi from > initializing. This slightly modifies the behaviour if multiple mtd > devices are specified on the command line. Now every mtd device is > probed and, if possible, attached, i.e. a faulty mtd device doesn't > stop the others from being attached. > > Signed-off-by: Marc Kleine-Budde > --- > drivers/mtd/ubi/build.c | 12 ++++++++++-- > 1 files changed, 10 insertions(+), 2 deletions(-) > > diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c > index 14cec04..2f6f09f 100644 > --- a/drivers/mtd/ubi/build.c > +++ b/drivers/mtd/ubi/build.c > @@ -123,6 +123,12 @@ static struct device_attribute dev_bgt_enabled = > static struct device_attribute dev_mtd_num = > __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); > > +#ifdef CONFIG_MTD_UBI_MODULE > +static inline int ubi_is_module(void) { return 1; } > +#else > +static inline int ubi_is_module(void) { return 0; } > +#endif I really hate these ifdefs. Dunno why, but they feel disgusting. I understand your issue and agree that is should be fixed. And I cannot really see a better solution. So if no-one complains, I'll accept your patch. However, for consistency with other UBI code (see debug.h), please, do this like #ifdef CONFIG_MTD_UBI_MODULE #define ubi_is_module() 1 #else #define ubi_is_module() 1 #endif Not a big deal, just to be consistent and have uniform code style. Thanks... :-( > + > /** > * ubi_volume_notify - send a volume change notification. > * @ubi: UBI device description object > @@ -1200,9 +1206,11 @@ static int __init ubi_init(void) > p->vid_hdr_offs); > mutex_unlock(&ubi_devices_mutex); > if (err < 0) { > - put_mtd_device(mtd); > ubi_err("cannot attach mtd%d", mtd->index); > - goto out_detach; > + if (ubi_is_module()) { > + put_mtd_device(mtd); > + goto out_detach; > + } > } > } > -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:14:42 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:14:42 +0300 Subject: [PATCH] ubi: init even if mtd device cannot be attached, if built into kernel In-Reply-To: <1273036359.3702.35.camel@localhost> References: <1272537664-21603-1-git-send-email-mkl@pengutronix.de> <1273036359.3702.35.camel@localhost> Message-ID: <1273036482.3702.37.camel@localhost> On Wed, 2010-05-05 at 08:12 +0300, Artem Bityutskiy wrote: > > +#ifdef CONFIG_MTD_UBI_MODULE > > +static inline int ubi_is_module(void) { return 1; } > > +#else > > +static inline int ubi_is_module(void) { return 0; } > > +#endif > > I really hate these ifdefs. Dunno why, but they feel disgusting. > > I understand your issue and agree that is should be fixed. And I cannot > really see a better solution. So if no-one complains, I'll accept your > patch. > > However, for consistency with other UBI code (see debug.h), please, do > this like > > #ifdef CONFIG_MTD_UBI_MODULE > #define ubi_is_module() 1 > #else > #define ubi_is_module() 1 > #endif Err, of course the second one should be 0, not 1. I can actually do this modification myself, or you can re-send your patch. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:30:49 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:30:49 +0300 Subject: UBIFS failure after extended use In-Reply-To: <4BD98D81.7030504@lambsys.com> References: <4BD98D81.7030504@lambsys.com> Message-ID: <1273037449.3702.51.camel@localhost> Hi, On Thu, 2010-04-29 at 08:45 -0500, David Lambert wrote: > I am a relative newbie to UBI/MTD but the following puzzles me. I have a > UBI partition "bulkdata" that suddenly appeared to be corrupted after > around a week of working perfectly. The kernel is 2.6.30.1 running on an > Atmel ARM9 ATRM9200. Any suggestions would be very welcome, as I have no > idea on how to proceed from here. Is this SLC or MLC NAND? > AT91 NAND: 8-bit, Software ECC Probably SLC, MLCs usually have HW ECC support, AFAIK. > Scanning device for bad blocks > Bad eraseblock 347 at 0x0000056c0000 > Bad eraseblock 1613 at 0x000019340000 > Bad eraseblock 1981 at 0x00001ef40000 > Bad eraseblock 2174 at 0x000021f80000 > Bad eraseblock 3004 at 0x00002ef00000 > Bad eraseblock 3940 at 0x00003d900000 > Bad eraseblock 4132 at 0x000040900000 > Bad eraseblock 4321 at 0x000043840000 > Bad eraseblock 4487 at 0x0000461c0000 > Bad eraseblock 4642 at 0x000048880000 > Bad eraseblock 5120 at 0x000050000000 > Bad eraseblock 5521 at 0x000056440000 > Bad eraseblock 5904 at 0x00005c400000 > Bad eraseblock 5946 at 0x00005ce80000 > Bad eraseblock 6288 at 0x000062400000 > Bad eraseblock 6364 at 0x000063700000 > Bad eraseblock 6510 at 0x000065b80000 > Bad eraseblock 6602 at 0x000067280000 > Bad eraseblock 6781 at 0x000069f40000 > Bad eraseblock 6861 at 0x00006b340000 > Bad eraseblock 7144 at 0x00006fa00000 > Bad eraseblock 7223 at 0x000070dc0000 > Bad eraseblock 7344 at 0x000072c00000 > Bad eraseblock 7432 at 0x000074200000 > Bad eraseblock 7997 at 0x00007cf40000 > Creating 2 MTD partitions on "NAND 2GiB 3,3V 8-bit": > 0x000000000000-0x000006400000 : "ubirootfs" > 0x000006400000-0x000080000000 : "bulkdata" > UBI: attaching mtd4 to ubi0 > UBI: physical eraseblock size: 262144 bytes (256 KiB) > UBI: logical eraseblock size: 258048 bytes > UBI: smallest flash I/O unit: 4096 > UBI: sub-page size: 1024 > UBI: VID header offset: 1024 (aligned 1024) > UBI: data offset: 4096 > UBI: attached mtd4 to ubi0 > UBI: MTD device name: "ubirootfs" > UBI: MTD device size: 100 MiB > UBI: number of good PEBs: 399 > UBI: number of bad PEBs: 1 > UBI: max. allowed volumes: 128 > UBI: wear-leveling threshold: 4096 > UBI: number of internal volumes: 1 > UBI: number of user volumes: 1 > UBI: available PEBs: 0 > UBI: total number of reserved PEBs: 399 > UBI: number of PEBs reserved for bad PEB handling: 3 > UBI: max/mean erase counter: 3/0 > UBI: background thread "ubi_bgt0d" started, PID 264 > > UBI: attaching mtd5 to ubi1 > UBI: physical eraseblock size: 262144 bytes (256 KiB) > UBI: logical eraseblock size: 258048 bytes > UBI: smallest flash I/O unit: 4096 > UBI: sub-page size: 1024 > UBI: VID header offset: 1024 (aligned 1024) > UBI: data offset: 4096 > UBI: attached mtd5 to ubi1 > UBI: MTD device name: "bulkdata" > UBI: MTD device size: 1948 MiB > UBI: number of good PEBs: 7768 > UBI: number of bad PEBs: 24 > UBI: max. allowed volumes: 128 > UBI: wear-leveling threshold: 4096 > UBI: number of internal volumes: 1 > UBI: number of user volumes: 1 > UBI: available PEBs: 0 > UBI: total number of reserved PEBs: 7768 > UBI: number of PEBs reserved for bad PEB handling: 77 > UBI: max/mean erase counter: 8306/75 > UBI: background thread "ubi_bgt1d" started, PID 355 > UBI device number 1, total 7768 LEBs (2004516864 bytes, 1.9 GiB), > available 0 LEBs (0 bytes), LEB size 258048 bytes (252.0 KiB) > UBIFS: recovery needed > UBIFS: recovery completed > UBIFS: mounted UBI device 1, volume 0, name "bulkdata" > UBIFS: file system size: 1980260352 bytes (1933848 KiB, 1888 MiB, 7674 > LEBs) > UBIFS: journal size: 33546240 bytes (32760 KiB, 31 MiB, 130 LEBs) > UBIFS: media format: w4/r0 (latest is w4/r0) > UBIFS: default compressor: none > UBIFS: reserved for root: 4952683 bytes (4836 KiB) > > All seems OK up to here - then all hell breaks loose... > > # uncorrectable error : <3>UBI error: ubi_io_read: error -74 while > reading 13 bytes from PEB 718:175672, read 13 bytes So, the NAND driver prints 'uncorrectable error', which means that data in that NAND page is corrupted, and your ECC could not fix the corruption. > UBIFS error (pid 85): make_reservation: cannot reserve 4144 bytes in > jhead 2, error -74 Probably 'make_reservation()' tried to find a free eraseblock, for which it had to walk lprops and read from flash. The read operation failed, so the reservation also failed. > UBIFS error (pid 85): do_writepage: cannot write page 1981 of inode > 6925, error -74 > UBIFS warning (pid 85): ubifs_ro_mode: switched to read-only mode, error > -74 And UBIFS switched to R/O mode, because it started getting errors when it tries to write. This is just a protective measure. > UBIFS error (pid 85): make_reservation: cannot reserve 160 bytes in > jhead 1, error -30 I'm sure there were more prints, e.g., a stackdump. You just did not look at your dmesg. Please, follow this guide if you send more bugreports: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_how_send_bugreport Anyway, my suggestions are: 1. Try to understand why your NAND returns -EBADMSG (= -74 = uncorrectable ECC error). There may be many reasons, e.g.: a). Your ECC algorithms are too weak b) Some one wrote more than once to the same page. c) There may be SW bugs in the driver d) You may have HW issues (e.g., timings) 2. Validate your flash with the MTD tests. This may help you catching problems c and d. Try to run the torture test for several days, for example. 3. Enable I/O debugging checks in UBI - there is debugging code which will read flash region before every write and make sure this region contains all 0xFFs. 4. Try to even enable all debugging checks in both UBI and UBIFS. Everything will be very slow, but this may help. Please, see the bug report guide. Play with your flash, and report your findings, but properly, including all messages. HTH. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:40:27 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:40:27 +0300 Subject: [PATCHv3] mtd: cfi_cmdset_0002: Add reboot notifier for AMD flashes In-Reply-To: <471a5dfa1495f2d33e41435e4d37852ad489b112@localhost.localdomain> References: <1272519262.7750.66.camel@localhost> <471a5dfa1495f2d33e41435e4d37852ad489b112@localhost.localdomain> Message-ID: <1273038027.3702.52.camel@localhost> On Thu, 2010-04-29 at 10:26 -0700, Kevin Cernekee wrote: > Ensure that the flash device is in a quiescent state before rebooting. > The implementation is closely modeled after the cfi_cmdset_0001 reboot > notifier, commit 963a6fb0a0d336d0513083b7e4b5c3ff9d6d2061 . > > Signed-off-by: Kevin Cernekee > --- > drivers/mtd/chips/cfi_cmdset_0002.c | 56 +++++++++++++++++++++++++++++++++++ > 1 files changed, 56 insertions(+), 0 deletions(-) Pushed to l2-mtd-2.6 / master, thanks. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:45:49 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:45:49 +0300 Subject: [PATCH] sst25l.c: fix multi-part messages with broken spi masters In-Reply-To: <0D753D10438DA54287A00B0270842697636E305D4A@AUSP01VMBX24.collaborationhost.net> References: <0D753D10438DA54287A00B0270842697636E305D4A@AUSP01VMBX24.collaborationhost.net> Message-ID: <1273038349.3702.54.camel@localhost> On Thu, 2010-04-29 at 13:34 -0500, H Hartley Sweeten wrote: > Some SPI masters (ep93xx) have limitations when using the SFRMOUT > signal for the spi device chip select. The SFRMOUT signal is > only asserted as long as the spi transmit fifo contains data. As > soon as the last bit is clocked into the receive fifo it gets > deasserted. > > The functions sst25l_status and sst25l_match_device use the API > function spi_write_then_read to write a command to the flash then > read the response back. This API function creates a two part spi > message for the write then read. When this message is transferred > the SFRMOUT signal ends up getting deasserted after the command > phase. This causes the command to get aborted by the device so > the read phase returns invalid data. > > By changing sst25l_status and sst25l_match_device to use a single > transfer synchronous message, the SFRMOUT signal stays asserted > during the entire message so the correct data always gets returned. > > This change will have no effect on SPI masters which use a chip > select mechanism (GPIO's, etc.) which does stay asserted correctly. > As a bonus, the single transfer synchronous messages complete faster > than multi-part messages. > > Signed-off-by: H Hartley Sweeten > Cc: David Woodhouse > Cc: Artem Bityutskiy > Cc: Andre Renaud > Cc: Ryan Mallon Pushed to l2-mtd-2.6 / dunno. But please, notice for future: 1. It is much nicer to put something like [PATCH v2] when you re-send. 2. In MTD we prefix everything with mtd: -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind at infradead.org Wed May 5 01:51:17 2010 From: dedekind at infradead.org (Artem Bityutskiy) Date: Wed, 05 May 2010 08:51:17 +0300 Subject: [PATCH] sst25l.c: remove unnecessary MTD_DEBUG_LEVEL2 messages In-Reply-To: <0D753D10438DA54287A00B0270842697636E825604@AUSP01VMBX24.collaborationhost.net> References: <0D753D10438DA54287A00B0270842697636E825604@AUSP01VMBX24.collaborationhost.net> Message-ID: <1273038677.3702.55.camel@localhost> On Thu, 2010-04-29 at 17:52 -0500, H Hartley Sweeten wrote: > All the SST25L series flash parts have uniform erase sectors. Remove > the extra MTD_DEBUG_LEVEL2 messages showing the eraseregions info > since they could never be shown. > > Signed-off-by: H Hartley Sweeten > Cc: David Woodhouse > Cc: Andre Renaud > Cc: Ryan Mallon Pushed to l2-mtd-2.6 / master -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:55:48 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:55:48 +0300 Subject: [patch 1/2] kirkwood: allow machines to register RnB line with mtd driver In-Reply-To: <20100429231313.519744154@fluff.org.uk> References: <20100429231253.465019575@fluff.org.uk> <20100429231313.519744154@fluff.org.uk> Message-ID: <1273038948.3702.56.camel@localhost> On Fri, 2010-04-30 at 00:12 +0100, Ben Dooks wrote: > plain text document attachment (slinux) > Add a kirkwood_nand_init_rnb() call to allow boards which > have RnB line detection to register this instead of a > static delay. > > Signed-off-by: Ben Dooks > Cc: Linux MTD I have this patch in l2-mtd-2.6 / dunno -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 01:56:19 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 08:56:19 +0300 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: <1273038979.3702.57.camel@localhost> Probably Adrian could comment on this? On Fri, 2010-04-30 at 12:05 +0200, Enric Balletb? i Serra wrote: > Hello all, > > After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: > Flex-OneNAND support) the onenand support for my device is broken. > > Before this commit when I run the nandtest program all is ok > --- > # nandtest /dev/mtd3 > ECC corrections: 0 > ECC failures : 0 > Bad blocks : 0 > BBT blocks : 0 > 002c0000: checking... > Finished pass 1 successfully > -- > > Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest > fails with: > --- > # nandtest /dev/mtd3 > ECC corrections: 0 > ECC failures : 0 > Bad blocks : 0 > BBT blocks : 0 > 00000000: reading... > [ 299.092041] onenand_wait: ECC error = 0x8488 > ( ... lots of ECC errors ... ) > [ 299.092041] onenand_wait: ECC error = 0x8488 > ECC failed at 00000000 > 00000000: checking... > compare failed. seed 1804289383 > Byte 0x1 is 5a should be da > Byte 0x3 is 82 should be 92 > Byte 0x4 is 10 should be 1a > ( ... ) > --- > > Investigating a little I see a significant difference introduced by > this patch. In line > > 347: page = (int) (addr - onenand_addr(this, block)) >> > this->page_shift; (patch applied) > > instead of > > 347: page = (int) (addr >> this->page_shift); (without patch) > > I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced > the line 347 and now works again. Fantastic, but I suspect this is not > the proper solution (probably this breaks other onenands devices, I > can't test). > > I'm just introducing in OneNAND devices so anyone can help me to > understand and solve the problem ? Note that my device is a Numonyx > 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB > page ) > > Thanks in advance, > > ///:~Enric > > --- > diff --git a/drivers/mtd/onenand/onenand_base.c > b/drivers/mtd/onenand/onenand_base.c > index 081f97d..b1d50a3 100644 > --- a/drivers/mtd/onenand/onenand_base.c > +++ b/drivers/mtd/onenand/onenand_base.c > @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, > int cmd, loff_t addr, size_t le > > default: > block = (int) onenand_block(this, addr); > - page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; > + page = (int) (addr >> this->page_shift); > > if (ONENAND_IS_2PLANE(this)) { > /* Make the even block number */ > --- > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 02:04:16 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 09:04:16 +0300 Subject: [PATCH v2] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1272922368-18517-1-git-send-email-kirill@shutemov.name> References: <1272922368-18517-1-git-send-email-kirill@shutemov.name> Message-ID: <1273039456.3702.59.camel@localhost> On Tue, 2010-05-04 at 00:32 +0300, Kirill A. Shutemov wrote: > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > backing device of device node inode, since file->f_mapping is equal to > inode->i_mapping (see __dentry_open() in fs/open.c). > > Let's introduce separate inode for MTD device with appropriate backing > device. > > Signed-off-by: Kirill A. Shutemov > > --- > Changelog v1 -> v2: > - Fix error handling based on comments by Jan Kara. How about a version of this patch which applies to the mtd-2.6 tree git://git.infradead.org/mtd-2.6.git (webview: http://git.infradead.org/mtd-2.6.git) This one does not apply: [dedekind at eru mtd-2.6]$ git am ~/tmp/k Applying: mtd: Do not corrupt backing device of device node inode error: patch failed: drivers/mtd/mtdchar.c:954 error: drivers/mtd/mtdchar.c: patch does not apply error: patch failed: drivers/mtd/mtdcore.c:383 error: drivers/mtd/mtdcore.c: patch does not apply Patch failed at 0001 mtd: Do not corrupt backing device of device node inode When you have resolved this problem run "git am --resolved". If you would prefer to skip this patch, instead run "git am --skip". To restore the original branch and stop patching run "git am --abort". [dedekind at eru mtd-2.6]$ patch -p1 < .git/rebase-apply/patch patching file drivers/mtd/mtdchar.c Hunk #2 succeeded at 88 (offset -3 lines). Hunk #3 succeeded at 119 (offset -3 lines). Hunk #4 succeeded at 145 (offset -3 lines). Hunk #5 FAILED at 979. 1 out of 5 hunks FAILED -- saving rejects to file drivers/mtd/mtdchar.c.rej patching file drivers/mtd/mtdcore.c Hunk #1 FAILED at 383. 1 out of 1 hunk FAILED -- saving rejects to file drivers/mtd/mtdcore.c.rej patching file include/linux/mtd/mtd.h Hunk #2 succeeded at 175 (offset -3 lines). -- Best Regards, Artem Bityutskiy (????? ????????) From vimal.newwork at gmail.com Wed May 5 02:11:39 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Wed, 5 May 2010 11:41:39 +0530 Subject: Upcoming merge window and omap NAND patches In-Reply-To: <1273034943.3702.19.camel@localhost> References: <20100504220803.GN29604@atomide.com> <1273034943.3702.19.camel@localhost> Message-ID: On Wed, May 5, 2010 at 10:19 AM, Artem Bityutskiy wrote: > On Wed, 2010-05-05 at 00:08 +0200, ext Tony Lindgren wrote: >> Hi all, >> >> There are several omap NAND patches pending, but some basic things >> should be fixed first. >> >> 1. The NAND driver needs to stop tinkering with the GPMC registers >> >> The omap General Purpose Memory Controller (GPMC) registers are omap >> specific, and not driver specific. Tinkering with these registers >> can cause issues with the other devices on the GPMC. >> >> To find out what needs to disappear fomr the NAND driver, just do: >> >> $ grep baseaddr drivers/mtd/nand/omap2.c >> >> Any GPMC register tinkering needs to happen in arch/arm/mach-omap2/gpmc.c. >> If there are not currently GPMC functions to do something in gpmc.c, then >> let's add the necessary support there. >> >> 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files >> >> Passing hardcoded GPMC virtual addressess is sure way to mess up >> things. This should all become unnecessary once the NAND drivers >> stops messing with the GPMC registers directly. >> >> So, as a result, I'm not planning on pushing any omap NAND related >> patches until these basic issues are fixed. I'll mark these patches >> as "Changes requested" in patchwork.kernel.org even if these patches >> don't have anything else wrong with them. >> >> Let's fix the basic things for good, and put the other patches on >> hold for a while. Sorry if this causes problems! > > Hi, > > fair enough. I guess Vimal should address this, as he seems to be the TI > mr. NAND, right? :-) Hi All, Sorry again. I am no more with TI and I don't have any board with me too. So, I'm unable to fix these. :( I hope someone else from TI can take care of it. -- Regards, Vimal Singh From ricard.wanderlof at axis.com Wed May 5 02:59:37 2010 From: ricard.wanderlof at axis.com (Ricard Wanderlof) Date: Wed, 5 May 2010 08:59:37 +0200 (CEST) Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <201005031505.18604.muehlfelder@enertex.de> References: <201005031505.18604.muehlfelder@enertex.de> Message-ID: On Mon, 3 May 2010, Thorsten M?hlfelder wrote: > PS: I could not reproduce the bit-flip problem. It just happens in rare cases. > Furthermore some of my devices are using Samsung NAND instead of the Micron > NAND and did not show any problems yet. So perhaps my problem are just some > bad NAND chip? But still I have to find a solution for the problem. In our experience, which is limited to 32 MiB and 128 MiB SLC flashes, Micron, Hynix and Numonyx have much worse bit read error rates that Samsung and Toshiba, even though the data sheets hint at the same level of data integrity. We made some random tests, reading again and again from the same flash partition, and the first group above tended to show uncorrectable ECC errors already after less than a million reads, whereas the second group showed only single-bit errors even after 20 or even 60 million reads. Of course, reading that many times from a flash partition, especially a boot partition, is hardly realistic, but in our experience, it simulates quite well the situation of a having a seldom-read boot partition in a flash where there is activity going on in other parts of the flash, i.e. an embedded system where a single flash chip provides all non-volatile storage, over a long period of time. Of course these are random samples only, but they've been very consistent so far. Lately a new batch of Numonyx 128 MiB flashes arrived which seem to have better error rates. One can speculate as to why but I'll leave that discussion off this mailing list. /Ricard -- Ricard Wolf Wanderl?f ricardw(at)axis.com Axis Communications AB, Lund, Sweden www.axis.com Phone +46 46 272 2016 Fax +46 46 13 61 30 From matthieu.castet at parrot.com Wed May 5 03:34:56 2010 From: matthieu.castet at parrot.com (Matthieu CASTET) Date: Wed, 5 May 2010 09:34:56 +0200 Subject: [PATCHv2 1/2] mtd: nand: Extend NAND flash detection to new MLC chips In-Reply-To: <10137ab89de6e6d229798d6f397688b0807024da@localhost.localdomain> References: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> <10137ab89de6e6d229798d6f397688b0807024da@localhost.localdomain> Message-ID: <4BE11FA0.20703@parrot.com> Hi, Kevin Cernekee a ?crit : > Some of the newer MLC devices have a 6-byte ID sequence in which > several field definitions differ from older chips in a manner that is > not backward compatible. For instance: > Doesn't these nand support ONFI "Read Parameter Page" (cmd 0xec) ? If yes it will be a more generic way to detect new nand features. Matthieu > Samsung K9GAG08U0M (5-byte sequence): ec d5 14 b6 74 > 4th byte, bits 1:0 encode the page size: 0=1KiB, 1=2KiB, 2=4KiB, 3=8KiB > 4th byte, bits 5:4 encode the block size: 0=64KiB, 1=128KiB, ... > 4th byte, bit 6 encodes the OOB size: 0=8B/512B, 1=16B/512B > > Samsung K9GAG08U0D (6-byte sequence): ec d5 94 29 34 41 > 4th byte, bits 1:0 encode the page size: 0=2KiB, 1=4KiB, 3=8KiB, 4=rsvd > 4th byte, bits 7;5:4 encode the block size: 0=128KiB, 1=256KiB, ... > 4th byte, bits 6;3:2 encode the OOB size: 1=128B/page, 2=218B/page > > This patch uses the new 6-byte scheme if the following conditions are > all true: > > 1) The ID code wraps around after exactly 6 bytes > > 2) Manufacturer is Samsung > > 3) 6th byte is zero > > The patch also extends the maximum OOB size from 128B to 256B. > From mkl at pengutronix.de Wed May 5 03:59:26 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Wed, 05 May 2010 09:59:26 +0200 Subject: [PATCH] ubi: init even if mtd device cannot be attached, if built into kernel In-Reply-To: <1273036482.3702.37.camel@localhost> References: <1272537664-21603-1-git-send-email-mkl@pengutronix.de> <1273036359.3702.35.camel@localhost> <1273036482.3702.37.camel@localhost> Message-ID: <4BE1255E.2090109@pengutronix.de> Artem Bityutskiy wrote: > On Wed, 2010-05-05 at 08:12 +0300, Artem Bityutskiy wrote: >>> +#ifdef CONFIG_MTD_UBI_MODULE >>> +static inline int ubi_is_module(void) { return 1; } >>> +#else >>> +static inline int ubi_is_module(void) { return 0; } >>> +#endif >> I really hate these ifdefs. Dunno why, but they feel disgusting. >> >> I understand your issue and agree that is should be fixed. And I cannot >> really see a better solution. So if no-one complains, I'll accept your >> patch. >> >> However, for consistency with other UBI code (see debug.h), please, do >> this like >> >> #ifdef CONFIG_MTD_UBI_MODULE >> #define ubi_is_module() 1 >> #else >> #define ubi_is_module() 1 >> #endif > > Err, of course the second one should be 0, not 1. I can actually do this > modification myself, or you can re-send your patch. I'll resend a patch. Cheers, Marc -- Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 260 bytes Desc: OpenPGP digital signature URL: From mkl at pengutronix.de Wed May 5 04:17:25 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Wed, 5 May 2010 10:17:25 +0200 Subject: [PATCH V2] ubi: init even if mtd device cannot be attached, if built into kernel Message-ID: <1273047445-23411-1-git-send-email-mkl@pengutronix.de> Ubi can be built into the kernel or be compiled as a kernel module. Further on the command line one can specify mtd devices to be attach to ubi while loading. In the current implementation the ubi driver refuses to load if one of the mtd devices cannot be attached. Consider: 1) ubi compiled into the kernel and 2) a mtd device specified on the command line and 3) this mtd device contains bogus data (for whatever reason). During init ubi tries to attach the mtd device is this fails the whole ubi subsystem isn't initialized. Later the userspace cannot attach any mtd to ubi because ubi isn't loaded. This patch keeps the current behaviour: if ubi is compiled as a module and a mtd device cannot be attached the ubi module cannot be loaded, but changes it for the ubi-is-built-into-the-kernel usecase. If ubi is builtin, a not attachable mtd device doen't stop ubi from initializing. This slightly modifies the behaviour if multiple mtd devices are specified on the command line. Now every mtd device is probed and, if possible, attached, i.e. a faulty mtd device doesn't stop the others from being attached. V2: integrated comments from Artem Bityutskiy: use defines instead of static inline functions Signed-off-by: Marc Kleine-Budde --- drivers/mtd/ubi/build.c | 12 ++++++++++-- 1 files changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index fad40aa..d0447a5 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -49,6 +49,12 @@ /* Maximum length of the 'mtd=' parameter */ #define MTD_PARAM_LEN_MAX 64 +#ifdef CONFIG_MTD_UBI_MODULE +#define ubi_is_module() 1 +#else +#define ubi_is_module() 0 +#endif + /** * struct mtd_dev_param - MTD device parameter description data structure. * @name: MTD character device node path, MTD device name, or MTD device number @@ -1240,9 +1246,11 @@ static int __init ubi_init(void) p->vid_hdr_offs); mutex_unlock(&ubi_devices_mutex); if (err < 0) { - put_mtd_device(mtd); ubi_err("cannot attach mtd%d", mtd->index); - goto out_detach; + if (ubi_is_module()) { + put_mtd_device(mtd); + goto out_detach; + } } } -- 1.7.1 From kirill at shutemov.name Wed May 5 04:21:28 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Wed, 5 May 2010 11:21:28 +0300 Subject: [PATCH v3] mtd: Do not corrupt backing device of device node inode Message-ID: <1273047688-20947-1-git-send-email-kirill@shutemov.name> We cannot modify file->f_mapping->backing_dev_info, because it will corrupt backing device of device node inode, since file->f_mapping is equal to inode->i_mapping (see __dentry_open() in fs/open.c). Let's introduce separate inode for MTD device with appropriate backing device. Signed-off-by: Kirill A. Shutemov Acked-by: Jan Kara --- Changelog v2 -> v3: - Rebase to mtd.git. v1 -> v2: - Fix error handling based on comments by Jan Kara. --- drivers/mtd/mtdchar.c | 77 ++++++++++++++++++++++++++++++++++++++++++----- drivers/mtd/mtdcore.c | 3 ++ include/linux/mtd/mtd.h | 3 ++ 3 files changed, 75 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index c355491..a2bb3ce 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include +#define MTD_INODE_FS_MAGIC 0x11307854 +static struct vfsmount *mtd_inode_mnt __read_mostly; /* * Data structure to hold the pointer to the mtd device as well @@ -85,11 +88,30 @@ static int mtd_open(struct inode *inode, struct file *file) goto out; } - if (mtd->backing_dev_info) - file->f_mapping->backing_dev_info = mtd->backing_dev_info; + if (!mtd->inode) { + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); + if (!mtd->inode) { + put_mtd_device(mtd); + ret = -ENOMEM; + goto out; + } + mtd->inode->i_mode = S_IFCHR; + mtd->inode->i_rdev = inode->i_rdev; + if (mtd->backing_dev_info) { + mtd->inode->i_data.backing_dev_info = + mtd->backing_dev_info; + } + } + + spin_lock(&inode_lock); + __iget(mtd->inode); + spin_unlock(&inode_lock); + + file->f_mapping = mtd->inode->i_mapping; /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { + iput(mtd->inode); put_mtd_device(mtd); ret = -EACCES; goto out; @@ -97,6 +119,7 @@ static int mtd_open(struct inode *inode, struct file *file) mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); if (!mfi) { + iput(mtd->inode); put_mtd_device(mtd); ret = -ENOMEM; goto out; @@ -122,6 +145,8 @@ static int mtd_close(struct inode *inode, struct file *file) if ((file->f_mode & FMODE_WRITE) && mtd->sync) mtd->sync(mtd); + iput(mtd->inode); + put_mtd_device(mtd); file->private_data = NULL; kfree(mfi); @@ -951,22 +976,58 @@ static const struct file_operations mtd_fops = { #endif }; +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, + mnt); +} + +static struct file_system_type mtd_inodefs_type = { + .name = "mtd_inodefs", + .get_sb = mtd_inodefs_get_sb, + .kill_sb = kill_anon_super, +}; + static int __init init_mtdchar(void) { - int status; + int ret; - status = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, + ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd", &mtd_fops); - if (status < 0) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); + if (ret < 0) { + pr_notice("Can't allocate major number %d for " + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); + return ret; + } + + ret = register_filesystem(&mtd_inodefs_type); + if (ret) { + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_chdev; } - return status; + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); + if (IS_ERR(mtd_inode_mnt)) { + ret = PTR_ERR(mtd_inode_mnt); + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_filesystem; + } + + return ret; + +err_unregister_filesystem: + unregister_filesystem(&mtd_inodefs_type); +err_unregister_chdev: + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); + return ret; } static void __exit cleanup_mtdchar(void) { + mntput(mtd_inode_mnt); + unregister_filesystem(&mtd_inodefs_type); __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 70a7858..fa424ad 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -369,6 +369,9 @@ int del_mtd_device (struct mtd_info *mtd) mtd->index, mtd->name, mtd->usecount); ret = -EBUSY; } else { + if (mtd->inode) + iput(mtd->inode); + device_unregister(&mtd->dev); idr_remove(&mtd_idr, mtd->index); diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 5326435..d66409a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,8 @@ struct mtd_info { */ struct backing_dev_info *backing_dev_info; + /* inode for mtd device */ + struct inode *inode; int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -- 1.7.0.4 From nvbolhuis at aimvalley.nl Wed May 5 04:34:14 2010 From: nvbolhuis at aimvalley.nl (Norbert van Bolhuis) Date: Wed, 05 May 2010 10:34:14 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <201005041659.26262.muehlfelder@enertex.de> References: <201005031505.18604.muehlfelder@enertex.de> <4BDFE8D6.1050704@aimvalley.nl> <201005041659.26262.muehlfelder@enertex.de> Message-ID: <4BE12D86.2070605@aimvalley.nl> Thorsten M?hlfelder wrote: . . . >> Maybe, as said check/ask your hardware supplier. >> Maybe "refreshing" the block helps (that is saving the data, erasing the >> block(s) and reprogramming all data). You could try this. > > I've already thought about something like this: > 1. After first succesful bootup dump a mtd0 image and calculate a md5sum of > it: > nanddump -o -b -f mtd0.img /dev/mtd0 > 2. Before each shutdown dump the image again and check if the md5sum has > changed. > 3. If it has changed write the initial dump back: > flash_eraseall /dev/mtd0 > nandwrite -p /dev/mtd0 mtd0.img > > Would this be the right method? > yes that's the idea, given that "refreshing" really helps to prevent (actually delay) future read disturbs. But this won't work well. nanddump doesn't tell you the single=corrected bit errors. Only if there's an uncorrectable error (2 or more bits flip) a change will be detected and the data will be refreshed. A read disturb tends to be unstable though, meaning sometimes it's there and sometimes not. This means you may miss an uncorrectable error (2 bits flip). Another problem is a sudden reboot (e.g. crash or power-loss). There's no check then. It much more easier to let UBI/UBIFS deal with this suff. It's designed for this. u-boot support UBIFS (read-only). This means you can put a kernel image on UBIFS and make u-boot read/boot it. hth, Norbert van Bolhuis. From ricard.wanderlof at axis.com Wed May 5 04:40:37 2010 From: ricard.wanderlof at axis.com (Ricard Wanderlof) Date: Wed, 5 May 2010 10:40:37 +0200 (CEST) Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <4BE12D86.2070605@aimvalley.nl> References: <201005031505.18604.muehlfelder@enertex.de> <4BDFE8D6.1050704@aimvalley.nl> <201005041659.26262.muehlfelder@enertex.de> <4BE12D86.2070605@aimvalley.nl> Message-ID: On Wed, 5 May 2010, Norbert van Bolhuis wrote: >> I've already thought about something like this: >> 1. After first succesful bootup dump a mtd0 image and calculate a md5sum of >> it: >> nanddump -o -b -f mtd0.img /dev/mtd0 >> 2. Before each shutdown dump the image again and check if the md5sum has >> changed. >> 3. If it has changed write the initial dump back: >> flash_eraseall /dev/mtd0 >> nandwrite -p /dev/mtd0 mtd0.img >> >> Would this be the right method? > > yes that's the idea, given that "refreshing" really helps to prevent > (actually delay) future read disturbs. > ... > > Another problem is a sudden reboot (e.g. crash or power-loss). There's > no check then. Also, if a power failure occurs during erase or nandwrite the system will not boot next time. /Ricard -- Ricard Wolf Wanderl?f ricardw(at)axis.com Axis Communications AB, Lund, Sweden www.axis.com Phone +46 46 272 2016 Fax +46 46 13 61 30 From dedekind1 at gmail.com Wed May 5 04:51:20 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 11:51:20 +0300 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: References: <201005031505.18604.muehlfelder@enertex.de> <4BDFE8D6.1050704@aimvalley.nl> <201005041659.26262.muehlfelder@enertex.de> <4BE12D86.2070605@aimvalley.nl> Message-ID: <1273049480.3702.129.camel@localhost> On Wed, 2010-05-05 at 10:40 +0200, Ricard Wanderlof wrote: > On Wed, 5 May 2010, Norbert van Bolhuis wrote: > > >> I've already thought about something like this: > >> 1. After first succesful bootup dump a mtd0 image and calculate a md5sum of > >> it: > >> nanddump -o -b -f mtd0.img /dev/mtd0 > >> 2. Before each shutdown dump the image again and check if the md5sum has > >> changed. > >> 3. If it has changed write the initial dump back: > >> flash_eraseall /dev/mtd0 > >> nandwrite -p /dev/mtd0 mtd0.img > >> > >> Would this be the right method? > > > > yes that's the idea, given that "refreshing" really helps to prevent > > (actually delay) future read disturbs. > > ... > > > > Another problem is a sudden reboot (e.g. crash or power-loss). There's > > no check then. > > Also, if a power failure occurs during erase or nandwrite the system will > not boot next time. Unless you supply your device with an UPS :-) I did not really follow the discussion, so sorry if the following is unrelated: I think it should not be too difficult to teach JFFS2 to force GC on eraseblocks with bit-flips. -- Best Regards, Artem Bityutskiy (????? ????????) From ricard.wanderlof at axis.com Wed May 5 05:20:42 2010 From: ricard.wanderlof at axis.com (Ricard Wanderlof) Date: Wed, 5 May 2010 11:20:42 +0200 (CEST) Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <1273049480.3702.129.camel@localhost> References: <201005031505.18604.muehlfelder@enertex.de> <4BDFE8D6.1050704@aimvalley.nl> <201005041659.26262.muehlfelder@enertex.de> <4BE12D86.2070605@aimvalley.nl> <1273049480.3702.129.camel@localhost> Message-ID: On Wed, 5 May 2010, Artem Bityutskiy wrote: > Unless you supply your device with an UPS :-) Or rather, unless you never power down you're device. An UPS is great for unexpected power outages, but sooner or later you might want to power down your device under manual control anyway... :-) > I did not really follow the discussion, so sorry if the following is > unrelated: I think it should not be too difficult to teach JFFS2 to > force GC on eraseblocks with bit-flips. I think in this case the partition in question just held a raw Linux kernel with no file system, so JFFS2 is out of the picture here. /Ricard -- Ricard Wolf Wanderl?f ricardw(at)axis.com Axis Communications AB, Lund, Sweden www.axis.com Phone +46 46 272 2016 Fax +46 46 13 61 30 From nvbolhuis at aimvalley.nl Wed May 5 05:29:09 2010 From: nvbolhuis at aimvalley.nl (Norbert van Bolhuis) Date: Wed, 05 May 2010 11:29:09 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <1273049480.3702.129.camel@localhost> References: <201005031505.18604.muehlfelder@enertex.de> <4BDFE8D6.1050704@aimvalley.nl> <201005041659.26262.muehlfelder@enertex.de> <4BE12D86.2070605@aimvalley.nl> <1273049480.3702.129.camel@localhost> Message-ID: <4BE13A65.1020701@aimvalley.nl> Artem Bityutskiy wrote: . . . > > Unless you supply your device with an UPS :-) > > I did not really follow the discussion, so sorry if the following is > unrelated: I think it should not be too difficult to teach JFFS2 to > force GC on eraseblocks with bit-flips. > I can confirm that ;-) we actually implemented this (for our ancient 2.4.25 kernel with JFFS2 version 2005) because we were seriously suffering from NAND bit flips on our Numonyx SLC NAND device. see: http://lists.infradead.org/pipermail/linux-mtd/2009-August/027080.html This would only benefit the OP if kernel image is kept on JFFS2 (too). From dedekind1 at gmail.com Wed May 5 07:18:46 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 14:18:46 +0300 Subject: [PATCH] mtd: nand_base: Extend NAND flash detection to new MLC chips In-Reply-To: <430ce15d6a65533b5c3677b02498e5ff2e41c78c@localhost.localdomain> References: <430ce15d6a65533b5c3677b02498e5ff2e41c78c@localhost.localdomain> Message-ID: <1273058326.3702.174.camel@localhost> On Mon, 2010-05-03 at 17:46 -0700, Kevin Cernekee wrote: > Some of the newer MLC devices have a 6-byte ID sequence in which > several field definitions differ from older chips in a manner that is > not backward compatible. For instance: > > Samsung K9GAG08U0M (5-byte sequence): ec d5 14 b6 74 > 4th byte, bits 1:0 encode the page size: 0=1KiB, 1=2KiB, 2=4KiB, 3=8KiB > 4th byte, bits 5:4 encode the block size: 0=64KiB, 1=128KiB, ... > 4th byte, bit 6 encodes the OOB size: 0=8B/512B, 1=16B/512B > > Samsung K9GAG08U0D (6-byte sequence): ec d5 94 29 34 41 > 4th byte, bits 1:0 encode the page size: 0=2KiB, 1=4KiB, 3=8KiB, 4=rsvd > 4th byte, bits 7;5:4 encode the block size: 0=128KiB, 1=256KiB, ... > 4th byte, bits 6;3:2 encode the OOB size: 1=128B/page, 2=218B/page > > This patch uses the new 6-byte scheme if the ID code wraps around > exactly at byte 6, and falls back to the old scheme otherwise. > > Signed-off-by: Kevin Cernekee Pushed to l2-mtd-2.6 / master -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 07:19:05 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 14:19:05 +0300 Subject: [PATCH] mtd: Increase NAND_MAX_OOBSIZE from 128 to 256 In-Reply-To: References: Message-ID: <1273058345.3702.175.camel@localhost> On Mon, 2010-05-03 at 21:20 -0700, Kevin Cernekee wrote: > NAND_MAX_OOBSIZE needs to be increased to support newer parts with > 218 or 224 byte spare areas. Tested with Samsung K9GAG08U0D. > > Signed-off-by: Kevin Cernekee Pushed to l2-mtd-2.6 / master -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 07:25:59 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 14:25:59 +0300 Subject: [PATCH] nanddump: Support 4096+218 and 4096+224 page sizes In-Reply-To: References: Message-ID: <1273058759.3702.176.camel@localhost> On Mon, 2010-05-03 at 21:14 -0700, Kevin Cernekee wrote: > Tested with Samsung K9GAG08U0D. > > Signed-off-by: Kevin Cernekee > --- > nanddump.c | 4 +++- > 1 files changed, 3 insertions(+), 1 deletions(-) Pushed to mtd-utils.git -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 07:26:34 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 14:26:34 +0300 Subject: [PATCHv2] nanddump: Support 4096+218 and 4096+224 page sizes In-Reply-To: <947e853e5d1ba35a67546703267b0fabe59af110@localhost.localdomain> References: <947e853e5d1ba35a67546703267b0fabe59af110@localhost.localdomain> Message-ID: <1273058794.3702.177.camel@localhost> On Mon, 2010-05-03 at 22:10 -0700, Kevin Cernekee wrote: > Tested with Samsung K9GAG08U0D (4096+218). > > This fixes three additional problems found after the initial patch > submission: > > 1) oobbuf was only 128B. Needs to be 256B now. > > 2) Random OOB data is output when nanddump hits a bad block, because > the code was initializing readbuf instead. > > 3) When using "-p", random data is displayed for bytes 218-223 since > the OOB does not end on a 16B boundary. > > Signed-off-by: Kevin Cernekee Does not apply to the latest mtd-utils: Applying: nanddump: Support 4096+218 and 4096+224 page sizes error: patch failed: nanddump.c:209 error: nanddump.c: patch does not apply Patch failed at 0001 nanddump: Support 4096+218 and 4096+224 page sizes When you have resolved this problem run "git am -i --resolved". If you would prefer to skip this patch, instead run "git am -i --skip". To restore the original branch and stop patching run "git am -i --abort". [dedekind at eru mtd-utils]$ patch -p1 < .git/rebase-apply/patch patching file nanddump.c Hunk #2 FAILED at 212. Hunk #3 succeeded at 359 (offset 2 lines). 1 out of 3 hunks FAILED -- saving rejects to file nanddump.c.rej -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 08:11:39 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 15:11:39 +0300 Subject: [PATCHv2] MTD: Suppress warnings in inline_map_read() In-Reply-To: References: <1270891582.4704.102.camel@macbook.infradead.org> <1272354388.26036.4.camel@localhost> <1272978272.3702.5.camel@localhost> Message-ID: <1273061499.3702.178.camel@localhost> On Tue, 2010-05-04 at 13:06 -0700, Kevin Cernekee wrote: > On Tue, May 4, 2010 at 6:04 AM, Artem Bityutskiy wrote: > > /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/map.h: In function 'inline_map_read': > > /home/dedekind/git/l2-mtd-2.6/include/linux/mtd/map.h:390: error: implicit declaration of function 'BUG' > > I did test my patch, but it didn't generate any warnings or errors on MIPS... > > Could you please apply this patch and retry: > > http://lists.infradead.org/pipermail/linux-mtd/2010-May/029904.html > > should probably be added anyway since there are two > other BUG statements in that file. Pushed this patch and the '[PATCH] mtd: map.h: add missing bug.h include' one back to l2-mtd-2.6 / dunno. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 5 08:19:20 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 15:19:20 +0300 Subject: [PATCHv2 0/2] mtd: nand: Extend MLC support In-Reply-To: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> References: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> Message-ID: <1273061960.3702.179.camel@localhost> On Tue, 2010-05-04 at 20:58 -0700, Kevin Cernekee wrote: > Part 1/2 is an improved version of my previous submission. Additional > checks were added to ensure that certain "5-byte" Micron and Samsung > parts are not falsely detected as having 6-byte IDs. I also rolled in > the 256B NAND_MAX_OOBSIZE change. > > Part 2/2 is a resubmission/rebase of Reuben Dowle's 2009/02/03 patch: > > http://lists.infradead.org/pipermail/linux-mtd/2009-February/024473.html > > I am trying to compile a table of NAND IDs to make sure the detection > algorithm correctly handles all known cases. If you could send me the > following information for any NAND chips you have access to (via > private email), it would be appreciated: > > 1) Part number > > 2) ID code (please read 8 bytes so I can see where it wraps around) > > 3) Device size, block size, page size, OOB bytes per page, bus width, > and bad block marker location > > 4) Datasheet, if available Removed older patches and taken these ones to l2-mtd-2.6 / dunno. -- Best Regards, Artem Bityutskiy (????? ????????) From s-ghorai at ti.com Wed May 5 08:33:22 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Wed, 5 May 2010 18:03:22 +0530 Subject: Upcoming merge window and omap NAND patches In-Reply-To: References: <20100504220803.GN29604@atomide.com> <1273034943.3702.19.camel@localhost> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D7DEB6B@dbde02.ent.ti.com> Tony, I understand your comment/input. And I will work on it. All existing omap3 boards are using same old fashion. So let me see how many board I can test before post the patch. I will update this next week. Regards, Ghorai > -----Original Message----- > From: Vimal Singh [mailto:vimal.newwork at gmail.com] > Sent: 2010-05-05 11:42 > To: Artem.Bityutskiy at nokia.com > Cc: Tony Lindgren; linux-omap at vger.kernel.org; linux- > mtd at lists.infradead.org; Ghorai, Sukumar; Steve Sakoman; Mike Rapoport > Subject: Re: Upcoming merge window and omap NAND patches > > On Wed, May 5, 2010 at 10:19 AM, Artem Bityutskiy > wrote: > > On Wed, 2010-05-05 at 00:08 +0200, ext Tony Lindgren wrote: > >> Hi all, > >> > >> There are several omap NAND patches pending, but some basic things > >> should be fixed first. > >> > >> 1. The NAND driver needs to stop tinkering with the GPMC registers > >> > >> The omap General Purpose Memory Controller (GPMC) registers are omap > >> specific, and not driver specific. Tinkering with these registers > >> can cause issues with the other devices on the GPMC. > >> > >> To find out what needs to disappear fomr the NAND driver, just do: > >> > >> $ grep baseaddr drivers/mtd/nand/omap2.c > >> > >> Any GPMC register tinkering needs to happen in arch/arm/mach- > omap2/gpmc.c. > >> If there are not currently GPMC functions to do something in gpmc.c, > then > >> let's add the necessary support there. > >> > >> 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files > >> > >> Passing hardcoded GPMC virtual addressess is sure way to mess up > >> things. This should all become unnecessary once the NAND drivers > >> stops messing with the GPMC registers directly. > >> > >> So, as a result, I'm not planning on pushing any omap NAND related > >> patches until these basic issues are fixed. I'll mark these patches > >> as "Changes requested" in patchwork.kernel.org even if these patches > >> don't have anything else wrong with them. > >> > >> Let's fix the basic things for good, and put the other patches on > >> hold for a while. Sorry if this causes problems! > > > > Hi, > > > > fair enough. I guess Vimal should address this, as he seems to be the TI > > mr. NAND, right? :-) > > Hi All, > > Sorry again. I am no more with TI and I don't have any board with me > too. So, I'm unable to fix these. :( > I hope someone else from TI can take care of it. > > -- > Regards, > Vimal Singh From mike at compulab.co.il Wed May 5 08:55:20 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Wed, 05 May 2010 15:55:20 +0300 Subject: Upcoming merge window and omap NAND patches In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B030D7DEB6B@dbde02.ent.ti.com> References: <20100504220803.GN29604@atomide.com> <1273034943.3702.19.camel@localhost> <2A3DCF3DA181AD40BDE86A3150B27B6B030D7DEB6B@dbde02.ent.ti.com> Message-ID: <4BE16AB8.7010308@compulab.co.il> Ghorai, Ghorai, Sukumar wrote: > Tony, > I understand your comment/input. And I will work on it. > > All existing omap3 boards are using same old fashion. So let me see how many board I can test before post the patch. I will update this next week. I'd be glad to test the patches on CM-T35 if you'd like to. > Regards, > Ghorai > >> -----Original Message----- >> From: Vimal Singh [mailto:vimal.newwork at gmail.com] >> Sent: 2010-05-05 11:42 >> To: Artem.Bityutskiy at nokia.com >> Cc: Tony Lindgren; linux-omap at vger.kernel.org; linux- >> mtd at lists.infradead.org; Ghorai, Sukumar; Steve Sakoman; Mike Rapoport >> Subject: Re: Upcoming merge window and omap NAND patches >> >> On Wed, May 5, 2010 at 10:19 AM, Artem Bityutskiy >> wrote: >>> On Wed, 2010-05-05 at 00:08 +0200, ext Tony Lindgren wrote: >>>> Hi all, >>>> >>>> There are several omap NAND patches pending, but some basic things >>>> should be fixed first. >>>> >>>> 1. The NAND driver needs to stop tinkering with the GPMC registers >>>> >>>> The omap General Purpose Memory Controller (GPMC) registers are omap >>>> specific, and not driver specific. Tinkering with these registers >>>> can cause issues with the other devices on the GPMC. >>>> >>>> To find out what needs to disappear fomr the NAND driver, just do: >>>> >>>> $ grep baseaddr drivers/mtd/nand/omap2.c >>>> >>>> Any GPMC register tinkering needs to happen in arch/arm/mach- >> omap2/gpmc.c. >>>> If there are not currently GPMC functions to do something in gpmc.c, >> then >>>> let's add the necessary support there. >>>> >>>> 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files >>>> >>>> Passing hardcoded GPMC virtual addressess is sure way to mess up >>>> things. This should all become unnecessary once the NAND drivers >>>> stops messing with the GPMC registers directly. >>>> >>>> So, as a result, I'm not planning on pushing any omap NAND related >>>> patches until these basic issues are fixed. I'll mark these patches >>>> as "Changes requested" in patchwork.kernel.org even if these patches >>>> don't have anything else wrong with them. >>>> >>>> Let's fix the basic things for good, and put the other patches on >>>> hold for a while. Sorry if this causes problems! >>> Hi, >>> >>> fair enough. I guess Vimal should address this, as he seems to be the TI >>> mr. NAND, right? :-) >> Hi All, >> >> Sorry again. I am no more with TI and I don't have any board with me >> too. So, I'm unable to fix these. :( >> I hope someone else from TI can take care of it. >> >> -- >> Regards, >> Vimal Singh -- Sincerely yours, Mike. From dedekind1 at gmail.com Wed May 5 10:17:19 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 05 May 2010 17:17:19 +0300 Subject: [PATCH v3] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1273047688-20947-1-git-send-email-kirill@shutemov.name> References: <1273047688-20947-1-git-send-email-kirill@shutemov.name> Message-ID: <1273069039.3702.188.camel@localhost> On Wed, 2010-05-05 at 11:21 +0300, Kirill A. Shutemov wrote: > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > backing device of device node inode, since file->f_mapping is equal to > inode->i_mapping (see __dentry_open() in fs/open.c). > > Let's introduce separate inode for MTD device with appropriate backing > device. > > Signed-off-by: Kirill A. Shutemov > Acked-by: Jan Kara I get the following build error: [dedekind at eru l2-mtd-2.6]$ make -j8 O=/home/dedekind/tmp/l2-mtd-2.6-x86_64/ GEN /home/dedekind/tmp/l2-mtd-2.6-x86_64/Makefile CHK include/linux/version.h CHK include/generated/utsrelease.h Using /home/dedekind/git/l2-mtd-2.6 as source for kernel CALL /home/dedekind/git/l2-mtd-2.6/scripts/checksyscalls.sh CHK include/generated/compile.h CHK include/linux/version.h make[3]: `scripts/unifdef' is up to date. Building modules, stage 2. Kernel: arch/x86/boot/bzImage is ready (#2) MODPOST 146 modules ERROR: "__iget" [drivers/mtd/mtdchar.ko] undefined! ERROR: "inode_lock" [drivers/mtd/mtdchar.ko] undefined! make[2]: *** [__modpost] Error 1 make[1]: *** [modules] Error 2 make: *** [sub-make] Error 2 __iget and inode_lock are not exported... -- Best Regards, Artem Bityutskiy (????? ????????) From jack at suse.cz Wed May 5 10:27:07 2010 From: jack at suse.cz (Jan Kara) Date: Wed, 5 May 2010 16:27:07 +0200 Subject: [PATCH v3] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1273069039.3702.188.camel@localhost> References: <1273047688-20947-1-git-send-email-kirill@shutemov.name> <1273069039.3702.188.camel@localhost> Message-ID: <20100505142707.GA3938@quack.suse.cz> On Wed 05-05-10 17:17:19, Artem Bityutskiy wrote: > On Wed, 2010-05-05 at 11:21 +0300, Kirill A. Shutemov wrote: > > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > > backing device of device node inode, since file->f_mapping is equal to > > inode->i_mapping (see __dentry_open() in fs/open.c). > > > > Let's introduce separate inode for MTD device with appropriate backing > > device. > > > > Signed-off-by: Kirill A. Shutemov > > Acked-by: Jan Kara > > I get the following build error: > > [dedekind at eru l2-mtd-2.6]$ make -j8 > O=/home/dedekind/tmp/l2-mtd-2.6-x86_64/ > GEN /home/dedekind/tmp/l2-mtd-2.6-x86_64/Makefile > CHK include/linux/version.h > CHK include/generated/utsrelease.h > Using /home/dedekind/git/l2-mtd-2.6 as source for kernel > CALL /home/dedekind/git/l2-mtd-2.6/scripts/checksyscalls.sh > CHK include/generated/compile.h > CHK include/linux/version.h > make[3]: `scripts/unifdef' is up to date. > Building modules, stage 2. > Kernel: arch/x86/boot/bzImage is ready (#2) > MODPOST 146 modules > ERROR: "__iget" [drivers/mtd/mtdchar.ko] undefined! > ERROR: "inode_lock" [drivers/mtd/mtdchar.ko] undefined! > make[2]: *** [__modpost] Error 1 > make[1]: *** [modules] Error 2 > make: *** [sub-make] Error 2 > > __iget and inode_lock are not exported... Ah, right. igrab() should be used instead of __iget inside the inode_lock. Honza -- Jan Kara SUSE Labs, CR From tony at atomide.com Wed May 5 11:11:11 2010 From: tony at atomide.com (Tony Lindgren) Date: Wed, 5 May 2010 08:11:11 -0700 Subject: Upcoming merge window and omap NAND patches In-Reply-To: <4BE16AB8.7010308@compulab.co.il> References: <20100504220803.GN29604@atomide.com> <1273034943.3702.19.camel@localhost> <2A3DCF3DA181AD40BDE86A3150B27B6B030D7DEB6B@dbde02.ent.ti.com> <4BE16AB8.7010308@compulab.co.il> Message-ID: <20100505151111.GT29604@atomide.com> * Mike Rapoport [100505 05:51]: > Ghorai, > > Ghorai, Sukumar wrote: > >Tony, > >I understand your comment/input. And I will work on it. Great, good to hear. > >All existing omap3 boards are using same old fashion. So let me see how many board I can test before post the patch. I will update this next week. > > I'd be glad to test the patches on CM-T35 if you'd like to. For this merge window how about just getting rid of OMAP34XX_GPMC_VIRT in the board-*.c files and move that to gpmc-nand.c? This may allow adding more board-*.c NAND files without having to patch all of them later on again. However, if there are more changes needed to all the board-*.c files for the NAND platform data, then let's just fix the existing ones first before adding new ones. After that, looks like most of the work is to move some of the GPMC functions from omap2.c to gpmc.c. Or should they rather be in gpmc-nand.c if they are only used with NAND connected to GPMC? Regards, Tony From cernekee at gmail.com Wed May 5 11:20:53 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Wed, 5 May 2010 08:20:53 -0700 Subject: [PATCHv2 1/2] mtd: nand: Extend NAND flash detection to new MLC chips In-Reply-To: <4BE11FA0.20703@parrot.com> References: <17c88de31cd52bb3794569c28cd2ae51996e6260@localhost.localdomain> <10137ab89de6e6d229798d6f397688b0807024da@localhost.localdomain> <4BE11FA0.20703@parrot.com> Message-ID: On Wed, May 5, 2010 at 12:34 AM, Matthieu CASTET wrote: > Doesn't these nand support ONFI "Read Parameter Page" (cmd 0xec) ? > If yes it will be a more generic way to detect new nand features. Unfortunately, Samsung and Toshiba do not support ONFI: http://onfi.org/membership/ http://www.hantat.com/News-Read-281-1.html From kirill at shutemov.name Wed May 5 11:40:54 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Wed, 5 May 2010 18:40:54 +0300 Subject: [PATCH v4] mtd: Do not corrupt backing device of device node inode Message-ID: <1273074054-11849-1-git-send-email-kirill@shutemov.name> We cannot modify file->f_mapping->backing_dev_info, because it will corrupt backing device of device node inode, since file->f_mapping is equal to inode->i_mapping (see __dentry_open() in fs/open.c). Let's introduce separate inode for MTD device with appropriate backing device. Signed-off-by: Kirill A. Shutemov --- Changelog: v3 -> v4: - Use igrab() instead of __iget inside the inode_lock; - Add stable@ to CC list. v2 -> v3: - Rebase to mtd-2.6.git. v1 -> v2: - Fix error handling based on comments by Jan Kara. --- drivers/mtd/mtdchar.c | 74 +++++++++++++++++++++++++++++++++++++++++----- drivers/mtd/mtdcore.c | 3 ++ include/linux/mtd/mtd.h | 3 ++ 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index c355491..7f4634e 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include +#define MTD_INODE_FS_MAGIC 0x11307854 +static struct vfsmount *mtd_inode_mnt __read_mostly; /* * Data structure to hold the pointer to the mtd device as well @@ -85,11 +88,27 @@ static int mtd_open(struct inode *inode, struct file *file) goto out; } - if (mtd->backing_dev_info) - file->f_mapping->backing_dev_info = mtd->backing_dev_info; + if (!mtd->inode) { + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); + if (!mtd->inode) { + put_mtd_device(mtd); + ret = -ENOMEM; + goto out; + } + mtd->inode->i_mode = S_IFCHR; + mtd->inode->i_rdev = inode->i_rdev; + if (mtd->backing_dev_info) { + mtd->inode->i_data.backing_dev_info = + mtd->backing_dev_info; + } + } + + igrab(mtd->inode); + file->f_mapping = mtd->inode->i_mapping; /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { + iput(mtd->inode); put_mtd_device(mtd); ret = -EACCES; goto out; @@ -97,6 +116,7 @@ static int mtd_open(struct inode *inode, struct file *file) mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); if (!mfi) { + iput(mtd->inode); put_mtd_device(mtd); ret = -ENOMEM; goto out; @@ -122,6 +142,8 @@ static int mtd_close(struct inode *inode, struct file *file) if ((file->f_mode & FMODE_WRITE) && mtd->sync) mtd->sync(mtd); + iput(mtd->inode); + put_mtd_device(mtd); file->private_data = NULL; kfree(mfi); @@ -951,22 +973,58 @@ static const struct file_operations mtd_fops = { #endif }; +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, + mnt); +} + +static struct file_system_type mtd_inodefs_type = { + .name = "mtd_inodefs", + .get_sb = mtd_inodefs_get_sb, + .kill_sb = kill_anon_super, +}; + static int __init init_mtdchar(void) { - int status; + int ret; - status = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, + ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd", &mtd_fops); - if (status < 0) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); + if (ret < 0) { + pr_notice("Can't allocate major number %d for " + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); + return ret; } - return status; + ret = register_filesystem(&mtd_inodefs_type); + if (ret) { + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_chdev; + } + + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); + if (IS_ERR(mtd_inode_mnt)) { + ret = PTR_ERR(mtd_inode_mnt); + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_filesystem; + } + + return ret; + +err_unregister_filesystem: + unregister_filesystem(&mtd_inodefs_type); +err_unregister_chdev: + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); + return ret; } static void __exit cleanup_mtdchar(void) { + mntput(mtd_inode_mnt); + unregister_filesystem(&mtd_inodefs_type); __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 70a7858..fa424ad 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -369,6 +369,9 @@ int del_mtd_device (struct mtd_info *mtd) mtd->index, mtd->name, mtd->usecount); ret = -EBUSY; } else { + if (mtd->inode) + iput(mtd->inode); + device_unregister(&mtd->dev); idr_remove(&mtd_idr, mtd->index); diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 5326435..d66409a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,8 @@ struct mtd_info { */ struct backing_dev_info *backing_dev_info; + /* inode for mtd device */ + struct inode *inode; int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -- 1.7.0.4 From linux_vpn at yahoo.com Wed May 5 13:38:12 2010 From: linux_vpn at yahoo.com (Zhiwei Yu) Date: Wed, 5 May 2010 10:38:12 -0700 (PDT) Subject: Francine NAUDIN Message-ID: <927620.93001.qm@web55002.mail.re4.yahoo.com> http://alpha-photo.fr/home.php From SteveDeiters at BASLER.com Wed May 5 14:48:38 2010 From: SteveDeiters at BASLER.com (Steve Deiters) Date: Wed, 5 May 2010 13:48:38 -0500 Subject: [PATCH resend] mpc5121_nfc: Changed SVR check to allow MPC5123. In-Reply-To: <1272980863.3702.10.camel@localhost> References: <181804936ABC2349BE503168465576460E95836C@exchserver.basler.com> <1272980863.3702.10.camel@localhost> Message-ID: <181804936ABC2349BE503168465576460EA16F75@exchserver.basler.com> The revision in SVR for MPC5123 is 3. The NFC is the same as MPC5121 revision 2. Signed-off-by: Steve Deiters --- drivers/mtd/nand/mpc5121_nfc.c | 4 ++-- 1 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 191bf99..dc04d74 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -666,10 +666,10 @@ static int __devinit mpc5121_nfc_probe(struct of_device *op, /* * Check SoC revision. This driver supports only NFC - * in MPC5121 revision 2. + * in MPC5121 revision 2 and MPC5123 revision 3. */ rev = (mfspr(SPRN_SVR) >> 4) & 0xF; - if (rev != 2) { + if ((rev != 2) && (rev != 3)) { dev_err(dev, "SoC revision %u is not supported!\n", rev); return -ENXIO; } -- 1.5.4.3 From jeff at garzik.org Wed May 5 15:29:12 2010 From: jeff at garzik.org (Jeff Garzik) Date: Wed, 5 May 2010 15:29:12 -0400 Subject: [git patches] Delete two zero-length files Message-ID: <20100505192912.GA5525@havoc.gtf.org> Please pull from 'zerolen' branch of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6.git zerolen to receive the following updates: 0 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 drivers/mtd/internal.h delete mode 100644 drivers/mtd/mtdbdi.c Jeff Garzik (1): [MTD] Remove zero-length files mtdbdi.c and internal.ho diff --git a/drivers/mtd/internal.h b/drivers/mtd/internal.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/mtd/mtdbdi.c b/drivers/mtd/mtdbdi.c deleted file mode 100644 index e69de29..0000000 From carolacisternas at manquehue.net Wed May 5 22:41:41 2010 From: carolacisternas at manquehue.net (NOKIA MOBILE GROUP) Date: Wed, 5 May 2010 22:41:41 -0400 (CLT) Subject: You 've won 600,000 usd send info full name,address,age,country Message-ID: <35446.41.206.15.1.1273113701.squirrel@webmail3c.manquehue.net> You 've won 600,000 usd send info full name,address,age,country From shinya.kuribayashi.px at renesas.com Wed May 5 23:39:47 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 12:39:47 +0900 Subject: A few cleanups against Linus' master Message-ID: <4BE23A03.1030001@renesas.com> Hi, Noticed and fixed while learning UBI subsystems. As for comment fixes a double-check by native speaker would be appricated. p.s. UBI fixes can be squashed into one at your option, thanks. Shinya Kuribayashi (3): UBI: Fix s/then/than/ typos UBI: Remaining typos and comments cleanups mtd: Remove empty mtd/mtdbdi.c and mtd/internal.h files drivers/mtd/ubi/Kconfig | 2 +- drivers/mtd/ubi/io.c | 4 ++-- drivers/mtd/ubi/kapi.c | 6 +++--- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/vtbl.c | 4 ++-- drivers/mtd/ubi/wl.c | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) delete mode 100644 drivers/mtd/internal.h delete mode 100644 drivers/mtd/mtdbdi.c -- Shinya Kuribayashi Renesas Electronics From shinya.kuribayashi.px at renesas.com Wed May 5 23:41:35 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 12:41:35 +0900 Subject: [PATCH] UBI: Fix s/then/than/ typos In-Reply-To: <4BE23A03.1030001@renesas.com> References: <4BE23A03.1030001@renesas.com> Message-ID: <4BE23A6F.1010406@renesas.com> Signed-off-by: Shinya Kuribayashi --- drivers/mtd/ubi/Kconfig | 2 +- drivers/mtd/ubi/io.c | 2 +- drivers/mtd/ubi/kapi.c | 6 +++--- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/wl.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 0a8c7ea..f702a16 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -27,7 +27,7 @@ config MTD_UBI_WL_THRESHOLD The default value should be OK for SLC NAND flashes, NOR flashes and other flashes which have eraseblock life-cycle 100000 or more. However, in case of MLC NAND flashes which typically have eraseblock - life-cycle less then 10000, the threshold should be lessened (e.g., + life-cycle less than 10000, the threshold should be lessened (e.g., to 128 or 256, although it does not have to be power of 2). config MTD_UBI_BEB_RESERVE diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 533b1a4..016ec13 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -65,7 +65,7 @@ * * A: because when writing a sub-page, MTD still writes a full 2K page but the * bytes which are no relevant to the sub-page are 0xFF. So, basically, writing - * 4x512 sub-pages is 4 times slower then writing one 2KiB NAND page. Thus, we + * 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. Thus, we * prefer to use sub-pages only for EV and VID headers. * * As it was noted above, the VID header may start at a non-aligned offset. diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 17f287d..69fa4ef 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -488,7 +488,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write); * * This function changes the contents of a logical eraseblock atomically. @buf * has to contain new logical eraseblock data, and @len - the length of the - * data, which has to be aligned. The length may be shorter then the logical + * data, which has to be aligned. The length may be shorter than the logical * eraseblock size, ant the logical eraseblock may be appended to more times * later on. This function guarantees that in case of an unclean reboot the old * contents is preserved. Returns zero in case of success and a negative error @@ -571,7 +571,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_erase); * * This function un-maps logical eraseblock @lnum and schedules the * corresponding physical eraseblock for erasure, so that it will eventually be - * physically erased in background. This operation is much faster then the + * physically erased in background. This operation is much faster than the * erase operation. * * Unlike erase, the un-map operation does not guarantee that the logical @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_erase); * * The main and obvious use-case of this function is when the contents of a * logical eraseblock has to be re-written. Then it is much more efficient to - * first un-map it, then write new data, rather then first erase it, then write + * first un-map it, then write new data, rather than first erase it, then write * new data. Note, once new data has been written to the logical eraseblock, * UBI guarantees that the old contents has gone forever. In other words, if an * unclean reboot happens after the logical eraseblock has been un-mapped and diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index dc5f688..aed19f3 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -231,7 +231,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, * case of success this function returns a positive value, in case of failure, a * negative error code is returned. The success return codes use the following * bits: - * o bit 0 is cleared: the first PEB (described by @seb) is newer then the + * o bit 0 is cleared: the first PEB (described by @seb) is newer than the * second PEB (described by @pnum and @vid_hdr); * o bit 0 is set: the second PEB is newer; * o bit 1 is cleared: no bit-flips were detected in the newer LEB; @@ -452,7 +452,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, if (cmp_res & 1) { /* - * This logical eraseblock is newer then the one + * This logical eraseblock is newer than the one * found earlier. */ err = validate_vid_hdr(vid_hdr, sv, pnum); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index f64ddab..ee7b1d8 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -350,7 +350,7 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e) * @max: highest possible erase counter * * This function looks for a wear leveling entry with erase counter closest to - * @max and less then @max. + * @max and less than @max. */ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max) { -- 1.7.1 From shinya.kuribayashi.px at renesas.com Wed May 5 23:42:05 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 12:42:05 +0900 Subject: [PATCH] UBI: Remaining typos and comments cleanups In-Reply-To: <4BE23A03.1030001@renesas.com> References: <4BE23A03.1030001@renesas.com> Message-ID: <4BE23A8D.7040106@renesas.com> Signed-off-by: Shinya Kuribayashi --- drivers/mtd/ubi/io.c | 2 +- drivers/mtd/ubi/vtbl.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 016ec13..cd0bf57 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -64,7 +64,7 @@ * device, e.g., make @ubi->min_io_size = 512 in the example above? * * A: because when writing a sub-page, MTD still writes a full 2K page but the - * bytes which are no relevant to the sub-page are 0xFF. So, basically, writing + * bytes which are not relevant to the sub-page are 0xFF. So, basically, writing * 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. Thus, we * prefer to use sub-pages only for EV and VID headers. * diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index cd90ff3..14c10be 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -414,7 +414,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, * 0 contains more recent information. * * So the plan is to first check LEB 0. Then - * a. if LEB 0 is OK, it must be containing the most resent data; then + * a. if LEB 0 is OK, it must be containing the most recent data; then * we compare it with LEB 1, and if they are different, we copy LEB * 0 to LEB 1; * b. if LEB 0 is corrupted, but LEB 1 has to be OK, and we copy LEB 1 @@ -848,7 +848,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) goto out_free; /* - * Get sure that the scanning information is consistent to the + * Make sure that the scanning information is consistent to the * information stored in the volume table. */ err = check_scanning_info(ubi, si); -- 1.7.1 From shinya.kuribayashi.px at renesas.com Wed May 5 23:43:23 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 12:43:23 +0900 Subject: [PATCH] mtd: Remove empty mtd/mtdbdi.c and mtd/internal.h files In-Reply-To: <4BE23A03.1030001@renesas.com> References: <4BE23A03.1030001@renesas.com> Message-ID: <4BE23ADB.9090409@renesas.com> Commit a33eb6b9 (Move mtd_bdi_*mappable to mtdcore.c) forgot to 'git rm' these files. Cc: Joern Engel Signed-off-by: Shinya Kuribayashi --- 0 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 drivers/mtd/internal.h delete mode 100644 drivers/mtd/mtdbdi.c diff --git a/drivers/mtd/internal.h b/drivers/mtd/internal.h deleted file mode 100644 index e69de29..0000000 diff --git a/drivers/mtd/mtdbdi.c b/drivers/mtd/mtdbdi.c deleted file mode 100644 index e69de29..0000000 -- 1.7.1 From kyungmin.park at samsung.com Wed May 5 23:46:10 2010 From: kyungmin.park at samsung.com (Kyungmin Park) Date: Thu, 6 May 2010 12:46:10 +0900 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: Hi, Can you add this statement at below the code? printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) onenand_addr(this, block), ((int) addr >> this->page_shift) & this->page_mask); In my test environment, it displays the correct page number. (addr - onenand_addr(this, block) >> this->page_shift is same as '(addr >> this->page_shift) & this->page_mask'. Thank you, Kyungmin Park On Fri, Apr 30, 2010 at 7:05 PM, Enric Balletb? i Serra wrote: > Hello all, > > After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: > Flex-OneNAND support) the onenand support for my device is broken. > > Before this commit when I run the nandtest program all is ok > --- > # nandtest /dev/mtd3 > ECC corrections: 0 > ECC failures ? : 0 > Bad blocks ? ? : 0 > BBT blocks ? ? : 0 > 002c0000: checking... > Finished pass 1 successfully > -- > > Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest > fails with: > --- > # nandtest /dev/mtd3 > ECC corrections: 0 > ECC failures ? : 0 > Bad blocks ? ? : 0 > BBT blocks ? ? : 0 > 00000000: reading... > [ ?299.092041] onenand_wait: ECC error = 0x8488 > ? ?( ... lots of ECC errors ... ) > [ ?299.092041] onenand_wait: ECC error = 0x8488 > ECC failed at 00000000 > 00000000: checking... > compare failed. seed 1804289383 > Byte 0x1 is 5a should be da > Byte 0x3 is 82 should be 92 > Byte 0x4 is 10 should be 1a > ? ?( ... ) > --- > > Investigating a little I see a significant difference introduced by > this patch. In line > > 347: ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> > this->page_shift; ? (patch applied) > > instead of > > 347: ? ? ? ?page = (int) (addr >> this->page_shift); ?(without patch) > > I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced > the line 347 and now works again. Fantastic, but I suspect this is not > the proper solution (probably this breaks other onenands devices, I > can't test). > > I'm just introducing in OneNAND devices so anyone can help me to > understand and solve the problem ? Note that my device is a Numonyx > 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB > page ) > > Thanks in advance, > > ///:~Enric > > --- > diff --git a/drivers/mtd/onenand/onenand_base.c > b/drivers/mtd/onenand/onenand_base.c > index 081f97d..b1d50a3 100644 > --- a/drivers/mtd/onenand/onenand_base.c > +++ b/drivers/mtd/onenand/onenand_base.c > @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, > int cmd, loff_t addr, size_t le > > ? ? ? ?default: > ? ? ? ? ? ? ? ?block = (int) onenand_block(this, addr); > - ? ? ? ? ? ? ? page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; > + ? ? ? ? ? ? ? page = (int) (addr >> this->page_shift); > > ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { > ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ > --- > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > From dedekind1 at gmail.com Thu May 6 02:15:25 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 09:15:25 +0300 Subject: [PATCH V2] ubi: init even if mtd device cannot be attached, if built into kernel In-Reply-To: <1273047445-23411-1-git-send-email-mkl@pengutronix.de> References: <1273047445-23411-1-git-send-email-mkl@pengutronix.de> Message-ID: <1273126525.3702.196.camel@localhost> On Wed, 2010-05-05 at 10:17 +0200, Marc Kleine-Budde wrote: > Ubi can be built into the kernel or be compiled as a kernel module. > Further on the command line one can specify mtd devices to be attach to > ubi while loading. In the current implementation the ubi driver refuses > to load if one of the mtd devices cannot be attached. > > Consider: > 1) ubi compiled into the kernel and > 2) a mtd device specified on the command line and > 3) this mtd device contains bogus data (for whatever reason). > > During init ubi tries to attach the mtd device is this fails the whole > ubi subsystem isn't initialized. Later the userspace cannot attach any > mtd to ubi because ubi isn't loaded. > > This patch keeps the current behaviour: if ubi is compiled as a module > and a mtd device cannot be attached the ubi module cannot be loaded, > but changes it for the ubi-is-built-into-the-kernel usecase. > > If ubi is builtin, a not attachable mtd device doen't stop ubi from > initializing. This slightly modifies the behaviour if multiple mtd > devices are specified on the command line. Now every mtd device is > probed and, if possible, attached, i.e. a faulty mtd device doesn't > stop the others from being attached. > > V2: integrated comments from Artem Bityutskiy: > use defines instead of static inline functions > > Signed-off-by: Marc Kleine-Budde > --- > drivers/mtd/ubi/build.c | 12 ++++++++++-- > 1 files changed, 10 insertions(+), 2 deletions(-) > > diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c > index fad40aa..d0447a5 100644 > --- a/drivers/mtd/ubi/build.c > +++ b/drivers/mtd/ubi/build.c > @@ -49,6 +49,12 @@ > /* Maximum length of the 'mtd=' parameter */ > #define MTD_PARAM_LEN_MAX 64 > > +#ifdef CONFIG_MTD_UBI_MODULE > +#define ubi_is_module() 1 > +#else > +#define ubi_is_module() 0 > +#endif > + > /** > * struct mtd_dev_param - MTD device parameter description data structure. > * @name: MTD character device node path, MTD device name, or MTD device number > @@ -1240,9 +1246,11 @@ static int __init ubi_init(void) > p->vid_hdr_offs); > mutex_unlock(&ubi_devices_mutex); > if (err < 0) { > - put_mtd_device(mtd); > ubi_err("cannot attach mtd%d", mtd->index); > - goto out_detach; > + if (ubi_is_module()) { > + put_mtd_device(mtd); We should put the MTD device even if we continue, because we did not attach it. > + goto out_detach; > + } > } > } > I've added a comment and fixed your patch, and pushed to ubi-2.6.git. Please, check it. >From af7ad7a0a6c0c1d8497a25b6b8b3b2ce9f52ff04 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Wed, 5 May 2010 10:17:25 +0200 Subject: [PATCH] UBI: init even if MTD device cannot be attached, if built into kernel UBI can be built into the kernel or be compiled as a kernel module. Further on the command line one can specify MTD devices to be attach to UBI while loading. In the current implementation the UBI driver refuses to load if one of the MTD devices cannot be attached. Consider: 1) UBI compiled into the kernel and 2) a MTD device specified on the command line and 3) this MTD device contains bogus data (for whatever reason). During init UBI tries to attach the MTD device is this fails the whole UBI subsystem isn't initialized. Later the userspace cannot attach any MTD to UBI because UBI isn't loaded. This patch keeps the current behaviour: if UBI is compiled as a module and a MTD device cannot be attached the UBI module cannot be loaded, but changes it for the UBI-is-built-into-the-kernel usecase. If UBI is builtin, a not attachable MTD device doen't stop UBI from initializing. This slightly modifies the behaviour if multiple MTD devices are specified on the command line. Now every MTD device is probed and, if possible, attached, i.e. a faulty MTD device doesn't stop the others from being attached. Artem: tweaked the patch Signed-off-by: Marc Kleine-Budde Signed-off-by: Artem Bityutskiy --- drivers/mtd/ubi/build.c | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c index 3a59a1d..13b05cb 100644 --- a/drivers/mtd/ubi/build.c +++ b/drivers/mtd/ubi/build.c @@ -49,6 +49,12 @@ /* Maximum length of the 'mtd=' parameter */ #define MTD_PARAM_LEN_MAX 64 +#ifdef CONFIG_MTD_UBI_MODULE +#define ubi_is_module() 1 +#else +#define ubi_is_module() 0 +#endif + /** * struct mtd_dev_param - MTD device parameter description data structure. * @name: MTD character device node path, MTD device name, or MTD device number @@ -1206,9 +1212,24 @@ static int __init ubi_init(void) p->vid_hdr_offs); mutex_unlock(&ubi_devices_mutex); if (err < 0) { - put_mtd_device(mtd); ubi_err("cannot attach mtd%d", mtd->index); - goto out_detach; + put_mtd_device(mtd); + + /* + * Originally UBI stopped initializing on any error. + * However, later on it was found out that this + * behavior is not very good when UBI is compiled into + * the kernel and the MTD devices to attach are passed + * through the command line. Indeed, UBI failure + * stopped whole boot sequence. + * + * To fix this, we changed the behavior for the + * non-module case, but preserved the old behavior for + * the module case, just for compatibility. This is a + * little inconsistent, though. + */ + if (ubi_is_module()) + goto out_detach; } } -- 1.6.6.1 -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Thu May 6 02:33:05 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 09:33:05 +0300 Subject: [PATCH] UBI: Fix s/then/than/ typos In-Reply-To: <4BE23A6F.1010406@renesas.com> References: <4BE23A03.1030001@renesas.com> <4BE23A6F.1010406@renesas.com> Message-ID: <1273127585.3702.198.camel@localhost> On Thu, 2010-05-06 at 12:41 +0900, Shinya Kuribayashi wrote: > Signed-off-by: Shinya Kuribayashi > --- > drivers/mtd/ubi/Kconfig | 2 +- > drivers/mtd/ubi/io.c | 2 +- > drivers/mtd/ubi/kapi.c | 6 +++--- > drivers/mtd/ubi/scan.c | 4 ++-- > drivers/mtd/ubi/wl.c | 2 +- > 5 files changed, 8 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig > index 0a8c7ea..f702a16 100644 Weird, but I cannot apply this patch. Could you please save it from the mailing list and try to apply? For me, all hunks fail: [dedekind at eru ubi-2.6]$ patch -p1 < ~/tmp/shinya1 patching file drivers/mtd/ubi/Kconfig Hunk #1 FAILED at 27. 1 out of 1 hunk FAILED -- saving rejects to file drivers/mtd/ubi/Kconfig.rej patching file drivers/mtd/ubi/io.c Hunk #1 FAILED at 65. 1 out of 1 hunk FAILED -- saving rejects to file drivers/mtd/ubi/io.c.rej patching file drivers/mtd/ubi/kapi.c Hunk #1 FAILED at 488. Hunk #2 FAILED at 571. Hunk #3 FAILED at 590. 3 out of 3 hunks FAILED -- saving rejects to file drivers/mtd/ubi/kapi.c.rej patching file drivers/mtd/ubi/scan.c Hunk #1 FAILED at 231. Hunk #2 FAILED at 452. 2 out of 2 hunks FAILED -- saving rejects to file drivers/mtd/ubi/scan.c.rej patching file drivers/mtd/ubi/wl.c Hunk #1 FAILED at 350. 1 out of 1 hunk FAILED -- saving rejects to file drivers/mtd/ubi/wl.c.rej -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Thu May 6 02:34:00 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 09:34:00 +0300 Subject: [PATCH] mtd: Remove empty mtd/mtdbdi.c and mtd/internal.h files In-Reply-To: <4BE23ADB.9090409@renesas.com> References: <4BE23A03.1030001@renesas.com> <4BE23ADB.9090409@renesas.com> Message-ID: <1273127640.3702.199.camel@localhost> On Thu, 2010-05-06 at 12:43 +0900, Shinya Kuribayashi wrote: > Commit a33eb6b9 (Move mtd_bdi_*mappable to mtdcore.c) forgot to 'git rm' > these files. > > Cc: Joern Engel > Signed-off-by: Shinya Kuribayashi > --- > 0 files changed, 0 insertions(+), 0 deletions(-) > delete mode 100644 drivers/mtd/internal.h > delete mode 100644 drivers/mtd/mtdbdi.c > > diff --git a/drivers/mtd/internal.h b/drivers/mtd/internal.h > deleted file mode 100644 > index e69de29..0000000 > diff --git a/drivers/mtd/mtdbdi.c b/drivers/mtd/mtdbdi.c > deleted file mode 100644 > index e69de29..0000000 Jeff Garzik just sent a pull request which takes care of this. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Thu May 6 02:42:07 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 09:42:07 +0300 Subject: [PATCH resend] mpc5121_nfc: Changed SVR check to allow MPC5123. In-Reply-To: <181804936ABC2349BE503168465576460EA16F75@exchserver.basler.com> References: <181804936ABC2349BE503168465576460E95836C@exchserver.basler.com> <1272980863.3702.10.camel@localhost> <181804936ABC2349BE503168465576460EA16F75@exchserver.basler.com> Message-ID: <1273128127.3702.201.camel@localhost> On Wed, 2010-05-05 at 13:48 -0500, Steve Deiters wrote: > The revision in SVR for MPC5123 is 3. The NFC is the same as MPC5121 > revision 2. > > Signed-off-by: Steve Deiters > --- > drivers/mtd/nand/mpc5121_nfc.c | 4 ++-- > 1 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/drivers/mtd/nand/mpc5121_nfc.c > b/drivers/mtd/nand/mpc5121_nfc.c > index 191bf99..dc04d74 100644 > --- a/drivers/mtd/nand/mpc5121_nfc.c > +++ b/drivers/mtd/nand/mpc5121_nfc.c > @@ -666,10 +666,10 @@ static int __devinit mpc5121_nfc_probe(struct > of_device *op, > > /* > * Check SoC revision. This driver supports only NFC > - * in MPC5121 revision 2. > + * in MPC5121 revision 2 and MPC5123 revision 3. > */ > rev = (mfspr(SPRN_SVR) >> 4) & 0xF; > - if (rev != 2) { > + if ((rev != 2) && (rev != 3)) { > dev_err(dev, "SoC revision %u is not supported!\n", > rev); > return -ENXIO; > } Now your patch is line-wrapped. But I fixed it and pushed to l2-mtd-2.6.git / master. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Thu May 6 02:47:24 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 09:47:24 +0300 Subject: [PATCH] UBI: Fix s/then/than/ typos In-Reply-To: <4BE23A6F.1010406@renesas.com> References: <4BE23A03.1030001@renesas.com> <4BE23A6F.1010406@renesas.com> Message-ID: <1273128444.3702.202.camel@localhost> On Thu, 2010-05-06 at 12:41 +0900, Shinya Kuribayashi wrote: > Signed-off-by: Shinya Kuribayashi > --- > drivers/mtd/ubi/Kconfig | 2 +- > drivers/mtd/ubi/io.c | 2 +- > drivers/mtd/ubi/kapi.c | 6 +++--- > drivers/mtd/ubi/scan.c | 4 ++-- > drivers/mtd/ubi/wl.c | 2 +- > 5 files changed, 8 insertions(+), 8 deletions(-) > > diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig > index 0a8c7ea..f702a16 100644 > --- a/drivers/mtd/ubi/Kconfig > +++ b/drivers/mtd/ubi/Kconfig > @@ -27,7 +27,7 @@ config MTD_UBI_WL_THRESHOLD > The default value should be OK for SLC NAND flashes, NOR flashes and > other flashes which have eraseblock life-cycle 100000 or more. > However, in case of MLC NAND flashes which typically have eraseblock > - life-cycle less then 10000, the threshold should be lessened (e.g., > + life-cycle less than 10000, the threshold should be lessened (e.g., > to 128 or 256, although it does not have to be power of 2). Thanks for the patches, but they really look corrupted. Could you please send applicable versions? -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Thu May 6 02:39:19 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 09:39:19 +0300 Subject: [PATCH v4] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1273074054-11849-1-git-send-email-kirill@shutemov.name> References: <1273074054-11849-1-git-send-email-kirill@shutemov.name> Message-ID: <1273127959.3702.200.camel@localhost> On Wed, 2010-05-05 at 18:40 +0300, Kirill A. Shutemov wrote: > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > backing device of device node inode, since file->f_mapping is equal to > inode->i_mapping (see __dentry_open() in fs/open.c). > > Let's introduce separate inode for MTD device with appropriate backing > device. > > Signed-off-by: Kirill A. Shutemov > --- > Changelog: > v3 -> v4: > - Use igrab() instead of __iget inside the inode_lock; > - Add stable@ to CC list. > v2 -> v3: > - Rebase to mtd-2.6.git. > v1 -> v2: > - Fix error handling based on comments by Jan Kara. Pushed to l2-mtd-2.6.git / dunno Also added Jan's ack which disappeared in v4 -- Best Regards, Artem Bityutskiy (????? ????????) From shinya.kuribayashi.px at renesas.com Thu May 6 03:06:47 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 16:06:47 +0900 Subject: [PATCH] UBI: Fix s/then/than/ typos In-Reply-To: <1273128444.3702.202.camel@localhost> References: <4BE23A03.1030001@renesas.com> <4BE23A6F.1010406@renesas.com> <1273128444.3702.202.camel@localhost> Message-ID: <4BE26A87.4030206@renesas.com> On 5/6/2010 3:47 PM, Artem Bityutskiy wrote: > Thanks for the patches, but they really look corrupted. Could you please > send applicable versions? Ah, the culprit must be 'format=flowed'. Recently I've migrated to Thunderbird3 and this was my first patch submission to communities. Should have disabled that option, sorry for inconvenience! Will fix and resubmit a few hours later to wait for any feedbacks. -- Shinya Kuribayashi Renesas Electronics From dedekind1 at gmail.com Thu May 6 03:21:35 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 10:21:35 +0300 Subject: [PATCH] UBI: Fix s/then/than/ typos In-Reply-To: <4BE26A87.4030206@renesas.com> References: <4BE23A03.1030001@renesas.com> <4BE23A6F.1010406@renesas.com> <1273128444.3702.202.camel@localhost> <4BE26A87.4030206@renesas.com> Message-ID: <1273130495.3702.205.camel@localhost> On Thu, 2010-05-06 at 16:06 +0900, Shinya Kuribayashi wrote: > On 5/6/2010 3:47 PM, Artem Bityutskiy wrote: > > Thanks for the patches, but they really look corrupted. Could you please > > send applicable versions? > > Ah, the culprit must be 'format=flowed'. Recently I've migrated to > Thunderbird3 and this was my first patch submission to communities. > Should have disabled that option, sorry for inconvenience! > > Will fix and resubmit a few hours later to wait for any feedbacks. AFAIK, format=flowed is just about displaying quoted text, not changing the contents. I also tried to use thunderbird in the past, but it is very unfrienly to patch submitters. So I switched to Evolution which is much better. But for sending patches git send-email is the tool to use in most of the cases, IMO. -- Best Regards, Artem Bityutskiy (????? ????????) From haojian.zhuang at gmail.com Thu May 6 05:01:22 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:01:22 -0400 Subject: [PATCH 01/20] pxa3xx_nand: refuse the flash definition get from platform Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:02:07 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:02:07 -0400 Subject: [PATCH 02/20] pxa3xx_nand: introduce common timing to reduce read id times Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:02:56 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:02:56 -0400 Subject: [PATCH 03/20] pxa3xx_nand: remove the flash info in driver structure Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:03:43 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:03:43 -0400 Subject: [PATCH 04/20] pxa3xx_nand: make scan procedure more clear Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:04:27 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:04:27 -0400 Subject: [PATCH 05/20] pxa3xx_nand: rework irq logic Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:05:12 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:05:12 -0400 Subject: [PATCH 06/20] pxa3xx_nand: unify prepare command Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:05:51 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:05:51 -0400 Subject: [PATCH 07/20] pxa3xx_nand: mtd scan id process could be defined by driver itself Message-ID: From leiwen at marvell.com Wed May 5 21:48:30 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 09:48:30 +0800 Subject: [PATCH] pxa3xx_nand: mtd scan id process could be defined by Message-ID: driver itself Different NAND driver may require its unique detection. For pxa3xx_nand, it use its self id database to get the necessary info. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 257 +++++++++++++++++++++++++++++----------- 1 files changed, 185 insertions(+), 72 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 854adad..7a8ff38 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -255,6 +255,8 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, }, }; +static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; + #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11) @@ -893,37 +895,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) return 0; } -static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, - const struct pxa3xx_nand_platform_data *pdata) -{ - const struct pxa3xx_nand_flash *f; - uint32_t id = -1; - int i; - - if (pdata->keep_config) - if (pxa3xx_nand_detect_config(info) == 0) - return 0; - - f = &builtin_flash_types[0]; - pxa3xx_nand_config_flash(info, f); - pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); - id = *((uint16_t *)(info->data_buff)); - - for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { - f = &builtin_flash_types[i]; - if (f->chip_id == id) { - dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); - pxa3xx_nand_config_flash(info, f); - return 0; - } - } - - dev_warn(&info->pdev->dev, - "failed to detect configured nand flash; found %04x instead of\n", - id); - return -ENODEV; -} - /* the maximum possible buffer size for large page with OOB data * is: 2048 + 64 = 2112 bytes, allocate a page here for both the * data buffer and the DMA descriptor @@ -980,41 +951,174 @@ static struct nand_ecclayout hw_largepage_ecclayout = { .oobfree = { {2, 38} } }; -static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, - struct pxa3xx_nand_info *info) +static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + struct pxa3xx_nand_info *info = mtd->priv; + + chip->read_buf(mtd, buf, mtd->writesize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + + if (info->retcode == ERR_SBERR) { + switch (info->use_ecc) { + case 1: + mtd->ecc_stats.corrected ++; + break; + + case 0: + default: + break; + } + } + else if (info->retcode == ERR_DBERR) { + int buf_blank; + + buf_blank = is_buf_blank(buf, mtd->writesize); + if (!buf_blank) + mtd->ecc_stats.failed++; + } + + return 0; +} + +static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + chip->write_buf(mtd, buf, mtd->writesize); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +} + +static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page) { - struct nand_chip *this = &info->nand_chip; - - this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; - - this->waitfunc = pxa3xx_nand_waitfunc; - this->select_chip = pxa3xx_nand_select_chip; - this->dev_ready = pxa3xx_nand_dev_ready; - this->cmdfunc = pxa3xx_nand_cmdfunc; - this->read_word = pxa3xx_nand_read_word; - this->read_byte = pxa3xx_nand_read_byte; - this->read_buf = pxa3xx_nand_read_buf; - this->write_buf = pxa3xx_nand_write_buf; - this->verify_buf = pxa3xx_nand_verify_buf; - - this->ecc.mode = NAND_ECC_HW; - this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; - this->ecc.calculate = pxa3xx_nand_ecc_calculate; - this->ecc.correct = pxa3xx_nand_ecc_correct; - this->ecc.size = info->page_size; - - if (info->page_size == 2048) - this->ecc.layout = &hw_largepage_ecclayout; + struct nand_chip *chip = mtd->priv; + /* Send commands to erase a block */ + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); +} + +static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) +{ + struct mtd_info *mtd = info->mtd; + struct nand_chip *chip = mtd->priv; + + /* use the common timing to make a try */ + pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); + chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); + if (info->state & STATE_READY) + return 1; else - this->ecc.layout = &hw_smallpage_ecclayout; + return 0; +} + +static int pxa3xx_nand_scan(struct mtd_info *mtd) +{ + struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_flash *f; + struct nand_chip *chip = mtd->priv; + uint32_t id = -1; + int i, ret; - this->chip_delay = 25; + ret = pxa3xx_nand_sensing(info); + if (!ret) { + kfree(mtd); + info->mtd = NULL; + printk(KERN_INFO "There is no nand chip on cs 0!\n"); + + return -EINVAL; + } + + chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); + if (id != 0) + printk(KERN_INFO "Detect a flash id %x\n", id); + else { + kfree(mtd); + info->mtd = NULL; + printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); + + return -EINVAL; + } + + for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { + + f = &builtin_flash_types[i]; + + /* find the chip in default list */ + if (f->chip_id == id) { + pxa3xx_nand_config_flash(info, f); + chip->cellinfo = info->data_buff[2]; + mtd->writesize = f->page_size; + mtd->writesize_shift = ffs(mtd->writesize) - 1; + mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; + mtd->oobsize = mtd->writesize / 32; + mtd->erasesize = f->page_size * f->page_per_block; + mtd->erasesize_shift = ffs(mtd->erasesize) - 1; + mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; + + mtd->name = mtd_names[0]; + break; + } + } + + if (i == ARRAY_SIZE(builtin_flash_types)) { + kfree(mtd); + info->mtd = NULL; + printk(KERN_ERR "ERROR!! flash not defined!!!\n"); + + return -EINVAL; + } + + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = f->page_size; + if (f->page_size == 2048) + chip->ecc.layout = &hw_largepage_ecclayout; + else + chip->ecc.layout = &hw_smallpage_ecclayout; + + chip->chipsize = (uint64_t)f->num_blocks * \ + f->page_per_block * \ + f->page_size; + + chip->chip_shift = ffs(chip->chipsize) - 1; + mtd->size = chip->chipsize; + + /* Calculate the address shift from the page size */ + chip->page_shift = ffs(mtd->writesize) - 1; + chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; + chip->numchips = 1; + chip->chip_delay = 25; + chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1; + + /* Set the bad block position */ + chip->badblockpos = mtd->writesize > 512 ? + NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; + + chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; + chip->options |= NAND_NO_AUTOINCR; + chip->options |= NAND_NO_READRDY; + chip->options |= NAND_USE_FLASH_BBT; + + return nand_scan_tail(mtd); +} + +static int pxa3xx_nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *chip = mtd->priv; + int block; + + block = (int)(ofs >> chip->bbt_erase_shift); + chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + return nand_update_bbt(mtd, ofs); +} + +static int pxa3xx_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + return 0; } static int alloc_nand_resource(struct platform_device *pdev) { - struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; struct pxa3xx_nand_info *info; + struct nand_chip *chip; struct mtd_info *mtd; struct resource *r; int ret, irq; @@ -1027,12 +1131,31 @@ static int alloc_nand_resource(struct platform_device *pdev) } info = (struct pxa3xx_nand_info *)(&mtd[1]); + chip = (struct nand_chip *)(&mtd[1]); info->pdev = pdev; - - mtd->priv = info; info->mtd = mtd; + mtd->priv = info; mtd->owner = THIS_MODULE; + chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; + chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->ecc.hwctl = pxa3xx_nand_ecc_hwctl; + chip->ecc.calculate = pxa3xx_nand_ecc_calculate; + chip->ecc.correct = pxa3xx_nand_ecc_correct; + chip->waitfunc = pxa3xx_nand_waitfunc; + chip->select_chip = pxa3xx_nand_select_chip; + chip->dev_ready = pxa3xx_nand_dev_ready; + chip->cmdfunc = pxa3xx_nand_cmdfunc; + chip->read_word = pxa3xx_nand_read_word; + chip->read_byte = pxa3xx_nand_read_byte; + chip->read_buf = pxa3xx_nand_read_buf; + chip->write_buf = pxa3xx_nand_write_buf; + chip->verify_buf = pxa3xx_nand_verify_buf; + chip->block_markbad = pxa3xx_nand_default_block_markbad; + chip->block_bad = pxa3xx_nand_block_bad; + chip->scan_bbt = nand_default_bbt; + chip->erase_cmd = pxa3xx_nand_erase_cmd; + info->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) { dev_err(&pdev->dev, "failed to get nand clock\n"); @@ -1100,21 +1223,11 @@ static int alloc_nand_resource(struct platform_device *pdev) goto fail_free_buf; } - ret = pxa3xx_nand_detect_flash(info, pdata); - if (ret) { - dev_err(&pdev->dev, "failed to detect flash\n"); - ret = -ENODEV; - goto fail_free_irq; - } - - pxa3xx_nand_init_mtd(mtd, info); platform_set_drvdata(pdev, info); - return 0; -fail_free_irq: - free_irq(irq, info); fail_free_buf: + free_irq(irq, info); if (use_dma) { pxa_free_dma(info->data_dma_ch); dma_free_coherent(&pdev->dev, info->data_buff_size, @@ -1182,7 +1295,7 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) return ret; info = platform_get_drvdata(pdev); - if (nand_scan(info->mtd, 1)) { + if (pxa3xx_nand_scan(info->mtd)) { dev_err(&pdev->dev, "failed to scan nand\n"); pxa3xx_nand_remove(pdev); return -ENODEV; -- 1.5.6.5 From haojian.zhuang at gmail.com Thu May 6 05:06:32 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:06:32 -0400 Subject: [PATCH 08/20] pxa3xx_nand: remove detect configure function Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:07:17 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:07:17 -0400 Subject: [PATCH 09/20] pxa3xx_nand: add two chip select Message-ID: From leiwen at marvell.com Wed May 5 22:30:32 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 10:30:32 +0800 Subject: [PATCH] pxa3xx_nand: add two chip select Message-ID: Current pxa3xx_nand controller has two chip select which both be workable. This patch enable this feature. Update platform driver to support this feature. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- arch/arm/mach-mmp/aspenite.c | 4 +- arch/arm/mach-mmp/avengers_lite.c | 51 ++ arch/arm/mach-pxa/cm-x300.c | 4 +- arch/arm/mach-pxa/colibri-pxa3xx.c | 4 +- arch/arm/mach-pxa/littleton.c | 4 +- arch/arm/mach-pxa/mxm8x10.c | 8 +- arch/arm/mach-pxa/raumfeld.c | 4 +- arch/arm/mach-pxa/zylonite.c | 4 +- arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 5 +- drivers/mtd/nand/pxa3xx_nand.c | 674 ++++++++++++++------------ 10 files changed, 422 insertions(+), 340 deletions(-) diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index 244655d..81ad58d 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -126,8 +126,8 @@ static struct mtd_partition aspenite_nand_partitions[] = { static struct pxa3xx_nand_platform_data aspenite_nand_info = { .enable_arbiter = 1, - .parts = aspenite_nand_partitions, - .nr_parts = ARRAY_SIZE(aspenite_nand_partitions), + .parts[0] = aspenite_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(aspenite_nand_partitions), }; static struct i2c_board_info aspenite_i2c_info[] __initdata = { diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c index 8c3fa5d..8a2883f 100644 --- a/arch/arm/mach-mmp/avengers_lite.c +++ b/arch/arm/mach-mmp/avengers_lite.c @@ -32,12 +32,63 @@ static unsigned long avengers_lite_pin_config_V16F[] __initdata = { GPIO89_UART2_RXD, }; +static struct mtd_partition avengers_nand_partitions_0[] = { + { + .name = "bootloader", + .offset = 0, + .size = SZ_1M, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = (SZ_2M + SZ_1M), + }, { + .name = "mass0", + .offset = MTDPART_OFS_APPEND, + .size = SZ_48M, + } +}; + +static struct mtd_partition avengers_nand_partitions_1[] = { + { + .name = "reserved", + .offset = 0, + .size = SZ_2M, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = SZ_512M, + }, { + .name = "mass1", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M, + }, { + .name = "mass2", + .offset = MTDPART_OFS_APPEND, + .size = SZ_256M, + } +}; + +static struct pxa3xx_nand_platform_data avengers_nand_info; +static void __init avengers_init_flash(void) +{ + avengers_nand_info.parts[0] = avengers_nand_partitions_0; + avengers_nand_info.nr_parts[0] = ARRAY_SIZE(avengers_nand_partitions_0); + avengers_nand_info.parts[1] = avengers_nand_partitions_1; + avengers_nand_info.nr_parts[1] = ARRAY_SIZE(avengers_nand_partitions_1); + avengers_nand_info.enable_arbiter = 1; + avengers_nand_info.naked_cmd_support = 1; + pxa168_add_nand(&avengers_nand_info); +} + static void __init avengers_lite_init(void) { mfp_config(ARRAY_AND_SIZE(avengers_lite_pin_config_V16F)); /* on-chip devices */ pxa168_add_uart(2); + avengers_init_flash(); } MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform") diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index fdda6be..ce1f6d3 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -419,8 +419,8 @@ static struct mtd_partition cm_x300_nand_partitions[] = { static struct pxa3xx_nand_platform_data cm_x300_nand_info = { .enable_arbiter = 1, .keep_config = 1, - .parts = cm_x300_nand_partitions, - .nr_parts = ARRAY_SIZE(cm_x300_nand_partitions), + .parts[0] = cm_x300_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(cm_x300_nand_partitions), }; static void __init cm_x300_init_nand(void) diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c index 199afa2..b33559c 100644 --- a/arch/arm/mach-pxa/colibri-pxa3xx.c +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c @@ -188,8 +188,8 @@ static struct mtd_partition colibri_nand_partitions[] = { static struct pxa3xx_nand_platform_data colibri_nand_info = { .enable_arbiter = 1, .keep_config = 1, - .parts = colibri_nand_partitions, - .nr_parts = ARRAY_SIZE(colibri_nand_partitions), + .parts[0] = colibri_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(colibri_nand_partitions), }; void __init colibri_pxa3xx_init_nand(void) diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index 9b90461..717cf92 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -325,8 +325,8 @@ static struct mtd_partition littleton_nand_partitions[] = { static struct pxa3xx_nand_platform_data littleton_nand_info = { .enable_arbiter = 1, - .parts = littleton_nand_partitions, - .nr_parts = ARRAY_SIZE(littleton_nand_partitions), + .parts[0] = littleton_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(littleton_nand_partitions), }; static void __init littleton_init_nand(void) diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c index 462167a..66c2086 100644 --- a/arch/arm/mach-pxa/mxm8x10.c +++ b/arch/arm/mach-pxa/mxm8x10.c @@ -389,10 +389,10 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = { }; static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = { - .enable_arbiter = 1, - .keep_config = 1, - .parts = mxm_8x10_nand_partitions, - .nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions) + .enable_arbiter = 1, + .keep_config = 1, + .parts[0] = mxm_8x10_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(mxm_8x10_nand_partitions) }; static void __init mxm_8x10_nand_init(void) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index d4b61b3..df75d4d 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -350,8 +350,8 @@ static struct mtd_partition raumfeld_nand_partitions[] = { static struct pxa3xx_nand_platform_data raumfeld_nand_info = { .enable_arbiter = 1, .keep_config = 1, - .parts = raumfeld_nand_partitions, - .nr_parts = ARRAY_SIZE(raumfeld_nand_partitions), + .parts[0] = raumfeld_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(raumfeld_nand_partitions), }; /** diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index c479cbe..9e5c6cd 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -356,8 +356,8 @@ static struct mtd_partition zylonite_nand_partitions[] = { static struct pxa3xx_nand_platform_data zylonite_nand_info = { .enable_arbiter = 1, - .parts = zylonite_nand_partitions, - .nr_parts = ARRAY_SIZE(zylonite_nand_partitions), + .parts[0] = zylonite_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(zylonite_nand_partitions), }; static void __init zylonite_init_nand(void) diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h index c494f68..76ebd21 100644 --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h @@ -4,6 +4,7 @@ #include #include +#define NUM_CHIP_SELECT (2) struct pxa3xx_nand_platform_data { /* the data flash bus is shared between the Static Memory @@ -15,8 +16,8 @@ struct pxa3xx_nand_platform_data { /* allow platform code to keep OBM/bootloader defined NFC config */ int keep_config; - const struct mtd_partition *parts; - unsigned int nr_parts; + const struct mtd_partition *parts[NUM_CHIP_SELECT]; + unsigned int nr_parts[NUM_CHIP_SELECT]; }; extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2c7f925..f8b16be 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -98,6 +98,8 @@ #define nand_readl(info, off) \ __raw_readl((info)->mmio_base + (off)) +#define get_mtd_by_info(info) \ + (struct mtd_info *)((void *)info - sizeof(struct mtd_info)) /* error code and state */ enum { @@ -158,60 +160,62 @@ struct pxa3xx_nand_flash { struct pxa3xx_nand_info { struct nand_chip nand_chip; - struct platform_device *pdev; - - struct clk *clk; - void __iomem *mmio_base; - unsigned long mmio_phys; - - unsigned int buf_start; - unsigned int buf_count; - - struct mtd_info *mtd; - /* DMA information */ - int drcmr_dat; - int drcmr_cmd; - + uint32_t page_size; /* page size of attached chip */ unsigned char *data_buff; unsigned char *oob_buff; + uint32_t buf_start; + uint32_t buf_count; + + /* dma related */ + int data_dma_ch; dma_addr_t data_buff_phys; - size_t data_buff_size; - int data_dma_ch; - struct pxa_dma_desc *data_desc; dma_addr_t data_desc_addr; + struct pxa_dma_desc *data_desc; + uint8_t chip_select; + uint8_t use_ecc; /* use HW ECC ? */ - uint32_t reg_ndcr; - - /* saved column/page_addr during CMD_SEQIN */ - int seqin_column; - int seqin_page_addr; + /* calculated from pxa3xx_nand_flash data */ + uint8_t col_addr_cycles; + uint8_t row_addr_cycles; + uint8_t read_id_bytes; - /* relate to the command */ - unsigned int state; + /* cached register value */ + uint32_t reg_ndcr; + uint32_t ndtr0cs0; + uint32_t ndtr1cs0; + uint32_t ndcb0; + uint32_t ndcb1; + uint32_t ndcb2; - int use_ecc; /* use HW ECC ? */ - int use_dma; /* use DMA ? */ + void *nand_data; +}; - unsigned int page_size; /* page size of attached chip */ - unsigned int data_size; /* data size in FIFO */ - int retcode; +struct pxa3xx_nand { + struct clk *clk; + void __iomem *mmio_base; + unsigned long mmio_phys; + struct nand_hw_control controller; struct completion cmd_complete; + struct platform_device *pdev; - /* generated NDCBx register values */ - uint32_t ndcb0; - uint32_t ndcb1; - uint32_t ndcb2; + uint8_t chip_select; + uint8_t use_ecc; + uint8_t use_dma; + uint8_t wait_mode; - /* timing calcuted from setting */ - uint32_t ndtr0cs0; - uint32_t ndtr1cs0; + /* relate to the command */ + uint32_t state; + uint32_t command; + uint16_t data_size; /* data size in FIFO */ + uint16_t oob_size; + uint32_t bad_count; + uint32_t retcode; - /* calculated from pxa3xx_nand_flash data */ - size_t oob_size; - size_t read_id_bytes; + /* DMA information */ + uint32_t drcmr_dat; + uint32_t drcmr_cmd; - unsigned int col_addr_cycles; - unsigned int row_addr_cycles; + struct pxa3xx_nand_info *info[NUM_CHIP_SELECT]; }; static int use_dma = 1; @@ -240,6 +244,7 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0, 0, 0, 0, 0, 0, { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, }, { 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, { 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, +{ 0xd3ec, 128, 2048, 8, 8, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, { 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, { 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, { 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, @@ -248,7 +253,7 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, }, }; -static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; +static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) @@ -281,9 +286,11 @@ static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_timing *t) { - unsigned long nand_clk = clk_get_rate(info->clk); + struct pxa3xx_nand *nand = info->nand_data; + unsigned long nand_clk; uint32_t ndtr0, ndtr1; + nand_clk = clk_get_rate(nand->clk); ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) | NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) | NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) | @@ -297,25 +304,26 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, info->ndtr0cs0 = ndtr0; info->ndtr1cs0 = ndtr1; - nand_writel(info, NDTR0CS0, ndtr0); - nand_writel(info, NDTR1CS0, ndtr1); + nand_writel(nand, NDTR0CS0, ndtr0); + nand_writel(nand, NDTR1CS0, ndtr1); } static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) { + struct pxa3xx_nand *nand = info->nand_data; int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; - info->data_size = info->page_size; + nand->data_size = info->page_size; if (!oob_enable) { - info->oob_size = 0; + nand->oob_size = 0; return; } switch (info->page_size) { case 2048: - info->oob_size = (info->use_ecc) ? 40 : 64; + nand->oob_size = (nand->use_ecc) ? 40 : 64; break; case 512: - info->oob_size = (info->use_ecc) ? 8 : 16; + nand->oob_size = (nand->use_ecc) ? 8 : 16; break; } } @@ -326,22 +334,24 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) * We enable all the interrupt at the same time, and * let pxa3xx_nand_irq to handle all logic. */ -static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) +static void pxa3xx_nand_start(struct pxa3xx_nand *nand) { + struct pxa3xx_nand_info *info; uint32_t ndcr; + info = nand->info[nand->chip_select]; ndcr = info->reg_ndcr; - ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; - ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR; + ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0; + ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR; ndcr |= NDCR_ND_RUN; /* clear status bits and run */ - nand_writel(info, NDCR, 0); - nand_writel(info, NDSR, NDSR_MASK); - nand_writel(info, NDCR, ndcr); + nand_writel(nand, NDCR, 0); + nand_writel(nand, NDSR, NDSR_MASK); + nand_writel(nand, NDCR, ndcr); } -static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) +static void pxa3xx_nand_stop(struct pxa3xx_nand *nand) { uint32_t ndcr; int timeout = NAND_STOP_DELAY; @@ -349,146 +359,152 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) /* wait RUN bit in NDCR become 0 */ do { /* clear status bits */ - nand_writel(info, NDSR, NDSR_MASK); - ndcr = nand_readl(info, NDCR); + nand_writel(nand, NDSR, NDSR_MASK); + ndcr = nand_readl(nand, NDCR); udelay(1); } while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0)); if (timeout <= 0) { ndcr &= ~(NDCR_ND_RUN); - nand_writel(info, NDCR, ndcr); + nand_writel(nand, NDCR, ndcr); } } -static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) +static void enable_int(struct pxa3xx_nand *nand, uint32_t int_mask) { uint32_t ndcr; - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~int_mask); + ndcr = nand_readl(nand, NDCR); + nand_writel(nand, NDCR, ndcr & ~int_mask); } -static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) +static void disable_int(struct pxa3xx_nand *nand, uint32_t int_mask) { uint32_t ndcr; - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr | int_mask); + ndcr = nand_readl(nand, NDCR); + nand_writel(nand, NDCR, ndcr | int_mask); } -static void handle_data_pio(struct pxa3xx_nand_info *info) +static void handle_data_pio(struct pxa3xx_nand *nand) { - if (info->state & STATE_IS_WRITE) { - __raw_writesl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); - if (info->oob_size > 0) - __raw_writesl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; + + if (nand->state & STATE_IS_WRITE) { + __raw_writesl(nand->mmio_base + NDDB, info->data_buff, + DIV_ROUND_UP(nand->data_size, 4)); + if (nand->oob_size > 0) + __raw_writesl(nand->mmio_base + NDDB, info->oob_buff, + DIV_ROUND_UP(nand->oob_size, 4)); } else { - __raw_readsl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); - if (info->oob_size > 0) - __raw_readsl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + __raw_readsl(nand->mmio_base + NDDB, info->data_buff, + DIV_ROUND_UP(nand->data_size, 4)); + if (nand->oob_size > 0) + __raw_readsl(nand->mmio_base + NDDB, info->oob_buff, + DIV_ROUND_UP(nand->oob_size, 4)); } } -static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) +static void start_data_dma(struct pxa3xx_nand *nand, int dir_out) { + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; struct pxa_dma_desc *desc = info->data_desc; - int dma_len = ALIGN(info->data_size + info->oob_size, 32); + int dma_len = ALIGN(nand->data_size + nand->oob_size, 32); desc->ddadr = DDADR_STOP; desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; if (dir_out) { desc->dsadr = info->data_buff_phys; - desc->dtadr = info->mmio_phys + NDDB; + desc->dtadr = nand->mmio_phys + NDDB; desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; } else { desc->dtadr = info->data_buff_phys; - desc->dsadr = info->mmio_phys + NDDB; + desc->dsadr = nand->mmio_phys + NDDB; desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; } - DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; + DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; DDADR(info->data_dma_ch) = info->data_desc_addr; DCSR(info->data_dma_ch) |= DCSR_RUN; } static void pxa3xx_nand_data_dma_irq(int channel, void *data) { - struct pxa3xx_nand_info *info = data; + struct pxa3xx_nand *nand = data; uint32_t dcsr; dcsr = DCSR(channel); DCSR(channel) = dcsr; if (dcsr & DCSR_BUSERR) { - info->retcode = ERR_DMABUSERR; + nand->retcode = ERR_DMABUSERR; } - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); + enable_int(nand, NDCR_INT_MASK); + nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); } static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { - struct pxa3xx_nand_info *info = devid; - unsigned int status, is_completed = 0; + struct pxa3xx_nand *nand = devid; + struct pxa3xx_nand_info *info; + unsigned int status, is_completed = 0, cs; + unsigned int ready, cmd_done, page_done, badblock_detect; - status = nand_readl(info, NDSR); + cs = nand->chip_select; + ready = (cs) ? NDSR_RDY : NDSR_FLASH_RDY; + cmd_done = (cs) ? NDSR_CS1_CMDD : NDSR_CS0_CMDD; + page_done = (cs) ? NDSR_CS1_PAGED : NDSR_CS0_PAGED; + badblock_detect = (cs) ? NDSR_CS1_BBD : NDSR_CS0_BBD; + info = nand->info[cs]; + status = nand_readl(nand, NDSR); if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; + nand->retcode = ERR_DBERR; if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; + nand->retcode = ERR_SBERR; if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { - info->state |= STATE_DATA_PROCESSING; + nand->state |= STATE_DATA_PROCESSING; /* whether use dma to transfer data */ - if (info->use_dma) { - disable_int(info, NDSR_WRDREQ); - start_data_dma(info, 0); + if (nand->use_dma) { + disable_int(nand, NDCR_INT_MASK); + start_data_dma(nand, nand->state & STATE_IS_WRITE); goto NORMAL_IRQ_EXIT; } else - handle_data_pio(info); + handle_data_pio(nand); - info->state |= STATE_DATA_DONE; + nand->state |= STATE_DATA_DONE; } - if (status & NDSR_CS0_CMDD) { - info->state |= STATE_CMD_DONE; + if (status & cmd_done) { + nand->state |= STATE_CMD_DONE; is_completed = 1; } - if (status & NDSR_FLASH_RDY) - info->state |= STATE_READY; - if (status & NDSR_CS0_PAGED) - info->state |= STATE_PAGE_DONE; + if (status & ready) + nand->state |= STATE_READY; + if (status & page_done) + nand->state |= STATE_PAGE_DONE; if (status & NDSR_WRCMDREQ) { - nand_writel(info, NDSR, NDSR_WRCMDREQ); + nand_writel(nand, NDSR, NDSR_WRCMDREQ); status &= ~NDSR_WRCMDREQ; - info->state |= STATE_CMD_WAIT_DONE; - nand_writel(info, NDCB0, info->ndcb0); - nand_writel(info, NDCB0, info->ndcb1); - nand_writel(info, NDCB0, info->ndcb2); + nand->state |= STATE_CMD_WAIT_DONE; + nand_writel(nand, NDCB0, info->ndcb0); + nand_writel(nand, NDCB0, info->ndcb1); + nand_writel(nand, NDCB0, info->ndcb2); } /* clear NDSR to let the controller exit the IRQ */ - nand_writel(info, NDSR, status); + nand_writel(nand, NDSR, status); if (is_completed) - complete(&info->cmd_complete); + complete(&nand->cmd_complete); NORMAL_IRQ_EXIT: return IRQ_HANDLED; } -static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) -{ - struct pxa3xx_nand_info *info = mtd->priv; - return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0; -} - static inline int is_buf_blank(uint8_t *buf, size_t len) { for (; len > 0; len--) @@ -497,29 +513,36 @@ static inline int is_buf_blank(uint8_t *buf, size_t len) return 1; } -static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, +static int prepare_command_pool(struct pxa3xx_nand *nand, int command, uint16_t column, int page_addr) { uint16_t cmd; int addr_cycle, exec_cmd, ndcb0; - struct mtd_info *mtd = info->mtd; + struct mtd_info *mtd; + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; - ndcb0 = 0; + mtd = get_mtd_by_info(info); + ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;; addr_cycle = 0; exec_cmd = 1; /* reset data and oob column point to handle data */ info->buf_start = 0; info->buf_count = 0; - info->oob_size = 0; - info->use_ecc = 0; + info->ndcb0 = ndcb0; + nand->data_size = 0; + nand->oob_size = 0; + nand->use_ecc = 0; + nand->use_dma = 0; + nand->state = 0; switch (command) { case NAND_CMD_READ0: case NAND_CMD_PAGEPROG: - info->use_ecc = 1; + nand->use_ecc = info->use_ecc; case NAND_CMD_READOOB: pxa3xx_set_datasize(info); + nand->use_dma = use_dma; break; case NAND_CMD_SEQIN: exec_cmd = 0; @@ -530,7 +553,6 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, break; } - info->ndcb0 = ndcb0; addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles); @@ -584,7 +606,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, } cmd = cmdset.program; - info->state |= STATE_IS_WRITE; + nand->state |= STATE_IS_WRITE; info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | NDCB0_AUTO_RS | NDCB0_ST_ROW_EN @@ -600,7 +622,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | NDCB0_ADDR_CYC(1) | cmd; - info->data_size = 8; + nand->data_size = 8; break; case NAND_CMD_STATUS: @@ -610,7 +632,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | NDCB0_ADDR_CYC(1) | cmd; - info->data_size = 8; + nand->data_size = 8; break; case NAND_CMD_ERASE1: @@ -648,6 +670,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; int ret, exec_cmd; /* if this is a x16 device ,then convert the input @@ -657,21 +680,28 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, if (info->reg_ndcr & NDCR_DWIDTH_M) column /= 2; - exec_cmd = prepare_command_pool(info, command, column, page_addr); + /* reset timing */ + if (nand->chip_select != info->chip_select) { + nand->chip_select = info->chip_select; + nand_writel(nand, NDTR0CS0, info->ndtr0cs0); + nand_writel(nand, NDTR1CS0, info->ndtr1cs0); + } + + exec_cmd = prepare_command_pool(nand, command, column, page_addr); if (exec_cmd) { - init_completion(&info->cmd_complete); - info->state |= STATE_CMD_PREPARED; - pxa3xx_nand_start(info); + init_completion(&nand->cmd_complete); + nand->state |= STATE_CMD_PREPARED; + pxa3xx_nand_start(nand); - ret = wait_for_completion_timeout(&info->cmd_complete, + ret = wait_for_completion_timeout(&nand->cmd_complete, CHIP_DELAY_TIMEOUT); if (!ret) { printk(KERN_ERR "Wait time out!!!\n"); } /* Stop State Machine for next command cycle */ - pxa3xx_nand_stop(info); - disable_int(info, NDCR_INT_MASK); - info->state &= ~STATE_CMD_PREPARED; + pxa3xx_nand_stop(nand); + disable_int(nand, NDCR_INT_MASK); + nand->state &= ~STATE_CMD_PREPARED; } } @@ -732,10 +762,11 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; /* pxa3xx_nand_send_command has waited for command complete */ if (this->state == FL_WRITING || this->state == FL_ERASING) { - if (info->retcode == ERR_NONE) + if (nand->retcode == ERR_NONE) return 0; else { /* @@ -749,48 +780,17 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return 0; } -static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode) -{ - return; -} - -static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd, - const uint8_t *dat, uint8_t *ecc_code) -{ - return 0; -} - -static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, - uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) -{ - struct pxa3xx_nand_info *info = mtd->priv; - /* - * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we - * consider it as a ecc error which will tell the caller the - * read fail We have distinguish all the errors, but the - * nand_read_ecc only check this function return value - * - * Corrected (single-bit) errors must also be noted. - */ - if (info->retcode == ERR_SBERR) - return 1; - else if (info->retcode != ERR_NONE) - return -1; - - return 0; -} - static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_flash *f) { - struct platform_device *pdev = info->pdev; + struct pxa3xx_nand *nand = info->nand_data; + struct platform_device *pdev = nand->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; uint32_t ndcr = 0; /* calculate flash information */ info->page_size = f->page_size; info->oob_buff = info->data_buff + f->page_size; - info->oob_size = (f->page_size == 2048) ? 64 : 16; info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; /* calculate addressing information */ @@ -823,41 +823,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, */ #define MAX_BUFF_SIZE PAGE_SIZE -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) -{ - struct platform_device *pdev = info->pdev; - int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); - - if (use_dma == 0) { - info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); - if (info->data_buff == NULL) - return -ENOMEM; - return 0; - } - - info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, - &info->data_buff_phys, GFP_KERNEL); - if (info->data_buff == NULL) { - dev_err(&pdev->dev, "failed to allocate dma buffer\n"); - return -ENOMEM; - } - - info->data_buff_size = MAX_BUFF_SIZE; - info->data_desc = (void *)info->data_buff + data_desc_offset; - info->data_desc_addr = info->data_buff_phys + data_desc_offset; - - info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW, - pxa3xx_nand_data_dma_irq, info); - if (info->data_dma_ch < 0) { - dev_err(&pdev->dev, "failed to request data dma\n"); - dma_free_coherent(&pdev->dev, info->data_buff_size, - info->data_buff, info->data_buff_phys); - return info->data_dma_ch; - } - - return 0; -} - static struct nand_ecclayout hw_smallpage_ecclayout = { .eccbytes = 6, .eccpos = {8, 9, 10, 11, 12, 13 }, @@ -873,26 +838,50 @@ static struct nand_ecclayout hw_largepage_ecclayout = { .oobfree = { {2, 38} } }; +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs) +{ + struct pxa3xx_nand *nand; + struct mtd_info *mtd; + + if (!info) + return; + + nand = info->nand_data; + if (use_dma) { + if (info->data_dma_ch >= 0) + pxa_free_dma(info->data_dma_ch); + if (info->data_buff) + dma_free_coherent(&nand->pdev->dev, MAX_BUFF_SIZE, + info->data_buff, info->data_buff_phys); + } else { + if (info->data_buff) + kfree(info->data_buff); + } + mtd = get_mtd_by_info(info); + kfree(mtd); + nand->info[cs] = NULL; +} + static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int page) { struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - if (info->retcode == ERR_SBERR) { - switch (info->use_ecc) { + if (nand->retcode == ERR_SBERR) { + switch (nand->use_ecc) { case 1: - mtd->ecc_stats.corrected ++; + mtd->ecc_stats.corrected++; break; case 0: default: break; } - } - else if (info->retcode == ERR_DBERR) { + } else if (nand->retcode == ERR_DBERR) { int buf_blank; buf_blank = is_buf_blank(buf, mtd->writesize); @@ -912,20 +901,18 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page) { - struct nand_chip *chip = mtd->priv; /* Send commands to erase a block */ - chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); + pxa3xx_nand_cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); } -static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_sensing(struct pxa3xx_nand *nand) { - struct mtd_info *mtd = info->mtd; - struct nand_chip *chip = mtd->priv; - + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; + struct mtd_info *mtd = get_mtd_by_info(info); /* use the common timing to make a try */ pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); - chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); - if (info->state & STATE_READY) + pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0); + if (nand->state & STATE_READY) return 1; else return 0; @@ -933,29 +920,29 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) static int pxa3xx_nand_scan(struct mtd_info *mtd) { - struct pxa3xx_nand_info *info = mtd->priv; struct pxa3xx_nand_flash *f; + struct pxa3xx_nand_info *info = mtd->priv; struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; uint32_t id = -1; int i, ret; - ret = pxa3xx_nand_sensing(info); + nand->chip_select = info->chip_select; + ret = pxa3xx_nand_sensing(nand); if (!ret) { - kfree(mtd); - info->mtd = NULL; - printk(KERN_INFO "There is no nand chip on cs 0!\n"); + pr_info("There is no nand chip on cs %d!\n", info->chip_select); + free_cs_resource(info, nand->chip_select); return -EINVAL; } - chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); + pxa3xx_nand_cmdfunc(mtd, NAND_CMD_READID, 0, 0); id = *((uint16_t *)(info->data_buff)); if (id != 0) - printk(KERN_INFO "Detect a flash id %x\n", id); + pr_info("Detect a flash id %x on cs %d\n", id, nand->chip_select); else { - kfree(mtd); - info->mtd = NULL; - printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); + pr_warning("Read out ID 0, potential timing set wrong!!\n"); + free_cs_resource(info, nand->chip_select); return -EINVAL; } @@ -976,15 +963,14 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) mtd->erasesize_shift = ffs(mtd->erasesize) - 1; mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; - mtd->name = mtd_names[0]; + mtd->name = mtd_names[nand->chip_select]; break; } } if (i == ARRAY_SIZE(builtin_flash_types)) { - kfree(mtd); - info->mtd = NULL; printk(KERN_ERR "ERROR!! flash not defined!!!\n"); + free_cs_resource(info, nand->chip_select); return -EINVAL; } @@ -1007,7 +993,6 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) chip->page_shift = ffs(mtd->writesize) - 1; chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; chip->numchips = 1; - chip->chip_delay = 25; chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1; /* Set the bad block position */ @@ -1041,50 +1026,26 @@ static int alloc_nand_resource(struct platform_device *pdev) { struct pxa3xx_nand_info *info; struct nand_chip *chip; + struct pxa3xx_nand *nand; struct mtd_info *mtd; struct resource *r; - int ret, irq; + int ret, irq, cs; + int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); - mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), - GFP_KERNEL); - if (!mtd) { + nand = kzalloc(sizeof(struct pxa3xx_nand), GFP_KERNEL); + if (!nand) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } - info = (struct pxa3xx_nand_info *)(&mtd[1]); - chip = (struct nand_chip *)(&mtd[1]); - info->pdev = pdev; - info->mtd = mtd; - mtd->priv = info; - mtd->owner = THIS_MODULE; - - chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; - chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; - chip->ecc.hwctl = pxa3xx_nand_ecc_hwctl; - chip->ecc.calculate = pxa3xx_nand_ecc_calculate; - chip->ecc.correct = pxa3xx_nand_ecc_correct; - chip->waitfunc = pxa3xx_nand_waitfunc; - chip->select_chip = pxa3xx_nand_select_chip; - chip->dev_ready = pxa3xx_nand_dev_ready; - chip->cmdfunc = pxa3xx_nand_cmdfunc; - chip->read_word = pxa3xx_nand_read_word; - chip->read_byte = pxa3xx_nand_read_byte; - chip->read_buf = pxa3xx_nand_read_buf; - chip->write_buf = pxa3xx_nand_write_buf; - chip->verify_buf = pxa3xx_nand_verify_buf; - chip->block_markbad = pxa3xx_nand_default_block_markbad; - chip->block_bad = pxa3xx_nand_block_bad; - chip->scan_bbt = nand_default_bbt; - chip->erase_cmd = pxa3xx_nand_erase_cmd; - - info->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(info->clk)) { + nand->pdev = pdev; + nand->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(nand->clk)) { dev_err(&pdev->dev, "failed to get nand clock\n"); - ret = PTR_ERR(info->clk); - goto fail_free_mtd; + ret = PTR_ERR(nand->clk); + goto fail_alloc; } - clk_enable(info->clk); + clk_enable(nand->clk); r = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (r == NULL) { @@ -1092,7 +1053,7 @@ static int alloc_nand_resource(struct platform_device *pdev) ret = -ENXIO; goto fail_put_clk; } - info->drcmr_dat = r->start; + nand->drcmr_dat = r->start; r = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (r == NULL) { @@ -1100,14 +1061,7 @@ static int alloc_nand_resource(struct platform_device *pdev) ret = -ENXIO; goto fail_put_clk; } - info->drcmr_cmd = r->start; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ resource defined\n"); - ret = -ENXIO; - goto fail_put_clk; - } + nand->drcmr_cmd = r->start; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { @@ -1123,80 +1077,145 @@ static int alloc_nand_resource(struct platform_device *pdev) goto fail_put_clk; } - info->mmio_base = ioremap(r->start, resource_size(r)); - if (info->mmio_base == NULL) { + nand->mmio_base = ioremap(r->start, resource_size(r)); + if (nand->mmio_base == NULL) { dev_err(&pdev->dev, "ioremap() failed\n"); ret = -ENODEV; goto fail_free_res; } - info->mmio_phys = r->start; - - ret = pxa3xx_nand_init_buff(info); - if (ret) - goto fail_free_io; + nand->mmio_phys = r->start; /* initialize all interrupts to be disabled */ - disable_int(info, NDSR_MASK); + disable_int(nand, NDSR_MASK); + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no IRQ resource defined\n"); + ret = -ENXIO; + goto fail_put_clk; + } ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED, - pdev->name, info); + pdev->name, nand); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto fail_free_buf; + ret = -ENXIO; + goto fail_free_irq; } - platform_set_drvdata(pdev, info); + platform_set_drvdata(pdev, nand); + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + mtd = kzalloc(sizeof(struct mtd_info) + + sizeof(struct pxa3xx_nand_info), + GFP_KERNEL); + if (!mtd) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + ret = -ENOMEM; + goto fail_free_irq; + } + + info = (struct pxa3xx_nand_info *)(&mtd[1]); + info->nand_data = nand; + info->chip_select = cs; + mtd->priv = info; + mtd->owner = THIS_MODULE; + nand->info[cs] = info; + + chip = (struct nand_chip *)(&mtd[1]); + chip->controller = &nand->controller; + chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; + chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->waitfunc = pxa3xx_nand_waitfunc; + chip->select_chip = pxa3xx_nand_select_chip; + chip->cmdfunc = pxa3xx_nand_cmdfunc; + chip->read_word = pxa3xx_nand_read_word; + chip->read_byte = pxa3xx_nand_read_byte; + chip->read_buf = pxa3xx_nand_read_buf; + chip->write_buf = pxa3xx_nand_write_buf; + chip->verify_buf = pxa3xx_nand_verify_buf; + chip->block_markbad = pxa3xx_nand_default_block_markbad; + chip->block_bad = pxa3xx_nand_block_bad; + chip->scan_bbt = nand_default_bbt; + chip->erase_cmd = pxa3xx_nand_erase_cmd; + + if (use_dma == 0) { + info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); + if (info->data_buff == NULL) { + ret = -ENOMEM; + goto fail_free_buf; + } + continue; + } + + info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, + &info->data_buff_phys, GFP_KERNEL); + if (info->data_buff == NULL) { + dev_err(&pdev->dev, "failed to allocate dma buffer\n"); + ret = -ENOMEM; + goto fail_free_buf; + } + + info->data_desc = (void *)info->data_buff + data_desc_offset; + info->data_desc_addr = info->data_buff_phys + data_desc_offset; + info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW, + pxa3xx_nand_data_dma_irq, nand); + if (info->data_dma_ch < 0) { + dev_err(&pdev->dev, "failed to request data dma\n"); + ret = -ENXIO; + goto fail_free_buf; + } + } + + spin_lock_init(&nand->controller.lock); + init_waitqueue_head(&nand->controller.wq); return 0; fail_free_buf: - free_irq(irq, info); - if (use_dma) { - pxa_free_dma(info->data_dma_ch); - dma_free_coherent(&pdev->dev, info->data_buff_size, - info->data_buff, info->data_buff_phys); - } else - kfree(info->data_buff); -fail_free_io: - iounmap(info->mmio_base); + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + info = nand->info[cs]; + free_cs_resource(info, cs); + } +fail_free_irq: + free_irq(irq, nand); + iounmap(nand->mmio_base); fail_free_res: release_mem_region(r->start, resource_size(r)); fail_put_clk: - clk_disable(info->clk); - clk_put(info->clk); -fail_free_mtd: - kfree(mtd); + clk_disable(nand->clk); + clk_put(nand->clk); +fail_alloc: + kfree(nand); return ret; } static int pxa3xx_nand_remove(struct platform_device *pdev) { - struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); - struct mtd_info *mtd = info->mtd; + struct pxa3xx_nand *nand = platform_get_drvdata(pdev); + struct pxa3xx_nand_info *info; + struct mtd_info *mtd; struct resource *r; - int irq; + int irq, cs; platform_set_drvdata(pdev, NULL); - del_mtd_device(mtd); - del_mtd_partitions(mtd); irq = platform_get_irq(pdev, 0); if (irq >= 0) - free_irq(irq, info); - if (use_dma) { - pxa_free_dma(info->data_dma_ch); - dma_free_writecombine(&pdev->dev, info->data_buff_size, - info->data_buff, info->data_buff_phys); - } else - kfree(info->data_buff); + free_irq(irq, nand); - iounmap(info->mmio_base); + iounmap(nand->mmio_base); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(r->start, resource_size(r)); - - clk_disable(info->clk); - clk_put(info->clk); - - kfree(mtd); + clk_disable(nand->clk); + clk_put(nand->clk); + + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + info = nand->info[cs]; + if (!info) + continue; + mtd = get_mtd_by_info(info); + del_mtd_partitions(mtd); + del_mtd_device(mtd); + free_cs_resource(info, cs); + } return 0; } @@ -1204,7 +1223,9 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) { struct pxa3xx_nand_platform_data *pdata; struct pxa3xx_nand_info *info; - int ret; + struct pxa3xx_nand *nand; + struct mtd_info *mtd; + int ret, cs, probe_success = 0; pdata = pdev->dev.platform_data; if (!pdata) { @@ -1216,14 +1237,23 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) if (ret) return ret; - info = platform_get_drvdata(pdev); - if (pxa3xx_nand_scan(info->mtd)) { - dev_err(&pdev->dev, "failed to scan nand\n"); - pxa3xx_nand_remove(pdev); - return -ENODEV; + nand = platform_get_drvdata(pdev); + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + info = nand->info[cs]; + mtd = get_mtd_by_info(info); + if (pxa3xx_nand_scan(mtd)) { + dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs); + continue; + } + ret = add_mtd_partitions(mtd, pdata->parts[cs], + pdata->nr_parts[cs]); + if (!ret) + probe_success = 1; } - return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); + if (!probe_success) + pxa3xx_nand_remove(pdev); + return ret; } #ifdef CONFIG_PM -- 1.5.6.5 From haojian.zhuang at gmail.com Thu May 6 05:07:57 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:07:57 -0400 Subject: [PATCH 10/20] pxa3xx_nand: add bch ecc support Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:08:52 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:08:52 -0400 Subject: [PATCH 11/20] pxa3xx_nand: add debug messege Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:09:36 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:09:36 -0400 Subject: [PATCH 12/20] pxa3xx_nand: enable 4k page operation Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:10:14 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:10:14 -0400 Subject: [PATCH 13/20] pxa3xx_nand: show the real time used by the controller Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:10:54 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:10:54 -0400 Subject: [PATCH 14/20] pxa3xx_nand: add polling mode support Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:11:36 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:11:36 -0400 Subject: [PATCH 15/20] [ARM] mmp: add nand support to mmp2 Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:12:08 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:12:08 -0400 Subject: [PATCH 16/20] pxa3xx_nand: fix reset timeout on mmp2 Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:12:44 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:12:44 -0400 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support Message-ID: From leiwen at marvell.com Wed May 5 22:42:13 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 10:42:13 +0800 Subject: [PATCH] pxa3xx_nand: add cmdline part parser support Message-ID: Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 26 ++++++++++++++++++++++++-- 1 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2eebd20..793b64c 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -349,6 +349,9 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0, 10, 35, 15, 25, 15, 25, 25000, 0, 60, 10, }, }, }; +#ifdef CONFIG_MTD_CMDLINE_PARTS +static const char *part_probes[] = { "cmdlinepart", NULL }; +#endif static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; /* convert nano-seconds to nand flash controller clock cycles */ @@ -1726,6 +1729,10 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) struct pxa3xx_nand *nand; struct mtd_info *mtd; int ret, cs, probe_success = 0; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *partitions = NULL; + int num_part = 0; +#endif pdata = pdev->dev.platform_data; if (!pdata) { @@ -1747,8 +1754,23 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs); continue; } - ret = add_mtd_partitions(mtd, pdata->parts[cs], - pdata->nr_parts[cs]); + mtd->name = mtd_names[cs]; +#ifdef CONFIG_MTD_PARTITIONS +#ifdef CONFIG_MTD_CMDLINE_PARTS + num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0); +#endif + if (num_part <= 0) { + num_part = pdata->nr_parts[cs]; + partitions = pdata->parts[cs]; + } + + if (partitions && num_part > 0) + ret = add_mtd_partitions(mtd, partitions, num_part); + else + ret = add_mtd_device(mtd); +#else + ret = add_mtd_device(mtd); +#endif if (!ret) probe_success = 1; } -- 1.5.6.5 From haojian.zhuang at gmail.com Thu May 6 05:13:22 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:13:22 -0400 Subject: [PATCH 18/20] [ARM] mmp: refresh nand timing Message-ID: From haojian.zhuang at gmail.com Thu May 6 05:14:41 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:14:41 -0400 Subject: [PATCH 19/20] pxa3xx_nand: reimplment read oob command to increase performance Message-ID: From leiwen at marvell.com Wed May 5 22:43:57 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 10:43:57 +0800 Subject: [PATCH] pxa3xx_nand: reimplment read oob command to increase Message-ID: performance For read oob command only care about the spare area part, we truly need not to transfer all page data to the controller side. By random data out, we could do the naked read first to let one page data transfer from NAND chip to its internal ram. Then we use random data out command to change the offset to the start of oob part. After all this, we toggle only oob size of RE# to the controller side. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 122 ++++++++++++++++++++++++++++++---------- 1 files changed, 92 insertions(+), 30 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 7c871af..2e1c8b6 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -129,6 +129,7 @@ #define NDCB0_CMD_XTYPE_MASK (0x7 << 29) #define NDCB0_CMD_XTYPE(x) (((x) << 29) & NDCB0_CMD_XTYPE_MASK) +#define NDCB0_LEN_OVRD (0x1 << 28) #define NDCB0_ST_ROW_EN (0x1 << 26) #define NDCB0_AUTO_RS (0x1 << 25) #define NDCB0_CSEL (0x1 << 24) @@ -257,8 +258,9 @@ struct pxa3xx_nand_info { uint8_t total_cmds; uint8_t wait_ready[CMD_POOL_SIZE]; uint32_t ndcb0[CMD_POOL_SIZE]; - uint32_t ndcb1; - uint32_t ndcb2; + uint32_t ndcb1[CMD_POOL_SIZE]; + uint32_t ndcb2[CMD_POOL_SIZE]; + uint32_t ndcb3[CMD_POOL_SIZE]; uint32_t reg_ndcr; uint32_t ndtr0cs0; uint32_t ndtr1cs0; @@ -646,9 +648,9 @@ static void nand_error_dump(struct pxa3xx_nand *nand) printk(KERN_ERR "Totally %d command for sending\n", info->total_cmds); for (i = 0; i < info->total_cmds; i ++) - printk(KERN_ERR "NDCB0:%d: %x\n", - i, info->ndcb0[i]); - printk(KERN_ERR "NDCB1: %x; NDCB2 %x\n", info->ndcb1, info->ndcb2); + printk(KERN_ERR "==%d: NDCB0 %x, NDCB1 %x, NDCB2 %x, NDCB3 %x\n", + i, info->ndcb0[i], info->ndcb1[i], + info->ndcb2[i], info->ndcb3[i]); printk(KERN_ERR "\nRegister DUMPing ##############\n"); printk(KERN_ERR "NDCR %x\n" @@ -775,7 +777,7 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand) { struct pxa3xx_nand_info *info; - unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2; + unsigned int status, is_completed = 0, cs, cmd_seqs; unsigned int ready, cmd_done, page_done, badblock_detect; cs = nand->chip_select; @@ -842,24 +844,20 @@ static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand) nand_writel(nand, NDSR, NDSR_WRCMDREQ); if (cmd_seqs < info->total_cmds) { - info->cmd_seqs ++; - if (cmd_seqs == 0) { - ndcb1 = info->ndcb1; - ndcb2 = info->ndcb2; - } - else { - ndcb1 = 0; - ndcb2 = 0; - } + info->cmd_seqs++; nand->state &= ~STATE_MASK; nand->state |= STATE_CMD_WAIT_DONE; nand_writel(nand, NDCB0, info->ndcb0[cmd_seqs]); - nand_writel(nand, NDCB0, ndcb1); - nand_writel(nand, NDCB0, ndcb2); - DBG_NAND(printk("\tndcb0 %x ndcb1 %x ndcb2 %x\n", - info->ndcb0[cmd_seqs], ndcb1, ndcb2)); - } - else + nand_writel(nand, NDCB0, info->ndcb1[cmd_seqs]); + nand_writel(nand, NDCB0, info->ndcb2[cmd_seqs]); + if (info->ndcb0[cmd_seqs] & NDCB0_LEN_OVRD) + nand_writel(nand, NDCB0, info->ndcb3[cmd_seqs]); + DBG_NAND(printk("\tndcb0 %x ndcb1 %x ndcb2 %x, ndcb3 %x\n", + info->ndcb0[cmd_seqs], + info->ndcb1[cmd_seqs], + info->ndcb2[cmd_seqs], + info->ndcb3[cmd_seqs])); + } else is_completed = 1; } @@ -938,6 +936,7 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, case NAND_CMD_PAGEPROG: nand->use_ecc = info->use_ecc; case NAND_CMD_READOOB: + case NAND_CMD_RNDOUT: pxa3xx_set_datasize(info); nand->use_dma = use_dma; chunks = info->page_size / nand->data_size; @@ -946,8 +945,8 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, exec_cmd = 0; break; default: - info->ndcb1 = 0; - info->ndcb2 = 0; + info->ndcb1[0] = 0; + info->ndcb2[0] = 0; break; } @@ -1005,26 +1004,73 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, case NAND_CMD_SEQIN: /* small page addr setting */ if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) { - info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) + info->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8) | (column & 0xFF); - info->ndcb2 = 0; + info->ndcb2[0] = 0; } else { - info->ndcb1 = ((page_addr & 0xFFFF) << 16) + info->ndcb1[0] = ((page_addr & 0xFFFF) << 16) | (column & 0xFFFF); if (page_addr & 0xFF0000) - info->ndcb2 = (page_addr & 0xFF0000) >> 16; + info->ndcb2[0] = (page_addr & 0xFF0000) >> 16; else - info->ndcb2 = 0; + info->ndcb2[0] = 0; } + for (i = 1; i <=chunks; i ++) { + info->ndcb1[i] = info->ndcb1[0]; + info->ndcb2[i] = info->ndcb2[0]; + } info->buf_count = mtd->writesize + mtd->oobsize; memset(info->data_buff, 0xFF, info->buf_count); break; + case NAND_CMD_RNDOUT: + /* current RNDOUT only support 2k nand */ + if (info->page_size > PAGE_CHUNK_SIZE) + BUG(); + + cmd = cmdset.read1; + info->total_cmds = 3; + info->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6) + | NDCB0_CMD_TYPE(0) + | NDCB0_DBC + | NDCB0_NC + | addr_cycle + | cmd; + + info->ndcb0[1] |= NDCB0_CMD_XTYPE(0x6) + | NDCB0_CMD_TYPE(0) + | NDCB0_DBC + | NDCB0_NC + | NDCB0_ADDR_CYC(info->col_addr_cycles) + | (NAND_CMD_RNDOUTSTART << 8) + | NAND_CMD_RNDOUT; + + info->ndcb0[2] |= NDCB0_CMD_XTYPE(0x5) + | NDCB0_LEN_OVRD; + + info->ndcb1[0] = ((page_addr & 0xFFFF) << 16) + | (column & 0xFFFF); + info->ndcb1[1] = mtd->writesize; + info->ndcb1[2] = 0; + + if (page_addr & 0xFF0000) + info->ndcb2[0] = (page_addr & 0xFF0000) >> 16; + else + info->ndcb2[0] = 0; + info->ndcb2[1] = info->ndcb2[2] = 0; + info->ndcb3[0] = info->ndcb3[1] = 0; + info->ndcb3[2] = mtd->oobsize; + info->buf_count = mtd->oobsize; + info->wait_ready[1] = 1; + nand->data_size = mtd->oobsize; + nand->oob_size = 0; + break; + case NAND_CMD_PAGEPROG: if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) { exec_cmd = 0; @@ -1096,8 +1142,8 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, | NDCB0_ADDR_CYC(3) | NDCB0_DBC | cmd; - info->ndcb1 = page_addr; - info->ndcb2 = 0; + info->ndcb1[0] = page_addr; + info->ndcb2[0] = 0; break; case NAND_CMD_RESET: @@ -1245,6 +1291,21 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return 0; } +static int pxa3xx_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page, int sndcmd) +{ + struct pxa3xx_nand_info *info = (struct pxa3xx_nand_info *)chip; + if (sndcmd) { + if ((info->page_size <= PAGE_CHUNK_SIZE) && naked_cmd_support) + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, page); + else + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + return sndcmd; +} + static void pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, struct pxa3xx_nand_flash *f, int show_timing) { @@ -1626,6 +1687,7 @@ static int alloc_nand_resource(struct platform_device *pdev) chip->controller = &nand->controller; chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->ecc.read_oob = pxa3xx_nand_read_oob; chip->waitfunc = pxa3xx_nand_waitfunc; chip->select_chip = pxa3xx_nand_select_chip; chip->cmdfunc = pxa3xx_nand_cmdfunc; -- 1.5.6.5 From haojian.zhuang at gmail.com Thu May 6 05:15:18 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Thu, 6 May 2010 05:15:18 -0400 Subject: [PATCH 20/20] pxa3xx_nand: fix power management support Message-ID: From shinya.kuribayashi.px at renesas.com Thu May 6 05:26:30 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 18:26:30 +0900 Subject: [PATCH] UBI: Remaining typos and comments cleanups In-Reply-To: <4BE23A8D.7040106@renesas.com> References: <4BE23A03.1030001@renesas.com> <4BE23A8D.7040106@renesas.com> Message-ID: <4BE28B46.40908@renesas.com> Artem-san, On 5/6/2010 12:42 PM, Shinya Kuribayashi wrote: > diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c > index 016ec13..cd0bf57 100644 > --- a/drivers/mtd/ubi/io.c > +++ b/drivers/mtd/ubi/io.c > @@ -64,7 +64,7 @@ > * device, e.g., make @ubi->min_io_size = 512 in the example above? > * > * A: because when writing a sub-page, MTD still writes a full 2K page but the > - * bytes which are no relevant to the sub-page are 0xFF. So, basically, writing > + * bytes which are not relevant to the sub-page are 0xFF. So, basically, writing > * 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. Thus, we > * prefer to use sub-pages only for EV and VID headers. > * ^^^^ Looking at the last line, I think above 'EV' is a typo of 'EC', right? I'll incorporate it in the next submission, -- Shinya Kuribayashi Renesas Electronics From sebastian at breakpoint.cc Thu May 6 05:34:40 2010 From: sebastian at breakpoint.cc (Sebastian Andrzej Siewior) Date: Thu, 6 May 2010 11:34:40 +0200 Subject: [PATCH 2/4] UBI: introduce a new IO return code In-Reply-To: <1272881582-17196-3-git-send-email-Artem.Bityutskiy@nokia.com> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> <1272881582-17196-3-git-send-email-Artem.Bityutskiy@nokia.com> Message-ID: <20100506093440.GA15335@Chamillionaire.breakpoint.cc> * Artem Bityutskiy | 2010-05-03 13:13:00 [+0300]: >diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c >index f52adca..65d03b5 100644 >--- a/drivers/mtd/ubi/scan.c >+++ b/drivers/mtd/ubi/scan.c >@@ -745,7 +745,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, > bitflips = 1; > else if (err == UBI_IO_PEB_EMPTY) > return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); >- else if (err == UBI_IO_BAD_HDR) { >+ else if (err = UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { That part should be == and not = but you fix this in the next patch so I guess it is okay. > /* > * We have to also look at the VID header, possibly it is not > * corrupted. Set %bitflips flag in order to make this PEB be Sebastian From sebastian at breakpoint.cc Thu May 6 05:52:18 2010 From: sebastian at breakpoint.cc (Sebastian Andrzej Siewior) Date: Thu, 6 May 2010 11:52:18 +0200 Subject: [PATCH 0/4] UBI: improve empty flash handling In-Reply-To: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> Message-ID: <20100506095218.GB15335@Chamillionaire.breakpoint.cc> * Artem Bityutskiy | 2010-05-03 13:12:58 [+0300]: >Hi Sebastian, Hi Artem, >Please, review and test the following series. The code looks fine. I wiped the flash and the test resulted in: | UBI: attaching mtd9 to ubi0 | UBI: physical eraseblock size: 131072 bytes (128 KiB) | UBI: logical eraseblock size: 129024 bytes | UBI: smallest flash I/O unit: 2048 | UBI: sub-page size: 512 | UBI: VID header offset: 512 (aligned 512) | UBI: data offset: 2048 | UBI error: ubi_io_read: error -74 while reading 64 bytes from PEB 3399:0, read 64 bytes | Call Trace: | [cfbd7c70] [c0008558] show_stack+0x48/0x19c (unreliable) | [cfbd7cb0] [c01ab6e0] ubi_io_read+0x1a4/0x2ac | [cfbd7cf0] [c01abb4c] ubi_io_read_ec_hdr+0x48/0x21c | [cfbd7d10] [c01b0060] ubi_scan+0x194/0x11b8 | [cfbd7d80] [c01a5e48] ubi_attach_mtd_dev+0x67c/0xe30 | [cfbd7e80] [c01a6804] ctrl_cdev_ioctl+0x140/0x1d8 | [cfbd7ec0] [c008bf1c] do_ioctl+0x3c/0xc4 | [cfbd7ee0] [c008c024] vfs_ioctl+0x80/0x448 | [cfbd7f10] [c008c42c] sys_ioctl+0x40/0x88 | [cfbd7f40] [c001008c] ret_from_syscall+0x0/0x38 | --- Exception: c01 at 0xff59908 | LR = 0xff5986c | UBI: empty MTD device detected | UBI: corrupted PEBs will be formatted | UBI: create volume table (copy #1) | UBI: create volume table (copy #2) | UBI: attached mtd9 to ubi0 | UBI: MTD device name: "ubi" | UBI: MTD device size: 512 MiB | UBI: number of good PEBs: 4096 | UBI: number of bad PEBs: 0 | UBI: max. allowed volumes: 128 | UBI: wear-leveling threshold: 4096 | UBI: number of internal volumes: 1 | UBI: number of user volumes: 0 | UBI: available PEBs: 4052 | UBI: total number of reserved PEBs: 44 | UBI: number of PEBs reserved for bad PEB handling: 40 | UBI: max/mean erase counter: 0/0 | UBI: image sequence number: 0 | UBI: background thread "ubi_bgt0d" started, PID 2003 | UBI error: ubi_io_read: error -74 while reading 64 bytes from PEB 3399:0, read 64 bytes | Call Trace: | [cfa7bea0] [c0008558] show_stack+0x48/0x19c (unreliable) | [cfa7bee0] [c01ab6e0] ubi_io_read+0x1a4/0x2ac | [cfa7bf20] [c01abb4c] ubi_io_read_ec_hdr+0x48/0x21c | [cfa7bf40] [c01ad628] erase_worker+0x5c/0x670 | [cfa7bf70] [c01ae794] do_work+0xb0/0x16c | [cfa7bf90] [c01ae990] ubi_thread+0x140/0x1bc | [cfa7bfd0] [c0037bec] kthread+0x50/0x88 | [cfa7bff0] [c000fdf8] kernel_thread+0x44/0x60 | UBI error: do_sync_erase: cannot erase PEB 3399, error -5 | Call Trace: | [cfa7be00] [c0008558] show_stack+0x48/0x19c (unreliable) | [cfa7be40] [c01ac494] do_sync_erase+0x208/0x220 | [cfa7bec0] [c01ac6bc] ubi_io_sync_erase+0x210/0x400 | [cfa7bf40] [c01ad668] erase_worker+0x9c/0x670 | [cfa7bf70] [c01ae794] do_work+0xb0/0x16c | [cfa7bf90] [c01ae990] ubi_thread+0x140/0x1bc | [cfa7bfd0] [c0037bec] kthread+0x50/0x88 | [cfa7bff0] [c000fdf8] kernel_thread+0x44/0x60 | UBI error: erase_worker: failed to erase PEB 3399, error -5 | UBI: reserve more 1 PEBs | UBI: mark PEB 3399 as bad | UBI: 40 PEBs left in the reserve So it looks fine. Attaching partitions with non-ubi material failed. >P.S. I gave it only a very quick try Works good for that :) > >Artem. Sebastian From shinya.kuribayashi.px at renesas.com Thu May 6 06:18:25 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 19:18:25 +0900 Subject: A few cleanups against Linus' master (v2) Message-ID: <4BE29771.4050800@renesas.com> Hi, > Noticed and fixed while learning UBI subsystems. As for comment fixes > a double-check by native speaker would be appricated. > > p.s. UBI fixes can be squashed into one at your option, thanks. v2: - Incorporate s/EV/EC/ typo fix, too - Drop 'mtd: Remove empty mtd/mtdbdi.c and mtd/internal.h files' Shinya Kuribayashi (2): UBI: Fix s/then/than/ typos UBI: Misc comment fixes drivers/mtd/ubi/Kconfig | 2 +- drivers/mtd/ubi/io.c | 6 +++--- drivers/mtd/ubi/kapi.c | 6 +++--- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/vtbl.c | 4 ++-- drivers/mtd/ubi/wl.c | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) From dedekind1 at gmail.com Thu May 6 06:19:37 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 06 May 2010 13:19:37 +0300 Subject: [PATCH] UBI: Remaining typos and comments cleanups In-Reply-To: <4BE28B46.40908@renesas.com> References: <4BE23A03.1030001@renesas.com> <4BE23A8D.7040106@renesas.com> <4BE28B46.40908@renesas.com> Message-ID: <1273141177.3702.227.camel@localhost> On Thu, 2010-05-06 at 18:26 +0900, Shinya Kuribayashi wrote: > Artem-san, > > On 5/6/2010 12:42 PM, Shinya Kuribayashi wrote: > > diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c > > index 016ec13..cd0bf57 100644 > > --- a/drivers/mtd/ubi/io.c > > +++ b/drivers/mtd/ubi/io.c > > @@ -64,7 +64,7 @@ > > * device, e.g., make @ubi->min_io_size = 512 in the example above? > > * > > * A: because when writing a sub-page, MTD still writes a full 2K page but the > > - * bytes which are no relevant to the sub-page are 0xFF. So, basically, writing > > + * bytes which are not relevant to the sub-page are 0xFF. So, basically, writing > > * 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. Thus, we > > * prefer to use sub-pages only for EV and VID headers. > > * ^^^^ > > Looking at the last line, I think above 'EV' is a typo of 'EC', right? > I'll incorporate it in the next submission, Right -- Best Regards, Artem Bityutskiy (????? ????????) From shinya.kuribayashi.px at renesas.com Thu May 6 06:21:47 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 19:21:47 +0900 Subject: [PATCH 1/2] UBI: Fix s/then/than/ typos In-Reply-To: <4BE29771.4050800@renesas.com> References: <4BE29771.4050800@renesas.com> Message-ID: <4BE2983B.4090605@renesas.com> Signed-off-by: Shinya Kuribayashi --- Nothing's changed, just resent with correcting Tb3's settings. drivers/mtd/ubi/Kconfig | 2 +- drivers/mtd/ubi/io.c | 2 +- drivers/mtd/ubi/kapi.c | 6 +++--- drivers/mtd/ubi/scan.c | 4 ++-- drivers/mtd/ubi/wl.c | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig index 0a8c7ea..f702a16 100644 --- a/drivers/mtd/ubi/Kconfig +++ b/drivers/mtd/ubi/Kconfig @@ -27,7 +27,7 @@ config MTD_UBI_WL_THRESHOLD The default value should be OK for SLC NAND flashes, NOR flashes and other flashes which have eraseblock life-cycle 100000 or more. However, in case of MLC NAND flashes which typically have eraseblock - life-cycle less then 10000, the threshold should be lessened (e.g., + life-cycle less than 10000, the threshold should be lessened (e.g., to 128 or 256, although it does not have to be power of 2). config MTD_UBI_BEB_RESERVE diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 533b1a4..016ec13 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -65,7 +65,7 @@ * * A: because when writing a sub-page, MTD still writes a full 2K page but the * bytes which are no relevant to the sub-page are 0xFF. So, basically, writing - * 4x512 sub-pages is 4 times slower then writing one 2KiB NAND page. Thus, we + * 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. Thus, we * prefer to use sub-pages only for EV and VID headers. * * As it was noted above, the VID header may start at a non-aligned offset. diff --git a/drivers/mtd/ubi/kapi.c b/drivers/mtd/ubi/kapi.c index 17f287d..69fa4ef 100644 --- a/drivers/mtd/ubi/kapi.c +++ b/drivers/mtd/ubi/kapi.c @@ -488,7 +488,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_write); * * This function changes the contents of a logical eraseblock atomically. @buf * has to contain new logical eraseblock data, and @len - the length of the - * data, which has to be aligned. The length may be shorter then the logical + * data, which has to be aligned. The length may be shorter than the logical * eraseblock size, ant the logical eraseblock may be appended to more times * later on. This function guarantees that in case of an unclean reboot the old * contents is preserved. Returns zero in case of success and a negative error @@ -571,7 +571,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_erase); * * This function un-maps logical eraseblock @lnum and schedules the * corresponding physical eraseblock for erasure, so that it will eventually be - * physically erased in background. This operation is much faster then the + * physically erased in background. This operation is much faster than the * erase operation. * * Unlike erase, the un-map operation does not guarantee that the logical @@ -590,7 +590,7 @@ EXPORT_SYMBOL_GPL(ubi_leb_erase); * * The main and obvious use-case of this function is when the contents of a * logical eraseblock has to be re-written. Then it is much more efficient to - * first un-map it, then write new data, rather then first erase it, then write + * first un-map it, then write new data, rather than first erase it, then write * new data. Note, once new data has been written to the logical eraseblock, * UBI guarantees that the old contents has gone forever. In other words, if an * unclean reboot happens after the logical eraseblock has been un-mapped and diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index dc5f688..aed19f3 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -231,7 +231,7 @@ static struct ubi_scan_volume *add_volume(struct ubi_scan_info *si, int vol_id, * case of success this function returns a positive value, in case of failure, a * negative error code is returned. The success return codes use the following * bits: - * o bit 0 is cleared: the first PEB (described by @seb) is newer then the + * o bit 0 is cleared: the first PEB (described by @seb) is newer than the * second PEB (described by @pnum and @vid_hdr); * o bit 0 is set: the second PEB is newer; * o bit 1 is cleared: no bit-flips were detected in the newer LEB; @@ -452,7 +452,7 @@ int ubi_scan_add_used(struct ubi_device *ubi, struct ubi_scan_info *si, if (cmp_res & 1) { /* - * This logical eraseblock is newer then the one + * This logical eraseblock is newer than the one * found earlier. */ err = validate_vid_hdr(vid_hdr, sv, pnum); diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c index f64ddab..ee7b1d8 100644 --- a/drivers/mtd/ubi/wl.c +++ b/drivers/mtd/ubi/wl.c @@ -350,7 +350,7 @@ static void prot_queue_add(struct ubi_device *ubi, struct ubi_wl_entry *e) * @max: highest possible erase counter * * This function looks for a wear leveling entry with erase counter closest to - * @max and less then @max. + * @max and less than @max. */ static struct ubi_wl_entry *find_wl_entry(struct rb_root *root, int max) { -- 1.7.1 From shinya.kuribayashi.px at renesas.com Thu May 6 06:22:09 2010 From: shinya.kuribayashi.px at renesas.com (Shinya Kuribayashi) Date: Thu, 06 May 2010 19:22:09 +0900 Subject: [PATCH 2/2] UBI: Misc comment fixes In-Reply-To: <4BE29771.4050800@renesas.com> References: <4BE29771.4050800@renesas.com> Message-ID: <4BE29851.7040006@renesas.com> Note that hunk #1 of the patch fixes two typos; s/no/not/ and s/EV/EC/. Signed-off-by: Shinya Kuribayashi --- v2: Incorporate s/EV/EC/ typo, too. As UBI comments are beatifully written conforming to 80-char-wide limit, I also would like to follow that good practice. drivers/mtd/ubi/io.c | 6 +++--- drivers/mtd/ubi/vtbl.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/ubi/io.c b/drivers/mtd/ubi/io.c index 016ec13..4b979e3 100644 --- a/drivers/mtd/ubi/io.c +++ b/drivers/mtd/ubi/io.c @@ -64,9 +64,9 @@ * device, e.g., make @ubi->min_io_size = 512 in the example above? * * A: because when writing a sub-page, MTD still writes a full 2K page but the - * bytes which are no relevant to the sub-page are 0xFF. So, basically, writing - * 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. Thus, we - * prefer to use sub-pages only for EV and VID headers. + * bytes which are not relevant to the sub-page are 0xFF. So, basically, + * writing 4x512 sub-pages is 4 times slower than writing one 2KiB NAND page. + * Thus, we prefer to use sub-pages only for EC and VID headers. * * As it was noted above, the VID header may start at a non-aligned offset. * For example, in case of a 2KiB page NAND flash with a 512 bytes sub-page, diff --git a/drivers/mtd/ubi/vtbl.c b/drivers/mtd/ubi/vtbl.c index cd90ff3..14c10be 100644 --- a/drivers/mtd/ubi/vtbl.c +++ b/drivers/mtd/ubi/vtbl.c @@ -414,7 +414,7 @@ static struct ubi_vtbl_record *process_lvol(struct ubi_device *ubi, * 0 contains more recent information. * * So the plan is to first check LEB 0. Then - * a. if LEB 0 is OK, it must be containing the most resent data; then + * a. if LEB 0 is OK, it must be containing the most recent data; then * we compare it with LEB 1, and if they are different, we copy LEB * 0 to LEB 1; * b. if LEB 0 is corrupted, but LEB 1 has to be OK, and we copy LEB 1 @@ -848,7 +848,7 @@ int ubi_read_volume_table(struct ubi_device *ubi, struct ubi_scan_info *si) goto out_free; /* - * Get sure that the scanning information is consistent to the + * Make sure that the scanning information is consistent to the * information stored in the volume table. */ err = check_scanning_info(ubi, si); -- 1.7.1 From eballetbo at gmail.com Thu May 6 07:22:57 2010 From: eballetbo at gmail.com (=?UTF-8?Q?Enric_Balletb=C3=B2_i_Serra?=) Date: Thu, 6 May 2010 13:22:57 +0200 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: Hi, 2010/5/6 Kyungmin Park : > Hi, > > Can you add this statement at below the code? > printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) > onenand_addr(this, block), ((int) addr >> this->page_shift) & > this->page_mask); Yes, With this code nandtest fails: onenand_base.c 377: default: block = onenand_block(this, addr); /* (line disabled) page = (int) (addr >> this->page_shift); */ page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) onenand_addr(this, block), ((int) addr >> this->page_shift) & this->page_mask); if (ONENAND_IS_2PLANE(this)) { /* Make the even block number */ block &= ~1; /* Is it the odd plane? */ if (addr & this->writesize) block++; page >>= 1; } page &= this->page_mask; break; --- start log nandtest fail --- # nandtest -l 262144 /dev/mtd3 ECC corrections: 0 ECC failures : 0 Bad blocks : 0 BBT blocks : 0 00000000: writing... [ 243.144287] onenand_command[382] page 0, 2621440, 0 [ 243.150787] onenand_command[382] page 2, 2621440, 2 [ 243.156158] onenand_command[382] page 4, 2621440, 4 (...) [ 243.310729] onenand_command[382] page 60, 2621440, 60 [ 243.316223] onenand_command[382] page 62, 2621440, 62 [ 243.322204] onenand_command[382] page 0, 2752512, 0 [ 243.327636] onenand_command[382] page 2, 2752512, 2 [ 243.332977] onenand_command[382] page 4, 2752512, 4 (...) [ 243.487487] onenand_command[382] page 60, 2752512, 60 [ 243.493041] onenand_command[382] page 62, 2752512, 62 00000000: reading... [ 243.498535] onenand_command[382] page 0, 2621440, 0 [ 243.505249] onenand_wait: ECC error = 0x8488 [ 243.509552] onenand_command[382] page 1, 2621440, 1 [ 243.514587] onenand_wait: ECC error = 0x8488 [ 243.518890] onenand_command[382] page 2, 2621440, 2 (...) [ 244.089050] onenand_command[382] page 62, 2621440, 62 [ 244.094268] onenand_wait: ECC error = 0x8448 [ 244.098602] onenand_command[382] page 63, 2621440, 63 [ 244.103790] onenand_wait: ECC error = 0x8488 [ 244.109191] onenand_command[382] page 0, 2752512, 0 [ 244.114196] onenand_wait: ECC error = 0x8488 [ 244.118469] onenand_command[382] page 1, 2752512, 1 [ 244.123535] onenand_wait: ECC error = 0x8488 [ 244.127838] onenand_command[382] page 2, 2752512, 2 (...) [ 244.698150] onenand_command[382] page 62, 2752512, 62 [ 244.703369] onenand_wait: ECC error = 0x8448 [ 244.707672] onenand_command[382] page 63, 2752512, 63 [ 244.712890] onenand_wait: ECC error = 0x8488 ECC failed at 00000000 00000000: checking... compare failed. seed 1804289383 Byte 0x1 is 5a should be da Byte 0x3 is 82 should be 92 Byte 0x4 is 10 should be 1a Byte 0x5 is 21 should be b7 --- end log nandtest fail --- With this other code nandtest pass onenand_base.c 377: default: block = onenand_block(this, addr); page = (int) (addr >> this->page_shift); /* (line disabled) page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; */ printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) onenand_addr(this, block), ((int) addr >> this->page_shift) & this->page_mask); if (ONENAND_IS_2PLANE(this)) { /* Make the even block number */ block &= ~1; /* Is it the odd plane? */ if (addr & this->writesize) block++; page >>= 1; } page &= this->page_mask; break; --- start log nandtest pass --- # nandtest -l 262144 /dev/mtd3 ECC corrections: 0 ECC failures : 33 Bad blocks : 0 BBT blocks : 0 00000000: writing... [ 2024.624664] onenand_command[382] page 1280, 2621440, 0 [ 2024.631530] onenand_command[382] page 1282, 2621440, 2 [ 2024.637145] onenand_command[382] page 1284, 2621440, 4 (...) [ 2024.796813] onenand_command[382] page 1340, 2621440, 60 [ 2024.802520] onenand_command[382] page 1342, 2621440, 62 [ 2024.808593] onenand_command[382] page 1344, 2752512, 0 [ 2024.814239] onenand_command[382] page 1346, 2752512, 2 (...) [ 2024.979644] onenand_command[382] page 1404, 2752512, 60 [ 2024.985351] onenand_command[382] page 1406, 2752512, 62 00000000: reading... [ 2024.990997] onenand_command[382] page 1280, 2621440, 0 [ 2024.997985] onenand_command[382] page 1281, 2621440, 1 [ 2025.003295] onenand_command[382] page 1282, 2621440, 2 (...) [ 2025.326782] onenand_command[382] page 1342, 2621440, 62 [ 2025.332214] onenand_command[382] page 1343, 2621440, 63 [ 2025.338592] onenand_command[382] page 1344, 2752512, 0 [ 2025.343811] onenand_command[382] page 1345, 2752512, 1 [ 2025.349151] onenand_command[382] page 1346, 2752512, 2 (...) [ 2025.672576] onenand_command[382] page 1406, 2752512, 62 [ 2025.677978] onenand_command[382] page 1407, 2752512, 63 00000000: checking... Finished pass 1 successfully --- end log nandtest pass --- > > In my test environment, it displays the correct page number. > (addr - onenand_addr(this, block) >> this->page_shift is same as > '(addr >> this->page_shift) & this->page_mask'. > Looks like page number is wrong ? Cheers, Enric > Thank you, > Kyungmin Park > > On Fri, Apr 30, 2010 at 7:05 PM, Enric Balletb? i Serra > wrote: >> Hello all, >> >> After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: >> Flex-OneNAND support) the onenand support for my device is broken. >> >> Before this commit when I run the nandtest program all is ok >> --- >> # nandtest /dev/mtd3 >> ECC corrections: 0 >> ECC failures ? : 0 >> Bad blocks ? ? : 0 >> BBT blocks ? ? : 0 >> 002c0000: checking... >> Finished pass 1 successfully >> -- >> >> Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest >> fails with: >> --- >> # nandtest /dev/mtd3 >> ECC corrections: 0 >> ECC failures ? : 0 >> Bad blocks ? ? : 0 >> BBT blocks ? ? : 0 >> 00000000: reading... >> [ ?299.092041] onenand_wait: ECC error = 0x8488 >> ? ?( ... lots of ECC errors ... ) >> [ ?299.092041] onenand_wait: ECC error = 0x8488 >> ECC failed at 00000000 >> 00000000: checking... >> compare failed. seed 1804289383 >> Byte 0x1 is 5a should be da >> Byte 0x3 is 82 should be 92 >> Byte 0x4 is 10 should be 1a >> ? ?( ... ) >> --- >> >> Investigating a little I see a significant difference introduced by >> this patch. In line >> >> 347: ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >> this->page_shift; ? (patch applied) >> >> instead of >> >> 347: ? ? ? ?page = (int) (addr >> this->page_shift); ?(without patch) >> >> I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced >> the line 347 and now works again. Fantastic, but I suspect this is not >> the proper solution (probably this breaks other onenands devices, I >> can't test). >> >> I'm just introducing in OneNAND devices so anyone can help me to >> understand and solve the problem ? Note that my device is a Numonyx >> 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB >> page ) >> >> Thanks in advance, >> >> ///:~Enric >> >> --- >> diff --git a/drivers/mtd/onenand/onenand_base.c >> b/drivers/mtd/onenand/onenand_base.c >> index 081f97d..b1d50a3 100644 >> --- a/drivers/mtd/onenand/onenand_base.c >> +++ b/drivers/mtd/onenand/onenand_base.c >> @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, >> int cmd, loff_t addr, size_t le >> >> ? ? ? ?default: >> ? ? ? ? ? ? ? ?block = (int) onenand_block(this, addr); >> - ? ? ? ? ? ? ? page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; >> + ? ? ? ? ? ? ? page = (int) (addr >> this->page_shift); >> >> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >> --- >> >> ______________________________________________________ >> Linux MTD discussion mailing list >> http://lists.infradead.org/mailman/listinfo/linux-mtd/ >> > From kmpark at infradead.org Thu May 6 07:44:44 2010 From: kmpark at infradead.org (Kyungmin Park) Date: Thu, 6 May 2010 20:44:44 +0900 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: Hi, What's your chip version? maybe some mis-probe it seems to be probed at 4KiB pagesize OneNAND. Thank you, Kyungmin Park On Thu, May 6, 2010 at 8:22 PM, Enric Balletb? i Serra wrote: > Hi, > > 2010/5/6 Kyungmin Park : >> Hi, >> >> Can you add this statement at below the code? >> printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) >> onenand_addr(this, block), ((int) addr >> this->page_shift) & >> this->page_mask); > > Yes, > > With this code nandtest fails: > > onenand_base.c > > 377: ? ? default: > ? ? ? ? ? ? ? ?block = onenand_block(this, addr); > /* ?(line disabled) ? page = (int) (addr >> this->page_shift); */ > ? ? ? ? ? ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> > this->page_shift; > > ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, > page, (int) > ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> > this->page_shift) & > ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); > > ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { > ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ > ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; > ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ > ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; > ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?page &= this->page_mask; > ? ? ? ? ? ? ? ?break; > > > --- start log nandtest fail --- > # nandtest -l 262144 /dev/mtd3 > ECC corrections: 0 > ECC failures ? : 0 > Bad blocks ? ? : 0 > BBT blocks ? ? : 0 > 00000000: writing... > [ ?243.144287] onenand_command[382] page 0, 2621440, 0 > [ ?243.150787] onenand_command[382] page 2, 2621440, 2 > [ ?243.156158] onenand_command[382] page 4, 2621440, 4 > (...) > [ ?243.310729] onenand_command[382] page 60, 2621440, 60 > [ ?243.316223] onenand_command[382] page 62, 2621440, 62 > [ ?243.322204] onenand_command[382] page 0, 2752512, 0 > [ ?243.327636] onenand_command[382] page 2, 2752512, 2 > [ ?243.332977] onenand_command[382] page 4, 2752512, 4 > (...) > [ ?243.487487] onenand_command[382] page 60, 2752512, 60 > [ ?243.493041] onenand_command[382] page 62, 2752512, 62 > 00000000: reading... > [ ?243.498535] onenand_command[382] page 0, 2621440, 0 > [ ?243.505249] onenand_wait: ECC error = 0x8488 > [ ?243.509552] onenand_command[382] page 1, 2621440, 1 > [ ?243.514587] onenand_wait: ECC error = 0x8488 > [ ?243.518890] onenand_command[382] page 2, 2621440, 2 > (...) > [ ?244.089050] onenand_command[382] page 62, 2621440, 62 > [ ?244.094268] onenand_wait: ECC error = 0x8448 > [ ?244.098602] onenand_command[382] page 63, 2621440, 63 > [ ?244.103790] onenand_wait: ECC error = 0x8488 > [ ?244.109191] onenand_command[382] page 0, 2752512, 0 > [ ?244.114196] onenand_wait: ECC error = 0x8488 > [ ?244.118469] onenand_command[382] page 1, 2752512, 1 > [ ?244.123535] onenand_wait: ECC error = 0x8488 > [ ?244.127838] onenand_command[382] page 2, 2752512, 2 > (...) > [ ?244.698150] onenand_command[382] page 62, 2752512, 62 > [ ?244.703369] onenand_wait: ECC error = 0x8448 > [ ?244.707672] onenand_command[382] page 63, 2752512, 63 > [ ?244.712890] onenand_wait: ECC error = 0x8488 > > ECC failed at 00000000 > 00000000: checking... > compare failed. seed 1804289383 > Byte 0x1 is 5a should be da > Byte 0x3 is 82 should be 92 > Byte 0x4 is 10 should be 1a > Byte 0x5 is 21 should be b7 > > --- end log nandtest fail --- > > > With this other code nandtest pass > > onenand_base.c > > 377: ? ? default: > ? ? ? ? ? ? ? ?block = onenand_block(this, addr); > ? ? ? ? ? ? ? ?page = (int) (addr >> this->page_shift); > /* (line disabled) ?page = (int) (addr - onenand_addr(this, block)) >> > this->page_shift; */ > > ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, > page, (int) > ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> > this->page_shift) & > ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); > > ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { > ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ > ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; > ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ > ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; > ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?page &= this->page_mask; > ? ? ? ? ? ? ? ?break; > > --- start log nandtest pass --- > # nandtest -l 262144 /dev/mtd3 > ECC corrections: 0 > ECC failures ? : 33 > Bad blocks ? ? : 0 > BBT blocks ? ? : 0 > 00000000: writing... > [ 2024.624664] onenand_command[382] page 1280, 2621440, 0 > [ 2024.631530] onenand_command[382] page 1282, 2621440, 2 > [ 2024.637145] onenand_command[382] page 1284, 2621440, 4 > (...) > [ 2024.796813] onenand_command[382] page 1340, 2621440, 60 > [ 2024.802520] onenand_command[382] page 1342, 2621440, 62 > [ 2024.808593] onenand_command[382] page 1344, 2752512, 0 > [ 2024.814239] onenand_command[382] page 1346, 2752512, 2 > (...) > [ 2024.979644] onenand_command[382] page 1404, 2752512, 60 > [ 2024.985351] onenand_command[382] page 1406, 2752512, 62 > 00000000: reading... > [ 2024.990997] onenand_command[382] page 1280, 2621440, 0 > [ 2024.997985] onenand_command[382] page 1281, 2621440, 1 > [ 2025.003295] onenand_command[382] page 1282, 2621440, 2 > (...) > > [ 2025.326782] onenand_command[382] page 1342, 2621440, 62 > [ 2025.332214] onenand_command[382] page 1343, 2621440, 63 > [ 2025.338592] onenand_command[382] page 1344, 2752512, 0 > [ 2025.343811] onenand_command[382] page 1345, 2752512, 1 > [ 2025.349151] onenand_command[382] page 1346, 2752512, 2 > (...) > [ 2025.672576] onenand_command[382] page 1406, 2752512, 62 > [ 2025.677978] onenand_command[382] page 1407, 2752512, 63 > 00000000: checking... > Finished pass 1 successfully > --- end log nandtest pass --- > >> >> In my test environment, it displays the correct page number. >> (addr - onenand_addr(this, block) >> this->page_shift is same as >> '(addr >> this->page_shift) & this->page_mask'. >> > > Looks like page number is wrong ? > > Cheers, > > Enric > >> Thank you, >> Kyungmin Park >> >> On Fri, Apr 30, 2010 at 7:05 PM, Enric Balletb? i Serra >> wrote: >>> Hello all, >>> >>> After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: >>> Flex-OneNAND support) the onenand support for my device is broken. >>> >>> Before this commit when I run the nandtest program all is ok >>> --- >>> # nandtest /dev/mtd3 >>> ECC corrections: 0 >>> ECC failures ? : 0 >>> Bad blocks ? ? : 0 >>> BBT blocks ? ? : 0 >>> 002c0000: checking... >>> Finished pass 1 successfully >>> -- >>> >>> Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest >>> fails with: >>> --- >>> # nandtest /dev/mtd3 >>> ECC corrections: 0 >>> ECC failures ? : 0 >>> Bad blocks ? ? : 0 >>> BBT blocks ? ? : 0 >>> 00000000: reading... >>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>> ? ?( ... lots of ECC errors ... ) >>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>> ECC failed at 00000000 >>> 00000000: checking... >>> compare failed. seed 1804289383 >>> Byte 0x1 is 5a should be da >>> Byte 0x3 is 82 should be 92 >>> Byte 0x4 is 10 should be 1a >>> ? ?( ... ) >>> --- >>> >>> Investigating a little I see a significant difference introduced by >>> this patch. In line >>> >>> 347: ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >>> this->page_shift; ? (patch applied) >>> >>> instead of >>> >>> 347: ? ? ? ?page = (int) (addr >> this->page_shift); ?(without patch) >>> >>> I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced >>> the line 347 and now works again. Fantastic, but I suspect this is not >>> the proper solution (probably this breaks other onenands devices, I >>> can't test). >>> >>> I'm just introducing in OneNAND devices so anyone can help me to >>> understand and solve the problem ? Note that my device is a Numonyx >>> 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB >>> page ) >>> >>> Thanks in advance, >>> >>> ///:~Enric >>> >>> --- >>> diff --git a/drivers/mtd/onenand/onenand_base.c >>> b/drivers/mtd/onenand/onenand_base.c >>> index 081f97d..b1d50a3 100644 >>> --- a/drivers/mtd/onenand/onenand_base.c >>> +++ b/drivers/mtd/onenand/onenand_base.c >>> @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, >>> int cmd, loff_t addr, size_t le >>> >>> ? ? ? ?default: >>> ? ? ? ? ? ? ? ?block = (int) onenand_block(this, addr); >>> - ? ? ? ? ? ? ? page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; >>> + ? ? ? ? ? ? ? page = (int) (addr >> this->page_shift); >>> >>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>> --- >>> >>> ______________________________________________________ >>> Linux MTD discussion mailing list >>> http://lists.infradead.org/mailman/listinfo/linux-mtd/ >>> >> > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at ?http://vger.kernel.org/majordomo-info.html > From arno.steffen at googlemail.com Thu May 6 08:30:34 2010 From: arno.steffen at googlemail.com (Arno Steffen) Date: Thu, 6 May 2010 14:30:34 +0200 Subject: <4>mtd->read(x bytes from y) returned ECC error / Node header CRC failed / READ error Message-ID: After some powercycles I get sometimes messages like this: uncorrectable error : <3>uncorrectable error : <4>mtd->read(0x3f8 bytes from 0x25d8408) returned ECC error JFFS2 notice: (220) jffs2_get_inode_nodes: Node header CRC failed at 0x25d8408. {ffe0,ffe0,ffe0ffe0,ffe0ffe0} I do check a 30MB file wether it contains the original information, but reading/compare give holes of 2048bytes which gives "0" instead of its content. I don't access the jffs-fs with writes, just boot and read some files. In the next reboot everything is fine again. So what can I do, to prevent this? Or who can I ask? I am lost. From eballetbo at gmail.com Thu May 6 09:02:42 2010 From: eballetbo at gmail.com (=?UTF-8?Q?Enric_Balletb=C3=B2_i_Serra?=) Date: Thu, 6 May 2010 15:02:42 +0200 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: Hi, 2010/5/6 Kyungmin Park : > Hi, > > What's your chip version? maybe some mis-probe it seems to be probed > at 4KiB pagesize OneNAND. Is a 4-Gbit DDP OneNAND device from Numonyx composed of two 2-Gbit 2KB page dice stacked together, the device is equipped with two DataRAMs, and two-plane NAND Flash memory array, These two component enables simultaneous program of 4KiB ( CONFIG_MTD_ONENAND_2X_PROGRAM) Cheers, Enric > > Thank you, > Kyungmin Park > > On Thu, May 6, 2010 at 8:22 PM, Enric Balletb? i Serra > wrote: >> Hi, >> >> 2010/5/6 Kyungmin Park : >>> Hi, >>> >>> Can you add this statement at below the code? >>> printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) >>> onenand_addr(this, block), ((int) addr >> this->page_shift) & >>> this->page_mask); >> >> Yes, >> >> With this code nandtest fails: >> >> onenand_base.c >> >> 377: ? ? default: >> ? ? ? ? ? ? ? ?block = onenand_block(this, addr); >> /* ?(line disabled) ? page = (int) (addr >> this->page_shift); */ >> ? ? ? ? ? ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >> this->page_shift; >> >> ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, >> page, (int) >> ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> >> this->page_shift) & >> ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); >> >> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >> ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; >> ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ >> ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; >> ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; >> ? ? ? ? ? ? ? ?} >> ? ? ? ? ? ? ? ?page &= this->page_mask; >> ? ? ? ? ? ? ? ?break; >> >> >> --- start log nandtest fail --- >> # nandtest -l 262144 /dev/mtd3 >> ECC corrections: 0 >> ECC failures ? : 0 >> Bad blocks ? ? : 0 >> BBT blocks ? ? : 0 >> 00000000: writing... >> [ ?243.144287] onenand_command[382] page 0, 2621440, 0 >> [ ?243.150787] onenand_command[382] page 2, 2621440, 2 >> [ ?243.156158] onenand_command[382] page 4, 2621440, 4 >> (...) >> [ ?243.310729] onenand_command[382] page 60, 2621440, 60 >> [ ?243.316223] onenand_command[382] page 62, 2621440, 62 >> [ ?243.322204] onenand_command[382] page 0, 2752512, 0 >> [ ?243.327636] onenand_command[382] page 2, 2752512, 2 >> [ ?243.332977] onenand_command[382] page 4, 2752512, 4 >> (...) >> [ ?243.487487] onenand_command[382] page 60, 2752512, 60 >> [ ?243.493041] onenand_command[382] page 62, 2752512, 62 >> 00000000: reading... >> [ ?243.498535] onenand_command[382] page 0, 2621440, 0 >> [ ?243.505249] onenand_wait: ECC error = 0x8488 >> [ ?243.509552] onenand_command[382] page 1, 2621440, 1 >> [ ?243.514587] onenand_wait: ECC error = 0x8488 >> [ ?243.518890] onenand_command[382] page 2, 2621440, 2 >> (...) >> [ ?244.089050] onenand_command[382] page 62, 2621440, 62 >> [ ?244.094268] onenand_wait: ECC error = 0x8448 >> [ ?244.098602] onenand_command[382] page 63, 2621440, 63 >> [ ?244.103790] onenand_wait: ECC error = 0x8488 >> [ ?244.109191] onenand_command[382] page 0, 2752512, 0 >> [ ?244.114196] onenand_wait: ECC error = 0x8488 >> [ ?244.118469] onenand_command[382] page 1, 2752512, 1 >> [ ?244.123535] onenand_wait: ECC error = 0x8488 >> [ ?244.127838] onenand_command[382] page 2, 2752512, 2 >> (...) >> [ ?244.698150] onenand_command[382] page 62, 2752512, 62 >> [ ?244.703369] onenand_wait: ECC error = 0x8448 >> [ ?244.707672] onenand_command[382] page 63, 2752512, 63 >> [ ?244.712890] onenand_wait: ECC error = 0x8488 >> >> ECC failed at 00000000 >> 00000000: checking... >> compare failed. seed 1804289383 >> Byte 0x1 is 5a should be da >> Byte 0x3 is 82 should be 92 >> Byte 0x4 is 10 should be 1a >> Byte 0x5 is 21 should be b7 >> >> --- end log nandtest fail --- >> >> >> With this other code nandtest pass >> >> onenand_base.c >> >> 377: ? ? default: >> ? ? ? ? ? ? ? ?block = onenand_block(this, addr); >> ? ? ? ? ? ? ? ?page = (int) (addr >> this->page_shift); >> /* (line disabled) ?page = (int) (addr - onenand_addr(this, block)) >> >> this->page_shift; */ >> >> ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, >> page, (int) >> ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> >> this->page_shift) & >> ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); >> >> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >> ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; >> ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ >> ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; >> ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; >> ? ? ? ? ? ? ? ?} >> ? ? ? ? ? ? ? ?page &= this->page_mask; >> ? ? ? ? ? ? ? ?break; >> >> --- start log nandtest pass --- >> # nandtest -l 262144 /dev/mtd3 >> ECC corrections: 0 >> ECC failures ? : 33 >> Bad blocks ? ? : 0 >> BBT blocks ? ? : 0 >> 00000000: writing... >> [ 2024.624664] onenand_command[382] page 1280, 2621440, 0 >> [ 2024.631530] onenand_command[382] page 1282, 2621440, 2 >> [ 2024.637145] onenand_command[382] page 1284, 2621440, 4 >> (...) >> [ 2024.796813] onenand_command[382] page 1340, 2621440, 60 >> [ 2024.802520] onenand_command[382] page 1342, 2621440, 62 >> [ 2024.808593] onenand_command[382] page 1344, 2752512, 0 >> [ 2024.814239] onenand_command[382] page 1346, 2752512, 2 >> (...) >> [ 2024.979644] onenand_command[382] page 1404, 2752512, 60 >> [ 2024.985351] onenand_command[382] page 1406, 2752512, 62 >> 00000000: reading... >> [ 2024.990997] onenand_command[382] page 1280, 2621440, 0 >> [ 2024.997985] onenand_command[382] page 1281, 2621440, 1 >> [ 2025.003295] onenand_command[382] page 1282, 2621440, 2 >> (...) >> >> [ 2025.326782] onenand_command[382] page 1342, 2621440, 62 >> [ 2025.332214] onenand_command[382] page 1343, 2621440, 63 >> [ 2025.338592] onenand_command[382] page 1344, 2752512, 0 >> [ 2025.343811] onenand_command[382] page 1345, 2752512, 1 >> [ 2025.349151] onenand_command[382] page 1346, 2752512, 2 >> (...) >> [ 2025.672576] onenand_command[382] page 1406, 2752512, 62 >> [ 2025.677978] onenand_command[382] page 1407, 2752512, 63 >> 00000000: checking... >> Finished pass 1 successfully >> --- end log nandtest pass --- >> >>> >>> In my test environment, it displays the correct page number. >>> (addr - onenand_addr(this, block) >> this->page_shift is same as >>> '(addr >> this->page_shift) & this->page_mask'. >>> >> >> Looks like page number is wrong ? >> >> Cheers, >> >> Enric >> >>> Thank you, >>> Kyungmin Park >>> >>> On Fri, Apr 30, 2010 at 7:05 PM, Enric Balletb? i Serra >>> wrote: >>>> Hello all, >>>> >>>> After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: >>>> Flex-OneNAND support) the onenand support for my device is broken. >>>> >>>> Before this commit when I run the nandtest program all is ok >>>> --- >>>> # nandtest /dev/mtd3 >>>> ECC corrections: 0 >>>> ECC failures ? : 0 >>>> Bad blocks ? ? : 0 >>>> BBT blocks ? ? : 0 >>>> 002c0000: checking... >>>> Finished pass 1 successfully >>>> -- >>>> >>>> Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest >>>> fails with: >>>> --- >>>> # nandtest /dev/mtd3 >>>> ECC corrections: 0 >>>> ECC failures ? : 0 >>>> Bad blocks ? ? : 0 >>>> BBT blocks ? ? : 0 >>>> 00000000: reading... >>>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>>> ? ?( ... lots of ECC errors ... ) >>>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>>> ECC failed at 00000000 >>>> 00000000: checking... >>>> compare failed. seed 1804289383 >>>> Byte 0x1 is 5a should be da >>>> Byte 0x3 is 82 should be 92 >>>> Byte 0x4 is 10 should be 1a >>>> ? ?( ... ) >>>> --- >>>> >>>> Investigating a little I see a significant difference introduced by >>>> this patch. In line >>>> >>>> 347: ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >>>> this->page_shift; ? (patch applied) >>>> >>>> instead of >>>> >>>> 347: ? ? ? ?page = (int) (addr >> this->page_shift); ?(without patch) >>>> >>>> I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced >>>> the line 347 and now works again. Fantastic, but I suspect this is not >>>> the proper solution (probably this breaks other onenands devices, I >>>> can't test). >>>> >>>> I'm just introducing in OneNAND devices so anyone can help me to >>>> understand and solve the problem ? Note that my device is a Numonyx >>>> 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB >>>> page ) >>>> >>>> Thanks in advance, >>>> >>>> ///:~Enric >>>> >>>> --- >>>> diff --git a/drivers/mtd/onenand/onenand_base.c >>>> b/drivers/mtd/onenand/onenand_base.c >>>> index 081f97d..b1d50a3 100644 >>>> --- a/drivers/mtd/onenand/onenand_base.c >>>> +++ b/drivers/mtd/onenand/onenand_base.c >>>> @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, >>>> int cmd, loff_t addr, size_t le >>>> >>>> ? ? ? ?default: >>>> ? ? ? ? ? ? ? ?block = (int) onenand_block(this, addr); >>>> - ? ? ? ? ? ? ? page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; >>>> + ? ? ? ? ? ? ? page = (int) (addr >> this->page_shift); >>>> >>>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>>> --- >>>> >>>> ______________________________________________________ >>>> Linux MTD discussion mailing list >>>> http://lists.infradead.org/mailman/listinfo/linux-mtd/ >>>> >>> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >> the body of a message to majordomo at vger.kernel.org >> More majordomo info at ?http://vger.kernel.org/majordomo-info.html >> > From hartleys at visionengravers.com Thu May 6 12:47:16 2010 From: hartleys at visionengravers.com (H Hartley Sweeten) Date: Thu, 6 May 2010 11:47:16 -0500 Subject: [PATCH 2/2] Remove now-defunct ts7250 nand driver In-Reply-To: References: <201001051459.58621.hartleys@visionengravers.com><1262784693.3181.8034.camel@macbook.infradead.org><1262799737.3181.8388.camel@macbook.infradead.org> Message-ID: <0D753D10438DA54287A00B0270842697636ECB4D36@AUSP01VMBX24.collaborationhost.net> Hello David, Do you know the status of these two patches in linux-next: commit 7603757993e7ce3e63b2280ccf61d8058b7b2414 Author: H Hartley Sweeten Date: Tue Jan 5 14:59:58 2010 -0700 mtd: Remove now-defunct ts7250 nand driver The ts72xx platform has been updated to use the generic platform nand driver (plat_nand.c). This removes the now-defunct ts7250.c nand driver. Signed-off-by: H Hartley Sweeten Cc: Matthieu Crapet Cc: Jesse Off Signed-off-by: David Woodhouse commit 030d2dd450a628b7a8e31e980af3d05854f68edb Author: H Hartley Sweeten Date: Tue Jan 5 14:59:56 2010 -0700 mtd: Update ep93xx/ts72xx to use generic platform nand driver Update the ts72xx platform's nand driver support. This changes the ts72xx platform from using a custom nand driver (ts7250.c) to the generic platform nand driver (plat_nand.c). Tested on TS-7250 with 32MiB NAND. Signed-off-by: H Hartley Sweeten Tested-by: Matthieu Crapet Cc: Jesse Off Signed-off-by: David Woodhouse I have some pending patches for arch/arm/mach-ep93xx/ts72xx.c that depend on these. Thanks, Hartley From dedekind1 at gmail.com Fri May 7 01:34:39 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 08:34:39 +0300 Subject: [PATCH 1/2] UBI: Fix s/then/than/ typos In-Reply-To: <4BE2983B.4090605@renesas.com> References: <4BE29771.4050800@renesas.com> <4BE2983B.4090605@renesas.com> Message-ID: <1273210479.2178.1.camel@localhost> On Thu, 2010-05-06 at 19:21 +0900, Shinya Kuribayashi wrote: > Signed-off-by: Shinya Kuribayashi > --- > Nothing's changed, just resent with correcting Tb3's settings. > > drivers/mtd/ubi/Kconfig | 2 +- > drivers/mtd/ubi/io.c | 2 +- > drivers/mtd/ubi/kapi.c | 6 +++--- > drivers/mtd/ubi/scan.c | 4 ++-- > drivers/mtd/ubi/wl.c | 2 +- > 5 files changed, 8 insertions(+), 8 deletions(-) Pushed both patches to the ubi-2.6.git tree, thanks! -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Fri May 7 01:37:31 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 08:37:31 +0300 Subject: [PATCH 2/4] UBI: introduce a new IO return code In-Reply-To: <20100506093440.GA15335@Chamillionaire.breakpoint.cc> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> <1272881582-17196-3-git-send-email-Artem.Bityutskiy@nokia.com> <20100506093440.GA15335@Chamillionaire.breakpoint.cc> Message-ID: <1273210651.2178.2.camel@localhost> On Thu, 2010-05-06 at 11:34 +0200, Sebastian Andrzej Siewior wrote: > * Artem Bityutskiy | 2010-05-03 13:13:00 [+0300]: > > >diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c > >index f52adca..65d03b5 100644 > >--- a/drivers/mtd/ubi/scan.c > >+++ b/drivers/mtd/ubi/scan.c > >@@ -745,7 +745,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, > > bitflips = 1; > > else if (err == UBI_IO_PEB_EMPTY) > > return add_to_list(si, pnum, UBI_SCAN_UNKNOWN_EC, &si->erase); > >- else if (err == UBI_IO_BAD_HDR) { > >+ else if (err = UBI_IO_BAD_HDR_READ || err == UBI_IO_BAD_HDR) { > > That part should be == and not = but you fix this in the next patch so I > guess it is okay. Fixed this in the wrong patch, I'll amend them and make sure this typo goes away, thanks. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Fri May 7 01:39:53 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 08:39:53 +0300 Subject: [PATCH 0/4] UBI: improve empty flash handling In-Reply-To: <20100506095218.GB15335@Chamillionaire.breakpoint.cc> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> <20100506095218.GB15335@Chamillionaire.breakpoint.cc> Message-ID: <1273210793.2178.4.camel@localhost> On Thu, 2010-05-06 at 11:52 +0200, Sebastian Andrzej Siewior wrote: > * Artem Bityutskiy | 2010-05-03 13:12:58 [+0300]: > > >Hi Sebastian, > Hi Artem, > > >Please, review and test the following series. > > The code looks fine. I wiped the flash and the test resulted in: Thanks, I'll push this to the ubi-2.6.git tree shortly. Will add Reviewed-by: Sebastian Andrzej Siewior Tested-by: Sebastian Andrzej Siewior If you object, please, let me know and I'll amend the tags. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Fri May 7 01:57:53 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 08:57:53 +0300 Subject: [PATCH 0/4] UBI: improve empty flash handling In-Reply-To: <20100506095218.GB15335@Chamillionaire.breakpoint.cc> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> <20100506095218.GB15335@Chamillionaire.breakpoint.cc> Message-ID: <1273211873.2178.7.camel@localhost> On Thu, 2010-05-06 at 11:52 +0200, Sebastian Andrzej Siewior wrote: > * Artem Bityutskiy | 2010-05-03 13:12:58 [+0300]: > > >Hi Sebastian, > Hi Artem, > > >Please, review and test the following series. > > The code looks fine. I wiped the flash and the test resulted in: Pushed the patches to the master branch so far. If everything is allright, I'll push them to linux-next in few days. This is because I can amend patches which are in the master branch (i.e., rebase the git tree), but when they go to linux-next, I try hard to avoid any re-basing. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Fri May 7 02:01:09 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 09:01:09 +0300 Subject: [PATCH 2/2] Remove now-defunct ts7250 nand driver In-Reply-To: <0D753D10438DA54287A00B0270842697636ECB4D36@AUSP01VMBX24.collaborationhost.net> References: <201001051459.58621.hartleys@visionengravers.com> <1262784693.3181.8034.camel@macbook.infradead.org> <1262799737.3181.8388.camel@macbook.infradead.org> <0D753D10438DA54287A00B0270842697636ECB4D36@AUSP01VMBX24.collaborationhost.net> Message-ID: <1273212069.2178.9.camel@localhost> On Thu, 2010-05-06 at 11:47 -0500, H Hartley Sweeten wrote: > Hello David, > > Do you know the status of these two patches in linux-next: I'm not David, but I think I know the answer. Last merge window was missed and the mtd tree was not merged, so the patches are waiting for the next merge window and will be merged. [snip] > I have some pending patches for arch/arm/mach-ep93xx/ts72xx.c that > depend on these. Just send your depending patches. -- Best Regards, Artem Bityutskiy (????? ????????) From arno.steffen at googlemail.com Fri May 7 05:45:57 2010 From: arno.steffen at googlemail.com (Arno Steffen) Date: Fri, 7 May 2010 11:45:57 +0200 Subject: <4>mtd->read(x bytes from y) returned ECC error / Node header CRC failed / READ error In-Reply-To: References: Message-ID: Thanks for this tip! For the first I have mounted the jffs2 (rootfs) as read only (confirmed by a "VFS: Mounted root (jffs2 filesystem) readonly message"). The behaviour is still the same. So does it makes a difference to set WriteProtection? The other question - if this is some selfhealing issue (as messages dissapear in next boot), why it will not try to heal itself right on time? Is it possible to force this? I cound't found a fitting option in kernel config (at least not one I would understood). Regards Arno 2010/5/6 Darwin Rambo : > Some flashes have write-protect (WP) pins that can be strapped to prevent writing as the power is being lost. This dramatically reduces flash corruption on power cycles. > > Darwin > >> -----Original Message----- >> From: linux-mtd-bounces at lists.infradead.org [mailto:linux-mtd- >> bounces at lists.infradead.org] On Behalf Of Arno Steffen >> Sent: Thursday, May 06, 2010 5:31 AM >> To: linux-mtd at lists.infradead.org >> Subject: <4>mtd->read(x bytes from y) returned ECC error / Node header >> CRC failed / READ error >> >> After some powercycles I get sometimes messages like this: >> >> uncorrectable error : <3>uncorrectable error : <4>mtd->read(0x3f8 >> bytes from 0x25d8408) returned ECC error >> JFFS2 notice: (220) jffs2_get_inode_nodes: Node header CRC failed at >> 0x25d8408. {ffe0,ffe0,ffe0ffe0,ffe0ffe0} >> >> I do check a 30MB file wether it contains the original information, >> but reading/compare give holes of 2048bytes which gives "0" instead of >> its content. >> >> I don't access the jffs-fs with writes, just boot and read some files. >> >> In the next reboot everything is fine again. So what can I do, to >> prevent this? >> >> Or who can I ask? I am lost. >> >> ______________________________________________________ >> Linux MTD discussion mailing list >> http://lists.infradead.org/mailman/listinfo/linux-mtd/ > > > From daniel at caiaq.de Fri May 7 06:20:22 2010 From: daniel at caiaq.de (Daniel Mack) Date: Fri, 7 May 2010 12:20:22 +0200 Subject: [PATCH 01/20] pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: Message-ID: <20100507102022.GL30801@buzzloop.caiaq.de> Hi, I'd like to test this, but ... On Thu, May 06, 2010 at 05:01:22AM -0400, Haojian Zhuang wrote: > From 135f6369a9c045e58d2cfa445c72bae2bbc645cd Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Sat, 20 Mar 2010 19:01:23 +0800 > Subject: [PATCH] pxa3xx_nand: refuse the flash definition get from platform > > For current usage, it is little reason to use a platform defined flash info > for the flash detection. Flash timing through platform should be the same. > And allow multiple platform to define the same flash chip would be a waste. > > Also condense the flash definition way in the c file to simplify adding a > new chip. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 40 ---- > drivers/mtd/nand/Kconfig | 7 - > drivers/mtd/nand/pxa3xx_nand.c | 251 ++++++-------------------- > 3 files changed, 60 insertions(+), 238 deletions(-) > [...] > +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { > +{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, > +{ 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, > 60, 10, }, }, > +{ 0xdc2c, 64, 2048, 8, 8, 4096, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, > +{ 0xcc2c, 64, 2048, 16, 16, 4096, { 10, 25, 15, 25, 15, 30, 25000, > 60, 10, }, }, That series is line-wrapped. Could you fix this and resend please? Daniel From haojian.zhuang at gmail.com Fri May 7 06:26:59 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 7 May 2010 06:26:59 -0400 Subject: [PATCH 01/20] pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <20100507102022.GL30801@buzzloop.caiaq.de> References: <20100507102022.GL30801@buzzloop.caiaq.de> Message-ID: On Fri, May 7, 2010 at 6:20 AM, Daniel Mack wrote: > Hi, > > I'd like to test this, but ... > > On Thu, May 06, 2010 at 05:01:22AM -0400, Haojian Zhuang wrote: >> From 135f6369a9c045e58d2cfa445c72bae2bbc645cd Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Sat, 20 Mar 2010 19:01:23 +0800 >> Subject: [PATCH] pxa3xx_nand: refuse the flash definition get from platform >> >> For current usage, it is little reason to use a platform defined flash info >> for the flash detection. Flash timing through platform should be the same. >> And allow multiple platform to define the same flash chip would be a waste. >> >> Also condense the flash definition way in the c file to simplify adding a >> new chip. >> >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 40 ---- >> ?drivers/mtd/nand/Kconfig ? ? ? ? ? ? ? ? ? ? | ? ?7 - >> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?251 ++++++-------------------- >> ?3 files changed, 60 insertions(+), 238 deletions(-) >> > > [...] > >> +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { >> +{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, >> +{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, >> +{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, >> +{ 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, >> +{ 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, >> 60, 10, }, }, >> +{ 0xdc2c, 64, 2048, 8, 8, 4096, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, >> +{ 0xcc2c, 64, 2048, 16, 16, 4096, { 10, 25, 15, 25, 15, 30, 25000, >> 60, 10, }, }, > > That series is line-wrapped. Could you fix this and resend please? > > Daniel > > Now I attached these patches. Try these. Thanks Haojian -------------- next part -------------- A non-text attachment was scrubbed... Name: pxa3xx_nand.tgz Type: application/x-gzip Size: 43457 bytes Desc: not available URL: From daniel at caiaq.de Fri May 7 09:16:52 2010 From: daniel at caiaq.de (Daniel Mack) Date: Fri, 7 May 2010 15:16:52 +0200 Subject: UBIFS: Oops while rebooting 2.6.34-rc6 Message-ID: <20100507131652.GT30801@buzzloop.caiaq.de> Hi, We've had a kernel Oops today when rebooting an ARM PXA based machine while file I/O via SSH was outstanding. Daniel # reboot # [ 671.190085] UBIFS: un-mount UBI device 0, volume 1 The system is going down NOW! Sent SIGTERM to all processes [ 672.083833] Unable to handle kernel NULL pointer dereference at virtual address 000000ac [ 672.094587] pgd = c0004000 [ 672.097301] [000000ac] *pgd=00000000 [ 672.100850] Internal error: Oops: 817 [#1] [ 672.104919] last sysfs file: /sys/devices/platform/spi_gpio.0/spi0.2/value [ 672.111741] Modules linked in: eeti_ts libertas_sdio libertas pxamci ds2760_battery w1_ds2760 wire [ 672.120641] CPU: 0 Tainted: G W (2.6.34-rc6 #154) [ 672.126376] PC is at mutex_lock+0x4/0x14 [ 672.130291] LR is at make_reservation+0x74/0x328 [ 672.134880] pc : [] lr : [] psr: 60000013 [ 672.134890] sp : c775fd18 ip : 00000088 fp : 000000ac [ 672.146281] r10: 00000000 r9 : 00000000 r8 : c7eb8000 [ 672.151469] r7 : 00000088 r6 : c7a68310 r5 : c7eb8000 r4 : 00000001 [ 672.157947] r3 : 00000000 r2 : 00000000 r1 : 00000000 r0 : 000000ac [ 672.164429] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel [ 672.171691] Control: 0000397f Table: a7f54018 DAC: 00000035 [ 672.177394] Process flush-ubifs_0_0 (pid: 1289, stack limit = 0xc775e278) [ 672.184131] Stack: (0xc775fd18 to 0xc7760000) [ 672.188458] fd00: c7f5ea00 00000000 [ 672.196588] fd20: 00000000 c775fde0 c7f6c000 000000a0 00000001 c7eb8144 00000000 c775e000 [ 672.204721] fd40: 00000001 00000088 00000004 00000000 00000004 c7a68310 c7eb8000 c7a68310 [ 672.212853] fd60: 00000000 000000a0 c6894180 00000000 00000000 c0143aa4 c775fde0 000006d0 [ 672.220978] fd80: 0000a1e0 c7eb8000 c775fdb4 c015634c 00000001 00000080 c7a68310 00000001 [ 672.229111] fda0: c7a68458 c7eb8000 00000000 00000000 00000063 c01489b0 c775fe74 c0085400 [ 672.237245] fdc0: c775e000 c775e000 c7a68310 c0558b00 00000063 c014559c c7a683ac c7a683ac [ 672.245377] fde0: 00000001 c775fef0 00000400 00000000 ffffffff c775fe34 00000000 c008b2e4 [ 672.253510] fe00: c0558b00 c008bb3c 0000000e c00865b4 00000007 ffffffff c7a683ac c008b2d0 [ 672.261642] fe20: c7a683ac 00000001 00000001 00000001 c775fe5c 00000001 00000000 c0558b00 [ 672.269767] fe40: c062cf40 c062cf60 c0629080 c06290a0 c06290c0 c06290e0 c062cd60 00000000 [ 672.277900] fe60: c062d0a0 00006872 00000000 c775fef0 00000000 00000001 c04eb4f8 00000007 [ 672.286034] fe80: c7a68310 c775fef0 c7eb8068 c7a683ac c04eb4f8 c775fef0 c7eb8088 c00c3f28 [ 672.294166] fea0: 00000000 c7a68310 00000000 c7eb8068 c7e12600 c00c4b48 c0246d3c c7eb8090 [ 672.302298] fec0: c7ac17b0 c7a68318 c7eb8068 00000000 c7eb8090 c0537a6c c775fef0 00000400 [ 672.310431] fee0: c775ff60 00000000 c7eb8068 c00c4d98 c7eb8008 00000000 00000000 00000000 [ 672.318555] ff00: 0000a277 00000400 00000000 00000000 00000000 00000000 ffffffff 7fffffff [ 672.326680] ff20: 00000000 00000000 c035b804 c0053aa8 c04f1f08 c04f1dbc c77a9f04 c68958c0 [ 672.334813] ff40: c7eb8068 0000a270 c775ff60 00000000 00000000 c7eb80a8 00000001 c00c4f74 [ 672.342944] ff60: 00000009 00000000 00000000 00000000 00000000 000001f4 c775e000 0000a270 [ 672.351070] ff80: c7eb8068 c04eb4f8 c04f22b0 0000000a 00007530 c00c50e0 00000000 c7eb8008 [ 672.359202] ffa0: c7eb8068 c7eb8068 c0095e18 00000000 00000000 00000000 00000000 c0095ec0 [ 672.367328] ffc0: c775ffd4 c7c4bf2c c7eb8068 c006ac50 00000000 00000000 c775ffd8 c775ffd8 [ 672.375459] ffe0: 00000000 00000000 00000000 00000000 00000000 c00458bc 5f455349 48504943 [ 672.383609] [] (mutex_lock+0x4/0x14) from [] (make_reservation+0x74/0x328) [ 672.392184] [] (make_reservation+0x74/0x328) from [] (ubifs_jnl_write_inode+0x80/0x1b8) [ 672.401871] [] (ubifs_jnl_write_inode+0x80/0x1b8) from [] (ubifs_write_inode+0x64/0xc4) [ 672.411554] [] (ubifs_write_inode+0x64/0xc4) from [] (ubifs_writepage+0x124/0x15c) [ 672.420830] [] (ubifs_writepage+0x124/0x15c) from [] (__writepage+0x14/0x64) [ 672.429572] [] (__writepage+0x14/0x64) from [] (write_cache_pages+0x1e4/0x2c0) [ 672.438498] [] (write_cache_pages+0x1e4/0x2c0) from [] (writeback_single_inode+0xd4/0x2b8) [ 672.448447] [] (writeback_single_inode+0xd4/0x2b8) from [] (writeback_inodes_wb+0x434/0x52c) [ 672.458568] [] (writeback_inodes_wb+0x434/0x52c) from [] (wb_writeback+0x158/0x1cc) [ 672.467907] [] (wb_writeback+0x158/0x1cc) from [] (wb_do_writeback+0x64/0x198) [ 672.476815] [] (wb_do_writeback+0x64/0x198) from [] (bdi_writeback_task+0x38/0xbc) [ 672.486084] [] (bdi_writeback_task+0x38/0xbc) from [] (bdi_start_fn+0xa8/0xf8) [ 672.495009] [] (bdi_start_fn+0xa8/0xf8) from [] (kthread+0x78/0x80) [ 672.502992] [] (kthread+0x78/0x80) from [] (kernel_thread_exit+0x0/0x8) [ 672.511293] Code: 05843000 e28dd010 e8bd81f0 e3a02000 (e1001092) [ 672.517534] ---[ end trace f5c79b7be5adbe31 ]--- Sent SIGKILL to all processes Requesting system reboot[ 674.543613] Restarting system. From dedekind1 at gmail.com Fri May 7 11:12:34 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 18:12:34 +0300 Subject: UBIFS: Oops while rebooting 2.6.34-rc6 In-Reply-To: <20100507131652.GT30801@buzzloop.caiaq.de> References: <20100507131652.GT30801@buzzloop.caiaq.de> Message-ID: <1273245154.4537.288.camel@localhost> Good Evening, On Fri, 2010-05-07 at 15:16 +0200, Daniel Mack wrote: > We've had a kernel Oops today when rebooting an ARM PXA based machine > while file I/O via SSH was outstanding. > > Daniel > > # reboot > # [ 671.190085] UBIFS: un-mount UBI device 0, volume 1 > The system is going down NOW! > Sent SIGTERM to all processes > [ 672.083833] Unable to handle kernel NULL pointer dereference at virtual address 000000ac > [ 672.094587] pgd = c0004000 > [ 672.097301] [000000ac] *pgd=00000000 > [ 672.100850] Internal error: Oops: 817 [#1] > [ 672.104919] last sysfs file: /sys/devices/platform/spi_gpio.0/spi0.2/value > [ 672.111741] Modules linked in: eeti_ts libertas_sdio libertas pxamci ds2760_battery w1_ds2760 wire > [ 672.120641] CPU: 0 Tainted: G W (2.6.34-rc6 #154) > [ 672.126376] PC is at mutex_lock+0x4/0x14 > [ 672.130291] LR is at make_reservation+0x74/0x328 Hi, is this reproducible? It looks like this came from: journal.c:127: mutex_lock_nested(&wbuf->io_mutex, wbuf->jhead); May be memory corruption? Did you try to see where exectly was the oops, on which C statement? Do you have lockdep enabled? Can it be that lockdep somehow shutdown first? This is unlikely, though. May be the FS was somehow unmounted, so UBIFS freed its data structures, and now UBIFS accesses freed memory? Try to inject some printks to ubifs_umount() or just enable the general UBIFS messages (enable UBIFS debugging in menuconfig first, then enable the general messages via module parameters or sysfs, see Documentation/filesystems/ubifs.txt). -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Fri May 7 11:23:46 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 07 May 2010 18:23:46 +0300 Subject: UBIFS: Oops while rebooting 2.6.34-rc6 In-Reply-To: <20100507131652.GT30801@buzzloop.caiaq.de> References: <20100507131652.GT30801@buzzloop.caiaq.de> Message-ID: <1273245826.4537.294.camel@localhost> On Fri, 2010-05-07 at 15:16 +0200, Daniel Mack wrote: > Hi, > > We've had a kernel Oops today when rebooting an ARM PXA based machine > while file I/O via SSH was outstanding. > > Daniel > > # reboot > # [ 671.190085] UBIFS: un-mount UBI device 0, volume 1 > The system is going down NOW! > Sent SIGTERM to all processes > [ 672.083833] Unable to handle kernel NULL pointer dereference at virtual address 000000ac > [ 672.094587] pgd = c0004000 > [ 672.097301] [000000ac] *pgd=00000000 > [ 672.100850] Internal error: Oops: 817 [#1] > [ 672.104919] last sysfs file: /sys/devices/platform/spi_gpio.0/spi0.2/value It's Firday, and I want to go home, so here is another quick idea for you where to dig. When the system reboots it re-mounts the FS to RO mode, usually. And there is some emergency remount business (see do_emergency_remount()), which will re-mount the FS even if there are files opened for writing. So, if there is a UBIFS or VFS bug, and somehow one process is in make_reservation() and is about to write something, and another process managed to re-mount the FS to R/O mode, then we may ooops, because UBIFS frees these 'wbuf' objects when it is mounted to R/O (see ubifs_remount_ro()). So, inject printks to ubifs_remount_ro() to check this theory. Have a nice weekend and bughunting! -- Best Regards, Artem Bityutskiy (????? ????????) From daniel at caiaq.de Fri May 7 11:26:40 2010 From: daniel at caiaq.de (Daniel Mack) Date: Fri, 7 May 2010 17:26:40 +0200 Subject: UBIFS: Oops while rebooting 2.6.34-rc6 In-Reply-To: <1273245826.4537.294.camel@localhost> References: <20100507131652.GT30801@buzzloop.caiaq.de> <1273245826.4537.294.camel@localhost> Message-ID: <20100507152640.GX30801@buzzloop.caiaq.de> On Fri, May 07, 2010 at 06:23:46PM +0300, Artem Bityutskiy wrote: > On Fri, 2010-05-07 at 15:16 +0200, Daniel Mack wrote: > > Hi, > > > > We've had a kernel Oops today when rebooting an ARM PXA based machine > > while file I/O via SSH was outstanding. > > > > Daniel > > > > # reboot > > # [ 671.190085] UBIFS: un-mount UBI device 0, volume 1 > > The system is going down NOW! > > Sent SIGTERM to all processes > > [ 672.083833] Unable to handle kernel NULL pointer dereference at virtual address 000000ac > > [ 672.094587] pgd = c0004000 > > [ 672.097301] [000000ac] *pgd=00000000 > > [ 672.100850] Internal error: Oops: 817 [#1] > > [ 672.104919] last sysfs file: /sys/devices/platform/spi_gpio.0/spi0.2/value > > It's Firday, and I want to go home, so here is another quick idea for > you where to dig. > > When the system reboots it re-mounts the FS to RO mode, usually. And > there is some emergency remount business (see do_emergency_remount()), > which will re-mount the FS even if there are files opened for writing. > > So, if there is a UBIFS or VFS bug, and somehow one process is in > make_reservation() and is about to write something, and another process > managed to re-mount the FS to R/O mode, then we may ooops, because UBIFS > frees these 'wbuf' objects when it is mounted to R/O (see > ubifs_remount_ro()). > > So, inject printks to ubifs_remount_ro() to check this theory. > > Have a nice weekend and bughunting! Thanks for your feedback - I'll give that a try next week. Have a good weekend :) Daniel From broonie at opensource.wolfsonmicro.com Fri May 7 11:58:22 2010 From: broonie at opensource.wolfsonmicro.com (Mark Brown) Date: Fri, 7 May 2010 16:58:22 +0100 Subject: [PATCH] UBI: Fix s/then/than/ typos In-Reply-To: <1273130495.3702.205.camel@localhost> References: <4BE23A03.1030001@renesas.com> <4BE23A6F.1010406@renesas.com> <1273128444.3702.202.camel@localhost> <4BE26A87.4030206@renesas.com> <1273130495.3702.205.camel@localhost> Message-ID: <20100507155821.GB3425@sirena.org.uk> On Thu, May 06, 2010 at 10:21:35AM +0300, Artem Bityutskiy wrote: > AFAIK, format=flowed is just about displaying quoted text, not changing > the contents. No, it affects all text - it allows the MUA to re-wrap text in paragraphs to fit within the display regardless of the original line wrapping. It's very useful for human languages but unfortunate for patches. From hartleys at visionengravers.com Fri May 7 12:37:58 2010 From: hartleys at visionengravers.com (H Hartley Sweeten) Date: Fri, 7 May 2010 11:37:58 -0500 Subject: [PATCH 2/2] Remove now-defunct ts7250 nand driver In-Reply-To: <1273212069.2178.9.camel@localhost> References: <201001051459.58621.hartleys@visionengravers.com> <1262784693.3181.8034.camel@macbook.infradead.org> <1262799737.3181.8388.camel@macbook.infradead.org> <0D753D10438DA54287A00B0270842697636ECB4D36@AUSP01VMBX24.collaborationhost.net> <1273212069.2178.9.camel@localhost> Message-ID: <0D753D10438DA54287A00B0270842697636ED546A3@AUSP01VMBX24.collaborationhost.net> On Thursday, May 06, 2010 11:01 PM, Artem Bityutskiy wrote: > On Thu, 2010-05-06 at 11:47 -0500, H Hartley Sweeten wrote: >> Hello David, >> >> Do you know the status of these two patches in linux-next: > > I'm not David, but I think I know the answer. Last merge window was > missed and the mtd tree was not merged, so the patches are waiting for > the next merge window and will be merged. Hello Artem, Ah, thought that was the issue. It did appear that the mtd tree didn't get merged. > [snip] >> I have some pending patches for arch/arm/mach-ep93xx/ts72xx.c that >> depend on these. > > Just send your depending patches. I'll hold until this gets merged (or dropped if that happens). The patches are intended for the arm tree and I want to avoid any merge issues. Thanks for the update, Hartley From florian at openwrt.org Fri May 7 13:09:13 2010 From: florian at openwrt.org (Florian Fainelli) Date: Fri, 7 May 2010 19:09:13 +0200 Subject: [PATCH] NAND: add Toshiba TC58NVG0 device ID Message-ID: <201005071909.13259.florian@openwrt.org> This NAND flash part advertises 0xD1 as an identifier but is still a working 128MBytes x 8bits 3.3V NAND part. Signed-off-by: Florian Fainelli --- diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index 69ee2c9..89907ed 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c @@ -82,6 +82,7 @@ struct nand_flash_dev nand_flash_ids[] = { /* 1 Gigabit */ {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS}, + {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, From drambo at broadcom.com Fri May 7 16:45:14 2010 From: drambo at broadcom.com (Darwin Rambo) Date: Fri, 7 May 2010 13:45:14 -0700 Subject: <4>mtd->read(x bytes from y) returned ECC error / Node header CRC failed / READ error In-Reply-To: References: Message-ID: > For the first I have mounted the jffs2 (rootfs) as read only > (confirmed by a "VFS: Mounted root (jffs2 filesystem) readonly > message"). > The behaviour is still the same. So does it makes a difference to set > WriteProtection? > The other question - if this is some selfhealing issue (as messages > dissapear in next boot), why it will not try to heal itself right on > time? Is it possible to force this? > I cound't found a fitting option in kernel config (at least not one I > would understood). Sorry, I missed that. My comment was for writable file systems. > From brijesh.s.singh at gmail.com Sat May 8 15:39:47 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Sun, 9 May 2010 01:09:47 +0530 Subject: UBIL design doc Message-ID: Hi, ? I am forwarding you the design document for ubi with log. Please find the ubil document at http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL design document.pdf Thanks and Regards, Brijesh -------------- next part -------------- A non-text attachment was scrubbed... Name: UBIL design document.pdf Type: application/pdf Size: 353657 bytes Desc: not available URL: From dedekind1 at gmail.com Mon May 10 02:49:35 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 10 May 2010 09:49:35 +0300 Subject: Release of UBIL: ubi with log In-Reply-To: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> References: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> Message-ID: <1273474175.2209.61.camel@localhost> On Fri, 2010-02-26 at 18:28 +0530, Brijesh Singh wrote: > Hi, > It gives me great pleasure in sharing UBIL: ubi with log. We have > added logging functionality to ubi for reducing mount time. > UBIL uses the "same source base of UBI". The logging functionality can > be added or removed at compile time using "make menuconfig option". > > We have seen mount time reduction of 50% in 1GB NAND. We are expecting > even better results for larger flash memories. Was that SLC or MLC NAND? > The source code of UBIL can be found in the following git tree: > http://git.infradead.org/users/brijesh/ubi-2.6.git > > We have tested ubil for samsung nand and onenand. The test results can > be found in the following git tree: > http://git.infradead.org/users/brijesh/ubil_results Did you run any stress tests for UBIL? Which? I think it is very important to stress test it and make sure is stable. After that, we can start doing changes required for upstreaming it. I propose the following roadmap: The main idea is to make UBIL as stable as possible first. Then, make sure whatever change we introduce - it stays stable. IOW, run tests after each change and make sure nothing breaks. With this test-driven scheme we can add all the needed improvements and keep it working. > We are working on utilities and design document of UBIL. I will share > those as soon as possible. > > If someone wants to try, please follow the instructions: > make menuconfig > select ubi as module > select ubil feature. > compile ubi module. I think UBIL should not be compiled separately. UBI should automatically detect the format type. > 1) First mount of ubil is little different than ubi. > > insmod ubi mtd=1,ubinize. > (Second parameter "ubinize" is introduced to avoid accidental loss of data.) > insmod ubifs > mount ubifs Why this ubinize parameter exists? Why you cannot detect empty media just like UBI? > 2)For next mounts: > insmod ubi mtd=1 > insmod ubifs > mount ubifs > > Though UBIL is functionally complete,there is a lot of scope for > optimizations. All the help is very much appreciated. The main requirement for upstreaming is to make sure the on-flash format is stable. Once you are in upstream - you cannot change your on-flash data structures anymore. Any change will become huge PITA. Thus, it is very important to think carefully about on-flash format, and possibly invent mechanisms for future extensions. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Mon May 10 03:15:36 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 10 May 2010 10:15:36 +0300 Subject: UBIL design doc In-Reply-To: References: Message-ID: <1273475736.2209.88.camel@localhost> On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: > Hi, > I am forwarding you the design document for ubi with log. Please > find the ubil document at > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL > design document.pdf Hi guys, I've read the document. Looks very promising. Here some feed-back. 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 erease cycles? Won't the SB PEB wear out very quickly? Why you did not go for the chaining approach which I described in the old JFFS3 design doc? If we do not implement chaining, we should at least design it and make sure UBIL can be extended later so that SB chaining could be added. 2. SB PEB at the end. I think this is a very bad idea. Imagine you have to do UBIL images for production on the factory. With your design you have the following bad drawbacks: a. NAND flash has initial bad blocks, and you do not know how many, and where they sit. These may be the last 8 eraseblocks. So, when you prepare an image (say, with the ubinize user-space tool), where will you put the second SB PEB? b. Currently, UBI/UBIFS images are small. E.g., if you make an UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, your image will be few megs - it will contain the files, and all the needed UBI/UBIFS meta-data. So now what will be image size for UBIL - 1GiB, and this is bad. You then will transfer 1GiB of data to the devices during flashing or you will have to invent ways to work around this. Do you need these complexities? I think the second SB PEB should not be at the end. 3. Backward-compatibility. In UBIL you removed EC anc VID headers in PEBs. That's fine for optimization purposes. But it has draw-backs: a. If any of the UBIL meta-data blocks like SB, CMT or log are corrupted - that's it - we are screwed. You cannot anymore re-consturct the data by scanning. The robustness goes down. c. Backward compatibility - UBI will not be able to attach UBIL images. This is not very nice. So, I think you should keep EC and VID headers in PEBs. And you should make the SB/CMT/log blocks to be a new type of UBI volume with UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this case UBI will attach UBIL volumes just fine. Then, you can add an _option_ to have no EC/VID headers in PEBs. This then can be used for performance, if one wants to sacrifice robustness. But this should be the second step. In this case, you will just need to put a VID header with UBI_COMPAT_REJECT flag to the first PEB. I have some more notes, but these 3 are enough for now. What do you think? In any case, whatever you will try to change in UBIL, remember to make it stable as it is now first, then do all changes so that you do not break it. -- Best Regards, Artem Bityutskiy (????? ????????) From adrian.hunter at nokia.com Mon May 10 03:46:54 2010 From: adrian.hunter at nokia.com (Adrian Hunter) Date: Mon, 10 May 2010 10:46:54 +0300 Subject: UBIFS: Oops while rebooting 2.6.34-rc6 In-Reply-To: <20100507131652.GT30801@buzzloop.caiaq.de> References: <20100507131652.GT30801@buzzloop.caiaq.de> Message-ID: <4BE7B9EE.8040806@nokia.com> Daniel Mack wrote: > Hi, > > We've had a kernel Oops today when rebooting an ARM PXA based machine > while file I/O via SSH was outstanding. It could be that VFS un-mounting has been broken. For example, it looks like perhaps writeback is being run by bdi_destroy after the file system has been unmounted? > > Daniel > > # reboot > # [ 671.190085] UBIFS: un-mount UBI device 0, volume 1 > The system is going down NOW! > Sent SIGTERM to all processes > [ 672.083833] Unable to handle kernel NULL pointer dereference at virtual address 000000ac > [ 672.094587] pgd = c0004000 > [ 672.097301] [000000ac] *pgd=00000000 > [ 672.100850] Internal error: Oops: 817 [#1] > [ 672.104919] last sysfs file: /sys/devices/platform/spi_gpio.0/spi0.2/value > [ 672.111741] Modules linked in: eeti_ts libertas_sdio libertas pxamci ds2760_battery w1_ds2760 wire > [ 672.120641] CPU: 0 Tainted: G W (2.6.34-rc6 #154) > [ 672.126376] PC is at mutex_lock+0x4/0x14 > [ 672.130291] LR is at make_reservation+0x74/0x328 > [ 672.134880] pc : [] lr : [] psr: 60000013 > [ 672.134890] sp : c775fd18 ip : 00000088 fp : 000000ac > [ 672.146281] r10: 00000000 r9 : 00000000 r8 : c7eb8000 > [ 672.151469] r7 : 00000088 r6 : c7a68310 r5 : c7eb8000 r4 : 00000001 > [ 672.157947] r3 : 00000000 r2 : 00000000 r1 : 00000000 r0 : 000000ac > [ 672.164429] Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment kernel > [ 672.171691] Control: 0000397f Table: a7f54018 DAC: 00000035 > [ 672.177394] Process flush-ubifs_0_0 (pid: 1289, stack limit = 0xc775e278) > [ 672.184131] Stack: (0xc775fd18 to 0xc7760000) > [ 672.188458] fd00: c7f5ea00 00000000 > [ 672.196588] fd20: 00000000 c775fde0 c7f6c000 000000a0 00000001 c7eb8144 00000000 c775e000 > [ 672.204721] fd40: 00000001 00000088 00000004 00000000 00000004 c7a68310 c7eb8000 c7a68310 > [ 672.212853] fd60: 00000000 000000a0 c6894180 00000000 00000000 c0143aa4 c775fde0 000006d0 > [ 672.220978] fd80: 0000a1e0 c7eb8000 c775fdb4 c015634c 00000001 00000080 c7a68310 00000001 > [ 672.229111] fda0: c7a68458 c7eb8000 00000000 00000000 00000063 c01489b0 c775fe74 c0085400 > [ 672.237245] fdc0: c775e000 c775e000 c7a68310 c0558b00 00000063 c014559c c7a683ac c7a683ac > [ 672.245377] fde0: 00000001 c775fef0 00000400 00000000 ffffffff c775fe34 00000000 c008b2e4 > [ 672.253510] fe00: c0558b00 c008bb3c 0000000e c00865b4 00000007 ffffffff c7a683ac c008b2d0 > [ 672.261642] fe20: c7a683ac 00000001 00000001 00000001 c775fe5c 00000001 00000000 c0558b00 > [ 672.269767] fe40: c062cf40 c062cf60 c0629080 c06290a0 c06290c0 c06290e0 c062cd60 00000000 > [ 672.277900] fe60: c062d0a0 00006872 00000000 c775fef0 00000000 00000001 c04eb4f8 00000007 > [ 672.286034] fe80: c7a68310 c775fef0 c7eb8068 c7a683ac c04eb4f8 c775fef0 c7eb8088 c00c3f28 > [ 672.294166] fea0: 00000000 c7a68310 00000000 c7eb8068 c7e12600 c00c4b48 c0246d3c c7eb8090 > [ 672.302298] fec0: c7ac17b0 c7a68318 c7eb8068 00000000 c7eb8090 c0537a6c c775fef0 00000400 > [ 672.310431] fee0: c775ff60 00000000 c7eb8068 c00c4d98 c7eb8008 00000000 00000000 00000000 > [ 672.318555] ff00: 0000a277 00000400 00000000 00000000 00000000 00000000 ffffffff 7fffffff > [ 672.326680] ff20: 00000000 00000000 c035b804 c0053aa8 c04f1f08 c04f1dbc c77a9f04 c68958c0 > [ 672.334813] ff40: c7eb8068 0000a270 c775ff60 00000000 00000000 c7eb80a8 00000001 c00c4f74 > [ 672.342944] ff60: 00000009 00000000 00000000 00000000 00000000 000001f4 c775e000 0000a270 > [ 672.351070] ff80: c7eb8068 c04eb4f8 c04f22b0 0000000a 00007530 c00c50e0 00000000 c7eb8008 > [ 672.359202] ffa0: c7eb8068 c7eb8068 c0095e18 00000000 00000000 00000000 00000000 c0095ec0 > [ 672.367328] ffc0: c775ffd4 c7c4bf2c c7eb8068 c006ac50 00000000 00000000 c775ffd8 c775ffd8 > [ 672.375459] ffe0: 00000000 00000000 00000000 00000000 00000000 c00458bc 5f455349 48504943 > [ 672.383609] [] (mutex_lock+0x4/0x14) from [] (make_reservation+0x74/0x328) > [ 672.392184] [] (make_reservation+0x74/0x328) from [] (ubifs_jnl_write_inode+0x80/0x1b8) > [ 672.401871] [] (ubifs_jnl_write_inode+0x80/0x1b8) from [] (ubifs_write_inode+0x64/0xc4) > [ 672.411554] [] (ubifs_write_inode+0x64/0xc4) from [] (ubifs_writepage+0x124/0x15c) > [ 672.420830] [] (ubifs_writepage+0x124/0x15c) from [] (__writepage+0x14/0x64) > [ 672.429572] [] (__writepage+0x14/0x64) from [] (write_cache_pages+0x1e4/0x2c0) > [ 672.438498] [] (write_cache_pages+0x1e4/0x2c0) from [] (writeback_single_inode+0xd4/0x2b8) > [ 672.448447] [] (writeback_single_inode+0xd4/0x2b8) from [] (writeback_inodes_wb+0x434/0x52c) > [ 672.458568] [] (writeback_inodes_wb+0x434/0x52c) from [] (wb_writeback+0x158/0x1cc) > [ 672.467907] [] (wb_writeback+0x158/0x1cc) from [] (wb_do_writeback+0x64/0x198) > [ 672.476815] [] (wb_do_writeback+0x64/0x198) from [] (bdi_writeback_task+0x38/0xbc) > [ 672.486084] [] (bdi_writeback_task+0x38/0xbc) from [] (bdi_start_fn+0xa8/0xf8) > [ 672.495009] [] (bdi_start_fn+0xa8/0xf8) from [] (kthread+0x78/0x80) > [ 672.502992] [] (kthread+0x78/0x80) from [] (kernel_thread_exit+0x0/0x8) > [ 672.511293] Code: 05843000 e28dd010 e8bd81f0 e3a02000 (e1001092) > [ 672.517534] ---[ end trace f5c79b7be5adbe31 ]--- > Sent SIGKILL to all processes > Requesting system reboot[ 674.543613] Restarting system. > From brijesh.s.singh at gmail.com Mon May 10 05:03:17 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Mon, 10 May 2010 14:33:17 +0530 Subject: Release of UBIL: ubi with log In-Reply-To: <1273474175.2209.61.camel@localhost> References: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> <1273474175.2209.61.camel@localhost> Message-ID: Hi, On Mon, May 10, 2010 at 12:19 PM, Artem Bityutskiy wrote: > On Fri, 2010-02-26 at 18:28 +0530, Brijesh Singh wrote: >> Hi, >> ?It gives me great pleasure in sharing UBIL: ubi with log. ?We have >> added logging functionality to ubi for reducing mount time. >> UBIL uses the "same source base of UBI". The logging functionality can >> be added or removed at compile time using "make menuconfig option". >> >> We have seen mount time reduction of 50% in 1GB NAND. We are expecting >> even better results for larger flash memories. > > Was that SLC or MLC NAND? It was SLC NAND. >> The source code of UBIL can be found in the following git tree: >> http://git.infradead.org/users/brijesh/ubi-2.6.git >> >> We have tested ubil for samsung nand and onenand. The test results can >> be found in the following git tree: >> http://git.infradead.org/users/brijesh/ubil_results > > Did you run any stress tests for UBIL? Which? We ran 1) fsstress on UBIFS without power failure 2) fsstress on UBIFS with power failure > I think it is very important to stress test it and make sure is stable. > After that, we can start doing changes required for upstreaming it. I > propose the following roadmap: > > The main idea is to make UBIL as stable as possible first. Then, make > sure whatever change we introduce - it stays stable. IOW, run tests > after each change and make sure nothing breaks. With this test-driven > scheme we can add all the needed improvements and keep it working. > >> We are working on utilities and design document of UBIL. I will share >> those as soon as possible. >> >> If someone wants to try, please follow the instructions: >> make menuconfig >> ? ? ? ? ?select ubi as module >> ? ? ? ? ?select ubil feature. >> compile ubi module. > > I think UBIL should not be compiled separately. UBI should automatically > detect the format type. Possible. >> 1) First mount of ubil is little different than ubi. >> >> insmod ubi mtd=1,ubinize. >> ?(Second parameter "ubinize" is introduced to avoid accidental loss of data.) >> insmod ubifs >> mount ubifs > > Why this ubinize parameter exists? Why you cannot detect empty media > just like UBI? The idea was not to accidentally ubinize mtd partition. For example: the file system generally don't format empty partition on it's own. It is forced. >> 2)For next mounts: >> insmod ubi mtd=1 >> insmod ubifs >> mount ubifs >> >> Though UBIL is functionally complete,there is a lot of scope for >> optimizations. All the help is very much appreciated. > > The main requirement for upstreaming is to make sure the on-flash format > is stable. Once you are in upstream - you cannot change your on-flash > data structures anymore. Any change will become huge PITA. > > Thus, it is very important to think carefully about on-flash format, and > possibly invent mechanisms for future extensions. I agree. Thanks and Regards, Brijesh From dedekind1 at gmail.com Mon May 10 05:07:47 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 10 May 2010 12:07:47 +0300 Subject: Release of UBIL: ubi with log In-Reply-To: References: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> <1273474175.2209.61.camel@localhost> Message-ID: <1273482467.2209.101.camel@localhost> On Mon, 2010-05-10 at 14:33 +0530, Brijesh Singh wrote: > >> insmod ubi mtd=1,ubinize. > >> (Second parameter "ubinize" is introduced to avoid accidental loss of data.) > >> insmod ubifs > >> mount ubifs > > > > Why this ubinize parameter exists? Why you cannot detect empty media > > just like UBI? > > The idea was not to accidentally ubinize mtd partition. > For example: the file system generally don't format empty partition on > it's own. It is forced. File system just never formats the media, so of course they never corrupt anything. Utilities mkfs.ext3 and the like do this instead. In fact, you can thing of UBI the same way - it does not format, there is ubiformat tool for that. Then, there is one single exception - empty flash. It is just very handy to be able to attach it without ubiformat. You can consider this as an additional usefuls feature. And UBI does manage somehow to not corrupt anything. So the question was - why UBIL cannot? -- Best Regards, Artem Bityutskiy (????? ????????) From brijesh.s.singh at gmail.com Mon May 10 06:21:39 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Mon, 10 May 2010 15:51:39 +0530 Subject: Release of UBIL: ubi with log In-Reply-To: <1273482467.2209.101.camel@localhost> References: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> <1273474175.2209.61.camel@localhost> <1273482467.2209.101.camel@localhost> Message-ID: On Mon, May 10, 2010 at 2:37 PM, Artem Bityutskiy wrote: > On Mon, 2010-05-10 at 14:33 +0530, Brijesh Singh wrote: >> >> insmod ubi mtd=1,ubinize. >> >> ?(Second parameter "ubinize" is introduced to avoid accidental loss of data.) >> >> insmod ubifs >> >> mount ubifs >> > >> > Why this ubinize parameter exists? Why you cannot detect empty media >> > just like UBI? >> >> The idea was not to accidentally ubinize mtd partition. >> For example: the file system generally don't format empty partition on >> it's own. It is forced. > > File system just never formats the media, so of course they never > corrupt anything. Utilities mkfs.ext3 and the like do this instead. > > In fact, you can thing of UBI the same way - it does not format, there > is ubiformat tool for that. Then, there is one single exception - empty > flash. It is just very handy to be able to attach it without ubiformat. > You can consider this as an additional usefuls feature. > > And UBI does manage somehow to not corrupt anything. So the question was > - why UBIL cannot? Personally, I wasn't sure if it is nice idea to find empty flash and then format it on it's own. UBIL certainly can do this. I will add this, if you find it useful. From brijesh.s.singh at gmail.com Mon May 10 06:31:31 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Mon, 10 May 2010 16:01:31 +0530 Subject: UBIL design doc In-Reply-To: <1273475736.2209.88.camel@localhost> References: <1273475736.2209.88.camel@localhost> Message-ID: On Mon, May 10, 2010 at 12:45 PM, Artem Bityutskiy wrote: > On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: >> Hi, >> ? I am forwarding you the design document for ubi with log. Please >> find the ubil document at >> http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL >> design document.pdf > > Hi guys, > > I've read the document. Looks very promising. Here some feed-back. > > 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 > erease cycles? Won't the SB PEB wear out very quickly? Why you did not > go for the chaining approach which I described in the old JFFS3 design > doc? Right. > If we do not implement chaining, we should at least design it and make > sure UBIL can be extended later so that SB chaining could be added. This looks better for now. I will add it it to design. > 2. SB PEB at the end. I think this is a very bad idea. Imagine you have > to do UBIL images for production on the factory. With your design you > have the following bad drawbacks: > > ?a. NAND flash has initial bad blocks, and you do not know how many, > ? ? and where they sit. These may be the last 8 eraseblocks. So, when > ? ? you prepare an image (say, with the ubinize user-space tool), where > ? ? will you put the second SB PEB? > > ?b. Currently, UBI/UBIFS images are small. E.g., if you make an > ? ? UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, > ? ? your image will be few megs - it will contain the files, and all > ? ? the needed UBI/UBIFS meta-data. > > ? ? So now what will be image size for UBIL - 1GiB, and this is bad. > ? ? You then will transfer 1GiB of data to the devices during flashing > ? ? or you will have to invent ways to work around this. Do you need > ? ? these complexities? > > I think the second SB PEB should not be at the end. Good point. I will add it to first and second good block right now. > 3. Backward-compatibility. In UBIL you removed EC anc VID headers in > ? PEBs. That's fine for optimization purposes. But it has draw-backs: > > ? a. If any of the UBIL meta-data blocks like SB, CMT or log are > ? ? ?corrupted - that's it - we are screwed. You cannot anymore > ? ? ?re-consturct the data by scanning. The robustness goes down. > > ? c. Backward compatibility - UBI will not be able to attach UBIL > ? ? ?images. This is not very nice. > > So, I think you should keep EC and VID headers in PEBs. And you should > make the SB/CMT/log blocks to be a new type of UBI volume with > UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this > case UBI will attach UBIL volumes just fine. > > Then, you can add an _option_ to have no EC/VID headers in PEBs. This > then can be used for performance, if one wants to sacrifice robustness. > But this should be the second step. In this case, you will just need to > put a VID header with UBI_COMPAT_REJECT flag to the first PEB. > > I have some more notes, but these 3 are enough for now. > > What do you think? This is nice. But I need to think a bit. I will get back on this. From dedekind1 at gmail.com Mon May 10 07:02:56 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 10 May 2010 14:02:56 +0300 Subject: Release of UBIL: ubi with log In-Reply-To: References: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> <1273474175.2209.61.camel@localhost> Message-ID: <1273489376.2209.127.camel@localhost> On Mon, 2010-05-10 at 14:33 +0530, Brijesh Singh wrote: > Hi, > > On Mon, May 10, 2010 at 12:19 PM, Artem Bityutskiy wrote: > > On Fri, 2010-02-26 at 18:28 +0530, Brijesh Singh wrote: > >> Hi, > >> It gives me great pleasure in sharing UBIL: ubi with log. We have > >> added logging functionality to ubi for reducing mount time. > >> UBIL uses the "same source base of UBI". The logging functionality can > >> be added or removed at compile time using "make menuconfig option". > >> > >> We have seen mount time reduction of 50% in 1GB NAND. We are expecting > >> even better results for larger flash memories. > > > > Was that SLC or MLC NAND? > > It was SLC NAND. > > >> The source code of UBIL can be found in the following git tree: > >> http://git.infradead.org/users/brijesh/ubi-2.6.git > >> > >> We have tested ubil for samsung nand and onenand. The test results can > >> be found in the following git tree: > >> http://git.infradead.org/users/brijesh/ubil_results > > > > Did you run any stress tests for UBIL? Which? > > We ran > 1) fsstress on UBIFS without power failure > 2) fsstress on UBIFS with power failure Please, run also the integck test which you can find in the mtd-utils, it is a very good test, and I think it is better than fsstress even. If integck will work, this will mean UBIL is quite stable. Then let's make sure it does not regress when we introduce changes. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Mon May 10 07:09:36 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 10 May 2010 14:09:36 +0300 Subject: Release of UBIL: ubi with log In-Reply-To: References: <6b5362aa1002260458j571852cbl2f2d86130828333a@mail.gmail.com> <1273474175.2209.61.camel@localhost> <1273482467.2209.101.camel@localhost> Message-ID: <1273489776.2209.129.camel@localhost> On Mon, 2010-05-10 at 15:51 +0530, Brijesh Singh wrote: > On Mon, May 10, 2010 at 2:37 PM, Artem Bityutskiy wrote: > > On Mon, 2010-05-10 at 14:33 +0530, Brijesh Singh wrote: > >> >> insmod ubi mtd=1,ubinize. > >> >> (Second parameter "ubinize" is introduced to avoid accidental loss of data.) > >> >> insmod ubifs > >> >> mount ubifs > >> > > >> > Why this ubinize parameter exists? Why you cannot detect empty media > >> > just like UBI? > >> > >> The idea was not to accidentally ubinize mtd partition. > >> For example: the file system generally don't format empty partition on > >> it's own. It is forced. > > > > File system just never formats the media, so of course they never > > corrupt anything. Utilities mkfs.ext3 and the like do this instead. > > > > In fact, you can thing of UBI the same way - it does not format, there > > is ubiformat tool for that. Then, there is one single exception - empty > > flash. It is just very handy to be able to attach it without ubiformat. > > You can consider this as an additional usefuls feature. > > > > And UBI does manage somehow to not corrupt anything. So the question was > > - why UBIL cannot? > > Personally, I wasn't sure if it is nice idea to find empty flash and > then format it on it's own. > > UBIL certainly can do this. I will add this, if you find it useful. Well, many people found it very useful. I found it very useful for development as well. And since it already exists and is used, it is nice to make UBIL consistent with it. -- Best Regards, Artem Bityutskiy (????? ????????) From gary.hall at mps.k12.al.us Mon May 10 10:26:50 2010 From: gary.hall at mps.k12.al.us (Hall, Gary) Date: Mon, 10 May 2010 09:26:50 -0500 Subject: =?windows-1256?Q?CONTACT_ME_PRIVATELY=FE_@_jack.parkinson19@hotmail.com?= Message-ID: My name is Mr Jack parkinson and i work with the EURO lottery, i got your email address from your country website. i am soliciting for your opinion to make you a winner in our ongoing online lottery draws,And i can make you a winner and we will share the proceeds equally 50/50. if you are interested contact me via me personal email:jack.parkinson19 at hotmail.com From okpalin at gmail.com Mon May 10 23:46:13 2010 From: okpalin at gmail.com (=?Big5?B?qkykX65t?=) Date: Tue, 11 May 2010 11:46:13 +0800 Subject: Can not mount UBIFS In-Reply-To: References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> <1272888512.27729.46.camel@localhost> Message-ID: Dear all, I have modified bootloader to download image as ubiformat does. However, I still can not mount it. I also dump the content of mtd partition and compare. (Ex: dd if=/dev/block/mtdblock5 of=/data/mtd5bak) No difference between the content written by bootloader and written by ubiformat. The following is the debug messages: <7>UBI DBG (pid 732): ctrl_cdev_ioctl: attach MTD device <5>UBI: attaching mtd5 to ubi0 <7>UBI DBG (pid 732): io_init: min_io_size 2048 <7>UBI DBG (pid 732): io_init: hdrs_min_io_size 2048 <7>UBI DBG (pid 732): io_init: ec_hdr_alsize 2048 <7>UBI DBG (pid 732): io_init: vid_hdr_alsize 2048 <7>UBI DBG (pid 732): io_init: vid_hdr_offset 2048 <7>UBI DBG (pid 732): io_init: vid_hdr_aloffset 2048 <7>UBI DBG (pid 732): io_init: vid_hdr_shift 0 <7>UBI DBG (pid 732): io_init: leb_start 4096 <7>UBI DBG (pid 732): io_init: max_erroneous 51 <5>UBI: physical eraseblock size: 131072 bytes (128 KiB) <5>UBI: logical eraseblock size: 126976 bytes <5>UBI: smallest flash I/O unit: 2048 <5>UBI: VID header offset: 2048 (aligned 2048) <5>UBI: data offset: 4096 <7>UBI DBG (pid 732): ubi_scan: process PEB 0 <7>UBI DBG (pid 732): ubi_scan: process PEB 1 <7>UBI DBG (pid 732): ubi_scan: process PEB 2 <7>UBI DBG (pid 732): ubi_scan: process PEB 3 <7>UBI DBG (pid 732): ubi_scan: process PEB 4 <7>UBI DBG (pid 732): ubi_scan: process PEB 5 <7>UBI DBG (pid 732): ubi_scan: process PEB 6 <7>UBI DBG (pid 732): ubi_scan: process PEB 7 <7>UBI DBG (pid 732): ubi_scan: process PEB 8 <7>UBI DBG (pid 732): ubi_scan: process PEB 9 <7>UBI DBG (pid 732): ubi_scan: process PEB 10 <7>UBI DBG (pid 732): ubi_scan: process PEB 11 <7>UBI DBG (pid 732): ubi_scan: process PEB 12 <7>UBI DBG (pid 732): ubi_scan: process PEB 13 <7>UBI DBG (pid 732): ubi_scan: process PEB 14 <7>UBI DBG (pid 732): ubi_scan: process PEB 15 <7>UBI DBG (pid 732): ubi_scan: process PEB 16 <7>UBI DBG (pid 732): ubi_scan: process PEB 17 <7>UBI DBG (pid 732): ubi_scan: process PEB 18 <7>UBI DBG (pid 732): ubi_scan: process PEB 19 <7>UBI DBG (pid 732): ubi_scan: process PEB 20 <7>UBI DBG (pid 732): ubi_scan: process PEB 21 <7>UBI DBG (pid 732): ubi_scan: process PEB 22 <7>UBI DBG (pid 732): ubi_scan: process PEB 23 <7>UBI DBG (pid 732): ubi_scan: process PEB 24 <7>UBI DBG (pid 732): ubi_scan: process PEB 25 <7>UBI DBG (pid 732): ubi_scan: process PEB 26 <7>UBI DBG (pid 732): ubi_scan: process PEB 27 <7>UBI DBG (pid 732): ubi_scan: process PEB 28 <7>UBI DBG (pid 732): ubi_scan: process PEB 29 <7>UBI DBG (pid 732): ubi_scan: process PEB 30 <7>UBI DBG (pid 732): ubi_scan: process PEB 31 <7>UBI DBG (pid 732): ubi_scan: process PEB 32 <7>UBI DBG (pid 732): ubi_scan: process PEB 33 <7>UBI DBG (pid 732): ubi_scan: process PEB 34 <7>UBI DBG (pid 732): ubi_scan: process PEB 35 <7>UBI DBG (pid 732): ubi_scan: process PEB 36 <7>UBI DBG (pid 732): ubi_scan: process PEB 37 <7>UBI DBG (pid 732): ubi_scan: process PEB 38 <7>UBI DBG (pid 732): ubi_scan: process PEB 39 <7>UBI DBG (pid 732): ubi_scan: process PEB 40 <7>UBI DBG (pid 732): ubi_scan: process PEB 41 <7>UBI DBG (pid 732): ubi_scan: process PEB 42 <7>UBI DBG (pid 732): ubi_scan: process PEB 43 <7>UBI DBG (pid 732): ubi_scan: process PEB 44 <7>UBI DBG (pid 732): ubi_scan: process PEB 45 <7>UBI DBG (pid 732): ubi_scan: process PEB 46 <7>UBI DBG (pid 732): ubi_scan: process PEB 47 <7>UBI DBG (pid 732): ubi_scan: process PEB 48 <7>UBI DBG (pid 732): ubi_scan: process PEB 49 <7>UBI DBG (pid 732): ubi_scan: process PEB 50 <7>UBI DBG (pid 732): ubi_scan: process PEB 51 <7>UBI DBG (pid 732): ubi_scan: process PEB 52 <7>UBI DBG (pid 732): ubi_scan: process PEB 53 <7>UBI DBG (pid 732): ubi_scan: process PEB 54 <7>UBI DBG (pid 732): ubi_scan: process PEB 55 <7>UBI DBG (pid 732): ubi_scan: process PEB 56 <7>UBI DBG (pid 732): ubi_scan: process PEB 57 <7>UBI DBG (pid 732): ubi_scan: process PEB 58 <7>UBI DBG (pid 732): ubi_scan: process PEB 59 <7>UBI DBG (pid 732): ubi_scan: process PEB 60 <7>UBI DBG (pid 732): ubi_scan: process PEB 61 <7>UBI DBG (pid 732): ubi_scan: process PEB 62 <7>UBI DBG (pid 732): ubi_scan: process PEB 63 <7>UBI DBG (pid 732): ubi_scan: process PEB 64 <7>UBI DBG (pid 732): ubi_scan: process PEB 65 <6>Block 2540 is factory bad in chip 0, offset = 13d80000 <7>UBI DBG (pid 732): ubi_scan: process PEB 66 <6>Block 2541 is factory bad in chip 0, offset = 13da0000 <7>UBI DBG (pid 732): ubi_scan: process PEB 67 <7>UBI DBG (pid 732): ubi_scan: process PEB 68 <7>UBI DBG (pid 732): ubi_scan: process PEB 69 <7>UBI DBG (pid 732): ubi_scan: process PEB 70 <7>UBI DBG (pid 732): ubi_scan: process PEB 71 <7>UBI DBG (pid 732): ubi_scan: process PEB 72 <7>UBI DBG (pid 732): ubi_scan: process PEB 73 <7>UBI DBG (pid 732): ubi_scan: process PEB 74 <7>UBI DBG (pid 732): ubi_scan: process PEB 75 <7>UBI DBG (pid 732): ubi_scan: process PEB 76 <7>UBI DBG (pid 732): ubi_scan: process PEB 77 <7>UBI DBG (pid 732): ubi_scan: process PEB 78 <7>UBI DBG (pid 732): ubi_scan: process PEB 79 <7>UBI DBG (pid 732): ubi_scan: process PEB 80 <7>UBI DBG (pid 732): ubi_scan: process PEB 81 <7>UBI DBG (pid 732): ubi_scan: process PEB 82 <7>UBI DBG (pid 732): ubi_scan: process PEB 83 <7>UBI DBG (pid 732): ubi_scan: process PEB 84 <7>UBI DBG (pid 732): ubi_scan: process PEB 85 <7>UBI DBG (pid 732): ubi_scan: process PEB 86 <7>UBI DBG (pid 732): ubi_scan: process PEB 87 <7>UBI DBG (pid 732): ubi_scan: process PEB 88 <7>UBI DBG (pid 732): ubi_scan: process PEB 89 <7>UBI DBG (pid 732): ubi_scan: process PEB 90 <7>UBI DBG (pid 732): ubi_scan: process PEB 91 <7>UBI DBG (pid 732): ubi_scan: process PEB 92 <7>UBI DBG (pid 732): ubi_scan: process PEB 93 <7>UBI DBG (pid 732): ubi_scan: process PEB 94 <7>UBI DBG (pid 732): ubi_scan: process PEB 95 <7>UBI DBG (pid 732): ubi_scan: process PEB 96 <7>UBI DBG (pid 732): ubi_scan: process PEB 97 <7>UBI DBG (pid 732): ubi_scan: process PEB 98 <7>UBI DBG (pid 732): ubi_scan: process PEB 99 <7>UBI DBG (pid 732): ubi_scan: process PEB 100 <7>UBI DBG (pid 732): ubi_scan: process PEB 101 <7>UBI DBG (pid 732): ubi_scan: process PEB 102 <7>UBI DBG (pid 732): ubi_scan: process PEB 103 <7>UBI DBG (pid 732): ubi_scan: process PEB 104 <7>UBI DBG (pid 732): ubi_scan: process PEB 105 <7>UBI DBG (pid 732): ubi_scan: process PEB 106 <7>UBI DBG (pid 732): ubi_scan: process PEB 107 <7>UBI DBG (pid 732): ubi_scan: process PEB 108 <7>UBI DBG (pid 732): ubi_scan: process PEB 109 <7>UBI DBG (pid 732): ubi_scan: process PEB 110 <7>UBI DBG (pid 732): ubi_scan: process PEB 111 <7>UBI DBG (pid 732): ubi_scan: process PEB 112 <7>UBI DBG (pid 732): ubi_scan: process PEB 113 <7>UBI DBG (pid 732): ubi_scan: process PEB 114 <7>UBI DBG (pid 732): ubi_scan: process PEB 115 <7>UBI DBG (pid 732): ubi_scan: process PEB 116 <7>UBI DBG (pid 732): ubi_scan: process PEB 117 <7>UBI DBG (pid 732): ubi_scan: process PEB 118 <7>UBI DBG (pid 732): ubi_scan: process PEB 119 <7>UBI DBG (pid 732): ubi_scan: process PEB 120 <7>UBI DBG (pid 732): ubi_scan: process PEB 121 <7>UBI DBG (pid 732): ubi_scan: process PEB 122 <7>UBI DBG (pid 732): ubi_scan: process PEB 123 <7>UBI DBG (pid 732): ubi_scan: process PEB 124 <7>UBI DBG (pid 732): ubi_scan: process PEB 125 <7>UBI DBG (pid 732): ubi_scan: process PEB 126 <7>UBI DBG (pid 732): ubi_scan: process PEB 127 <7>UBI DBG (pid 732): ubi_scan: process PEB 128 <7>UBI DBG (pid 732): ubi_scan: process PEB 129 <7>UBI DBG (pid 732): ubi_scan: process PEB 130 <7>UBI DBG (pid 732): ubi_scan: process PEB 131 <7>UBI DBG (pid 732): ubi_scan: process PEB 132 <7>UBI DBG (pid 732): ubi_scan: process PEB 133 <7>UBI DBG (pid 732): ubi_scan: process PEB 134 <7>UBI DBG (pid 732): ubi_scan: process PEB 135 <7>UBI DBG (pid 732): ubi_scan: process PEB 136 <7>UBI DBG (pid 732): ubi_scan: process PEB 137 <7>UBI DBG (pid 732): ubi_scan: process PEB 138 <7>UBI DBG (pid 732): ubi_scan: process PEB 139 <7>UBI DBG (pid 732): ubi_scan: process PEB 140 <7>UBI DBG (pid 732): ubi_scan: process PEB 141 <7>UBI DBG (pid 732): ubi_scan: process PEB 142 <7>UBI DBG (pid 732): ubi_scan: process PEB 143 <7>UBI DBG (pid 732): ubi_scan: process PEB 144 <7>UBI DBG (pid 732): ubi_scan: process PEB 145 <7>UBI DBG (pid 732): ubi_scan: process PEB 146 <7>UBI DBG (pid 732): ubi_scan: process PEB 147 <7>UBI DBG (pid 732): ubi_scan: process PEB 148 <7>UBI DBG (pid 732): ubi_scan: process PEB 149 <7>UBI DBG (pid 732): ubi_scan: process PEB 150 <7>UBI DBG (pid 732): ubi_scan: process PEB 151 <7>UBI DBG (pid 732): ubi_scan: process PEB 152 <7>UBI DBG (pid 732): ubi_scan: process PEB 153 <7>UBI DBG (pid 732): ubi_scan: process PEB 154 <7>UBI DBG (pid 732): ubi_scan: process PEB 155 <7>UBI DBG (pid 732): ubi_scan: process PEB 156 <7>UBI DBG (pid 732): ubi_scan: process PEB 157 <7>UBI DBG (pid 732): ubi_scan: process PEB 158 <7>UBI DBG (pid 732): ubi_scan: process PEB 159 <7>UBI DBG (pid 732): ubi_scan: process PEB 160 <7>UBI DBG (pid 732): ubi_scan: process PEB 161 <7>UBI DBG (pid 732): ubi_scan: process PEB 162 <7>UBI DBG (pid 732): ubi_scan: process PEB 163 <7>UBI DBG (pid 732): ubi_scan: process PEB 164 <7>UBI DBG (pid 732): ubi_scan: process PEB 165 <7>UBI DBG (pid 732): ubi_scan: process PEB 166 <7>UBI DBG (pid 732): ubi_scan: process PEB 167 <7>UBI DBG (pid 732): ubi_scan: process PEB 168 <7>UBI DBG (pid 732): ubi_scan: process PEB 169 <7>UBI DBG (pid 732): ubi_scan: process PEB 170 <7>UBI DBG (pid 732): ubi_scan: process PEB 171 <7>UBI DBG (pid 732): ubi_scan: process PEB 172 <7>UBI DBG (pid 732): ubi_scan: process PEB 173 <7>UBI DBG (pid 732): ubi_scan: process PEB 174 <7>UBI DBG (pid 732): ubi_scan: process PEB 175 <7>UBI DBG (pid 732): ubi_scan: process PEB 176 <7>UBI DBG (pid 732): ubi_scan: process PEB 177 <7>UBI DBG (pid 732): ubi_scan: process PEB 178 <7>UBI DBG (pid 732): ubi_scan: process PEB 179 <7>UBI DBG (pid 732): ubi_scan: process PEB 180 <7>UBI DBG (pid 732): ubi_scan: process PEB 181 <7>UBI DBG (pid 732): ubi_scan: process PEB 182 <7>UBI DBG (pid 732): ubi_scan: process PEB 183 <7>UBI DBG (pid 732): ubi_scan: process PEB 184 <7>UBI DBG (pid 732): ubi_scan: process PEB 185 <7>UBI DBG (pid 732): ubi_scan: process PEB 186 <7>UBI DBG (pid 732): ubi_scan: process PEB 187 <7>UBI DBG (pid 732): ubi_scan: process PEB 188 <7>UBI DBG (pid 732): ubi_scan: process PEB 189 <7>UBI DBG (pid 732): ubi_scan: process PEB 190 <7>UBI DBG (pid 732): ubi_scan: process PEB 191 <7>UBI DBG (pid 732): ubi_scan: process PEB 192 <7>UBI DBG (pid 732): ubi_scan: process PEB 193 <7>UBI DBG (pid 732): ubi_scan: process PEB 194 <7>UBI DBG (pid 732): ubi_scan: process PEB 195 <7>UBI DBG (pid 732): ubi_scan: process PEB 196 <7>UBI DBG (pid 732): ubi_scan: process PEB 197 <7>UBI DBG (pid 732): ubi_scan: process PEB 198 <7>UBI DBG (pid 732): ubi_scan: process PEB 199 <7>UBI DBG (pid 732): ubi_scan: process PEB 200 <7>UBI DBG (pid 732): ubi_scan: process PEB 201 <7>UBI DBG (pid 732): ubi_scan: process PEB 202 <7>UBI DBG (pid 732): ubi_scan: process PEB 203 <7>UBI DBG (pid 732): ubi_scan: process PEB 204 <7>UBI DBG (pid 732): ubi_scan: process PEB 205 <7>UBI DBG (pid 732): ubi_scan: process PEB 206 <7>UBI DBG (pid 732): ubi_scan: process PEB 207 <7>UBI DBG (pid 732): ubi_scan: process PEB 208 <7>UBI DBG (pid 732): ubi_scan: process PEB 209 <7>UBI DBG (pid 732): ubi_scan: process PEB 210 <7>UBI DBG (pid 732): ubi_scan: process PEB 211 <7>UBI DBG (pid 732): ubi_scan: process PEB 212 <7>UBI DBG (pid 732): ubi_scan: process PEB 213 <7>UBI DBG (pid 732): ubi_scan: process PEB 214 <7>UBI DBG (pid 732): ubi_scan: process PEB 215 <7>UBI DBG (pid 732): ubi_scan: process PEB 216 <7>UBI DBG (pid 732): ubi_scan: process PEB 217 <7>UBI DBG (pid 732): ubi_scan: process PEB 218 <7>UBI DBG (pid 732): ubi_scan: process PEB 219 <7>UBI DBG (pid 732): ubi_scan: process PEB 220 <7>UBI DBG (pid 732): ubi_scan: process PEB 221 <7>UBI DBG (pid 732): ubi_scan: process PEB 222 <7>UBI DBG (pid 732): ubi_scan: process PEB 223 <7>UBI DBG (pid 732): ubi_scan: process PEB 224 <7>UBI DBG (pid 732): ubi_scan: process PEB 225 <7>UBI DBG (pid 732): ubi_scan: process PEB 226 <7>UBI DBG (pid 732): ubi_scan: process PEB 227 <7>UBI DBG (pid 732): ubi_scan: process PEB 228 <7>UBI DBG (pid 732): ubi_scan: process PEB 229 <7>UBI DBG (pid 732): ubi_scan: process PEB 230 <7>UBI DBG (pid 732): ubi_scan: process PEB 231 <7>UBI DBG (pid 732): ubi_scan: process PEB 232 <7>UBI DBG (pid 732): ubi_scan: process PEB 233 <7>UBI DBG (pid 732): ubi_scan: process PEB 234 <7>UBI DBG (pid 732): ubi_scan: process PEB 235 <7>UBI DBG (pid 732): ubi_scan: process PEB 236 <7>UBI DBG (pid 732): ubi_scan: process PEB 237 <7>UBI DBG (pid 732): ubi_scan: process PEB 238 <7>UBI DBG (pid 732): ubi_scan: process PEB 239 <7>UBI DBG (pid 732): ubi_scan: process PEB 240 <7>UBI DBG (pid 732): ubi_scan: process PEB 241 <7>UBI DBG (pid 732): ubi_scan: process PEB 242 <7>UBI DBG (pid 732): ubi_scan: process PEB 243 <7>UBI DBG (pid 732): ubi_scan: process PEB 244 <7>UBI DBG (pid 732): ubi_scan: process PEB 245 <7>UBI DBG (pid 732): ubi_scan: process PEB 246 <7>UBI DBG (pid 732): ubi_scan: process PEB 247 <7>UBI DBG (pid 732): ubi_scan: process PEB 248 <7>UBI DBG (pid 732): ubi_scan: process PEB 249 <7>UBI DBG (pid 732): ubi_scan: process PEB 250 <7>UBI DBG (pid 732): ubi_scan: process PEB 251 <7>UBI DBG (pid 732): ubi_scan: process PEB 252 <7>UBI DBG (pid 732): ubi_scan: process PEB 253 <7>UBI DBG (pid 732): ubi_scan: process PEB 254 <7>UBI DBG (pid 732): ubi_scan: process PEB 255 <7>UBI DBG (pid 732): ubi_scan: process PEB 256 <7>UBI DBG (pid 732): ubi_scan: process PEB 257 <7>UBI DBG (pid 732): ubi_scan: process PEB 258 <7>UBI DBG (pid 732): ubi_scan: process PEB 259 <7>UBI DBG (pid 732): ubi_scan: process PEB 260 <7>UBI DBG (pid 732): ubi_scan: process PEB 261 <7>UBI DBG (pid 732): ubi_scan: process PEB 262 <7>UBI DBG (pid 732): ubi_scan: process PEB 263 <7>UBI DBG (pid 732): ubi_scan: process PEB 264 <7>UBI DBG (pid 732): ubi_scan: process PEB 265 <7>UBI DBG (pid 732): ubi_scan: process PEB 266 <7>UBI DBG (pid 732): ubi_scan: process PEB 267 <7>UBI DBG (pid 732): ubi_scan: process PEB 268 <7>UBI DBG (pid 732): ubi_scan: process PEB 269 <7>UBI DBG (pid 732): ubi_scan: process PEB 270 <7>UBI DBG (pid 732): ubi_scan: process PEB 271 <7>UBI DBG (pid 732): ubi_scan: process PEB 272 <7>UBI DBG (pid 732): ubi_scan: process PEB 273 <7>UBI DBG (pid 732): ubi_scan: process PEB 274 <7>UBI DBG (pid 732): ubi_scan: process PEB 275 <7>UBI DBG (pid 732): ubi_scan: process PEB 276 <7>UBI DBG (pid 732): ubi_scan: process PEB 277 <7>UBI DBG (pid 732): ubi_scan: process PEB 278 <7>UBI DBG (pid 732): ubi_scan: process PEB 279 <7>UBI DBG (pid 732): ubi_scan: process PEB 280 <7>UBI DBG (pid 732): ubi_scan: process PEB 281 <7>UBI DBG (pid 732): ubi_scan: process PEB 282 <7>UBI DBG (pid 732): ubi_scan: process PEB 283 <7>UBI DBG (pid 732): ubi_scan: process PEB 284 <7>UBI DBG (pid 732): ubi_scan: process PEB 285 <7>UBI DBG (pid 732): ubi_scan: process PEB 286 <7>UBI DBG (pid 732): ubi_scan: process PEB 287 <7>UBI DBG (pid 732): ubi_scan: process PEB 288 <7>UBI DBG (pid 732): ubi_scan: process PEB 289 <7>UBI DBG (pid 732): ubi_scan: process PEB 290 <7>UBI DBG (pid 732): ubi_scan: process PEB 291 <7>UBI DBG (pid 732): ubi_scan: process PEB 292 <7>UBI DBG (pid 732): ubi_scan: process PEB 293 <7>UBI DBG (pid 732): ubi_scan: process PEB 294 <7>UBI DBG (pid 732): ubi_scan: process PEB 295 <7>UBI DBG (pid 732): ubi_scan: process PEB 296 <7>UBI DBG (pid 732): ubi_scan: process PEB 297 <7>UBI DBG (pid 732): ubi_scan: process PEB 298 <7>UBI DBG (pid 732): ubi_scan: process PEB 299 <7>UBI DBG (pid 732): ubi_scan: process PEB 300 <7>UBI DBG (pid 732): ubi_scan: process PEB 301 <7>UBI DBG (pid 732): ubi_scan: process PEB 302 <7>UBI DBG (pid 732): ubi_scan: process PEB 303 <7>UBI DBG (pid 732): ubi_scan: process PEB 304 <7>UBI DBG (pid 732): ubi_scan: process PEB 305 <7>UBI DBG (pid 732): ubi_scan: process PEB 306 <7>UBI DBG (pid 732): ubi_scan: process PEB 307 <7>UBI DBG (pid 732): ubi_scan: process PEB 308 <7>UBI DBG (pid 732): ubi_scan: process PEB 309 <7>UBI DBG (pid 732): ubi_scan: process PEB 310 <7>UBI DBG (pid 732): ubi_scan: process PEB 311 <7>UBI DBG (pid 732): ubi_scan: process PEB 312 <7>UBI DBG (pid 732): ubi_scan: process PEB 313 <7>UBI DBG (pid 732): ubi_scan: process PEB 314 <7>UBI DBG (pid 732): ubi_scan: process PEB 315 <7>UBI DBG (pid 732): ubi_scan: process PEB 316 <7>UBI DBG (pid 732): ubi_scan: process PEB 317 <7>UBI DBG (pid 732): ubi_scan: process PEB 318 <7>UBI DBG (pid 732): ubi_scan: process PEB 319 <7>UBI DBG (pid 732): ubi_scan: process PEB 320 <7>UBI DBG (pid 732): ubi_scan: process PEB 321 <7>UBI DBG (pid 732): ubi_scan: process PEB 322 <7>UBI DBG (pid 732): ubi_scan: process PEB 323 <7>UBI DBG (pid 732): ubi_scan: process PEB 324 <7>UBI DBG (pid 732): ubi_scan: process PEB 325 <7>UBI DBG (pid 732): ubi_scan: process PEB 326 <7>UBI DBG (pid 732): ubi_scan: process PEB 327 <7>UBI DBG (pid 732): ubi_scan: process PEB 328 <7>UBI DBG (pid 732): ubi_scan: process PEB 329 <7>UBI DBG (pid 732): ubi_scan: process PEB 330 <7>UBI DBG (pid 732): ubi_scan: process PEB 331 <7>UBI DBG (pid 732): ubi_scan: process PEB 332 <7>UBI DBG (pid 732): ubi_scan: process PEB 333 <7>UBI DBG (pid 732): ubi_scan: process PEB 334 <7>UBI DBG (pid 732): ubi_scan: process PEB 335 <7>UBI DBG (pid 732): ubi_scan: process PEB 336 <7>UBI DBG (pid 732): ubi_scan: process PEB 337 <7>UBI DBG (pid 732): ubi_scan: process PEB 338 <7>UBI DBG (pid 732): ubi_scan: process PEB 339 <7>UBI DBG (pid 732): ubi_scan: process PEB 340 <7>UBI DBG (pid 732): ubi_scan: process PEB 341 <7>UBI DBG (pid 732): ubi_scan: process PEB 342 <7>UBI DBG (pid 732): ubi_scan: process PEB 343 <7>UBI DBG (pid 732): ubi_scan: process PEB 344 <7>UBI DBG (pid 732): ubi_scan: process PEB 345 <7>UBI DBG (pid 732): ubi_scan: process PEB 346 <7>UBI DBG (pid 732): ubi_scan: process PEB 347 <7>UBI DBG (pid 732): ubi_scan: process PEB 348 <7>UBI DBG (pid 732): ubi_scan: process PEB 349 <7>UBI DBG (pid 732): ubi_scan: process PEB 350 <7>UBI DBG (pid 732): ubi_scan: process PEB 351 <7>UBI DBG (pid 732): ubi_scan: process PEB 352 <7>UBI DBG (pid 732): ubi_scan: process PEB 353 <7>UBI DBG (pid 732): ubi_scan: process PEB 354 <7>UBI DBG (pid 732): ubi_scan: process PEB 355 <7>UBI DBG (pid 732): ubi_scan: process PEB 356 <7>UBI DBG (pid 732): ubi_scan: process PEB 357 <7>UBI DBG (pid 732): ubi_scan: process PEB 358 <7>UBI DBG (pid 732): ubi_scan: process PEB 359 <7>UBI DBG (pid 732): ubi_scan: process PEB 360 <7>UBI DBG (pid 732): ubi_scan: process PEB 361 <7>UBI DBG (pid 732): ubi_scan: process PEB 362 <7>UBI DBG (pid 732): ubi_scan: process PEB 363 <7>UBI DBG (pid 732): ubi_scan: process PEB 364 <7>UBI DBG (pid 732): ubi_scan: process PEB 365 <7>UBI DBG (pid 732): ubi_scan: process PEB 366 <7>UBI DBG (pid 732): ubi_scan: process PEB 367 <7>UBI DBG (pid 732): ubi_scan: process PEB 368 <7>UBI DBG (pid 732): ubi_scan: process PEB 369 <7>UBI DBG (pid 732): ubi_scan: process PEB 370 <7>UBI DBG (pid 732): ubi_scan: process PEB 371 <7>UBI DBG (pid 732): ubi_scan: process PEB 372 <7>UBI DBG (pid 732): ubi_scan: process PEB 373 <7>UBI DBG (pid 732): ubi_scan: process PEB 374 <7>UBI DBG (pid 732): ubi_scan: process PEB 375 <7>UBI DBG (pid 732): ubi_scan: process PEB 376 <7>UBI DBG (pid 732): ubi_scan: process PEB 377 <7>UBI DBG (pid 732): ubi_scan: process PEB 378 <7>UBI DBG (pid 732): ubi_scan: process PEB 379 <7>UBI DBG (pid 732): ubi_scan: process PEB 380 <7>UBI DBG (pid 732): ubi_scan: process PEB 381 <7>UBI DBG (pid 732): ubi_scan: process PEB 382 <7>UBI DBG (pid 732): ubi_scan: process PEB 383 <7>UBI DBG (pid 732): ubi_scan: process PEB 384 <7>UBI DBG (pid 732): ubi_scan: process PEB 385 <7>UBI DBG (pid 732): ubi_scan: process PEB 386 <7>UBI DBG (pid 732): ubi_scan: process PEB 387 <7>UBI DBG (pid 732): ubi_scan: process PEB 388 <7>UBI DBG (pid 732): ubi_scan: process PEB 389 <7>UBI DBG (pid 732): ubi_scan: process PEB 390 <7>UBI DBG (pid 732): ubi_scan: process PEB 391 <7>UBI DBG (pid 732): ubi_scan: process PEB 392 <7>UBI DBG (pid 732): ubi_scan: process PEB 393 <7>UBI DBG (pid 732): ubi_scan: process PEB 394 <7>UBI DBG (pid 732): ubi_scan: process PEB 395 <7>UBI DBG (pid 732): ubi_scan: process PEB 396 <7>UBI DBG (pid 732): ubi_scan: process PEB 397 <7>UBI DBG (pid 732): ubi_scan: process PEB 398 <7>UBI DBG (pid 732): ubi_scan: process PEB 399 <7>UBI DBG (pid 732): ubi_scan: process PEB 400 <7>UBI DBG (pid 732): ubi_scan: process PEB 401 <7>UBI DBG (pid 732): ubi_scan: process PEB 402 <7>UBI DBG (pid 732): ubi_scan: process PEB 403 <7>UBI DBG (pid 732): ubi_scan: process PEB 404 <7>UBI DBG (pid 732): ubi_scan: process PEB 405 <7>UBI DBG (pid 732): ubi_scan: process PEB 406 <7>UBI DBG (pid 732): ubi_scan: process PEB 407 <7>UBI DBG (pid 732): ubi_scan: process PEB 408 <7>UBI DBG (pid 732): ubi_scan: process PEB 409 <7>UBI DBG (pid 732): ubi_scan: process PEB 410 <7>UBI DBG (pid 732): ubi_scan: process PEB 411 <7>UBI DBG (pid 732): ubi_scan: process PEB 412 <7>UBI DBG (pid 732): ubi_scan: process PEB 413 <7>UBI DBG (pid 732): ubi_scan: process PEB 414 <7>UBI DBG (pid 732): ubi_scan: process PEB 415 <7>UBI DBG (pid 732): ubi_scan: process PEB 416 <7>UBI DBG (pid 732): ubi_scan: process PEB 417 <7>UBI DBG (pid 732): ubi_scan: process PEB 418 <7>UBI DBG (pid 732): ubi_scan: process PEB 419 <7>UBI DBG (pid 732): ubi_scan: process PEB 420 <7>UBI DBG (pid 732): ubi_scan: process PEB 421 <7>UBI DBG (pid 732): ubi_scan: process PEB 422 <7>UBI DBG (pid 732): ubi_scan: process PEB 423 <7>UBI DBG (pid 732): ubi_scan: process PEB 424 <7>UBI DBG (pid 732): ubi_scan: process PEB 425 <7>UBI DBG (pid 732): ubi_scan: process PEB 426 <7>UBI DBG (pid 732): ubi_scan: process PEB 427 <7>UBI DBG (pid 732): ubi_scan: process PEB 428 <7>UBI DBG (pid 732): ubi_scan: process PEB 429 <7>UBI DBG (pid 732): ubi_scan: process PEB 430 <7>UBI DBG (pid 732): ubi_scan: process PEB 431 <7>UBI DBG (pid 732): ubi_scan: process PEB 432 <7>UBI DBG (pid 732): ubi_scan: process PEB 433 <7>UBI DBG (pid 732): ubi_scan: process PEB 434 <7>UBI DBG (pid 732): ubi_scan: process PEB 435 <7>UBI DBG (pid 732): ubi_scan: process PEB 436 <7>UBI DBG (pid 732): ubi_scan: process PEB 437 <7>UBI DBG (pid 732): ubi_scan: process PEB 438 <7>UBI DBG (pid 732): ubi_scan: process PEB 439 <7>UBI DBG (pid 732): ubi_scan: process PEB 440 <7>UBI DBG (pid 732): ubi_scan: process PEB 441 <7>UBI DBG (pid 732): ubi_scan: process PEB 442 <7>UBI DBG (pid 732): ubi_scan: process PEB 443 <7>UBI DBG (pid 732): ubi_scan: process PEB 444 <7>UBI DBG (pid 732): ubi_scan: process PEB 445 <7>UBI DBG (pid 732): ubi_scan: process PEB 446 <7>UBI DBG (pid 732): ubi_scan: process PEB 447 <7>UBI DBG (pid 732): ubi_scan: process PEB 448 <7>UBI DBG (pid 732): ubi_scan: process PEB 449 <7>UBI DBG (pid 732): ubi_scan: process PEB 450 <7>UBI DBG (pid 732): ubi_scan: process PEB 451 <7>UBI DBG (pid 732): ubi_scan: process PEB 452 <7>UBI DBG (pid 732): ubi_scan: process PEB 453 <7>UBI DBG (pid 732): ubi_scan: process PEB 454 <7>UBI DBG (pid 732): ubi_scan: process PEB 455 <7>UBI DBG (pid 732): ubi_scan: process PEB 456 <7>UBI DBG (pid 732): ubi_scan: process PEB 457 <7>UBI DBG (pid 732): ubi_scan: process PEB 458 <7>UBI DBG (pid 732): ubi_scan: process PEB 459 <7>UBI DBG (pid 732): ubi_scan: process PEB 460 <7>UBI DBG (pid 732): ubi_scan: process PEB 461 <6>Block 2936 is factory bad in chip 0, offset = 16f00000 <7>UBI DBG (pid 732): ubi_scan: process PEB 462 <7>UBI DBG (pid 732): ubi_scan: process PEB 463 <7>UBI DBG (pid 732): ubi_scan: process PEB 464 <7>UBI DBG (pid 732): ubi_scan: process PEB 465 <7>UBI DBG (pid 732): ubi_scan: process PEB 466 <7>UBI DBG (pid 732): ubi_scan: process PEB 467 <7>UBI DBG (pid 732): ubi_scan: process PEB 468 <7>UBI DBG (pid 732): ubi_scan: process PEB 469 <7>UBI DBG (pid 732): ubi_scan: process PEB 470 <7>UBI DBG (pid 732): ubi_scan: process PEB 471 <7>UBI DBG (pid 732): ubi_scan: process PEB 472 <7>UBI DBG (pid 732): ubi_scan: process PEB 473 <7>UBI DBG (pid 732): ubi_scan: process PEB 474 <7>UBI DBG (pid 732): ubi_scan: process PEB 475 <7>UBI DBG (pid 732): ubi_scan: process PEB 476 <7>UBI DBG (pid 732): ubi_scan: process PEB 477 <7>UBI DBG (pid 732): ubi_scan: process PEB 478 <7>UBI DBG (pid 732): ubi_scan: process PEB 479 <7>UBI DBG (pid 732): ubi_scan: process PEB 480 <7>UBI DBG (pid 732): ubi_scan: process PEB 481 <7>UBI DBG (pid 732): ubi_scan: process PEB 482 <7>UBI DBG (pid 732): ubi_scan: process PEB 483 <7>UBI DBG (pid 732): ubi_scan: process PEB 484 <7>UBI DBG (pid 732): ubi_scan: process PEB 485 <7>UBI DBG (pid 732): ubi_scan: process PEB 486 <7>UBI DBG (pid 732): ubi_scan: process PEB 487 <7>UBI DBG (pid 732): ubi_scan: process PEB 488 <7>UBI DBG (pid 732): ubi_scan: process PEB 489 <7>UBI DBG (pid 732): ubi_scan: process PEB 490 <7>UBI DBG (pid 732): ubi_scan: process PEB 491 <7>UBI DBG (pid 732): ubi_scan: process PEB 492 <7>UBI DBG (pid 732): ubi_scan: process PEB 493 <7>UBI DBG (pid 732): ubi_scan: process PEB 494 <7>UBI DBG (pid 732): ubi_scan: process PEB 495 <7>UBI DBG (pid 732): ubi_scan: process PEB 496 <7>UBI DBG (pid 732): ubi_scan: process PEB 497 <7>UBI DBG (pid 732): ubi_scan: process PEB 498 <7>UBI DBG (pid 732): ubi_scan: process PEB 499 <7>UBI DBG (pid 732): ubi_scan: process PEB 500 <7>UBI DBG (pid 732): ubi_scan: process PEB 501 <7>UBI DBG (pid 732): ubi_scan: process PEB 502 <7>UBI DBG (pid 732): ubi_scan: process PEB 503 <7>UBI DBG (pid 732): ubi_scan: process PEB 504 <7>UBI DBG (pid 732): ubi_scan: process PEB 505 <7>UBI DBG (pid 732): ubi_scan: process PEB 506 <7>UBI DBG (pid 732): ubi_scan: process PEB 507 <7>UBI DBG (pid 732): ubi_scan: process PEB 508 <7>UBI DBG (pid 732): ubi_scan: process PEB 509 <7>UBI DBG (pid 732): ubi_scan: process PEB 510 <7>UBI DBG (pid 732): ubi_scan: process PEB 511 <7>UBI DBG (pid 732): ubi_scan: scanning is finished <6>Block 2540 is factory bad in chip 0, offset = 13d80000 <6>Block 2541 is factory bad in chip 0, offset = 13da0000 <6>Block 2936 is factory bad in chip 0, offset = 16f00000 <7>UBI DBG (pid 732): process_lvol: check layout volume <7>UBI DBG (pid 732): ubi_resize_volume: re-size device 0, volume 2 to from 133 to 234 PEBs <5>UBI: volume 2 ("userdata") re-sized from 133 to 234 LEBs <7>UBI DBG (pid 732): uif_init: ubi0 major is 249 <7>UBI DBG (pid 732): ubi_add_volume: add volume 0 <7>UBI DBG (pid 732): ubi_add_volume: add volume 1 <7>UBI DBG (pid 732): ubi_add_volume: add volume 2 <5>UBI: attached mtd5 to ubi0 <5>UBI: MTD device name: "ubi" <5>UBI: MTD device size: 64 MiB <5>UBI: number of good PEBs: 509 <5>UBI: number of bad PEBs: 3 <5>UBI: max. allowed volumes: 128 <5>UBI: wear-leveling threshold: 4096 <5>UBI: number of internal volumes: 1 <5>UBI: number of user volumes: 3 <5>UBI: available PEBs: 0 <5>UBI: total number of reserved PEBs: 509 <5>UBI: number of PEBs reserved for bad PEB handling: 5 <5>UBI: max/mean erase counter: 1/0 <5>UBI: image sequence number: 506431851 <5>UBI: background thread "ubi_bgt0d" started, PID 737 <7>UBIFS DBG (pid 763): ubifs_get_sb: name ubi0_0, flags 0x8000 <7>UBI DBG (pid 763): ubi_open_volume_path: open volume ubi0_0, mode 1 <7>UBI DBG (pid 763): ubi_open_volume: open device 0, volume 0, mode 1 <7>UBIFS DBG (pid 763): ubifs_get_sb: opened ubi0_0 <7>UBI DBG (pid 763): ubi_open_volume: open device 0, volume 0, mode 2 <7>UBI DBG (pid 763): ubi_is_mapped: test LEB 0:0 <7>UBIFS DBG (pid 763): ubifs_read_node: LEB 0:0, superblock node, length 4096 <7>UBI DBG (pid 763): ubi_leb_read: read 4096 bytes from LEB 0:0:0 <7>UBIFS DBG (pid 763): ubifs_read_superblock: Auto resizing (sb) from 64 LEBs to 128 LEBs <7>UBI DBG (pid 763): ubi_leb_change: atomically write 4096 bytes to LEB 0:0 <7>UBIFS DBG (pid 763): ubifs_start_scan: scan LEB 1:0 <7>UBI DBG (pid 763): ubi_leb_read: read 126976 bytes from LEB 0:1:0 <7>UBIFS DBG (pid 765): ubifs_bg_thread: background thread "ubifs_bgt0_0" started, PID 765 <7>UBIFS DBG (pid 763): ubifs_scan: look at LEB 1:0 (126976 bytes left) <7>UBIFS DBG (pid 763): ubifs_scan_a_node: scanning master node <7>UBIFS DBG (pid 763): ubifs_scan: look at LEB 1:512 (126464 bytes left) <7>UBIFS DBG (pid 763): ubifs_scan_a_node: scanning padding node <7>UBIFS DBG (pid 763): ubifs_scan_a_node: 1508 bytes padded, offset now 2048 <7>UBIFS DBG (pid 763): ubifs_scan: look at LEB 1:2048 (124928 bytes left) <7>UBIFS DBG (pid 763): ubifs_scan_a_node: hit empty space <7>UBIFS DBG (pid 763): ubifs_end_scan: stop scanning LEB 1 at offset 2048 <7>UBIFS DBG (pid 763): ubifs_start_scan: scan LEB 2:0 <7>UBI DBG (pid 763): ubi_leb_read: read 126976 bytes from LEB 0:2:0 <7>UBIFS DBG (pid 763): ubifs_scan: look at LEB 2:0 (126976 bytes left) <7>UBIFS DBG (pid 763): ubifs_scan_a_node: scanning master node <7>UBIFS DBG (pid 763): ubifs_scan: look at LEB 2:512 (126464 bytes left) <7>UBIFS DBG (pid 763): ubifs_scan_a_node: scanning padding node <7>UBIFS DBG (pid 763): ubifs_scan_a_node: 1508 bytes padded, offset now 2048 <7>UBIFS DBG (pid 763): ubifs_scan: look at LEB 2:2048 (124928 bytes left) <7>UBIFS DBG (pid 763): ubifs_scan_a_node: hit empty space <7>UBIFS DBG (pid 763): ubifs_end_scan: stop scanning LEB 2 at offset 2048 <7>UBIFS DBG (pid 763): ubifs_read_master: Auto resizing (master) from 64 LEBs to 128 LEBs <7>UBIFS DBG (pid 763): ubifs_read_node: LEB 63:74888, indexing node, length 148 <7>UBI DBG (pid 763): ubi_leb_read: read 148 bytes from LEB 0:63:74888 <7>UBIFS DBG (pid 763): ubifs_write_node: LEB 1:2048, master node, length 512 (aligned 2048) <7>UBI DBG (pid 763): ubi_leb_write: write 2048 bytes to LEB 0:1:2048 <3>UBI error: ubi_io_read: error -22 while reading 2048 bytes from PEB 3:6144, read 0 bytes Backtrace: [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c) r7:00000800 r6:db100800 r5:ffffffea r4:00000800 [] (dump_stack+0x0/0x1c) from [] (ubi_io_read+0x160/0x284) [] (ubi_io_read+0x0/0x284) from [] (ubi_dbg_check_write+0x4c/0x19c) [] (ubi_dbg_check_write+0x0/0x19c) from [] (ubi_io_write+0x12c/0x3dc) [] (ubi_io_write+0x0/0x3dc) from [] (ubi_eba_write_leb+0x90/0x840) [] (ubi_eba_write_leb+0x0/0x840) from [] (ubi_leb_write+0x134/0x140) [] (ubi_leb_write+0x0/0x140) from [] (dbg_leb_write+0x128/0x140) [] (dbg_leb_write+0x0/0x140) from [] (ubifs_write_node+0xd4/0x210) [] (ubifs_write_node+0x0/0x210) from [] (ubifs_write_master+0xac/0x15c) [] (ubifs_write_master+0x0/0x15c) from [] (ubifs_fill_super+0xbfc/0x1a80) r7:00000070 r6:db085008 r5:db085000 r4:00000000 [] (ubifs_fill_super+0x0/0x1a80) from [] (ubifs_get_sb+0xec/0x36c) [] (ubifs_get_sb+0x0/0x36c) from [] (vfs_kern_mount+0x58/0xac) [] (vfs_kern_mount+0x0/0xac) from [] (do_kern_mount+0x3c/0xdc) r8:00008000 r7:db08f000 r6:00000000 r5:dbad1000 r4:c04d5d58 [] (do_kern_mount+0x0/0xdc) from [] (do_mount+0x16c/0x76c) r9:00000000 r8:00008000 r7:dbad1000 r6:db08f000 r5:00000000 r4:00000000 [] (do_mount+0x0/0x76c) from [] (sys_mount+0x90/0xdc) [] (sys_mount+0x0/0xdc) from [] (ret_fast_syscall+0x0/0x2c) r7:00000015 r6:afe47470 r5:00000104 r4:00000000 <4>UBI warning: ubi_eba_write_leb: failed to write data to PEB 3 <4>UBI warning: ubi_ro_mode: switch to read-only mode <3>UBIFS error (pid 763): ubifs_write_node: cannot write 2048 bytes to LEB 1:2048, error -22 <7> magic 0x6101831 <7> crc 0xfd668bb6 <7> node_type 7 (master node) <7> group_type 0 (no node group) <7> sqnum 3342 <7> len 512 <7> highest_inum 276 <7> commit number 0 <7> flags 0x3 <7> log_lnum 3 <7> root_lnum 63 <7> root_offs 74888 <7> root_len 148 <7> gc_lnum 62 <7> ihead_lnum 63 <7> ihead_offs 75776 <7> index_size 75040 <7> lpt_lnum 7 <7> lpt_offs 298 <7> nhead_lnum 7 <7> nhead_offs 2048 <7> ltab_lnum 7 <7> ltab_offs 310 <7> lsave_lnum 0 <7> lsave_offs 0 <7> lscan_lnum 10 <7> leb_cnt 128 <7> empty_lebs 65 <7> idx_lebs 1 <7> total_free 8345600 <7> total_dirty 42592 <7> total_used 6519936 <7> total_dead 30120 <7> total_dark 451432 Backtrace: [] (dump_backtrace+0x0/0x10c) from [] (dump_stack+0x18/0x1c) r7:ffffffea r6:00000001 r5:00000800 r4:db085000 [] (dump_stack+0x0/0x1c) from [] (ubifs_write_node+0x128/0x210) [] (ubifs_write_node+0x0/0x210) from [] (ubifs_write_master+0xac/0x15c) [] (ubifs_write_master+0x0/0x15c) from [] (ubifs_fill_super+0xbfc/0x1a80) r7:00000070 r6:db085008 r5:db085000 r4:00000000 [] (ubifs_fill_super+0x0/0x1a80) from [] (ubifs_get_sb+0xec/0x36c) [] (ubifs_get_sb+0x0/0x36c) from [] (vfs_kern_mount+0x58/0xac) [] (vfs_kern_mount+0x0/0xac) from [] (do_kern_mount+0x3c/0xdc) r8:00008000 r7:db08f000 r6:00000000 r5:dbad1000 r4:c04d5d58 [] (do_kern_mount+0x0/0xdc) from [] (do_mount+0x16c/0x76c) r9:00000000 r8:00008000 r7:dbad1000 r6:db08f000 r5:00000000 r4:00000000 [] (do_mount+0x0/0x76c) from [] (sys_mount+0x90/0xdc) [] (sys_mount+0x0/0xdc) from [] (ret_fast_syscall+0x0/0x2c) r7:00000015 r6:afe47470 r5:00000104 r4:00000000 <7>UBIFS DBG (pid 765): ubifs_bg_thread: background thread "ubifs_bgt0_0" stops <7>UBI DBG (pid 763): ubi_close_volume: close device 0, volume 0, mode 2 <7>UBI DBG (pid 763): ubi_close_volume: close device 0, volume 0, mode 1 ?? 2010??5??4??????11:20???????? ?????? > Dear all, > > I find the root cause: bootloader > > UBI image, written by bootloader, could not be mount. > UBI image, written by ubiformat command, could be mount correctly. > > I guess that bootloader may not write ubi image correctly. > I will port ubiformat in bootloader. > > Thank you, > Best regards, > > 2010/5/3 Artem Bityutskiy : >> On Mon, 2010-05-03 at 19:54 +0800, ?????? wrote: >>> Dear all, >>> >>> Thank you for your support. >>> I can mount UBIFS now after fixing mtd read function. >>> >>> However, if I enable the "extra checks" of UBI and UBIFS, then I can >>> not mount UBIFS. >>> What's the different after enable "extra checks" of UBI and UBIFS. >> >> Well, these are various self-checks. There are many of them and they are >> different. E.g., in UBI some of them read flash before every writing and >> make sure the area contains all 0xFF bytes. In UBIFS this can be walking >> through the whole index tree and checks it. There are many of them and >> they are different. >> >> If things stop working for you when you enable all checks, this either >> means a bug in the debugging code or a real problem. Please, post your >> error report. Use this guide: >> >> http://www.linux-mtd.infradead.org/doc/ubifs.html#L_how_send_bugreport >> >> -- >> Best Regards, >> Artem Bityutskiy (?????????? ????????????????) >> >> > From dedekind1 at gmail.com Tue May 11 01:44:50 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 11 May 2010 08:44:50 +0300 Subject: Can not mount UBIFS In-Reply-To: References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> <1272888512.27729.46.camel@localhost> Message-ID: <1273556690.2209.146.camel@localhost> On Tue, 2010-05-11 at 11:46 +0800, ??? wrote: > Dear all, > > I have modified bootloader to download image as ubiformat does. > However, I still can not mount it. > I also dump the content of mtd partition and compare. > (Ex: dd if=/dev/block/mtdblock5 of=/data/mtd5bak) > No difference between the content written by bootloader and written by > ubiformat. > ... snip ... > <3>UBI error: ubi_io_read: error -22 while reading 2048 bytes from PEB > 3:6144, read 0 bytes Well, find out why your driver returns -EINVAL and read count 0 when you read 2048 bytes from PEB 3 on this partition, and offset 6144. Dig the driver. -- Best Regards, Artem Bityutskiy (????? ????????) From muehlfelder at enertex.de Tue May 11 03:59:35 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Tue, 11 May 2010 09:59:35 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: References: <201005031505.18604.muehlfelder@enertex.de> <1273049480.3702.129.camel@localhost> Message-ID: <201005110959.36213.muehlfelder@enertex.de> Am Wednesday 05 May 2010 11:20:42 schrieb Ricard Wanderlof: > > I did not really follow the discussion, so sorry if the following is > > unrelated: I think it should not be too difficult to teach JFFS2 to > > force GC on eraseblocks with bit-flips. > > I think in this case the partition in question just held a raw Linux > kernel with no file system, so JFFS2 is out of the picture here. > > /Ricard After investigating the problem I can tell you, that you are completly right ;-) Atmel's flash tool Sam-ba 2.5 was used to flash the first NAND partition as follows: 1. Bootstrap 2. U-Boot bootloader 3. U-Boot environment variables 4. uImage Linux kernel All these things are just written raw to predefined memory addresses and if some bit in there will flip, the system won't boot anymore. So my idea was to create an image of that partition from within running Linux, check if the partition changes and if so write it back before shutdown. At least this may reduce the failing rate. But unfortunately the Sam-Ba 2.5 tool has a bug: it uses different bad block table structure and Linux refuses to read/write every block, that was written by Sam-Ba 2.5 because it recognizes them as bad blocks. So for now I have no idea what I can do to reduce the failing rate. At least there is still no board using Samsung flash that has failed and I hope all problems are related to the Micron flash. Kind regards Thorsten From muehlfelder at enertex.de Tue May 11 04:09:06 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Tue, 11 May 2010 10:09:06 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <4BE12D86.2070605@aimvalley.nl> References: <201005031505.18604.muehlfelder@enertex.de> <201005041659.26262.muehlfelder@enertex.de> <4BE12D86.2070605@aimvalley.nl> Message-ID: <201005111009.06724.muehlfelder@enertex.de> Am Wednesday 05 May 2010 10:34:14 schrieb Norbert van Bolhuis: > It much more easier to let UBI/UBIFS deal with this suff. It's designed for > this. > u-boot support UBIFS (read-only). This means you can put a kernel image > on UBIFS and make u-boot read/boot it. How would I do this? The only thing I've found about it is this discussion of April 2008: http://lists.infradead.org/pipermail/linux-mtd/2008-April/021268.html Thanks for any tip Thorsten From saeed.bishara at gmail.com Tue May 11 04:28:59 2010 From: saeed.bishara at gmail.com (saeed bishara) Date: Tue, 11 May 2010 11:28:59 +0300 Subject: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices In-Reply-To: References: Message-ID: hi, This patch is needed when using >4GiB nand partitions, any idea why it has not been merged yet? saeed On Fri, Apr 3, 2009 at 11:18 PM, Kevin Cernekee wrote: > Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB > flash devices. > > Use the new sysfs interface to query device info. > > Dependencies: > > "4GiB" extended ioctls: > http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html > > Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477 > > Optional: Driver model updates 2/2: > http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html > > Signed-off-by: Kevin Cernekee > --- > ?Makefile ? ? ? ? ? ? ? | ? 19 +++- > ?flash_erase.c ? ? ? ? ?| ? 59 ++++++---- > ?flash_eraseall.c ? ? ? | ? 31 +++-- > ?flash_lock.c ? ? ? ? ? | ? 21 ++-- > ?flash_unlock.c ? ? ? ? | ? ?9 +- > ?flashcp.c ? ? ? ? ? ? ?| ? 22 ++-- > ?include/mtd/mtd-abi.h ?| ? 24 ++++- > ?include/mtd/mtd-user.h | ? ?4 +- > ?mtd_debug.c ? ? ? ? ? ?| ?114 ++++++++++--------- > ?mtd_ioctl.c ? ? ? ? ? ?| ?303 ++++++++++++++++++++++++++++++++++++++++++++++++ > ?mtd_ioctl.h ? ? ? ? ? ?| ? 38 ++++++ > ?nanddump.c ? ? ? ? ? ? | ? 23 +++-- > ?nandtest.c ? ? ? ? ? ? | ? 35 +++--- > ?nandwrite.c ? ? ? ? ? ?| ? 54 +++++---- > ?14 files changed, 585 insertions(+), 171 deletions(-) > ?create mode 100644 mtd_ioctl.c > ?create mode 100644 mtd_ioctl.h > > diff --git a/Makefile b/Makefile > index 969ab87..8bf2695 100644 > --- a/Makefile > +++ b/Makefile > @@ -41,7 +41,24 @@ $(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\ > ?LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS) > ?LDLIBS_mkfs.jffs2 ?= -lz -llzo2 > > -$(BUILDDIR)/flash_eraseall: $(BUILDDIR)/crc32.o $(BUILDDIR)/flash_eraseall.o > +$(BUILDDIR)/flash_eraseall: $(BUILDDIR)/crc32.o $(BUILDDIR)/flash_eraseall.o \ > + ? ? ? $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/flash_erase: $(BUILDDIR)/flash_erase.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/nandwrite: $(BUILDDIR)/nandwrite.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/nandtest: $(BUILDDIR)/nandtest.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/nanddump: $(BUILDDIR)/nanddump.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/flashcp: $(BUILDDIR)/flashcp.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/flash_lock: $(BUILDDIR)/flash_lock.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/flash_unlock: $(BUILDDIR)/flash_unlock.o $(BUILDDIR)/mtd_ioctl.o > + > +$(BUILDDIR)/mtd_debug: $(BUILDDIR)/mtd_debug.o $(BUILDDIR)/mtd_ioctl.o > > ?$(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o > ?LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS) > diff --git a/flash_erase.c b/flash_erase.c > index fdf9918..f689cf5 100644 > --- a/flash_erase.c > +++ b/flash_erase.c > @@ -11,22 +11,25 @@ > ?#include > ?#include > ?#include > +#include "mtd_ioctl.h" > > -int region_erase(int Fd, int start, int count, int unlock, int regcount) > +int region_erase(int Fd, long long start, int count, int unlock, int regcount) > ?{ > ? ? ? ?int i, j; > - ? ? ? region_info_t * reginfo; > + ? ? ? region_info64_t * reginfo; > > ? ? ? ?reginfo = calloc(regcount, sizeof(region_info_t)); > > ? ? ? ?for(i = 0; i < regcount; i++) > ? ? ? ?{ > ? ? ? ? ? ? ? ?reginfo[i].regionindex = i; > - ? ? ? ? ? ? ? if(ioctl(Fd,MEMGETREGIONINFO,&(reginfo[i])) != 0) > + ? ? ? ? ? ? ? if(mtd_ioctl_getregioninfo(Fd,&(reginfo[i])) != 0) > ? ? ? ? ? ? ? ? ? ? ? ?return 8; > ? ? ? ? ? ? ? ?else > - ? ? ? ? ? ? ? ? ? ? ? printf("Region %d is at %d of %d sector and with sector " > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "size %x\n", i, reginfo[i].offset, reginfo[i].numblocks, > + ? ? ? ? ? ? ? ? ? ? ? printf("Region %d is at %lld of %d sector and with sector " > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "size %x\n", i, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)reginfo[i].offset, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? reginfo[i].numblocks, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?reginfo[i].erasesize); > ? ? ? ?} > > @@ -34,7 +37,7 @@ int region_erase(int Fd, int start, int count, int > unlock, int regcount) > > ? ? ? ?for(i = 0; i < regcount; i++) > ? ? ? ?{ //Loop through the regions > - ? ? ? ? ? ? ? region_info_t * r = &(reginfo[i]); > + ? ? ? ? ? ? ? region_info64_t * r = &(reginfo[i]); > > ? ? ? ? ? ? ? ?if((start >= reginfo[i].offset) && > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(start < (r->offset + r->numblocks*r->erasesize))) > @@ -43,7 +46,7 @@ int region_erase(int Fd, int start, int count, int > unlock, int regcount) > > ? ? ? ?if(i >= regcount) > ? ? ? ?{ > - ? ? ? ? ? ? ? printf("Starting offset %x not within chip.\n", start); > + ? ? ? ? ? ? ? printf("Starting offset %llx not within chip.\n", start); > ? ? ? ? ? ? ? ?return 8; > ? ? ? ?} > > @@ -52,25 +55,28 @@ int region_erase(int Fd, int start, int count, int > unlock, int regcount) > > ? ? ? ?for(j = 0; (j < count)&&(i < regcount); j++) > ? ? ? ?{ > - ? ? ? ? ? ? ? erase_info_t erase; > - ? ? ? ? ? ? ? region_info_t * r = &(reginfo[i]); > + ? ? ? ? ? ? ? erase_info64_t erase; > + ? ? ? ? ? ? ? region_info64_t * r = &(reginfo[i]); > + > + ? ? ? ? ? ? ? memset(&erase, 0, sizeof(erase)); > > ? ? ? ? ? ? ? ?erase.start = start; > ? ? ? ? ? ? ? ?erase.length = r->erasesize; > > ? ? ? ? ? ? ? ?if(unlock != 0) > ? ? ? ? ? ? ? ?{ //Unlock the sector first. > - ? ? ? ? ? ? ? ? ? ? ? if(ioctl(Fd, MEMUNLOCK, &erase) != 0) > + ? ? ? ? ? ? ? ? ? ? ? if(mtd_ioctl_unlock(Fd, &erase) != 0) > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?perror("\nMTD Unlock failure"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?close(Fd); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?return 8; > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?} > - ? ? ? ? ? ? ? printf("\rPerforming Flash Erase of length %u at offset 0x%x", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? erase.length, erase.start); > + ? ? ? ? ? ? ? printf("\rPerforming Flash Erase of length %llu at offset 0x%llx", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.length, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.start); > ? ? ? ? ? ? ? ?fflush(stdout); > - ? ? ? ? ? ? ? if(ioctl(Fd, MEMERASE, &erase) != 0) > + ? ? ? ? ? ? ? if(mtd_ioctl_erase(Fd, &erase) != 0) > ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?perror("\nMTD Erase failure"); > ? ? ? ? ? ? ? ? ? ? ? ?close(Fd); > @@ -91,28 +97,31 @@ int region_erase(int Fd, int start, int count, int > unlock, int regcount) > ? ? ? ?return 0; > ?} > > -int non_region_erase(int Fd, int start, int count, int unlock) > +int non_region_erase(int Fd, long long start, int count, int unlock) > ?{ > - ? ? ? mtd_info_t meminfo; > + ? ? ? mtd_info64_t meminfo; > > - ? ? ? if (ioctl(Fd,MEMGETINFO,&meminfo) == 0) > + ? ? ? if (mtd_ioctl_getinfo(Fd,&meminfo) == 0) > ? ? ? ?{ > - ? ? ? ? ? ? ? erase_info_t erase; > + ? ? ? ? ? ? ? erase_info64_t erase; > > - ? ? ? ? ? ? ? erase.start = start; > + ? ? ? ? ? ? ? memset(&erase, 0, sizeof(erase)); > > + ? ? ? ? ? ? ? erase.start = start; > ? ? ? ? ? ? ? ?erase.length = meminfo.erasesize; > > ? ? ? ? ? ? ? ?for (; count > 0; count--) { > - ? ? ? ? ? ? ? ? ? ? ? printf("\rPerforming Flash Erase of length %u at offset 0x%x", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? erase.length, erase.start); > + ? ? ? ? ? ? ? ? ? ? ? printf("\rPerforming Flash Erase of length %llu at offset 0x%llx", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.length, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.start); > ? ? ? ? ? ? ? ? ? ? ? ?fflush(stdout); > > ? ? ? ? ? ? ? ? ? ? ? ?if(unlock != 0) > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//Unlock the sector first. > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("\rPerforming Flash unlock at offset 0x%x",erase.start); > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(ioctl(Fd, MEMUNLOCK, &erase) != 0) > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf("\rPerforming Flash unlock at offset 0x%llx", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.start); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(mtd_ioctl_unlock(Fd, &erase) != 0) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?perror("\nMTD Unlock failure"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?close(Fd); > @@ -120,7 +129,7 @@ int non_region_erase(int Fd, int start, int count, > int unlock) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ?} > > - ? ? ? ? ? ? ? ? ? ? ? if (ioctl(Fd,MEMERASE,&erase) != 0) > + ? ? ? ? ? ? ? ? ? ? ? if (mtd_ioctl_erase(Fd,&erase) != 0) > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?perror("\nMTD Erase failure"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?close(Fd); > @@ -137,7 +146,7 @@ int main(int argc,char *argv[]) > ?{ > ? ? ? ?int regcount; > ? ? ? ?int Fd; > - ? ? ? int start; > + ? ? ? long long start; > ? ? ? ?int count; > ? ? ? ?int unlock; > ? ? ? ?int res = 0; > @@ -149,7 +158,7 @@ int main(int argc,char *argv[]) > ? ? ? ?} > > ? ? ? ?if (argc > 2) > - ? ? ? ? ? ? ? start = strtol(argv[2], NULL, 0); > + ? ? ? ? ? ? ? start = strtoll(argv[2], NULL, 0); > ? ? ? ?else > ? ? ? ? ? ? ? ?start = 0; > > diff --git a/flash_eraseall.c b/flash_eraseall.c > index a22fc49..8f44570 100644 > --- a/flash_eraseall.c > +++ b/flash_eraseall.c > @@ -36,6 +36,7 @@ > ?#include > ?#include > ?#include "crc32.h" > +#include "mtd_ioctl.h" > > ?#include > ?#include > @@ -49,7 +50,7 @@ static int quiet; ? ? ? ? ? ? /* true -- don't output progress */ > ?static int jffs2; ? ? ? ? ? ? ?// format for jffs2 usage > > ?static void process_options (int argc, char *argv[]); > -void show_progress (mtd_info_t *meminfo, erase_info_t *erase); > +void show_progress (mtd_info64_t *meminfo, erase_info64_t *erase); > ?static void display_help (void); > ?static void display_version (void); > ?static struct jffs2_unknown_node cleanmarker; > @@ -57,9 +58,9 @@ int target_endian = __BYTE_ORDER; > > ?int main (int argc, char *argv[]) > ?{ > - ? ? ? mtd_info_t meminfo; > + ? ? ? mtd_info64_t meminfo; > ? ? ? ?int fd, clmpos = 0, clmlen = 8; > - ? ? ? erase_info_t erase; > + ? ? ? erase_info64_t erase; > ? ? ? ?int isNAND, bbtest = 1; > > ? ? ? ?process_options(argc, argv); > @@ -70,11 +71,12 @@ int main (int argc, char *argv[]) > ? ? ? ?} > > > - ? ? ? if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { > + ? ? ? if (mtd_ioctl_getinfo(fd, &meminfo) != 0) { > ? ? ? ? ? ? ? ?fprintf(stderr, "%s: %s: unable to get MTD device info\n", > exe_name, mtd_device); > ? ? ? ? ? ? ? ?return 1; > ? ? ? ?} > > + ? ? ? memset(&erase, 0, sizeof(erase)); > ? ? ? ?erase.length = meminfo.erasesize; > ? ? ? ?isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0; > > @@ -130,7 +132,8 @@ int main (int argc, char *argv[]) > ? ? ? ? ? ? ? ? ? ? ? ?int ret = ioctl(fd, MEMGETBADBLOCK, &offset); > ? ? ? ? ? ? ? ? ? ? ? ?if (ret > 0) { > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (!quiet) > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf ("\nSkipping bad block at 0x%08x\n", erase.start); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf ("\nSkipping bad block at 0x%08llx\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.start); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?continue; > ? ? ? ? ? ? ? ? ? ? ? ?} else if (ret < 0) { > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (errno == EOPNOTSUPP) { > @@ -149,7 +152,7 @@ int main (int argc, char *argv[]) > ? ? ? ? ? ? ? ?if (!quiet) > ? ? ? ? ? ? ? ? ? ? ? ?show_progress(&meminfo, &erase); > > - ? ? ? ? ? ? ? if (ioctl(fd, MEMERASE, &erase) != 0) { > + ? ? ? ? ? ? ? if (mtd_ioctl_erase(fd, &erase) != 0) { > ? ? ? ? ? ? ? ? ? ? ? ?fprintf(stderr, "\n%s: %s: MTD Erase failure: %s\n", exe_name, > mtd_device, strerror(errno)); > ? ? ? ? ? ? ? ? ? ? ? ?continue; > ? ? ? ? ? ? ? ?} > @@ -160,11 +163,12 @@ int main (int argc, char *argv[]) > > ? ? ? ? ? ? ? ?/* write cleanmarker */ > ? ? ? ? ? ? ? ?if (isNAND) { > - ? ? ? ? ? ? ? ? ? ? ? struct mtd_oob_buf oob; > - ? ? ? ? ? ? ? ? ? ? ? oob.ptr = (unsigned char *) &cleanmarker; > + ? ? ? ? ? ? ? ? ? ? ? struct mtd_oob_buf64 oob; > + ? ? ? ? ? ? ? ? ? ? ? memset(&oob, 0, sizeof(oob)); > + ? ? ? ? ? ? ? ? ? ? ? oob.usr_ptr = (uintptr_t) &cleanmarker; > ? ? ? ? ? ? ? ? ? ? ? ?oob.start = erase.start + clmpos; > ? ? ? ? ? ? ? ? ? ? ? ?oob.length = clmlen; > - ? ? ? ? ? ? ? ? ? ? ? if (ioctl (fd, MEMWRITEOOB, &oob) != 0) { > + ? ? ? ? ? ? ? ? ? ? ? if (mtd_ioctl_writeoob(fd, &oob) != 0) { > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, > mtd_device, strerror(errno)); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?continue; > ? ? ? ? ? ? ? ? ? ? ? ?} > @@ -179,7 +183,8 @@ int main (int argc, char *argv[]) > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?if (!quiet) > - ? ? ? ? ? ? ? ? ? ? ? printf (" Cleanmarker written at %x.", erase.start); > + ? ? ? ? ? ? ? ? ? ? ? printf (" Cleanmarker written at %llx.", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.start); > ? ? ? ?} > ? ? ? ?if (!quiet) { > ? ? ? ? ? ? ? ?show_progress(&meminfo, &erase); > @@ -250,10 +255,10 @@ void process_options (int argc, char *argv[]) > ? ? ? ?mtd_device = argv[optind]; > ?} > > -void show_progress (mtd_info_t *meminfo, erase_info_t *erase) > +void show_progress (mtd_info64_t *meminfo, erase_info64_t *erase) > ?{ > - ? ? ? printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.", > - ? ? ? ? ? ? ? meminfo->erasesize / 1024, erase->start, > + ? ? ? printf("\rErasing %d Kibyte @ %llx -- %2llu %% complete.", > + ? ? ? ? ? ? ? meminfo->erasesize / 1024, (unsigned long long)erase->start, > ? ? ? ? ? ? ? ?(unsigned long long) erase->start * 100 / meminfo->size); > ? ? ? ?fflush(stdout); > ?} > diff --git a/flash_lock.c b/flash_lock.c > index dca6794..37509bf 100644 > --- a/flash_lock.c > +++ b/flash_lock.c > @@ -15,14 +15,15 @@ > ?#include > > ?#include > +#include "mtd_ioctl.h" > > ?int main(int argc, char *argv[]) > ?{ > ? ? ? ?int fd; > - ? ? ? struct mtd_info_user mtdInfo; > - ? ? ? struct erase_info_user mtdLockInfo; > - ? ? ? int num_sectors; > - ? ? ? int ofs; > + ? ? ? struct mtd_info_user64 mtdInfo; > + ? ? ? struct erase_info_user64 mtdLockInfo; > + ? ? ? long long num_sectors; > + ? ? ? long long ofs; > > ? ? ? ?/* > ? ? ? ? * Parse command line options > @@ -45,17 +46,17 @@ int main(int argc, char *argv[]) > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > > - ? ? ? if(ioctl(fd, MEMGETINFO, &mtdInfo)) > + ? ? ? if(mtd_ioctl_getinfo(fd, &mtdInfo)) > ? ? ? ?{ > ? ? ? ? ? ? ? ?fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]); > ? ? ? ? ? ? ? ?close(fd); > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > - ? ? ? sscanf(argv[2], "%x",&ofs); > - ? ? ? sscanf(argv[3], "%d",&num_sectors); > + ? ? ? sscanf(argv[2], "%llx",&ofs); > + ? ? ? sscanf(argv[3], "%lld",&num_sectors); > ? ? ? ?if(ofs > mtdInfo.size - mtdInfo.erasesize) > ? ? ? ?{ > - ? ? ? ? ? ? ? fprintf(stderr, "%x is beyond device size %x\n",ofs,(unsigned > int)(mtdInfo.size - mtdInfo.erasesize)); > + ? ? ? ? ? ? ? fprintf(stderr, "%llx is beyond device size %llx\n",ofs,(unsigned > long long)(mtdInfo.size - mtdInfo.erasesize)); > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > > @@ -65,14 +66,14 @@ int main(int argc, char *argv[]) > ? ? ? ?else { > ? ? ? ? ? ? ? ?if(num_sectors > mtdInfo.size/mtdInfo.erasesize) > ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "%d are too many sectors, device only has > %d\n",num_sectors,(int)(mtdInfo.size/mtdInfo.erasesize)); > + ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "%lld are too many sectors, device only has > %lld\n",num_sectors,(long long)(mtdInfo.size/mtdInfo.erasesize)); > ? ? ? ? ? ? ? ? ? ? ? ?exit(1); > ? ? ? ? ? ? ? ?} > ? ? ? ?} > > ? ? ? ?mtdLockInfo.start = ofs; > ? ? ? ?mtdLockInfo.length = num_sectors * mtdInfo.erasesize; > - ? ? ? if(ioctl(fd, MEMLOCK, &mtdLockInfo)) > + ? ? ? if(mtd_ioctl_lock(fd, &mtdLockInfo)) > ? ? ? ?{ > ? ? ? ? ? ? ? ?fprintf(stderr, "Could not lock MTD device: %s\n", argv[1]); > ? ? ? ? ? ? ? ?close(fd); > diff --git a/flash_unlock.c b/flash_unlock.c > index 648dc4f..b7793b7 100644 > --- a/flash_unlock.c > +++ b/flash_unlock.c > @@ -15,12 +15,13 @@ > ?#include > > ?#include > +#include "mtd_ioctl.h" > > ?int main(int argc, char *argv[]) > ?{ > ? ? ? ?int fd; > - ? ? ? struct mtd_info_user mtdInfo; > - ? ? ? struct erase_info_user mtdLockInfo; > + ? ? ? struct mtd_info_user64 mtdInfo; > + ? ? ? struct erase_info_user64 mtdLockInfo; > > ? ? ? ?/* > ? ? ? ? * Parse command line options > @@ -43,7 +44,7 @@ int main(int argc, char *argv[]) > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > > - ? ? ? if(ioctl(fd, MEMGETINFO, &mtdInfo)) > + ? ? ? if(mtd_ioctl_getinfo(fd, &mtdInfo)) > ? ? ? ?{ > ? ? ? ? ? ? ? ?fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]); > ? ? ? ? ? ? ? ?close(fd); > @@ -52,7 +53,7 @@ int main(int argc, char *argv[]) > > ? ? ? ?mtdLockInfo.start = 0; > ? ? ? ?mtdLockInfo.length = mtdInfo.size; > - ? ? ? if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) > + ? ? ? if(mtd_ioctl_unlock(fd, &mtdLockInfo)) > ? ? ? ?{ > ? ? ? ? ? ? ? ?fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]); > ? ? ? ? ? ? ? ?close(fd); > diff --git a/flashcp.c b/flashcp.c > index 8775022..d9bab84 100644 > --- a/flashcp.c > +++ b/flashcp.c > @@ -40,6 +40,7 @@ > ?#include > ?#include > ?#include > +#include "mtd_ioctl.h" > > ?typedef int bool; > ?#define true 1 > @@ -169,8 +170,8 @@ int main (int argc,char *argv[]) > ? ? ? ?int i,flags = FLAG_NONE; > ? ? ? ?ssize_t result; > ? ? ? ?size_t size,written; > - ? ? ? struct mtd_info_user mtd; > - ? ? ? struct erase_info_user erase; > + ? ? ? struct mtd_info_user64 mtd; > + ? ? ? struct erase_info_user64 erase; > ? ? ? ?struct stat filestat; > ? ? ? ?unsigned char src[BUFSIZE],dest[BUFSIZE]; > > @@ -226,7 +227,7 @@ int main (int argc,char *argv[]) > > ? ? ? ?/* get some info about the flash device */ > ? ? ? ?dev_fd = safe_open (device,O_SYNC | O_RDWR); > - ? ? ? if (ioctl (dev_fd,MEMGETINFO,&mtd) < 0) > + ? ? ? if (mtd_ioctl_getinfo (dev_fd,&mtd) < 0) > ? ? ? ?{ > ? ? ? ? ? ? ? ?DEBUG("ioctl(): %m\n"); > ? ? ? ? ? ? ? ?log_printf (LOG_ERROR,"This doesn't seem to be a valid MTD flash device!\n"); > @@ -254,6 +255,7 @@ int main (int argc,char *argv[]) > > ?#warning "Check for smaller erase regions" > > + ? ? ? memset(&erase, 0, sizeof(erase)); > ? ? ? ?erase.start = 0; > ? ? ? ?erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize; > ? ? ? ?erase.length *= mtd.erasesize; > @@ -261,18 +263,18 @@ int main (int argc,char *argv[]) > ? ? ? ?if (flags & FLAG_VERBOSE) > ? ? ? ?{ > ? ? ? ? ? ? ? ?/* if the user wants verbose output, erase 1 block at a time and > show him/her what's going on */ > - ? ? ? ? ? ? ? int blocks = erase.length / mtd.erasesize; > + ? ? ? ? ? ? ? long long blocks = erase.length / mtd.erasesize; > ? ? ? ? ? ? ? ?erase.length = mtd.erasesize; > ? ? ? ? ? ? ? ?log_printf (LOG_NORMAL,"Erasing blocks: 0/%d (0%%)",blocks); > ? ? ? ? ? ? ? ?for (i = 1; i <= blocks; i++) > ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d > (%d%%)",i,blocks,PERCENTAGE (i,blocks)); > - ? ? ? ? ? ? ? ? ? ? ? if (ioctl (dev_fd,MEMERASE,&erase) < 0) > + ? ? ? ? ? ? ? ? ? ? ? if (mtd_ioctl_erase (dev_fd, &erase) < 0) > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?log_printf (LOG_NORMAL,"\n"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?log_printf (LOG_ERROR, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "While erasing blocks 0x%.8x-0x%.8x on %s: %m\n", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned int) erase.start,(unsigned int) (erase.start + > erase.length),device); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "While erasing blocks 0x%.8llx-0x%.8llx on %s: %m\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? erase.start, (erase.start + erase.length),device); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?exit (EXIT_FAILURE); > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ?erase.start += mtd.erasesize; > @@ -282,11 +284,11 @@ int main (int argc,char *argv[]) > ? ? ? ?else > ? ? ? ?{ > ? ? ? ? ? ? ? ?/* if not, erase the whole chunk in one shot */ > - ? ? ? ? ? ? ? if (ioctl (dev_fd,MEMERASE,&erase) < 0) > + ? ? ? ? ? ? ? if (mtd_ioctl_erase (dev_fd, &erase) < 0) > ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ?log_printf (LOG_ERROR, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "While erasing blocks from 0x%.8x-0x%.8x on %s: %m\n", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned int) erase.start,(unsigned int) (erase.start + > erase.length),device); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "While erasing blocks from 0x%.8llx-0x%.8llx on %s: %m\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? erase.start, (erase.start + erase.length),device); > ? ? ? ? ? ? ? ? ? ? ? ?exit (EXIT_FAILURE); > ? ? ? ? ? ? ? ?} > ? ? ? ?} > diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h > index 86defe1..5e336bf 100644 > --- a/include/mtd/mtd-abi.h > +++ b/include/mtd/mtd-abi.h > @@ -1,23 +1,35 @@ > ?/* > - * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $ > - * > ?* Portions of MTD ABI definition which are shared by kernel and user space > ?*/ > > ?#ifndef __MTD_ABI_H__ > ?#define __MTD_ABI_H__ > > +#include > + > ?struct erase_info_user { > ? ? ? ?uint32_t start; > ? ? ? ?uint32_t length; > ?}; > > +struct erase_info_user64 { > + ? ? ? __u64 ? ?start; > + ? ? ? __u64 ? ?length; > +}; > + > ?struct mtd_oob_buf { > ? ? ? ?uint32_t start; > ? ? ? ?uint32_t length; > ? ? ? ?unsigned char *ptr; > ?}; > > +struct mtd_oob_buf64 { > + ? ? ? __u64 ? ?start; > + ? ? ? __u32 ? ?res0; > + ? ? ? __u32 ? ?length; > + ? ? ? __u64 ? ?usr_ptr; > +}; > + > ?#define MTD_ABSENT ? ? ? ? ? ? 0 > ?#define MTD_RAM ? ? ? ? ? ? ? ? ? ? ? ?1 > ?#define MTD_ROM ? ? ? ? ? ? ? ? ? ? ? ?2 > @@ -29,7 +41,7 @@ struct mtd_oob_buf { > ?#define MTD_WRITEABLE ? ? ? ? ?0x400 ? /* Device is writeable */ > ?#define MTD_BIT_WRITEABLE ? ? ?0x800 ? /* Single bits can be flipped */ > ?#define MTD_NO_ERASE ? ? ? ? ? 0x1000 ?/* No erase necessary */ > -#define MTD_STUPID_LOCK ? ? ? ? ? ? ? ?0x2000 ?/* Always locked after reset */ > +#define MTD_POWERUP_LOCK ? ? ? 0x2000 ?/* Always locked after reset */ > > ?// Some common devices / combinations of capabilities > ?#define MTD_CAP_ROM ? ? ? ? ? ?0 > @@ -96,6 +108,12 @@ struct otp_info { > ?#define ECCGETSTATS ? ? ? ? ? ?_IOR('M', 18, struct mtd_ecc_stats) > ?#define MTDFILEMODE ? ? ? ? ? ?_IO('M', 19) > > +#define MEMERASE64 ? ? ? ? ? ? _IOW('M', 20, struct erase_info_user64) > +#define MEMWRITEOOB64 ? ? ? ? ?_IOWR('M', 21, struct mtd_oob_buf64) > +#define MEMREADOOB64 ? ? ? ? ? _IOWR('M', 22, struct mtd_oob_buf64) > +#define MEMLOCK64 ? ? ? ? ? ? ?_IOW('M', 23, struct erase_info_user64) > +#define MEMUNLOCK64 ? ? ? ? ? ?_IOW('M', 24, struct erase_info_user64) > + > ?/* > ?* Obsolete legacy interface. Keep it in order not to break userspace > ?* interfaces > diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h > index 713f34d..a5ec18e 100644 > --- a/include/mtd/mtd-user.h > +++ b/include/mtd/mtd-user.h > @@ -1,6 +1,4 @@ > ?/* > - * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $ > - * > ?* MTD ABI header for use by user space only. > ?*/ > > @@ -18,4 +16,6 @@ typedef struct region_info_user region_info_t; > ?typedef struct nand_oobinfo nand_oobinfo_t; > ?typedef struct nand_ecclayout nand_ecclayout_t; > > +typedef struct erase_info_user64 erase_info64_t; > + > ?#endif /* __MTD_USER_H__ */ > diff --git a/mtd_debug.c b/mtd_debug.c > index 85d48e9..7d7dc3b 100644 > --- a/mtd_debug.c > +++ b/mtd_debug.c > @@ -37,28 +37,13 @@ > ?#include > ?#include > ?#include > - > -/* > - * MEMGETINFO > - */ > -static int getmeminfo (int fd,struct mtd_info_user *mtd) > -{ > - ? ? ? return (ioctl (fd,MEMGETINFO,mtd)); > -} > - > -/* > - * MEMERASE > - */ > -static int memerase (int fd,struct erase_info_user *erase) > -{ > - ? ? ? return (ioctl (fd,MEMERASE,erase)); > -} > +#include "mtd_ioctl.h" > > ?/* > ?* MEMGETREGIONCOUNT > - * MEMGETREGIONINFO > + * MEMGETREGIONINFO64 > ?*/ > -static int getregions (int fd,struct region_info_user *regions,int *n) > +static int getregions (int fd,struct region_info_user64 *regions,int *n) > ?{ > ? ? ? ?int i,err; > ? ? ? ?err = ioctl (fd,MEMGETREGIONCOUNT,n); > @@ -66,44 +51,48 @@ static int getregions (int fd,struct > region_info_user *regions,int *n) > ? ? ? ?for (i = 0; i < *n; i++) > ? ? ? ?{ > ? ? ? ? ? ? ? ?regions[i].regionindex = i; > - ? ? ? ? ? ? ? err = ioctl (fd,MEMGETREGIONINFO,®ions[i]); > + ? ? ? ? ? ? ? err = mtd_ioctl_getregioninfo (fd,®ions[i]); > ? ? ? ? ? ? ? ?if (err) return (err); > ? ? ? ?} > ? ? ? ?return (0); > ?} > > -int erase_flash (int fd,u_int32_t offset,u_int32_t bytes) > +int erase_flash (int fd,u_int64_t offset,u_int64_t bytes) > ?{ > ? ? ? ?int err; > - ? ? ? struct erase_info_user erase; > + ? ? ? struct erase_info_user64 erase; > + > + ? ? ? memset(&erase, 0, sizeof(erase)); > ? ? ? ?erase.start = offset; > ? ? ? ?erase.length = bytes; > - ? ? ? err = memerase (fd,&erase); > + > + ? ? ? err = mtd_ioctl_erase (fd,&erase); > ? ? ? ?if (err < 0) > ? ? ? ?{ > ? ? ? ? ? ? ? ?perror ("MEMERASE"); > ? ? ? ? ? ? ? ?return (1); > ? ? ? ?} > - ? ? ? fprintf (stderr,"Erased %d bytes from address 0x%.8x in > flash\n",bytes,offset); > + ? ? ? fprintf (stderr,"Erased %lld bytes from address 0x%.8llx in flash\n", > + ? ? ? ? ? ? ? (unsigned long long)bytes, (unsigned long long)offset); > ? ? ? ?return (0); > ?} > > -void printsize (u_int32_t x) > +void printsize (u_int64_t x) > ?{ > ? ? ? ?int i; > ? ? ? ?static const char *flags = "KMGT"; > - ? ? ? printf ("%u ",x); > + ? ? ? printf ("%llu ", (unsigned long long)x); > ? ? ? ?for (i = 0; x >= 1024 && flags[i] != '\0'; i++) x /= 1024; > ? ? ? ?i--; > - ? ? ? if (i >= 0) printf ("(%u%c)",x,flags[i]); > + ? ? ? if (i >= 0) printf ("(%llu%c)",(unsigned long long)x,flags[i]); > ?} > > -int flash_to_file (int fd,u_int32_t offset,size_t len,const char *filename) > +int flash_to_file (int fd, off_t offset,size_t len,const char *filename) > ?{ > ? ? ? ?u_int8_t *buf = NULL; > ? ? ? ?int outfd,err; > - ? ? ? int size = len * sizeof (u_int8_t); > - ? ? ? int n = len; > + ? ? ? size_t size = len * sizeof (u_int8_t); > + ? ? ? size_t n = len; > > ? ? ? ?if (offset != lseek (fd,offset,SEEK_SET)) > ? ? ? ?{ > @@ -121,10 +110,12 @@ retry: > ? ? ? ?if ((buf = (u_int8_t *) malloc (size)) == NULL) > ? ? ? ?{ > ?#define BUF_SIZE ? ? ? (64 * 1024 * sizeof (u_int8_t)) > - ? ? ? ? ? ? ? fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__, size); > + ? ? ? ? ? ? ? fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__, > + ? ? ? ? ? ? ? ? ? ? ? (unsigned int)size); > ? ? ? ? ? ? ? ?if (size != BUF_SIZE) { > ? ? ? ? ? ? ? ? ? ? ? ?size = BUF_SIZE; > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: trying buffer size %#x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (unsigned int)size); > ? ? ? ? ? ? ? ? ? ? ? ?goto retry; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?perror ("malloc()"); > @@ -136,20 +127,25 @@ retry: > ? ? ? ? ? ? ? ?err = read (fd,buf,size); > ? ? ? ? ? ? ? ?if (err < 0) > ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: read, size %#x, n %#x\n", __FUNCTION__, size, n); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: read, size %#x, n %#x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (unsigned int)size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned int)n); > ? ? ? ? ? ? ? ? ? ? ? ?perror ("read()"); > ? ? ? ? ? ? ? ? ? ? ? ?goto err2; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?err = write (outfd,buf,size); > ? ? ? ? ? ? ? ?if (err < 0) > ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: write, size %#x, n %#x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (unsigned int)size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned int)n); > ? ? ? ? ? ? ? ? ? ? ? ?perror ("write()"); > ? ? ? ? ? ? ? ? ? ? ? ?goto err2; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?if (err != size) > ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes > copied)\n",filename,err,size); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? filename,err,(int)size); > ? ? ? ? ? ? ? ? ? ? ? ?goto err2; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?n -= size; > @@ -158,7 +154,8 @@ retry: > ? ? ? ?if (buf != NULL) > ? ? ? ? ? ? ? ?free (buf); > ? ? ? ?close (outfd); > - ? ? ? printf ("Copied %d bytes from address 0x%.8x in flash to > %s\n",len,offset,filename); > + ? ? ? printf ("Copied %d bytes from address 0x%.8llx in flash to %s\n", > + ? ? ? ? ? ? ? (int)len,(unsigned long long)offset,filename); > ? ? ? ?return (0); > > ?err2: > @@ -170,13 +167,13 @@ err0: > ? ? ? ?return (1); > ?} > > -int file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char *filename) > +int file_to_flash (int fd, off_t offset, size_t len,const char *filename) > ?{ > ? ? ? ?u_int8_t *buf = NULL; > ? ? ? ?FILE *fp; > ? ? ? ?int err; > - ? ? ? int size = len * sizeof (u_int8_t); > - ? ? ? int n = len; > + ? ? ? size_t size = len * sizeof (u_int8_t); > + ? ? ? size_t n = len; > > ? ? ? ?if (offset != lseek (fd,offset,SEEK_SET)) > ? ? ? ?{ > @@ -191,10 +188,12 @@ int file_to_flash (int fd,u_int32_t > offset,u_int32_t len,const char *filename) > ?retry: > ? ? ? ?if ((buf = (u_int8_t *) malloc (size)) == NULL) > ? ? ? ?{ > - ? ? ? ? ? ? ? fprintf (stderr, "%s: malloc(%#x) failed\n", __FUNCTION__, size); > + ? ? ? ? ? ? ? fprintf (stderr, "%s: malloc(%#x) failed\n", > + ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (int)size); > ? ? ? ? ? ? ? ?if (size != BUF_SIZE) { > ? ? ? ? ? ? ? ? ? ? ? ?size = BUF_SIZE; > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: trying buffer size %#x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (int)size); > ? ? ? ? ? ? ? ? ? ? ? ?goto retry; > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?perror ("malloc()"); > @@ -206,7 +205,9 @@ retry: > ? ? ? ? ? ? ? ? ? ? ? ?size = n; > ? ? ? ? ? ? ? ?if (fread (buf,size,1,fp) != 1 || ferror (fp)) > ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: fread, size %#x, n %#x\n", __FUNCTION__, size, n); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: fread, size %#x, n %#x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (unsigned int)size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned int)n); > ? ? ? ? ? ? ? ? ? ? ? ?perror ("fread()"); > ? ? ? ? ? ? ? ? ? ? ? ?free (buf); > ? ? ? ? ? ? ? ? ? ? ? ?fclose (fp); > @@ -215,7 +216,9 @@ retry: > ? ? ? ? ? ? ? ?err = write (fd,buf,size); > ? ? ? ? ? ? ? ?if (err < 0) > ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n); > + ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "%s: write, size %#x, n %#x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __FUNCTION__, (unsigned int)size, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned int)n); > ? ? ? ? ? ? ? ? ? ? ? ?perror ("write()"); > ? ? ? ? ? ? ? ? ? ? ? ?free (buf); > ? ? ? ? ? ? ? ? ? ? ? ?fclose (fp); > @@ -227,23 +230,26 @@ retry: > ? ? ? ?if (buf != NULL) > ? ? ? ? ? ? ? ?free (buf); > ? ? ? ?fclose (fp); > - ? ? ? printf ("Copied %d bytes from %s to address 0x%.8x in > flash\n",len,filename,offset); > + ? ? ? printf ("Copied %d bytes from %s to address 0x%.8llx in flash\n", > + ? ? ? ? ? ? ? (int)len,filename,(unsigned long long)offset); > ? ? ? ?return (0); > ?} > > ?int showinfo (int fd) > ?{ > ? ? ? ?int i,err,n; > - ? ? ? struct mtd_info_user mtd; > - ? ? ? static struct region_info_user region[1024]; > + ? ? ? struct mtd_info_user64 mtd; > + ? ? ? static struct region_info_user64 region[1024]; > > - ? ? ? err = getmeminfo (fd,&mtd); > + ? ? ? err = mtd_ioctl_getinfo (fd,&mtd); > ? ? ? ?if (err < 0) > ? ? ? ?{ > - ? ? ? ? ? ? ? perror ("MEMGETINFO"); > + ? ? ? ? ? ? ? perror ("MEMGETINFO64"); > ? ? ? ? ? ? ? ?return (1); > ? ? ? ?} > > + ? ? ? memset(region, 0, sizeof(region)); > + > ? ? ? ?err = getregions (fd,region,&n); > ? ? ? ?if (err < 0) > ? ? ? ?{ > @@ -301,7 +307,7 @@ int showinfo (int fd) > ? ? ? ? ? ? ? ? ? ? ? ?{ "MTD_WRITEABLE", MTD_WRITEABLE }, > ? ? ? ? ? ? ? ? ? ? ? ?{ "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE }, > ? ? ? ? ? ? ? ? ? ? ? ?{ "MTD_NO_ERASE", MTD_NO_ERASE }, > - ? ? ? ? ? ? ? ? ? ? ? { "MTD_STUPID_LOCK", MTD_STUPID_LOCK }, > + ? ? ? ? ? ? ? ? ? ? ? { "MTD_POWERUP_LOCK", MTD_POWERUP_LOCK }, > ? ? ? ? ? ? ? ? ? ? ? ?{ NULL, -1 } > ? ? ? ? ? ? ? ?}; > ? ? ? ? ? ? ? ?for (i = 0; flags[i].name != NULL; i++) > @@ -309,7 +315,7 @@ int showinfo (int fd) > ? ? ? ? ? ? ? ? ? ? ? ?{ > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (first) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?{ > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf (flags[i].name); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf ("%s", flags[i].name); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?first = 0; > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?else printf (" | %s",flags[i].name); > @@ -335,9 +341,9 @@ int showinfo (int fd) > > ? ? ? ?for (i = 0; i < n; i++) > ? ? ? ?{ > - ? ? ? ? ? ? ? printf ("region[%d].offset = 0x%.8x\n" > + ? ? ? ? ? ? ? printf ("region[%d].offset = 0x%.8llx\n" > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"region[%d].erasesize = ", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? i,region[i].offset,i); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? i,(unsigned long long)region[i].offset,i); > ? ? ? ? ? ? ? ?printsize (region[i].erasesize); > ? ? ? ? ? ? ? ?printf ("\nregion[%d].numblocks = %d\n" > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?"region[%d].regionindex = %d\n", > @@ -399,13 +405,13 @@ int main (int argc,char *argv[]) > ? ? ? ? ? ? ? ? ? ? ? ?showinfo (fd); > ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ?case OPT_READ: > - ? ? ? ? ? ? ? ? ? ? ? err = flash_to_file (fd,strtol (argv[3],NULL,0),strtol > (argv[4],NULL,0),argv[5]); > + ? ? ? ? ? ? ? ? ? ? ? err = flash_to_file (fd,strtoll (argv[3],NULL,0),strtoll > (argv[4],NULL,0),argv[5]); > ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ?case OPT_WRITE: > - ? ? ? ? ? ? ? ? ? ? ? err = file_to_flash (fd,strtol (argv[3],NULL,0),strtol > (argv[4],NULL,0),argv[5]); > + ? ? ? ? ? ? ? ? ? ? ? err = file_to_flash (fd,strtoll (argv[3],NULL,0),strtoll > (argv[4],NULL,0),argv[5]); > ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ?case OPT_ERASE: > - ? ? ? ? ? ? ? ? ? ? ? err = erase_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0)); > + ? ? ? ? ? ? ? ? ? ? ? err = erase_flash (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0)); > ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ?} > > diff --git a/mtd_ioctl.c b/mtd_ioctl.c > new file mode 100644 > index 0000000..500a743 > --- /dev/null > +++ b/mtd_ioctl.c > @@ -0,0 +1,303 @@ > +/* > + * mtd_ioctl.c - backward compatibility wrappers for MTD ioctls > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include "mtd_ioctl.h" > + > +#define BUF_LEN ? ? ? ? ? ? ? ?64 > + > +static int use_old_abi = 0; > + > +static int try_new_ioctl(int fd, unsigned int cmd, unsigned long arg, > int *retp) > +{ > + ? ? ? int ret; > + > + ? ? ? if(use_old_abi) > + ? ? ? ? ? ? ? return(0); > + ? ? ? ret = ioctl(fd, cmd, arg); > + ? ? ? if((ret < 0) && (errno == ENOTTY)) { > + ? ? ? ? ? ? ? use_old_abi = 1; > + ? ? ? ? ? ? ? return(0); > + ? ? ? } > + ? ? ? *retp = ret; > + ? ? ? return(1); > +} > + > +/** > + * mkpath - compose full path from 2 given components. > + * @path: the first component > + * @name: the second component > + * > + * This function returns the resulting path in case of success and %NULL in > + * case of failure. > + */ > +static char *mkpath(const char *path, const char *name) > +{ > + ? ? ? char *n; > + ? ? ? int len1 = strlen(path); > + ? ? ? int len2 = strlen(name); > + > + ? ? ? n = malloc(len1 + len2 + 2); > + ? ? ? if (!n) { > + ? ? ? ? ? ? ? return NULL; > + ? ? ? } > + > + ? ? ? memcpy(n, path, len1); > + ? ? ? if (n[len1 - 1] != '/') > + ? ? ? ? ? ? ? n[len1++] = '/'; > + > + ? ? ? memcpy(n + len1, name, len2 + 1); > + ? ? ? return n; > +} > + > +/** > + * read_data - read data from a file. > + * @file: the file to read from > + * @buf: the buffer to read to > + * @buf_len: buffer length > + * > + * This function returns number of read bytes in case of success and %-1 in > + * case of failure. Note, if the file contains more then @buf_len bytes of > + * date, this function fails with %EINVAL error code. > + */ > +static int sysfs_get_str(const char *prefix, const char *element, > + ? ? ? char *buf, int buf_len) > +{ > + ? ? ? int fd, rd, tmp, tmp1; > + ? ? ? char *file = mkpath(prefix, element), *sep; > + > + ? ? ? if(! file) > + ? ? ? ? ? ? ? return -1; > + > + ? ? ? fd = open(file, O_RDONLY); > + ? ? ? if (fd == -1) { > + ? ? ? ? ? ? ? free(file); > + ? ? ? ? ? ? ? return -1; > + ? ? ? } > + > + ? ? ? rd = read(fd, buf, buf_len); > + ? ? ? if (rd == -1) { > + ? ? ? ? ? ? ? goto out_error; > + ? ? ? } > + > + ? ? ? /* Make sure all data is read */ > + ? ? ? tmp1 = read(fd, &tmp, 1); > + ? ? ? if (tmp1 == 1) { > + ? ? ? ? ? ? ? goto out_error; > + ? ? ? } > + ? ? ? if (tmp1) { > + ? ? ? ? ? ? ? errno = EINVAL; > + ? ? ? ? ? ? ? goto out_error; > + ? ? ? } > + > + ? ? ? if (close(fd)) { > + ? ? ? ? ? ? ? rd = -1; > + ? ? ? } > + > + ? ? ? sep = index(buf, '\n'); > + ? ? ? if(sep) > + ? ? ? ? ? ? ? *sep = 0; > + ? ? ? else > + ? ? ? ? ? ? ? buf[buf_len - 1] = 0; > + > + ? ? ? free(file); > + ? ? ? return rd; > + > +out_error: > + ? ? ? close(fd); > + ? ? ? free(file); > + ? ? ? return -1; > +} > + > +static int sysfs_get_ull(const char *prefix, const char *element, > + ? ? ? unsigned long long *out) > +{ > + ? ? ? int ret; > + ? ? ? char buf[BUF_LEN]; > + > + ? ? ? ret = sysfs_get_str(prefix, element, buf, BUF_LEN); > + ? ? ? if(ret <= 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? if(sscanf(buf, "0x%llx", out) == 1) > + ? ? ? ? ? ? ? return(0); > + > + ? ? ? if(sscanf(buf, "%llu", out) == 1) > + ? ? ? ? ? ? ? return(0); > + > + ? ? ? return(-1); > +} > + > +int mtd_ioctl_getinfo(int fd, struct mtd_info_user64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct mtd_info_user oldarg; > + ? ? ? struct stat st; > + ? ? ? char prefix[BUF_LEN], str[BUF_LEN]; > + ? ? ? unsigned long long tmp; > + > + ? ? ? if((fstat(fd, &st) < 0) || !S_ISCHR(st.st_mode)) > + ? ? ? ? ? ? ? return(-1); > + > + ? ? ? snprintf(prefix, BUF_LEN, "/sys/class/mtd/mtd%d/", > + ? ? ? ? ? ? ? minor(st.st_rdev) >> 1); > + > + ? ? ? if(sysfs_get_str(prefix, "type", str, BUF_LEN) > 0) { > + ? ? ? ? ? ? ? if(strcasecmp(str, "absent") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_ABSENT; > + ? ? ? ? ? ? ? else if(strcasecmp(str, "ram") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_RAM; > + ? ? ? ? ? ? ? else if(strcasecmp(str, "rom") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_ROM; > + ? ? ? ? ? ? ? else if(strcasecmp(str, "nor") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_NORFLASH; > + ? ? ? ? ? ? ? else if(strcasecmp(str, "nand") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_NANDFLASH; > + ? ? ? ? ? ? ? else if(strcasecmp(str, "dataflash") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_DATAFLASH; > + ? ? ? ? ? ? ? else if(strcasecmp(str, "ubi") == 0) > + ? ? ? ? ? ? ? ? ? ? ? arg->type = MTD_UBIVOLUME; > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? return(-1); > + > + ? ? ? ? ? ? ? if(sysfs_get_ull(prefix, "flags", &tmp) != 0) > + ? ? ? ? ? ? ? ? ? ? ? return(-1); > + ? ? ? ? ? ? ? arg->flags = tmp; > + > + ? ? ? ? ? ? ? if(sysfs_get_ull(prefix, "size", &tmp) != 0) > + ? ? ? ? ? ? ? ? ? ? ? return(-1); > + ? ? ? ? ? ? ? arg->size = tmp; > + > + ? ? ? ? ? ? ? if(sysfs_get_ull(prefix, "erasesize", &tmp) != 0) > + ? ? ? ? ? ? ? ? ? ? ? return(-1); > + ? ? ? ? ? ? ? arg->erasesize = tmp; > + > + ? ? ? ? ? ? ? if(sysfs_get_ull(prefix, "writesize", &tmp) != 0) > + ? ? ? ? ? ? ? ? ? ? ? return(-1); > + ? ? ? ? ? ? ? arg->writesize = tmp; > + > + ? ? ? ? ? ? ? if(sysfs_get_ull(prefix, "oobsize", &tmp) != 0) > + ? ? ? ? ? ? ? ? ? ? ? return(-1); > + ? ? ? ? ? ? ? arg->oobsize = tmp; > + > + ? ? ? ? ? ? ? return(0); > + ? ? ? } > + > + ? ? ? ret = ioctl(fd, MEMGETINFO, (unsigned long)&oldarg); > + ? ? ? if(ret < 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? arg->type = oldarg.type; > + ? ? ? arg->flags = oldarg.flags; > + ? ? ? arg->size = oldarg.size; > + ? ? ? arg->erasesize = oldarg.erasesize; > + ? ? ? arg->writesize = oldarg.writesize; > + ? ? ? arg->oobsize = oldarg.oobsize; > + > + ? ? ? return(ret); > +} > + > +int mtd_ioctl_erase(int fd, struct erase_info_user64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct erase_info_user oldarg; > + > + ? ? ? if(try_new_ioctl(fd, MEMERASE64, (unsigned long)arg, &ret) != 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? oldarg.start = arg->start; > + ? ? ? oldarg.length = arg->length; > + > + ? ? ? return(ioctl(fd, MEMERASE, (unsigned long)&oldarg)); > +} > + > +int mtd_ioctl_writeoob(int fd, struct mtd_oob_buf64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct mtd_oob_buf oldarg; > + > + ? ? ? if(try_new_ioctl(fd, MEMWRITEOOB64, (unsigned long)arg, &ret) != 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? oldarg.start = arg->start; > + ? ? ? oldarg.length = arg->length; > + ? ? ? oldarg.ptr = (void *)(uintptr_t)arg->usr_ptr; > + > + ? ? ? ret = ioctl(fd, MEMWRITEOOB, (unsigned long)&oldarg); > + > + ? ? ? arg->length = oldarg.length; > + ? ? ? return(ret); > +} > + > +int mtd_ioctl_readoob(int fd, struct mtd_oob_buf64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct mtd_oob_buf oldarg; > + > + ? ? ? if(try_new_ioctl(fd, MEMREADOOB64, (unsigned long)arg, &ret) != 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? oldarg.start = arg->start; > + ? ? ? oldarg.length = arg->length; > + ? ? ? oldarg.ptr = (void *)(uintptr_t)arg->usr_ptr; > + > + ? ? ? ret = ioctl(fd, MEMREADOOB, (unsigned long)&oldarg); > + > + ? ? ? /* old ABI puts returned length in "start" */ > + ? ? ? arg->length = oldarg.start; > + ? ? ? return(ret); > +} > + > +int mtd_ioctl_lock(int fd, struct erase_info_user64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct erase_info_user oldarg; > + > + ? ? ? if(try_new_ioctl(fd, MEMLOCK64, (unsigned long)arg, &ret) != 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? oldarg.start = arg->start; > + ? ? ? oldarg.length = arg->length; > + > + ? ? ? return(ioctl(fd, MEMLOCK, (unsigned long)&oldarg)); > +} > + > +int mtd_ioctl_unlock(int fd, struct erase_info_user64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct erase_info_user oldarg; > + > + ? ? ? if(try_new_ioctl(fd, MEMUNLOCK64, (unsigned long)arg, &ret) != 0) > + ? ? ? ? ? ? ? return(ret); > + > + ? ? ? oldarg.start = arg->start; > + ? ? ? oldarg.length = arg->length; > + > + ? ? ? return(ioctl(fd, MEMUNLOCK, (unsigned long)&oldarg)); > +} > + > +int mtd_ioctl_getregioninfo(int fd, struct region_info_user64 *arg) > +{ > + ? ? ? int ret; > + ? ? ? struct region_info_user oldarg; > + > + ? ? ? oldarg.regionindex = arg->regionindex; > + > + ? ? ? ret = ioctl(fd, MEMGETREGIONINFO, (unsigned long)&oldarg); > + > + ? ? ? arg->offset = oldarg.offset; > + ? ? ? arg->erasesize = oldarg.erasesize; > + ? ? ? arg->numblocks = oldarg.numblocks; > + > + ? ? ? return(ret); > +} > diff --git a/mtd_ioctl.h b/mtd_ioctl.h > new file mode 100644 > index 0000000..2c62553 > --- /dev/null > +++ b/mtd_ioctl.h > @@ -0,0 +1,38 @@ > +/* > + * mtd_ioctl.h - backward compatibility wrappers for MTD ioctls > + */ > + > +#ifndef _MTD_IOCTL_H > +#define _MTD_IOCTL_H > + > +#include > + > +struct region_info_user64 { > + ? ? ? uint64_t offset; ? ? ? ? ? ? ? ?/* At which this region starts, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?* from the beginning of the MTD */ > + ? ? ? uint32_t erasesize; ? ? ? ? ? ? /* For this region */ > + ? ? ? uint32_t numblocks; ? ? ? ? ? ? /* Number of blocks in this region */ > + ? ? ? uint32_t regionindex; > +}; > + > +struct mtd_info_user64 { > + ? ? ? uint32_t type; > + ? ? ? uint32_t flags; > + ? ? ? uint64_t size; ? ? ? ? ? ? ? ? ?/* Total size of the MTD */ > + ? ? ? uint32_t erasesize; > + ? ? ? uint32_t writesize; > + ? ? ? uint32_t oobsize; ? ? ? ? ? ? ? /* OOB bytes per page (e.g. 16) */ > +}; > + > +typedef struct mtd_info_user64 mtd_info64_t; > +typedef struct region_info_user64 region_info64_t; > + > +int mtd_ioctl_getinfo(int fd, struct mtd_info_user64 *arg); > +int mtd_ioctl_erase(int fd, struct erase_info_user64 *arg); > +int mtd_ioctl_writeoob(int fd, struct mtd_oob_buf64 *arg); > +int mtd_ioctl_readoob(int fd, struct mtd_oob_buf64 *arg); > +int mtd_ioctl_lock(int fd, struct erase_info_user64 *arg); > +int mtd_ioctl_unlock(int fd, struct erase_info_user64 *arg); > +int mtd_ioctl_getregioninfo(int fd, struct region_info_user64 *arg); > + > +#endif /* !_MTD_IOCTL_H */ > diff --git a/nanddump.c b/nanddump.c > index 678d684..fbe4f9a 100644 > --- a/nanddump.c > +++ b/nanddump.c > @@ -29,6 +29,7 @@ > > ?#include > ?#include > +#include "mtd_ioctl.h" > > ?#define PROGRAM "nanddump" > ?#define VERSION "$Revision: 1.29 $" > @@ -182,11 +183,15 @@ static unsigned char oobbuf[128]; > ?*/ > ?int main(int argc, char * const argv[]) > ?{ > - ? ? ? unsigned long ofs, end_addr = 0; > + ? ? ? unsigned long long ofs, end_addr = 0; > ? ? ? ?unsigned long long blockstart = 1; > ? ? ? ?int ret, i, fd, ofd, bs, badblock = 0; > - ? ? ? struct mtd_oob_buf oob = {0, 16, oobbuf}; > - ? ? ? mtd_info_t meminfo; > + ? ? ? struct mtd_oob_buf64 oob = { > + ? ? ? ? ? ? ? .start = 0, > + ? ? ? ? ? ? ? .length = 16, > + ? ? ? ? ? ? ? .usr_ptr = (uintptr_t)oobbuf, > + ? ? ? }; > + ? ? ? mtd_info64_t meminfo; > ? ? ? ?char pretty_buf[80]; > ? ? ? ?int oobinfochanged = 0 ; > ? ? ? ?struct nand_oobinfo old_oobinfo; > @@ -202,8 +207,8 @@ int main(int argc, char * const argv[]) > ? ? ? ?} > > ? ? ? ?/* Fill in MTD device capability structure */ > - ? ? ? if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { > - ? ? ? ? ? ? ? perror("MEMGETINFO"); > + ? ? ? if (mtd_ioctl_getinfo(fd, &meminfo) != 0) { > + ? ? ? ? ? ? ? perror("MEMGETINFO64"); > ? ? ? ? ? ? ? ?close(fd); > ? ? ? ? ? ? ? ?exit (EXIT_FAILURE); > ? ? ? ?} > @@ -320,11 +325,11 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ?if (stat1.failed != stat2.failed) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fprintf(stderr, "ECC: %d uncorrectable bitflip(s)" > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " at offset 0x%08lx\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " at offset 0x%08llx\n", > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?stat2.failed - stat1.failed, ofs); > ? ? ? ? ? ? ? ? ? ? ? ?if (stat1.corrected != stat2.corrected) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fprintf(stderr, "ECC: %d corrected bitflip(s) at" > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " offset 0x%08lx\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " offset 0x%08llx\n", > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?stat2.corrected - stat1.corrected, ofs); > ? ? ? ? ? ? ? ? ? ? ? ?stat1 = stat2; > ? ? ? ? ? ? ? ?} > @@ -359,8 +364,8 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ?} else { > ? ? ? ? ? ? ? ? ? ? ? ?/* Read OOB data and exit on failure */ > ? ? ? ? ? ? ? ? ? ? ? ?oob.start = ofs; > - ? ? ? ? ? ? ? ? ? ? ? if (ioctl(fd, MEMREADOOB, &oob) != 0) { > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror("ioctl(MEMREADOOB)"); > + ? ? ? ? ? ? ? ? ? ? ? if (mtd_ioctl_readoob(fd, &oob) != 0) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror("ioctl(MEMREADOOB64)"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto closeall; > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?} > diff --git a/nandtest.c b/nandtest.c > index 7613a52..48ec1a7 100644 > --- a/nandtest.c > +++ b/nandtest.c > @@ -14,6 +14,7 @@ > > ?#include > ?#include "mtd/mtd-user.h" > +#include "mtd_ioctl.h" > > ?void usage(void) > ?{ > @@ -28,7 +29,7 @@ void usage(void) > ? ? ? ?exit(1); > ?} > > -struct mtd_info_user meminfo; > +struct mtd_info_user64 meminfo; > ?struct mtd_ecc_stats oldstats, newstats; > ?int fd; > ?int markbad=0; > @@ -36,26 +37,28 @@ int seed; > > ?int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf) > ?{ > - ? ? ? struct erase_info_user er; > + ? ? ? struct erase_info_user64 er; > ? ? ? ?ssize_t len; > ? ? ? ?int i; > > - ? ? ? printf("\r%08x: erasing... ", (unsigned)ofs); > + ? ? ? printf("\r%08llx: erasing... ", ofs); > ? ? ? ?fflush(stdout); > > + ? ? ? memset(&er, 0, sizeof(er)); > + > ? ? ? ?er.start = ofs; > ? ? ? ?er.length = meminfo.erasesize; > > - ? ? ? if (ioctl(fd, MEMERASE, &er)) { > - ? ? ? ? ? ? ? perror("MEMERASE"); > + ? ? ? if (mtd_ioctl_erase(fd, &er)) { > + ? ? ? ? ? ? ? perror("MEMERASE64"); > ? ? ? ? ? ? ? ?if (markbad) { > - ? ? ? ? ? ? ? ? ? ? ? printf("Mark block bad at %08lx\n", (long)ofs); > + ? ? ? ? ? ? ? ? ? ? ? printf("Mark block bad at %08llx\n", ofs); > ? ? ? ? ? ? ? ? ? ? ? ?ioctl(fd, MEMSETBADBLOCK, &ofs); > ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ?return 1; > ? ? ? ?} > > - ? ? ? printf("\r%08x: writing...", (unsigned)ofs); > + ? ? ? printf("\r%08llx: writing...", ofs); > ? ? ? ?fflush(stdout); > > ? ? ? ?len = pwrite(fd, data, meminfo.erasesize, ofs); > @@ -132,8 +135,8 @@ int main(int argc, char **argv) > ? ? ? ?int pass; > ? ? ? ?int nr_passes = 1; > ? ? ? ?int keep_contents = 0; > - ? ? ? uint32_t offset = 0; > - ? ? ? uint32_t length = -1; > + ? ? ? uint64_t offset = 0; > + ? ? ? uint64_t length = -1; > > ? ? ? ?for (;;) { > ? ? ? ? ? ? ? ?static const char *short_options="hkl:mo:p:s:"; > @@ -175,11 +178,11 @@ int main(int argc, char **argv) > ? ? ? ? ? ? ? ? ? ? ? ?break; > > ? ? ? ? ? ? ? ?case 'o': > - ? ? ? ? ? ? ? ? ? ? ? offset = atol(optarg); > + ? ? ? ? ? ? ? ? ? ? ? offset = atoll(optarg); > ? ? ? ? ? ? ? ? ? ? ? ?break; > > ? ? ? ? ? ? ? ?case 'l': > - ? ? ? ? ? ? ? ? ? ? ? length = strtol(optarg, NULL, 0); > + ? ? ? ? ? ? ? ? ? ? ? length = strtoll(optarg, NULL, 0); > ? ? ? ? ? ? ? ? ? ? ? ?break; > > ? ? ? ? ? ? ? ?} > @@ -193,8 +196,8 @@ int main(int argc, char **argv) > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > > - ? ? ? if (ioctl(fd, MEMGETINFO, &meminfo)) { > - ? ? ? ? ? ? ? perror("MEMGETINFO"); > + ? ? ? if (mtd_ioctl_getinfo(fd, &meminfo)) { > + ? ? ? ? ? ? ? perror("MEMGETINFO64"); > ? ? ? ? ? ? ? ?close(fd); > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > @@ -203,17 +206,17 @@ int main(int argc, char **argv) > ? ? ? ? ? ? ? ?length = meminfo.size; > > ? ? ? ?if (offset % meminfo.erasesize) { > - ? ? ? ? ? ? ? fprintf(stderr, "Offset %x not multiple of erase size %x\n", > + ? ? ? ? ? ? ? fprintf(stderr, "Offset %llx not multiple of erase size %x\n", > ? ? ? ? ? ? ? ? ? ? ? ?offset, meminfo.erasesize); > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > ? ? ? ?if (length % meminfo.erasesize) { > - ? ? ? ? ? ? ? fprintf(stderr, "Length %x not multiple of erase size %x\n", > + ? ? ? ? ? ? ? fprintf(stderr, "Length %llx not multiple of erase size %x\n", > ? ? ? ? ? ? ? ? ? ? ? ?length, meminfo.erasesize); > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > ? ? ? ?if (length + offset > meminfo.size) { > - ? ? ? ? ? ? ? fprintf(stderr, "Length %x + offset %x exceeds device size %x\n", > + ? ? ? ? ? ? ? fprintf(stderr, "Length %llx + offset %llx exceeds device size %llx\n", > ? ? ? ? ? ? ? ? ? ? ? ?length, offset, meminfo.size); > ? ? ? ? ? ? ? ?exit(1); > ? ? ? ?} > diff --git a/nandwrite.c b/nandwrite.c > index 0b2a9ee..4221722 100644 > --- a/nandwrite.c > +++ b/nandwrite.c > @@ -38,6 +38,7 @@ > > ?#include > ?#include "mtd/mtd-user.h" > +#include "mtd_ioctl.h" > > ?#define PROGRAM "nandwrite" > ?#define VERSION "$Revision: 1.32 $" > @@ -114,7 +115,7 @@ static void display_version (void) > > ?static const char ? ? ?*standard_input = "-"; > ?static const char ? ? ?*mtd_device, *img; > -static int ? ? ? ? ? ? mtdoffset = 0; > +static long long ? ? ? mtdoffset = 0; > ?static bool ? ? ? ? ? ?quiet = false; > ?static bool ? ? ? ? ? ?writeoob = false; > ?static bool ? ? ? ? ? ?autoplace = false; > @@ -195,7 +196,7 @@ static void process_options (int argc, char * const argv[]) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?pad = true; > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ? ? ? ? ?case 's': > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mtdoffset = strtol (optarg, NULL, 0); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mtdoffset = strtoll (optarg, NULL, 0); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?break; > ? ? ? ? ? ? ? ? ? ? ? ?case 'b': > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?blockalign = atoi (optarg); > @@ -207,7 +208,7 @@ static void process_options (int argc, char * const argv[]) > ? ? ? ?} > > ? ? ? ?if (mtdoffset < 0) { > - ? ? ? ? ? ? ? fprintf(stderr, "Can't specify a negative device offset `%d'\n", > + ? ? ? ? ? ? ? fprintf(stderr, "Can't specify a negative device offset `%lld'\n", > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?mtdoffset); > ? ? ? ? ? ? ? ?exit (EXIT_FAILURE); > ? ? ? ?} > @@ -253,14 +254,13 @@ int main(int argc, char * const argv[]) > ? ? ? ?int ifd = -1; > ? ? ? ?int imglen = 0, pagelen; > ? ? ? ?bool baderaseblock = false; > - ? ? ? int blockstart = -1; > - ? ? ? struct mtd_info_user meminfo; > - ? ? ? struct mtd_oob_buf oob; > + ? ? ? long long blockstart = -1; > + ? ? ? struct mtd_info_user64 meminfo; > + ? ? ? struct mtd_oob_buf64 oob; > ? ? ? ?loff_t offs; > ? ? ? ?int ret, readlen; > ? ? ? ?int oobinfochanged = 0; > ? ? ? ?struct nand_oobinfo old_oobinfo; > - ? ? ? int readcnt = 0; > > ? ? ? ?process_options(argc, argv); > > @@ -278,8 +278,8 @@ int main(int argc, char * const argv[]) > ? ? ? ?} > > ? ? ? ?/* Fill in MTD device capability structure */ > - ? ? ? if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { > - ? ? ? ? ? ? ? perror("MEMGETINFO"); > + ? ? ? if (mtd_ioctl_getinfo(fd, &meminfo) != 0) { > + ? ? ? ? ? ? ? perror("MEMGETINFO64"); > ? ? ? ? ? ? ? ?close(fd); > ? ? ? ? ? ? ? ?exit (EXIT_FAILURE); > ? ? ? ?} > @@ -375,8 +375,9 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ?} > ? ? ? ?} > > + ? ? ? memset(&oob, 0, sizeof(oob)); > ? ? ? ?oob.length = meminfo.oobsize; > - ? ? ? oob.ptr = noecc ? oobreadbuf : oobbuf; > + ? ? ? oob.usr_ptr = (uintptr_t)(noecc ? oobreadbuf : oobbuf); > > ? ? ? ?/* Determine if we are reading from standard input or from a file. */ > ? ? ? ?if (strcmp(img, standard_input) == 0) { > @@ -425,8 +426,9 @@ int main(int argc, char * const argv[]) > > ? ? ? ?// Check, if length fits into device > ? ? ? ?if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) { > - ? ? ? ? ? ? ? fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u > bytes, device size %u bytes\n", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? imglen, pagelen, meminfo.writesize, meminfo.size); > + ? ? ? ? ? ? ? fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u > bytes, device size %llu bytes\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? imglen, pagelen, meminfo.writesize, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)meminfo.size); > ? ? ? ? ? ? ? ?perror ("Input file does not fit into device"); > ? ? ? ? ? ? ? ?goto closeall; > ? ? ? ?} > @@ -450,7 +452,7 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ? ? ? ? ?offs = blockstart; > ? ? ? ? ? ? ? ? ? ? ? ?baderaseblock = false; > ? ? ? ? ? ? ? ? ? ? ? ?if (!quiet) > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf (stdout, "Writing data to block %d at offset 0x%x\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf (stdout, "Writing data to block %lld at offset 0x%llx\n", > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? blockstart / meminfo.erasesize, blockstart); > > ? ? ? ? ? ? ? ? ? ? ? ?/* Check all the blocks in an erase block for bad blocks */ > @@ -462,9 +464,10 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (ret == 1) { > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?baderaseblock = true; > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (!quiet) > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "Bad block at %x, %u block(s) " > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "from %x will be skipped\n", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (int) offs, blockalign, blockstart); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf (stderr, "Bad block at %llx, %u block(s) " > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? "from %llx will be skipped\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)offs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? blockalign, blockstart); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?} > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (baderaseblock) { > @@ -571,8 +574,8 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ?/* Write OOB data first, as ecc will be placed in there*/ > ? ? ? ? ? ? ? ? ? ? ? ?oob.start = mtdoffset; > - ? ? ? ? ? ? ? ? ? ? ? if (ioctl(fd, MEMWRITEOOB, &oob) != 0) { > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror ("ioctl(MEMWRITEOOB)"); > + ? ? ? ? ? ? ? ? ? ? ? if (mtd_ioctl_writeoob(fd, &oob) != 0) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror ("ioctl(MEMWRITEOOB64)"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto closeall; > ? ? ? ? ? ? ? ? ? ? ? ?} > ? ? ? ? ? ? ? ? ? ? ? ?imglen -= meminfo.oobsize; > @@ -582,7 +585,7 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ?if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != > meminfo.writesize) { > ? ? ? ? ? ? ? ? ? ? ? ?int rewind_blocks; > ? ? ? ? ? ? ? ? ? ? ? ?off_t rewind_bytes; > - ? ? ? ? ? ? ? ? ? ? ? erase_info_t erase; > + ? ? ? ? ? ? ? ? ? ? ? erase_info64_t erase; > > ? ? ? ? ? ? ? ? ? ? ? ?perror ("pwrite"); > ? ? ? ? ? ? ? ? ? ? ? ?/* Must rewind to blockstart if we can */ > @@ -595,18 +598,21 @@ int main(int argc, char * const argv[]) > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?fprintf(stderr, "Failed to seek backwards to recover from write error\n"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto closeall; > ? ? ? ? ? ? ? ? ? ? ? ?} > + ? ? ? ? ? ? ? ? ? ? ? memset(&erase, 0, sizeof(erase)); > ? ? ? ? ? ? ? ? ? ? ? ?erase.start = blockstart; > ? ? ? ? ? ? ? ? ? ? ? ?erase.length = meminfo.erasesize; > - ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Erasing failed write from %08lx-%08lx\n", > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (long)erase.start, (long)erase.start+erase.length-1); > - ? ? ? ? ? ? ? ? ? ? ? if (ioctl(fd, MEMERASE, &erase) != 0) { > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror("MEMERASE"); > + ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Erasing failed write from %08llx-%08llx\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)erase.start, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)(erase.start+erase.length-1)); > + ? ? ? ? ? ? ? ? ? ? ? if (mtd_ioctl_erase(fd, &erase) != 0) { > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? perror("MEMERASE64"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?goto closeall; > ? ? ? ? ? ? ? ? ? ? ? ?} > > ? ? ? ? ? ? ? ? ? ? ? ?if (markbad) { > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?loff_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1); > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Marking block at %08llx bad\n", > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (unsigned long long)bad_addr); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) { > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?perror("MEMSETBADBLOCK"); > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?/* But continue anyway */ > -- > 1.5.6.3 > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > From glecerf at gmail.com Tue May 11 04:43:04 2010 From: glecerf at gmail.com (Guillaume LECERF) Date: Tue, 11 May 2010 10:43:04 +0200 Subject: [PATCH v5 5/9] [MTD] remove bogus warning about missing boot bank location In-Reply-To: <1272520655.7750.74.camel@localhost> References: <20100424155751.14723.46761.stgit@shiryu.yomgui.biz> <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> <1272520655.7750.74.camel@localhost> Message-ID: Hi. 2010/4/29 Artem Bityutskiy : > Pushed this v5 series to l2-mtd-2.6 / dunno. But please, if you re-send > the series, use consistent "mtd: cfi_cmdset_0002:" prefix for this > patch. Then I will be able to do git-am without manual work. Now I have > to tweak this patch because git am removes [MTD]. David, could you please pick this series and push it to mtd-2.6.git before the merge window ? Thanks. -- Guillaume LECERF GeeXboX developer - www.geexbox.org From dedekind1 at gmail.com Tue May 11 04:43:09 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 11 May 2010 11:43:09 +0300 Subject: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices In-Reply-To: References: Message-ID: <1273567389.2209.173.camel@localhost> On Tue, 2010-05-11 at 11:28 +0300, saeed bishara wrote: > hi, > This patch is needed when using >4GiB nand partitions, any idea why > it has not been merged yet? > > saeed > > On Fri, Apr 3, 2009 at 11:18 PM, Kevin Cernekee wrote: > > Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB > > flash devices. > > > > Use the new sysfs interface to query device info. > > > > Dependencies: > > > > "4GiB" extended ioctls: > > http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html > > > > Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477 > > > > Optional: Driver model updates 2/2: > > http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html > > Dunno, I did not follow these. Kevin, would you re-send your patches please? -- Best Regards, Artem Bityutskiy (????? ????????) From ricard.wanderlof at axis.com Tue May 11 05:35:07 2010 From: ricard.wanderlof at axis.com (Ricard Wanderlof) Date: Tue, 11 May 2010 11:35:07 +0200 (CEST) Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <201005110959.36213.muehlfelder@enertex.de> References: <201005031505.18604.muehlfelder@enertex.de> <1273049480.3702.129.camel@localhost> <201005110959.36213.muehlfelder@enertex.de> Message-ID: On Tue, 11 May 2010, Thorsten M?hlfelder wrote: >> I think in this case the partition in question just held a raw Linux >> kernel with no file system, so JFFS2 is out of the picture here. >> > But unfortunately the Sam-Ba 2.5 tool has a bug: it uses different bad block > table structure and Linux refuses to read/write every block, that was written > by Sam-Ba 2.5 because it recognizes them as bad blocks. > So for now I have no idea what I can do to reduce the failing rate. I don't know if this is a good way, but you could patch your kernel so it doesn't stop you from erasing/writing badblocks. Then you could write your own application which checks for bad blocks in the same way that the Sam-Ba 2.5 tool does, which would allow you to rewrite everything written by that tool. > At least there is still no board using Samsung flash that has failed and I > hope all problems are related to the Micron flash. Even if you are not using jffs2, mtd will still perform single-bit error correction thanks the the ECC algorithm, so you need to be unlucky enough and get two bitflips within a 256 byte region for the system to fail. /Ricard -- Ricard Wolf Wanderl?f ricardw(at)axis.com Axis Communications AB, Lund, Sweden www.axis.com Phone +46 46 272 2016 Fax +46 46 13 61 30 From nvbolhuis at aimvalley.nl Tue May 11 10:55:19 2010 From: nvbolhuis at aimvalley.nl (Norbert van Bolhuis) Date: Tue, 11 May 2010 16:55:19 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <201005111009.06724.muehlfelder@enertex.de> References: <201005031505.18604.muehlfelder@enertex.de> <201005041659.26262.muehlfelder@enertex.de> <4BE12D86.2070605@aimvalley.nl> <201005111009.06724.muehlfelder@enertex.de> Message-ID: <4BE96FD7.7020005@aimvalley.nl> Thorsten M?hlfelder wrote: > Am Wednesday 05 May 2010 10:34:14 schrieb Norbert van Bolhuis: >> It much more easier to let UBI/UBIFS deal with this suff. It's designed for >> this. >> u-boot support UBIFS (read-only). This means you can put a kernel image >> on UBIFS and make u-boot read/boot it. > > How would I do this? The only thing I've found about it is this discussion of > April 2008: > http://lists.infradead.org/pipermail/linux-mtd/2008-April/021268.html > > Thanks for any tip > Thorsten > What I meant was to keep the NAND flash partitions the same and use UBIFS (i.s.o. JFFS2) and of course also put the kernel uImage on UBIFS. The goal here is to make u-boot read and boot the kernel image from UBIFS (i.s.o. from bare NAND). But I understand Linux cannot read whatever Sam-Ba 2.5 writes, so I guess it's not even possible to read the kernel image and put it on UBIFS. Or can you put a kernel image on it beforehand ? are we talking about deployed systems or to be deployed systems ? Maybe you first have to find a solution for the Sam-Ba Linux incompatibility. I guess u-boot can read the kernel uImage, so u-boot does seem to understand whatever Sam-Ba 2.5 writes. Anyway, if you switch to UBIFS and *can* put the kernel image on UBIFS fatal bit flips in the uImage on bare NAND don't matter. On the other hand: fatal bit flips in bootstrap/u-boot/u-boot_env will still prevent the system to boot. So maybe also refreshing those images is necessary. You need a recent linux kernel and u-boot for them to support UBIFS. Note that: if you would upgrade your system with a new u-boot/linux and UBIFS i.s.o. JFFS2, *everything* on flash will change. If you want to do this for deployed systems you need a huge upgrade script. I don't use NAND+UBIFS myself, so I have no experience there. The below pointers should have some relevant info though: - u-boot home-page: http://www.denx.de/wiki/U-Boot/WebHome - u-boot mailing list: http://lists.denx.de/pipermail/u-boot/ - u-boot source code GIT tree: http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=tree (checkout boards with NAND and boot-from-NAND support) - specialized GIT trees for NAND and UBI: http://www.denx.de/wiki/U-Boot/Custodians Regards, Norbert. From pazdnikov at list.ru Tue May 11 10:43:12 2010 From: pazdnikov at list.ru (Alexander Pazdnikov) Date: Tue, 11 May 2010 18:43:12 +0400 Subject: ubifs became broken on contigous power-fails Message-ID: Hello. We are stress-testing 8 devices by power loss in 5 minutes interval. Device uses sqlite database to store collected data, every 1 minute accumulated data (500-1000 records) is stored into database in transaction. ubifs (ubi2:dbfs on /usr/local/ecom/db bellow) with database on 6 of 8 devices after different time (1-3 days) became broken. Any advise for futher debugging or solving this problem is highly appriciated. kernel 2.6.32.12 suspicious -> reserved GC LEB: -1 # cat /proc/mtd dev: size erasesize name mtd0: 00020000 00020000 "bootstrap" mtd1: 00080000 00020000 "uboot" mtd2: 00020000 00020000 "uboot_env1" mtd3: 00020000 00020000 "uboot_env2" mtd4: 02000000 00020000 "ubi_main" mtd5: 02000000 00020000 "ubi_var" mtd6: 0bf00000 00020000 "ubi_database" mounting ubi2:dbfs on startup [ 14.328117] UBIFS: recovery needed [ 53.941378] UBIFS error (pid 462): ubifs_rcvry_gc_commit: could not find a dirty LEB [ 89.606399] UBIFS: recovery completed [ 89.609329] UBIFS assert failed in mount_ubifs at 1358 (pid 462) [ 89.616165] [] (unwind_backtrace+0x0/0xe4) from [] (ubifs_fill_super+0x11d0/0x1c4c) [ 89.625930] [] (ubifs_fill_super+0x11d0/0x1c4c) from [] (ubifs_get_sb+0x1b0/0x354) [ 89.635696] [] (ubifs_get_sb+0x1b0/0x354) from [] (vfs_kern_mount+0x50/0xe0) [ 89.644485] [] (vfs_kern_mount+0x50/0xe0) from [] (do_kern_mount+0x34/0xdc) [ 89.653274] [] (do_kern_mount+0x34/0xdc) from [] (do_mount+0x148/0x7cc) [ 89.662063] [] (do_mount+0x148/0x7cc) from [] (sys_mount+0x98/0xc8) [ 89.670852] [] (sys_mount+0x98/0xc8) from [] (ret_fast_syscall+0x0/0x28) [ 97.651317] UBIFS: mounted UBI device 2, volume 0, name "dbfs" [ 97.658153] UBIFS: file system size: 189278208 bytes (184842 KiB, 180 MiB, 1467 LEBs) [ 97.665965] UBIFS: journal size: 9418752 bytes (9198 KiB, 8 MiB, 73 LEBs) [ 97.673778] UBIFS: media format: w4/r0 (latest is w4/r0) [ 97.679637] UBIFS: default compressor: lzo [ 97.683543] UBIFS: reserved for root: 4952683 bytes (4836 KiB) [ 97.689403] UBIFS DBG (pid 462): mount_ubifs: compiled on: May 11 2010 at 20:19:55 [ 97.689403] UBIFS DBG (pid 462): mount_ubifs: min. I/O unit size: 2048 bytes [ 97.689403] UBIFS DBG (pid 462): mount_ubifs: LEB size: 129024 bytes (126 KiB) [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: data journal heads: 1 [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: UUID: 5CAFDFE5-09E9-4A11-8CF1-B3F01C33424B [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: big_lpt 0 [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: log LEBs: 5 (3 - 7) [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: LPT area LEBs: 2 (8 - 9) [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: orphan area LEBs: 1 (10 - 10) [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: main area LEBs: 1467 (11 - 1477) [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: index LEBs: 12 [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: total index bytes: 420080 (410 KiB, 0 MiB) [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: key hash type: 0 [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: tree fanout: 8 [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: reserved GC LEB: -1 [ 97.690379] UBIFS DBG (pid 462): mount_ubifs: first main LEB: 11 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: max. znode size 240 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: max. index node size 192 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: node sizes: data 48, inode 160, dentry 56 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: node sizes: trun 56, sb 4096, master 512 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: node sizes: ref 64, cmt. start 32, orph 32 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: max. node sizes: data 4144, inode 4256 dentry 312 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: dead watermark: 2048 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: dark watermark: 6144 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: LEB overhead: 560 [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: max. dark space: 9013248 (8802 KiB, 8 MiB) [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: maximum bud bytes: 8773632 (8568 KiB, 8 MiB) [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: BG commit bud bytes: 7128576 (6961 KiB, 6 MiB) [ 97.691356] UBIFS DBG (pid 462): mount_ubifs: current bud bytes 5298176 (5174 KiB, 5 MiB) [ 97.692332] UBIFS DBG (pid 462): mount_ubifs: max. seq. number: 11154807 [ 97.692332] UBIFS DBG (pid 462): mount_ubifs: commit number: 3049 # mount rootfs on / type rootfs (rw) ubi0:rootfs on / type ubifs (ro,relatime) proc on /proc type proc (rw,relatime) sysfs on /sys type sysfs (rw,relatime) tmpfs on /dev type tmpfs (rw,relatime,size=4k,mode=755) devpts on /dev/pts type devpts (rw,relatime,gid=4,mode=620) shm on /dev/shm type tmpfs (rw,relatime,size=1024k) tmpfs on /tmp type tmpfs (rw,relatime,size=1024k) tmpfs on /root type tmpfs (rw,relatime,size=1024k) ubi1:logs on /var/log type ubifs (rw,noatime,nodiratime) ubi1:tmp on /usr/local/ecom/tmp type ubifs (rw,noatime,nodiratime) ubi0:local on /var/local type ubifs (rw,noatime,nodiratime) ubi:config on /usr/local/ecom/conf type ubifs (rw,noatime,nodiratime) ubi2:dbfs on /usr/local/ecom/db type ubifs (rw,noatime,nodiratime) # rm /usr/local/ecom/db/running# rm /usr/local/ecom/db/running [ 225.285040] UBIFS assert failed in ubifs_garbage_collect_leb at 524 (pid 505) [ 225.293829] [] (unwind_backtrace+0x0/0xe4) from [] (ubifs_garbage_collect_leb+0x820/0x870) [ 225.305548] [] (ubifs_garbage_collect_leb+0x820/0x870) from [] (ubifs_garbage_collect+0x138/0x9a8) [ 225.317267] [] (ubifs_garbage_collect+0x138/0x9a8) from [] (ubifs_budget_space+0x364/0xae0) [ 225.328986] [] (ubifs_budget_space+0x364/0xae0) from [] (ubifs_unlink+0xa4/0x2e8) [ 225.339728] [] (ubifs_unlink+0xa4/0x2e8) from [] (vfs_unlink+0x80/0xe8) [ 225.349493] [] (vfs_unlink+0x80/0xe8) from [] (do_unlinkat+0x164/0x178) [ 225.359259] [] (do_unlinkat+0x164/0x178) from [] (ret_fast_syscall+0x0/0x28) [ 225.392462] UBIFS assert failed in switch_gc_head at 84 (pid 505) [ 225.400275] [] (unwind_backtrace+0x0/0xe4) from [] (switch_gc_head+0x148/0x190) [ 225.411017] [] (switch_gc_head+0x148/0x190) from [] (ubifs_garbage_collect_leb+0x218/0x870) [ 225.421759] [] (ubifs_garbage_collect_leb+0x218/0x870) from [] (ubifs_garbage_collect+0x138/0x9a8) [ 225.434454] [] (ubifs_garbage_collect+0x138/0x9a8) from [] (ubifs_budget_space+0x364/0xae0) [ 225.446173] [] (ubifs_budget_space+0x364/0xae0) from [] (ubifs_unlink+0xa4/0x2e8) [ 225.456915] [] (ubifs_unlink+0xa4/0x2e8) from [] (vfs_unlink+0x80/0xe8) [ 225.466681] [] (vfs_unlink+0x80/0xe8) from [] (do_unlinkat+0x164/0x178) [ 225.476447] [] (do_unlinkat+0x164/0x178) from [] (ret_fast_syscall+0x0/0x28) [ 225.486212] UBIFS error (pid 505): ubifs_leb_unmap: unmap LEB -1 failed, error -22 [ 225.495001] UBIFS warning (pid 505): ubifs_ro_mode: switched to read-only mode, error -22 [ 225.504767] [] (unwind_backtrace+0x0/0xe4) from [] (ubifs_garbage_collect+0x300/0x9a8) [ 225.515509] [] (ubifs_garbage_collect+0x300/0x9a8) from [] (ubifs_budget_space+0x364/0xae0) [ 225.527228] [] (ubifs_budget_space+0x364/0xae0) from [] (ubifs_unlink+0xa4/0x2e8) [ 225.537970] [] (ubifs_unlink+0xa4/0x2e8) from [] (vfs_unlink+0x80/0xe8) [ 225.547736] [] (vfs_unlink+0x80/0xe8) from [] (do_unlinkat+0x164/0x178) [ 225.557501] [] (do_unlinkat+0x164/0x178) from [] (ret_fast_syscall+0x0/0x28) [ 225.572150] UBIFS error (pid 505): ubifs_budget_space: cannot budget space, error -22 rm: cannot remove '/usr/local/ecom/db/running': Invalid argument and fs goes into RO mode. # # Automatically generated make config: don't edit # Linux kernel version: 2.6.32.12 # Tue May 11 20:19:46 2010 # CONFIG_ARM=y CONFIG_SYS_SUPPORTS_APM_EMULATION=y CONFIG_GENERIC_GPIO=y CONFIG_GENERIC_TIME=y CONFIG_GENERIC_CLOCKEVENTS=y CONFIG_GENERIC_HARDIRQS=y CONFIG_STACKTRACE_SUPPORT=y CONFIG_HAVE_LATENCYTOP_SUPPORT=y CONFIG_LOCKDEP_SUPPORT=y CONFIG_TRACE_IRQFLAGS_SUPPORT=y CONFIG_HARDIRQS_SW_RESEND=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_RWSEM_GENERIC_SPINLOCK=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y CONFIG_VECTORS_BASE=0xffff0000 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y # # General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y # CONFIG_SWAP is not set CONFIG_SYSVIPC=y CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y CONFIG_POSIX_MQUEUE_SYSCTL=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set # CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set # # RCU Subsystem # CONFIG_TREE_RCU=y # CONFIG_TREE_PREEMPT_RCU is not set CONFIG_RCU_TRACE=y CONFIG_RCU_FANOUT=32 # CONFIG_RCU_FANOUT_EXACT is not set CONFIG_TREE_RCU_TRACE=y # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 # CONFIG_GROUP_SCHED is not set # CONFIG_CGROUPS is not set CONFIG_SYSFS_DEPRECATED=y CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set # CONFIG_NAMESPACES is not set # CONFIG_BLK_DEV_INITRD is not set # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_SYSCTL=y CONFIG_ANON_INODES=y CONFIG_EMBEDDED=y CONFIG_UID16=y CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SIGNALFD=y CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y # # Kernel Performance Events And Counters # CONFIG_VM_EVENT_COUNTERS=y CONFIG_COMPAT_BRK=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set # CONFIG_PROFILING is not set CONFIG_HAVE_OPROFILE=y CONFIG_HAVE_KPROBES=y CONFIG_HAVE_KRETPROBES=y CONFIG_HAVE_CLK=y # # GCOV-based kernel profiling # # CONFIG_GCOV_KERNEL is not set # CONFIG_SLOW_WORK is not set CONFIG_HAVE_GENERIC_DMA_COHERENT=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y CONFIG_BASE_SMALL=0 # CONFIG_MODULES is not set CONFIG_BLOCK=y CONFIG_LBDAF=y # CONFIG_BLK_DEV_BSG is not set # CONFIG_BLK_DEV_INTEGRITY is not set # # IO Schedulers # CONFIG_IOSCHED_NOOP=y CONFIG_IOSCHED_AS=y # CONFIG_IOSCHED_DEADLINE is not set CONFIG_IOSCHED_CFQ=y # CONFIG_DEFAULT_AS is not set # CONFIG_DEFAULT_DEADLINE is not set CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" # CONFIG_FREEZER is not set # # System Type # CONFIG_MMU=y # CONFIG_ARCH_AAEC2000 is not set # CONFIG_ARCH_INTEGRATOR is not set # CONFIG_ARCH_REALVIEW is not set # CONFIG_ARCH_VERSATILE is not set CONFIG_ARCH_AT91=y # CONFIG_ARCH_CLPS711X is not set # CONFIG_ARCH_GEMINI is not set # CONFIG_ARCH_EBSA110 is not set # CONFIG_ARCH_EP93XX is not set # CONFIG_ARCH_FOOTBRIDGE is not set # CONFIG_ARCH_MXC is not set # CONFIG_ARCH_STMP3XXX is not set # CONFIG_ARCH_NETX is not set # CONFIG_ARCH_H720X is not set # CONFIG_ARCH_NOMADIK is not set # CONFIG_ARCH_IOP13XX is not set # CONFIG_ARCH_IOP32X is not set # CONFIG_ARCH_IOP33X is not set # CONFIG_ARCH_IXP23XX is not set # CONFIG_ARCH_IXP2000 is not set # CONFIG_ARCH_IXP4XX is not set # CONFIG_ARCH_L7200 is not set # CONFIG_ARCH_KIRKWOOD is not set # CONFIG_ARCH_LOKI is not set # CONFIG_ARCH_MV78XX0 is not set # CONFIG_ARCH_ORION5X is not set # CONFIG_ARCH_MMP is not set # CONFIG_ARCH_KS8695 is not set # CONFIG_ARCH_NS9XXX is not set # CONFIG_ARCH_W90X900 is not set # CONFIG_ARCH_PNX4008 is not set # CONFIG_ARCH_PXA is not set # CONFIG_ARCH_MSM is not set # CONFIG_ARCH_RPC is not set # CONFIG_ARCH_SA1100 is not set # CONFIG_ARCH_S3C2410 is not set # CONFIG_ARCH_S3C64XX is not set # CONFIG_ARCH_S5PC1XX is not set # CONFIG_ARCH_SHARK is not set # CONFIG_ARCH_LH7A40X is not set # CONFIG_ARCH_U300 is not set # CONFIG_ARCH_DAVINCI is not set # CONFIG_ARCH_OMAP is not set # CONFIG_ARCH_BCMRING is not set # # Atmel AT91 System-on-Chip # # CONFIG_ARCH_AT91RM9200 is not set CONFIG_ARCH_AT91SAM9260=y # CONFIG_ARCH_AT91SAM9261 is not set # CONFIG_ARCH_AT91SAM9G10 is not set # CONFIG_ARCH_AT91SAM9263 is not set # CONFIG_ARCH_AT91SAM9RL is not set # CONFIG_ARCH_AT91SAM9G20 is not set # CONFIG_ARCH_AT91SAM9G45 is not set # CONFIG_ARCH_AT91CAP9 is not set # CONFIG_ARCH_AT91X40 is not set CONFIG_AT91_PMC_UNIT=y # # AT91SAM9260 Variants # # CONFIG_ARCH_AT91SAM9260_SAM9XE is not set # # AT91SAM9260 / AT91SAM9XE Board Type # CONFIG_MACH_AT91SAM9260EK=y # CONFIG_MACH_CAM60 is not set # CONFIG_MACH_SAM9_L9260 is not set # CONFIG_MACH_AFEB9260 is not set # CONFIG_MACH_USB_A9260 is not set # CONFIG_MACH_QIL_A9260 is not set # CONFIG_MACH_CPU9260 is not set # # AT91 Board Options # # CONFIG_MTD_AT91_DATAFLASH_CARD is not set # CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16 is not set # # AT91 Feature Selections # CONFIG_AT91_PROGRAMMABLE_CLOCKS=y CONFIG_AT91_TIMER_HZ=1024 CONFIG_AT91_EARLY_DBGU=y # CONFIG_AT91_EARLY_USART0 is not set # CONFIG_AT91_EARLY_USART1 is not set # CONFIG_AT91_EARLY_USART2 is not set # CONFIG_AT91_EARLY_USART3 is not set # CONFIG_AT91_EARLY_USART4 is not set # CONFIG_AT91_EARLY_USART5 is not set # # Processor Type # CONFIG_CPU_32=y CONFIG_CPU_ARM926T=y CONFIG_CPU_32v5=y CONFIG_CPU_ABRT_EV5TJ=y CONFIG_CPU_PABRT_LEGACY=y CONFIG_CPU_CACHE_VIVT=y CONFIG_CPU_COPY_V4WB=y CONFIG_CPU_TLB_V4WBI=y CONFIG_CPU_CP15=y CONFIG_CPU_CP15_MMU=y # # Processor Features # # CONFIG_ARM_THUMB is not set # CONFIG_CPU_ICACHE_DISABLE is not set # CONFIG_CPU_DCACHE_DISABLE is not set # CONFIG_CPU_DCACHE_WRITETHROUGH is not set # CONFIG_CPU_CACHE_ROUND_ROBIN is not set CONFIG_ARM_L1_CACHE_SHIFT=5 # # Bus support # # CONFIG_PCI_SYSCALL is not set # CONFIG_ARCH_SUPPORTS_MSI is not set # CONFIG_PCCARD is not set # # Kernel Features # # CONFIG_NO_HZ is not set # CONFIG_HIGH_RES_TIMERS is not set CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_VMSPLIT_3G=y # CONFIG_VMSPLIT_2G is not set # CONFIG_VMSPLIT_1G is not set CONFIG_PAGE_OFFSET=0xC0000000 # CONFIG_PREEMPT_NONE is not set # CONFIG_PREEMPT_VOLUNTARY is not set CONFIG_PREEMPT=y CONFIG_HZ=1024 CONFIG_AEABI=y # CONFIG_OABI_COMPAT is not set # CONFIG_ARCH_SPARSEMEM_DEFAULT is not set # CONFIG_ARCH_SELECT_MEMORY_MODEL is not set # CONFIG_HIGHMEM is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set # CONFIG_SPARSEMEM_MANUAL is not set CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y CONFIG_PAGEFLAGS_EXTENDED=y CONFIG_SPLIT_PTLOCK_CPUS=4096 # CONFIG_PHYS_ADDR_T_64BIT is not set CONFIG_ZONE_DMA_FLAG=0 CONFIG_VIRT_TO_BUS=y CONFIG_HAVE_MLOCK=y CONFIG_HAVE_MLOCKED_PAGE_BIT=y # CONFIG_KSM is not set CONFIG_DEFAULT_MMAP_MIN_ADDR=4096 CONFIG_LEDS=y CONFIG_LEDS_CPU=y CONFIG_ALIGNMENT_TRAP=y # CONFIG_UACCESS_WITH_MEMCPY is not set # # Boot options # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 CONFIG_CMDLINE="" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set # # CPU Power Management # # CONFIG_CPU_IDLE is not set # # Floating point emulation # # # At least one emulation must be selected # # CONFIG_VFP is not set # # Userspace binary formats # CONFIG_BINFMT_ELF=y # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set CONFIG_HAVE_AOUT=y # CONFIG_BINFMT_AOUT is not set # CONFIG_BINFMT_MISC is not set # # Power management options # # CONFIG_PM is not set CONFIG_ARCH_SUSPEND_POSSIBLE=y CONFIG_NET=y # # Networking options # CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y # CONFIG_IP_MULTICAST is not set CONFIG_IP_ADVANCED_ROUTER=y CONFIG_ASK_IP_FIB_HASH=y # CONFIG_IP_FIB_TRIE is not set CONFIG_IP_FIB_HASH=y CONFIG_IP_MULTIPLE_TABLES=y # CONFIG_IP_ROUTE_MULTIPATH is not set CONFIG_IP_ROUTE_VERBOSE=y # CONFIG_IP_PNP is not set # CONFIG_NET_IPIP is not set # CONFIG_NET_IPGRE is not set # CONFIG_ARPD is not set # CONFIG_SYN_COOKIES is not set # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set # CONFIG_INET_XFRM_MODE_TRANSPORT is not set # CONFIG_INET_XFRM_MODE_TUNNEL is not set # CONFIG_INET_XFRM_MODE_BEET is not set # CONFIG_INET_LRO is not set # CONFIG_INET_DIAG is not set # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" # CONFIG_TCP_MD5SIG is not set # CONFIG_IPV6 is not set # CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_NETFILTER_ADVANCED=y # # Core Netfilter Configuration # # CONFIG_NETFILTER_NETLINK_QUEUE is not set # CONFIG_NETFILTER_NETLINK_LOG is not set # CONFIG_NF_CONNTRACK is not set # CONFIG_NETFILTER_XTABLES is not set # CONFIG_IP_VS is not set # # IP: Netfilter Configuration # # CONFIG_NF_DEFRAG_IPV4 is not set # CONFIG_IP_NF_QUEUE is not set # CONFIG_IP_NF_IPTABLES is not set # CONFIG_IP_NF_ARPTABLES is not set # CONFIG_IP_DCCP is not set # CONFIG_IP_SCTP is not set # CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set # CONFIG_NET_DSA is not set # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set # CONFIG_PHONET is not set # CONFIG_IEEE802154 is not set # CONFIG_NET_SCHED is not set # CONFIG_DCB is not set # # Network testing # # CONFIG_NET_PKTGEN is not set # CONFIG_HAMRADIO is not set # CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set # CONFIG_AF_RXRPC is not set CONFIG_FIB_RULES=y CONFIG_WIRELESS=y # CONFIG_CFG80211 is not set CONFIG_CFG80211_DEFAULT_PS_VALUE=0 # CONFIG_WIRELESS_OLD_REGULATORY is not set CONFIG_WIRELESS_EXT=y CONFIG_WIRELESS_EXT_SYSFS=y # CONFIG_LIB80211 is not set # # CFG80211 needs to be enabled for MAC80211 # # CONFIG_WIMAX is not set # CONFIG_RFKILL is not set # CONFIG_NET_9P is not set # # Device Drivers # # # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" # CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y CONFIG_FIRMWARE_IN_KERNEL=y CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DRIVER is not set # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set CONFIG_MTD=y # CONFIG_MTD_DEBUG is not set # CONFIG_MTD_CONCAT is not set CONFIG_MTD_PARTITIONS=y # CONFIG_MTD_REDBOOT_PARTS is not set CONFIG_MTD_CMDLINE_PARTS=y # CONFIG_MTD_AFS_PARTS is not set # CONFIG_MTD_AR7_PARTS is not set # # User Modules And Translation Layers # CONFIG_MTD_CHAR=y CONFIG_MTD_BLKDEVS=y CONFIG_MTD_BLOCK=y # CONFIG_FTL is not set # CONFIG_NFTL is not set # CONFIG_INFTL is not set # CONFIG_RFD_FTL is not set # CONFIG_SSFDC is not set # CONFIG_MTD_OOPS is not set # # RAM/ROM/Flash chip drivers # # CONFIG_MTD_CFI is not set # CONFIG_MTD_JEDECPROBE is not set CONFIG_MTD_MAP_BANK_WIDTH_1=y CONFIG_MTD_MAP_BANK_WIDTH_2=y CONFIG_MTD_MAP_BANK_WIDTH_4=y # CONFIG_MTD_MAP_BANK_WIDTH_8 is not set # CONFIG_MTD_MAP_BANK_WIDTH_16 is not set # CONFIG_MTD_MAP_BANK_WIDTH_32 is not set CONFIG_MTD_CFI_I1=y CONFIG_MTD_CFI_I2=y # CONFIG_MTD_CFI_I4 is not set # CONFIG_MTD_CFI_I8 is not set # CONFIG_MTD_RAM is not set # CONFIG_MTD_ROM is not set # CONFIG_MTD_ABSENT is not set # # Mapping drivers for chip access # # CONFIG_MTD_COMPLEX_MAPPINGS is not set # CONFIG_MTD_PLATRAM is not set # # Self-contained MTD device drivers # # CONFIG_MTD_DATAFLASH is not set # CONFIG_MTD_M25P80 is not set # CONFIG_MTD_SST25L is not set # CONFIG_MTD_SLRAM is not set # CONFIG_MTD_PHRAM is not set # CONFIG_MTD_MTDRAM is not set # CONFIG_MTD_BLOCK2MTD is not set # # Disk-On-Chip Device Drivers # # CONFIG_MTD_DOC2000 is not set # CONFIG_MTD_DOC2001 is not set # CONFIG_MTD_DOC2001PLUS is not set CONFIG_MTD_NAND=y # CONFIG_MTD_NAND_VERIFY_WRITE is not set # CONFIG_MTD_NAND_ECC_SMC is not set # CONFIG_MTD_NAND_MUSEUM_IDS is not set # CONFIG_MTD_NAND_GPIO is not set CONFIG_MTD_NAND_IDS=y # CONFIG_MTD_NAND_DISKONCHIP is not set CONFIG_MTD_NAND_ATMEL=y # CONFIG_MTD_NAND_ATMEL_ECC_HW is not set CONFIG_MTD_NAND_ATMEL_ECC_SOFT=y # CONFIG_MTD_NAND_ATMEL_ECC_NONE is not set # CONFIG_MTD_NAND_NANDSIM is not set # CONFIG_MTD_NAND_PLATFORM is not set # CONFIG_MTD_ALAUDA is not set # CONFIG_MTD_ONENAND is not set # # LPDDR flash memory drivers # # CONFIG_MTD_LPDDR is not set # # UBI - Unsorted block images # CONFIG_MTD_UBI=y CONFIG_MTD_UBI_WL_THRESHOLD=4096 CONFIG_MTD_UBI_BEB_RESERVE=3 # CONFIG_MTD_UBI_GLUEBI is not set # # UBI debugging options # # CONFIG_MTD_UBI_DEBUG is not set # CONFIG_PARPORT is not set CONFIG_BLK_DEV=y # CONFIG_BLK_DEV_COW_COMMON is not set CONFIG_BLK_DEV_LOOP=y # CONFIG_BLK_DEV_CRYPTOLOOP is not set # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_UB is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=1 CONFIG_BLK_DEV_RAM_SIZE=16384 # CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set # CONFIG_MG_DISK is not set # CONFIG_MISC_DEVICES is not set CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # # SCSI device support # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y CONFIG_SCSI_DMA=y # CONFIG_SCSI_TGT is not set # CONFIG_SCSI_NETLINK is not set # CONFIG_SCSI_PROC_FS is not set # # SCSI support type (disk, tape, CD-ROM) # CONFIG_BLK_DEV_SD=y # CONFIG_CHR_DEV_ST is not set # CONFIG_CHR_DEV_OSST is not set # CONFIG_BLK_DEV_SR is not set # CONFIG_CHR_DEV_SG is not set # CONFIG_CHR_DEV_SCH is not set # CONFIG_SCSI_MULTI_LUN is not set # CONFIG_SCSI_CONSTANTS is not set # CONFIG_SCSI_LOGGING is not set # CONFIG_SCSI_SCAN_ASYNC is not set # # SCSI Transports # # CONFIG_SCSI_SPI_ATTRS is not set # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set # CONFIG_SCSI_SRP_ATTRS is not set # CONFIG_SCSI_LOWLEVEL is not set # CONFIG_SCSI_DH is not set # CONFIG_SCSI_OSD_INITIATOR is not set # CONFIG_ATA is not set # CONFIG_MD is not set CONFIG_NETDEVICES=y CONFIG_DUMMY=y # CONFIG_BONDING is not set # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set # CONFIG_VETH is not set CONFIG_PHYLIB=y # # MII PHY device drivers # # CONFIG_MARVELL_PHY is not set # CONFIG_DAVICOM_PHY is not set # CONFIG_QSEMI_PHY is not set # CONFIG_LXT_PHY is not set # CONFIG_CICADA_PHY is not set # CONFIG_VITESSE_PHY is not set # CONFIG_SMSC_PHY is not set # CONFIG_BROADCOM_PHY is not set # CONFIG_ICPLUS_PHY is not set # CONFIG_REALTEK_PHY is not set # CONFIG_NATIONAL_PHY is not set # CONFIG_STE10XP is not set # CONFIG_LSI_ET1011C_PHY is not set # CONFIG_FIXED_PHY is not set # CONFIG_MDIO_BITBANG is not set CONFIG_NET_ETHERNET=y # CONFIG_MII is not set CONFIG_MACB=y # CONFIG_AX88796 is not set # CONFIG_SMC91X is not set # CONFIG_DM9000 is not set # CONFIG_ENC28J60 is not set # CONFIG_ETHOC is not set # CONFIG_SMC911X is not set # CONFIG_SMSC911X is not set # CONFIG_DNET is not set # CONFIG_IBM_NEW_EMAC_ZMII is not set # CONFIG_IBM_NEW_EMAC_RGMII is not set # CONFIG_IBM_NEW_EMAC_TAH is not set # CONFIG_IBM_NEW_EMAC_EMAC4 is not set # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set # CONFIG_B44 is not set # CONFIG_KS8842 is not set # CONFIG_KS8851 is not set # CONFIG_KS8851_MLL is not set # CONFIG_NETDEV_1000 is not set # CONFIG_NETDEV_10000 is not set CONFIG_WLAN=y # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set # # Enable WiMAX (Networking options) to see the WiMAX drivers # # # USB Network Adapters # # CONFIG_USB_CATC is not set # CONFIG_USB_KAWETH is not set # CONFIG_USB_PEGASUS is not set # CONFIG_USB_RTL8150 is not set # CONFIG_USB_USBNET is not set # CONFIG_WAN is not set CONFIG_PPP=y CONFIG_PPP_MULTILINK=y CONFIG_PPP_FILTER=y CONFIG_PPP_ASYNC=y CONFIG_PPP_SYNC_TTY=y CONFIG_PPP_DEFLATE=y CONFIG_PPP_BSDCOMP=y CONFIG_PPP_MPPE=y CONFIG_PPPOE=y CONFIG_PPPOL2TP=y # CONFIG_SLIP is not set CONFIG_SLHC=y # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set # CONFIG_ISDN is not set # CONFIG_PHONE is not set # # Input device support # CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set # CONFIG_INPUT_POLLDEV is not set # # Userland interfaces # # CONFIG_INPUT_MOUSEDEV is not set # CONFIG_INPUT_JOYDEV is not set CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_EVBUG is not set # # Input Device Drivers # CONFIG_INPUT_KEYBOARD=y # CONFIG_KEYBOARD_ATKBD is not set # CONFIG_KEYBOARD_LKKBD is not set CONFIG_KEYBOARD_GPIO=y # CONFIG_KEYBOARD_MATRIX is not set # CONFIG_KEYBOARD_NEWTON is not set # CONFIG_KEYBOARD_OPENCORES is not set # CONFIG_KEYBOARD_STOWAWAY is not set # CONFIG_KEYBOARD_SUNKBD is not set # CONFIG_KEYBOARD_XTKBD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set # CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set CONFIG_INPUT_MISC=y CONFIG_INPUT_AT91_BEEPER=y # CONFIG_INPUT_ATI_REMOTE is not set # CONFIG_INPUT_ATI_REMOTE2 is not set # CONFIG_INPUT_KEYSPAN_REMOTE is not set # CONFIG_INPUT_POWERMATE is not set # CONFIG_INPUT_YEALINK is not set # CONFIG_INPUT_CM109 is not set # CONFIG_INPUT_UINPUT is not set # CONFIG_INPUT_GPIO_ROTARY_ENCODER is not set # # Hardware I/O ports # # CONFIG_SERIO is not set # CONFIG_GAMEPORT is not set # # Character devices # # CONFIG_VT is not set # CONFIG_DEVKMEM is not set # CONFIG_SERIAL_NONSTANDARD is not set # # Serial drivers # CONFIG_SERIAL_8250=y # CONFIG_SERIAL_8250_CONSOLE is not set CONFIG_SERIAL_8250_9260=y CONFIG_SERIAL_8250_NR_UARTS=64 CONFIG_SERIAL_8250_RUNTIME_UARTS=64 CONFIG_SERIAL_8250_EXTENDED=y CONFIG_SERIAL_8250_MANY_PORTS=y CONFIG_SERIAL_8250_SHARE_IRQ=y # CONFIG_SERIAL_8250_DETECT_IRQ is not set # CONFIG_SERIAL_8250_RSA is not set # # Non-8250 serial port support # CONFIG_SERIAL_ATMEL=y CONFIG_SERIAL_ATMEL_CONSOLE=y # CONFIG_SERIAL_ATMEL_PDC is not set CONFIG_SERIAL_ATMEL_TTYAT=y # CONFIG_SERIAL_MAX3100 is not set CONFIG_SERIAL_CORE=y CONFIG_SERIAL_CORE_CONSOLE=y CONFIG_UNIX98_PTYS=y # CONFIG_DEVPTS_MULTIPLE_INSTANCES is not set # CONFIG_LEGACY_PTYS is not set # CONFIG_IPMI_HANDLER is not set CONFIG_HW_RANDOM=y # CONFIG_HW_RANDOM_TIMERIOMEM is not set # CONFIG_R3964 is not set # CONFIG_RAW_DRIVER is not set # CONFIG_TCG_TPM is not set # CONFIG_I2C is not set CONFIG_SPI=y # CONFIG_SPI_DEBUG is not set CONFIG_SPI_MASTER=y # # SPI Master Controller Drivers # CONFIG_SPI_ATMEL=y # CONFIG_SPI_BITBANG is not set # CONFIG_SPI_GPIO is not set # # SPI Protocol Masters # # CONFIG_SPI_SPIDEV is not set # CONFIG_SPI_TLE62X0 is not set # # PPS support # CONFIG_PPS=y # CONFIG_PPS_DEBUG is not set CONFIG_PPS_CLIENT_AT91SAM9260PS=y CONFIG_ARCH_REQUIRE_GPIOLIB=y CONFIG_GPIOLIB=y # CONFIG_DEBUG_GPIO is not set # CONFIG_GPIO_SYSFS is not set # # Memory mapped GPIO expanders: # # # I2C GPIO expanders: # # # PCI GPIO expanders: # # # SPI GPIO expanders: # # CONFIG_GPIO_MAX7301 is not set # CONFIG_GPIO_MCP23S08 is not set # CONFIG_GPIO_MC33880 is not set # # AC97 GPIO expanders: # CONFIG_W1=y # # 1-wire Bus Masters # # CONFIG_W1_MASTER_DS2490 is not set # CONFIG_W1_MASTER_DS1WM is not set CONFIG_W1_MASTER_GPIO=y # # 1-wire Slaves # # CONFIG_W1_SLAVE_THERM is not set CONFIG_W1_SLAVE_SMEM=y # CONFIG_W1_SLAVE_DS2431 is not set # CONFIG_W1_SLAVE_DS2433 is not set # CONFIG_W1_SLAVE_DS2760 is not set # CONFIG_W1_SLAVE_BQ27000 is not set # CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set # CONFIG_THERMAL is not set CONFIG_WATCHDOG=y CONFIG_WATCHDOG_NOWAYOUT=y # # Watchdog Device Drivers # # CONFIG_SOFT_WATCHDOG is not set CONFIG_AT91SAM9X_WATCHDOG=y # # USB-based Watchdog Cards # # CONFIG_USBPCWATCHDOG is not set CONFIG_SSB_POSSIBLE=y # # Sonics Silicon Backplane # # CONFIG_SSB is not set # # Multifunction device drivers # # CONFIG_MFD_CORE is not set # CONFIG_MFD_SM501 is not set # CONFIG_MFD_ASIC3 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set # CONFIG_MFD_TC6393XB is not set # CONFIG_MFD_MC13783 is not set # CONFIG_EZX_PCAP is not set # CONFIG_REGULATOR is not set # CONFIG_MEDIA_SUPPORT is not set # # Graphics support # # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set # CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Display device support # # CONFIG_DISPLAY_SUPPORT is not set # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y # CONFIG_USB_ARCH_HAS_EHCI is not set CONFIG_USB=y # CONFIG_USB_DEBUG is not set # CONFIG_USB_ANNOUNCE_NEW_DEVICES is not set # # Miscellaneous USB options # # CONFIG_USB_DEVICEFS is not set # CONFIG_USB_DEVICE_CLASS is not set CONFIG_USB_DYNAMIC_MINORS=y # CONFIG_USB_OTG is not set # CONFIG_USB_OTG_WHITELIST is not set # CONFIG_USB_OTG_BLACKLIST_HUB is not set # CONFIG_USB_MON is not set # CONFIG_USB_WUSB is not set # CONFIG_USB_WUSB_CBAF is not set # # USB Host Controller Drivers # # CONFIG_USB_C67X00_HCD is not set # CONFIG_USB_OXU210HP_HCD is not set # CONFIG_USB_ISP116X_HCD is not set # CONFIG_USB_ISP1760_HCD is not set # CONFIG_USB_ISP1362_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set # CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y # CONFIG_USB_SL811_HCD is not set # CONFIG_USB_R8A66597_HCD is not set # CONFIG_USB_HWA_HCD is not set # CONFIG_USB_MUSB_HDRC is not set # # USB Device Class drivers # # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set # CONFIG_USB_WDM is not set # CONFIG_USB_TMC is not set # # NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may # # # also be needed; see USB_STORAGE Help for more info # CONFIG_USB_STORAGE=y # CONFIG_USB_STORAGE_DEBUG is not set # CONFIG_USB_STORAGE_DATAFAB is not set # CONFIG_USB_STORAGE_FREECOM is not set # CONFIG_USB_STORAGE_ISD200 is not set # CONFIG_USB_STORAGE_USBAT is not set # CONFIG_USB_STORAGE_SDDR09 is not set # CONFIG_USB_STORAGE_SDDR55 is not set # CONFIG_USB_STORAGE_JUMPSHOT is not set # CONFIG_USB_STORAGE_ALAUDA is not set # CONFIG_USB_STORAGE_ONETOUCH is not set # CONFIG_USB_STORAGE_KARMA is not set # CONFIG_USB_STORAGE_CYPRESS_ATACB is not set # CONFIG_USB_LIBUSUAL is not set # # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set # # USB port drivers # # CONFIG_USB_SERIAL is not set # # USB Miscellaneous drivers # # CONFIG_USB_EMI62 is not set # CONFIG_USB_EMI26 is not set # CONFIG_USB_ADUTUX is not set # CONFIG_USB_SEVSEG is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_IDMOUSE is not set # CONFIG_USB_FTDI_ELAN is not set # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_LD is not set # CONFIG_USB_TRANCEVIBRATOR is not set # CONFIG_USB_IOWARRIOR is not set # CONFIG_USB_TEST is not set # CONFIG_USB_ISIGHTFW is not set # CONFIG_USB_VST is not set # CONFIG_USB_GADGET is not set # # OTG and related infrastructure # # CONFIG_USB_GPIO_VBUS is not set # CONFIG_NOP_USB_XCEIV is not set CONFIG_MMC=y # CONFIG_MMC_DEBUG is not set # CONFIG_MMC_UNSAFE_RESUME is not set # # MMC/SD/SDIO Card Drivers # CONFIG_MMC_BLOCK=y CONFIG_MMC_BLOCK_BOUNCE=y # CONFIG_SDIO_UART is not set # CONFIG_MMC_TEST is not set # # MMC/SD/SDIO Host Controller Drivers # # CONFIG_MMC_SDHCI is not set CONFIG_MMC_AT91=y # CONFIG_MMC_ATMELMCI is not set # CONFIG_MMC_SPI is not set # CONFIG_MEMSTICK is not set CONFIG_NEW_LEDS=y CONFIG_LEDS_CLASS=y # # LED drivers # CONFIG_LEDS_GPIO=y CONFIG_LEDS_GPIO_PLATFORM=y # CONFIG_LEDS_DAC124S085 is not set # # LED Triggers # CONFIG_LEDS_TRIGGERS=y CONFIG_LEDS_TRIGGER_TIMER=y CONFIG_LEDS_TRIGGER_HEARTBEAT=y # CONFIG_LEDS_TRIGGER_BACKLIGHT is not set # CONFIG_LEDS_TRIGGER_GPIO is not set CONFIG_LEDS_TRIGGER_DEFAULT_ON=y # # iptables trigger is under Netfilter config (LED target) # # CONFIG_ACCESSIBILITY is not set CONFIG_RTC_LIB=y CONFIG_RTC_CLASS=y CONFIG_RTC_HCTOSYS=y CONFIG_RTC_HCTOSYS_DEVICE="rtc0" # CONFIG_RTC_DEBUG is not set # # RTC interfaces # CONFIG_RTC_INTF_SYSFS=y CONFIG_RTC_INTF_PROC=y CONFIG_RTC_INTF_DEV=y # CONFIG_RTC_INTF_DEV_UIE_EMUL is not set # CONFIG_RTC_DRV_TEST is not set # # SPI RTC drivers # # CONFIG_RTC_DRV_M41T94 is not set # CONFIG_RTC_DRV_DS1305 is not set # CONFIG_RTC_DRV_DS1390 is not set # CONFIG_RTC_DRV_MAX6902 is not set # CONFIG_RTC_DRV_R9701 is not set # CONFIG_RTC_DRV_RS5C348 is not set # CONFIG_RTC_DRV_DS3234 is not set # CONFIG_RTC_DRV_PCF2123 is not set # # Platform RTC drivers # # CONFIG_RTC_DRV_CMOS is not set # CONFIG_RTC_DRV_DS1286 is not set # CONFIG_RTC_DRV_DS1511 is not set # CONFIG_RTC_DRV_DS1553 is not set # CONFIG_RTC_DRV_DS1742 is not set # CONFIG_RTC_DRV_STK17TA8 is not set # CONFIG_RTC_DRV_M48T86 is not set # CONFIG_RTC_DRV_M48T35 is not set # CONFIG_RTC_DRV_M48T59 is not set # CONFIG_RTC_DRV_BQ4802 is not set # CONFIG_RTC_DRV_V3020 is not set # # on-CPU RTC drivers # CONFIG_RTC_DRV_AT91SAM9=y CONFIG_RTC_DRV_AT91SAM9_RTT=0 CONFIG_RTC_DRV_AT91SAM9_GPBR=0 # CONFIG_DMADEVICES is not set # CONFIG_AUXDISPLAY is not set # CONFIG_UIO is not set # # TI VLYNQ # CONFIG_STAGING=y # CONFIG_STAGING_EXCLUDE_BUILD is not set # CONFIG_USB_IP_COMMON is not set # CONFIG_PRISM2_USB is not set # CONFIG_ECHO is not set CONFIG_COMEDI=y CONFIG_COMEDI_DEBUG=y # CONFIG_COMEDI_USB_DRIVERS is not set # CONFIG_ASUS_OLED is not set # CONFIG_TRANZPORT is not set # # Android # # # Qualcomm MSM Camera And Video # # # Camera Sensor Selection # # CONFIG_INPUT_GPIO is not set # CONFIG_DST is not set # CONFIG_POHMELFS is not set # CONFIG_PLAN9AUTH is not set # CONFIG_VT6656 is not set # # RAR Register Driver # # CONFIG_RAR_REGISTER is not set # CONFIG_IIO is not set # # File systems # CONFIG_EXT2_FS=y # CONFIG_EXT2_FS_XATTR is not set # CONFIG_EXT2_FS_XIP is not set CONFIG_EXT3_FS=y # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set # CONFIG_EXT3_FS_XATTR is not set # CONFIG_EXT4_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set # CONFIG_REISERFS_FS is not set # CONFIG_JFS_FS is not set # CONFIG_FS_POSIX_ACL is not set # CONFIG_XFS_FS is not set # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set # CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set # CONFIG_FUSE_FS is not set # # Caches # # CONFIG_FSCACHE is not set # # CD-ROM/DVD Filesystems # # CONFIG_ISO9660_FS is not set # CONFIG_UDF_FS is not set # # DOS/FAT/NT Filesystems # CONFIG_FAT_FS=y CONFIG_MSDOS_FS=y CONFIG_VFAT_FS=y CONFIG_FAT_DEFAULT_CODEPAGE=866 CONFIG_FAT_DEFAULT_IOCHARSET="koi8-r" # CONFIG_NTFS_FS is not set # # Pseudo filesystems # CONFIG_PROC_FS=y CONFIG_PROC_SYSCTL=y CONFIG_PROC_PAGE_MONITOR=y CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_TMPFS_POSIX_ACL is not set # CONFIG_HUGETLB_PAGE is not set CONFIG_CONFIGFS_FS=y CONFIG_MISC_FILESYSTEMS=y # CONFIG_ADFS_FS is not set # CONFIG_AFFS_FS is not set # CONFIG_HFS_FS is not set # CONFIG_HFSPLUS_FS is not set # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set CONFIG_JFFS2_FS=y CONFIG_JFFS2_FS_DEBUG=0 CONFIG_JFFS2_FS_WRITEBUFFER=y # CONFIG_JFFS2_FS_WBUF_VERIFY is not set # CONFIG_JFFS2_SUMMARY is not set # CONFIG_JFFS2_FS_XATTR is not set # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set CONFIG_JFFS2_ZLIB=y # CONFIG_JFFS2_LZO is not set CONFIG_JFFS2_RTIME=y # CONFIG_JFFS2_RUBIN is not set CONFIG_UBIFS_FS=y CONFIG_UBIFS_FS_XATTR=y CONFIG_UBIFS_FS_ADVANCED_COMPR=y CONFIG_UBIFS_FS_LZO=y CONFIG_UBIFS_FS_ZLIB=y CONFIG_UBIFS_FS_DEBUG=y CONFIG_UBIFS_FS_DEBUG_MSG_LVL=0 CONFIG_UBIFS_FS_DEBUG_CHKS=y # CONFIG_CRAMFS is not set # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set # CONFIG_MINIX_FS is not set # CONFIG_OMFS_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set # CONFIG_ROMFS_FS is not set # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_NETWORK_FILESYSTEMS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y CONFIG_NLS=y CONFIG_NLS_DEFAULT="koi8-r" CONFIG_NLS_CODEPAGE_437=y # CONFIG_NLS_CODEPAGE_737 is not set # CONFIG_NLS_CODEPAGE_775 is not set # CONFIG_NLS_CODEPAGE_850 is not set # CONFIG_NLS_CODEPAGE_852 is not set # CONFIG_NLS_CODEPAGE_855 is not set # CONFIG_NLS_CODEPAGE_857 is not set # CONFIG_NLS_CODEPAGE_860 is not set # CONFIG_NLS_CODEPAGE_861 is not set # CONFIG_NLS_CODEPAGE_862 is not set # CONFIG_NLS_CODEPAGE_863 is not set # CONFIG_NLS_CODEPAGE_864 is not set # CONFIG_NLS_CODEPAGE_865 is not set CONFIG_NLS_CODEPAGE_866=y # CONFIG_NLS_CODEPAGE_869 is not set # CONFIG_NLS_CODEPAGE_936 is not set # CONFIG_NLS_CODEPAGE_950 is not set # CONFIG_NLS_CODEPAGE_932 is not set # CONFIG_NLS_CODEPAGE_949 is not set # CONFIG_NLS_CODEPAGE_874 is not set # CONFIG_NLS_ISO8859_8 is not set # CONFIG_NLS_CODEPAGE_1250 is not set # CONFIG_NLS_CODEPAGE_1251 is not set # CONFIG_NLS_ASCII is not set CONFIG_NLS_ISO8859_1=y # CONFIG_NLS_ISO8859_2 is not set # CONFIG_NLS_ISO8859_3 is not set # CONFIG_NLS_ISO8859_4 is not set # CONFIG_NLS_ISO8859_5 is not set # CONFIG_NLS_ISO8859_6 is not set # CONFIG_NLS_ISO8859_7 is not set # CONFIG_NLS_ISO8859_9 is not set # CONFIG_NLS_ISO8859_13 is not set # CONFIG_NLS_ISO8859_14 is not set # CONFIG_NLS_ISO8859_15 is not set CONFIG_NLS_KOI8_R=y # CONFIG_NLS_KOI8_U is not set CONFIG_NLS_UTF8=y # CONFIG_DLM is not set # # Kernel hacking # CONFIG_PRINTK_TIME=y # CONFIG_ENABLE_WARN_DEPRECATED is not set # CONFIG_ENABLE_MUST_CHECK is not set CONFIG_FRAME_WARN=1024 # CONFIG_MAGIC_SYSRQ is not set # CONFIG_STRIP_ASM_SYMS is not set # CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_FS=y # CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC is not set CONFIG_BOOTPARAM_SOFTLOCKUP_PANIC_VALUE=0 CONFIG_DETECT_HUNG_TASK=y # CONFIG_BOOTPARAM_HUNG_TASK_PANIC is not set CONFIG_BOOTPARAM_HUNG_TASK_PANIC_VALUE=0 CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set # CONFIG_TIMER_STATS is not set # CONFIG_DEBUG_OBJECTS is not set # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_KMEMLEAK is not set CONFIG_DEBUG_PREEMPT=y # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set # CONFIG_DEBUG_LOCK_ALLOC is not set # CONFIG_PROVE_LOCKING is not set # CONFIG_LOCK_STAT is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_WRITECOUNT is not set # CONFIG_DEBUG_MEMORY_INIT is not set # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set # CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set CONFIG_RCU_CPU_STALL_DETECTOR=y # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set # CONFIG_DEBUG_FORCE_WEAK_PER_CPU is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set CONFIG_SYSCTL_SYSCALL_CHECK=y # CONFIG_PAGE_POISONING is not set CONFIG_HAVE_FUNCTION_TRACER=y CONFIG_TRACING_SUPPORT=y # CONFIG_FTRACE is not set # CONFIG_DYNAMIC_DEBUG is not set # CONFIG_SAMPLES is not set CONFIG_HAVE_ARCH_KGDB=y # CONFIG_KGDB is not set CONFIG_ARM_UNWIND=y # CONFIG_DEBUG_USER is not set # CONFIG_DEBUG_ERRORS is not set # CONFIG_DEBUG_STACK_USAGE is not set # CONFIG_DEBUG_LL is not set # # Security options # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set # CONFIG_SECURITYFS is not set # CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y # # Crypto core or helper # # CONFIG_CRYPTO_FIPS is not set CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_ALGAPI2=y CONFIG_CRYPTO_AEAD2=y CONFIG_CRYPTO_BLKCIPHER=y CONFIG_CRYPTO_BLKCIPHER2=y CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_HASH2=y CONFIG_CRYPTO_RNG=y CONFIG_CRYPTO_RNG2=y CONFIG_CRYPTO_PCOMP=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_MANAGER2=y # CONFIG_CRYPTO_GF128MUL is not set # CONFIG_CRYPTO_NULL is not set CONFIG_CRYPTO_WORKQUEUE=y # CONFIG_CRYPTO_CRYPTD is not set # CONFIG_CRYPTO_AUTHENC is not set # # Authenticated Encryption with Associated Data # # CONFIG_CRYPTO_CCM is not set # CONFIG_CRYPTO_GCM is not set # CONFIG_CRYPTO_SEQIV is not set # # Block modes # # CONFIG_CRYPTO_CBC is not set # CONFIG_CRYPTO_CTR is not set # CONFIG_CRYPTO_CTS is not set CONFIG_CRYPTO_ECB=y # CONFIG_CRYPTO_LRW is not set # CONFIG_CRYPTO_PCBC is not set # CONFIG_CRYPTO_XTS is not set # # Hash modes # # CONFIG_CRYPTO_HMAC is not set # CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_VMAC is not set # # Digest # CONFIG_CRYPTO_CRC32C=y # CONFIG_CRYPTO_GHASH is not set # CONFIG_CRYPTO_MD4 is not set # CONFIG_CRYPTO_MD5 is not set # CONFIG_CRYPTO_MICHAEL_MIC is not set # CONFIG_CRYPTO_RMD128 is not set # CONFIG_CRYPTO_RMD160 is not set # CONFIG_CRYPTO_RMD256 is not set # CONFIG_CRYPTO_RMD320 is not set CONFIG_CRYPTO_SHA1=y # CONFIG_CRYPTO_SHA256 is not set # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_TGR192 is not set # CONFIG_CRYPTO_WP512 is not set # # Ciphers # CONFIG_CRYPTO_AES=y # CONFIG_CRYPTO_ANUBIS is not set CONFIG_CRYPTO_ARC4=y # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_CAST5 is not set # CONFIG_CRYPTO_CAST6 is not set # CONFIG_CRYPTO_DES is not set # CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_SALSA20 is not set # CONFIG_CRYPTO_SEED is not set # CONFIG_CRYPTO_SERPENT is not set # CONFIG_CRYPTO_TEA is not set # CONFIG_CRYPTO_TWOFISH is not set # # Compression # CONFIG_CRYPTO_DEFLATE=y # CONFIG_CRYPTO_ZLIB is not set CONFIG_CRYPTO_LZO=y # # Random Number Generation # CONFIG_CRYPTO_ANSI_CPRNG=y CONFIG_CRYPTO_HW=y # CONFIG_BINARY_PRINTF is not set # # Library routines # CONFIG_BITREVERSE=y CONFIG_GENERIC_FIND_LAST_BIT=y CONFIG_CRC_CCITT=y CONFIG_CRC16=y # CONFIG_CRC_T10DIF is not set # CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y # CONFIG_CRC7 is not set CONFIG_LIBCRC32C=y CONFIG_ZLIB_INFLATE=y CONFIG_ZLIB_DEFLATE=y CONFIG_LZO_COMPRESS=y CONFIG_LZO_DECOMPRESS=y CONFIG_HAS_IOMEM=y CONFIG_HAS_IOPORT=y CONFIG_HAS_DMA=y CONFIG_NLATTR=y From tglx at linutronix.de Tue May 11 15:17:20 2010 From: tglx at linutronix.de (Thomas Gleixner) Date: Tue, 11 May 2010 21:17:20 +0200 (CEST) Subject: UBIL design doc In-Reply-To: <1273475736.2209.88.camel@localhost> References: <1273475736.2209.88.camel@localhost> Message-ID: B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: > On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: > > Hi, > > I am forwarding you the design document for ubi with log. Please > > find the ubil document at > > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL > > design document.pdf @Brijesh, thanks for tackling this ! > Hi guys, > > I've read the document. Looks very promising. Here some feed-back. > > 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 > erease cycles? Won't the SB PEB wear out very quickly? Why you did not > go for the chaining approach which I described in the old JFFS3 design > doc? > > If we do not implement chaining, we should at least design it and make > sure UBIL can be extended later so that SB chaining could be added. The super block needs to be scanned for from the beginning of flash anyway due to bad blocks. Putting it into a fixed position (first good erase block) is a very bad design decision vs. wear leveling. The super block must be moveable like any other block, though we can keep it as close to the start of flash as possible. Also chaining has a tradeoff. The more chains you need to walk the closer you get to the point where you are equally bad as a full scan. > 2. SB PEB at the end. I think this is a very bad idea. Imagine you have > to do UBIL images for production on the factory. With your design you > have the following bad drawbacks: > > a. NAND flash has initial bad blocks, and you do not know how many, > and where they sit. These may be the last 8 eraseblocks. So, when > you prepare an image (say, with the ubinize user-space tool), where > will you put the second SB PEB? > > b. Currently, UBI/UBIFS images are small. E.g., if you make an > UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, > your image will be few megs - it will contain the files, and all > the needed UBI/UBIFS meta-data. > > So now what will be image size for UBIL - 1GiB, and this is bad. > You then will transfer 1GiB of data to the devices during flashing > or you will have to invent ways to work around this. Do you need > these complexities? > > I think the second SB PEB should not be at the end. I think we do not need a second SB at all. UBI should not depend on the super block in any way. The super block is an optimization for the common case - nothing more. > 3. Backward-compatibility. In UBIL you removed EC anc VID headers in > PEBs. That's fine for optimization purposes. But it has draw-backs: > > a. If any of the UBIL meta-data blocks like SB, CMT or log are > corrupted - that's it - we are screwed. You cannot anymore > re-consturct the data by scanning. The robustness goes down. > > c. Backward compatibility - UBI will not be able to attach UBIL > images. This is not very nice. > > So, I think you should keep EC and VID headers in PEBs. And you should > make the SB/CMT/log blocks to be a new type of UBI volume with > UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this > case UBI will attach UBIL volumes just fine. > > Then, you can add an _option_ to have no EC/VID headers in PEBs. This > then can be used for performance, if one wants to sacrifice robustness. > But this should be the second step. In this case, you will just need to > put a VID header with UBI_COMPAT_REJECT flag to the first PEB. I don't think it's a good idea to kill the EC/VID headers. It not only violates the backwards compability it also fundamentally weakens UBIs reliability for no good reason and I doubt that the performance win is big enough to make it worth. The performance gain is at attach time by getting rid of the flash scan, but not by getting rid of writing the EC/VID headers. The logging is a speed up / optimization for the common case, but it needs to preserve full reconstruction via scanning all eraseblocks and checking the EC/VID headers. That also allows retrofitting on existing devices. I'd rather see the super block / log volume as a checkpointing mechanism which provides a snapshot of the EC/VID headers at a given point and a list of eraseblocks which need to be scanned at attach time. That has two main advantages: 1) It limits the number of log writes 2) It allows full backward and forward compatibility Looking at http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf I still see a linear - though less steep - attach time. For the 1GB flash size it's still 0.8s which is nice progress vs. the 2s for the non logging case. But that's surprising as one would expect that logging would provide a more aggressive and non linear gain. Just doing the simple math: 1GB FLASH with erase block size 128K and page size 2k, that translates to 8192 erase blocks So UBI scans 8192 erase block EC/VID headers in 2 seconds. That equals to 8192 FLASH pages. UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH pages (or spends the equivivalent time) to achieve the same result. That looks wrong. Care to explain ? Thanks, tglx From okpalin at gmail.com Tue May 11 21:18:05 2010 From: okpalin at gmail.com (=?Big5?B?qkykX65t?=) Date: Wed, 12 May 2010 09:18:05 +0800 Subject: Can not mount UBIFS In-Reply-To: <1273556690.2209.146.camel@localhost> References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> <1272888512.27729.46.camel@localhost> <1273556690.2209.146.camel@localhost> Message-ID: Dear Sir, I am very confused. If the driver has some problems, why images written by ubiformat can work well? Images written by bootloader or ubiformat should have the same problem, if the driver is wrong. Thank you, Best regards, 2010/5/11 Artem Bityutskiy : > On Tue, 2010-05-11 at 11:46 +0800, ??? wrote: >> Dear all, >> >> I have modified bootloader to download image as ubiformat does. >> However, I still can not mount it. >> I also dump the content of mtd partition and compare. >> (Ex: dd if=/dev/block/mtdblock5 of=/data/mtd5bak) >> No difference between the content written by bootloader and written by >> ubiformat. >> > ... snip ... > >> <3>UBI error: ubi_io_read: error -22 while reading 2048 bytes from PEB >> 3:6144, read 0 bytes > > Well, find out why your driver returns -EINVAL and read count 0 when you > read 2048 bytes from PEB 3 on this partition, and offset 6144. Dig the > driver. > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > > From jon at ringle.org Tue May 11 22:30:56 2010 From: jon at ringle.org (Jon Ringle) Date: Tue, 11 May 2010 22:30:56 -0400 Subject: Erase race? In-Reply-To: <1272373142.7750.5.camel@localhost> References: <1272373142.7750.5.camel@localhost> Message-ID: On Tue, Apr 27, 2010 at 8:59 AM, Artem Bityutskiy wrote: > On Tue, 2010-04-20 at 16:24 -0400, Jon Ringle wrote: >> On Tue, Apr 13, 2010 at 4:15 PM, Jon Ringle wrote: >> > Hi, >> > I have a few machines that have UBI and UBIFS on NOR flash that are >> > undergoing continuous reboot testing. >> > One of them just caught the following failure: >> > >> > [ ? 51.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) >> > [ ? 51.250000] UBI error: ubi_io_write: error -22 while writing 64 >> > bytes to PEB 226:0, written 0 bytes >> > [ ? 51.270000] UBI error: erase_worker: failed to erase PEB 226, error -22 >> > [ ? 51.270000] UBI warning: ubi_ro_mode: switch to read-only mode >> > [ ? 51.290000] UBI error: do_work: work failed with error code -22 >> > [ ? 51.290000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 >> > >> > Looking at this it appears that the failure might have been caused due >> > to the erase_worker and ubi_io_write occurring out of order... since >> > it looks like ubi_io_write was trying to write at offset 0 of the PEB, >> > which I imagine would have to be the EC header, which should happen >> > after the block is erased. But it doesn't seem to be the case here. >> >> I had this issue occur again on another system: >> [ ? 48.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) >> [ ? 48.250000] UBI error: ubi_io_write: error -22 while writing 64 >> bytes to PEB 111:0, written 0 bytes >> [ ? 48.280000] UBI error: erase_worker: failed to erase PEB 111, error -22 >> [ ? 48.280000] UBI warning: ubi_ro_mode: switch to read-only mode >> [ ? 48.310000] UBI error: do_work: work failed with error code -22 >> [ ? 48.310000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 >> >> Can anyone comment as to my theory that this is a race condition >> between ubi_io_write and erase_worker occurring out of order? > > Did you debug this further? Any new findings? I finally got a capture of this with CONFIG_MTD_UBI_DEBUG turned on: [ 61.710000] IXP4XX-Flash.0: buffer write error (status 0xd0) [ 61.710000] UBI error: ubi_io_write: error -22 while writing 64 bytes to PEB 136:0, written 0 bytes [ 61.740000] [] (unwind_backtrace+0x0/0x170) from [] (ubi_io_write+0x1ec/0x214 [ubi]) [ 61.770000] [] (ubi_io_write+0x1ec/0x214 [ubi]) from [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) [ 61.800000] [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) from [] (sync_erase+0xd4/0x128 [ubi]) [ 61.830000] [] (sync_erase+0xd4/0x128 [ubi]) from [] (erase_worker+0x28/0x2d8 [ubi]) [ 61.860000] [] (erase_worker+0x28/0x2d8 [ubi]) from [] (do_work+0x98/0x13c [ubi]) [ 61.860000] [] (do_work+0x98/0x13c [ubi]) from [] (ubi_thread+0xc4/0x158 [ubi]) [ 61.890000] [] (ubi_thread+0xc4/0x158 [ubi]) from [] (kthread+0x7c/0x84) [ 61.890000] [] (kthread+0x7c/0x84) from [] (kernel_thread_exit+0x0/0x8) [ 61.920000] UBI error: erase_worker: failed to erase PEB 136, error -22 [ 61.920000] UBI warning: ubi_ro_mode: switch to read-only mode [ 61.950000] UBI error: do_work: work failed with error code -22 [ 61.950000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > From dedekind1 at gmail.com Tue May 11 23:30:24 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 06:30:24 +0300 Subject: Can not mount UBIFS In-Reply-To: References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> <1272888512.27729.46.camel@localhost> <1273556690.2209.146.camel@localhost> Message-ID: <1273635024.8881.1.camel@localhost.localdomain> On Wed, 2010-05-12 at 09:18 +0800, ??? wrote: > Dear Sir, > > I am very confused. > If the driver has some problems, why images written by ubiformat can work well? > Images written by bootloader or ubiformat should have the same > problem, if the driver is wrong. I do not know. May be this is not a driver problem. May be you write twice to the same page? Just dig your driver, insert printks and find out where exactly it decides to return error. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Tue May 11 23:32:55 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 06:32:55 +0300 Subject: Erase race? In-Reply-To: References: <1272373142.7750.5.camel@localhost> Message-ID: <1273635175.8881.3.camel@localhost.localdomain> On Tue, 2010-05-11 at 22:30 -0400, Jon Ringle wrote: > On Tue, Apr 27, 2010 at 8:59 AM, Artem Bityutskiy wrote: > > On Tue, 2010-04-20 at 16:24 -0400, Jon Ringle wrote: > >> On Tue, Apr 13, 2010 at 4:15 PM, Jon Ringle wrote: > >> > Hi, > >> > I have a few machines that have UBI and UBIFS on NOR flash that are > >> > undergoing continuous reboot testing. > >> > One of them just caught the following failure: > >> > > >> > [ 51.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) > >> > [ 51.250000] UBI error: ubi_io_write: error -22 while writing 64 > >> > bytes to PEB 226:0, written 0 bytes > >> > [ 51.270000] UBI error: erase_worker: failed to erase PEB 226, error -22 > >> > [ 51.270000] UBI warning: ubi_ro_mode: switch to read-only mode > >> > [ 51.290000] UBI error: do_work: work failed with error code -22 > >> > [ 51.290000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 > >> > > >> > Looking at this it appears that the failure might have been caused due > >> > to the erase_worker and ubi_io_write occurring out of order... since > >> > it looks like ubi_io_write was trying to write at offset 0 of the PEB, > >> > which I imagine would have to be the EC header, which should happen > >> > after the block is erased. But it doesn't seem to be the case here. > >> > >> I had this issue occur again on another system: > >> [ 48.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) > >> [ 48.250000] UBI error: ubi_io_write: error -22 while writing 64 > >> bytes to PEB 111:0, written 0 bytes > >> [ 48.280000] UBI error: erase_worker: failed to erase PEB 111, error -22 > >> [ 48.280000] UBI warning: ubi_ro_mode: switch to read-only mode > >> [ 48.310000] UBI error: do_work: work failed with error code -22 > >> [ 48.310000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 > >> > >> Can anyone comment as to my theory that this is a race condition > >> between ubi_io_write and erase_worker occurring out of order? > > > > Did you debug this further? Any new findings? > > I finally got a capture of this with CONFIG_MTD_UBI_DEBUG turned on: > > [ 61.710000] IXP4XX-Flash.0: buffer write error (status 0xd0) > [ 61.710000] UBI error: ubi_io_write: error -22 while writing 64 > bytes to PEB 136:0, written 0 bytes > [ 61.740000] [] (unwind_backtrace+0x0/0x170) from > [] (ubi_io_write+0x1ec/0x214 [ubi]) > [ 61.770000] [] (ubi_io_write+0x1ec/0x214 [ubi]) from > [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) > [ 61.800000] [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) > from [] (sync_erase+0xd4/0x128 [ubi]) > [ 61.830000] [] (sync_erase+0xd4/0x128 [ubi]) from > [] (erase_worker+0x28/0x2d8 [ubi]) > [ 61.860000] [] (erase_worker+0x28/0x2d8 [ubi]) from > [] (do_work+0x98/0x13c [ubi]) > [ 61.860000] [] (do_work+0x98/0x13c [ubi]) from > [] (ubi_thread+0xc4/0x158 [ubi]) > [ 61.890000] [] (ubi_thread+0xc4/0x158 [ubi]) from > [] (kthread+0x7c/0x84) > [ 61.890000] [] (kthread+0x7c/0x84) from [] > (kernel_thread_exit+0x0/0x8) > [ 61.920000] UBI error: erase_worker: failed to erase PEB 136, error -22 > [ 61.920000] UBI warning: ubi_ro_mode: switch to read-only mode > [ 61.950000] UBI error: do_work: work failed with error code -22 > [ 61.950000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 So it is probably not a kind of race you assumed before. Your flash for some reasons encounters an error, dunno why. -- Best Regards, Artem Bityutskiy (????? ????????) From brijesh.s.singh at gmail.com Wed May 12 03:03:18 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Wed, 12 May 2010 12:33:18 +0530 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> Message-ID: Hi, On Wed, May 12, 2010 at 12:47 AM, Thomas Gleixner wrote: > B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: > >> On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: >> > Hi, >> > ? I am forwarding you the design document for ubi with log. Please >> > find the ubil document at >> > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL >> > design document.pdf > > @Brijesh, thanks for tackling this ! > >> Hi guys, >> >> I've read the document. Looks very promising. Here some feed-back. >> >> 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 >> erease cycles? Won't the SB PEB wear out very quickly? Why you did not >> go for the chaining approach which I described in the old JFFS3 design >> doc? >> >> If we do not implement chaining, we should at least design it and make >> sure UBIL can be extended later so that SB chaining could be added. > > The super block needs to be scanned for from the beginning of flash > anyway due to bad blocks. Putting it into a fixed position (first good > erase block) is a very bad design decision vs. wear leveling. This scan is minimal once the bad blocks are marked bad. Flash driver generally returns error by reading oob area or in ram bbt table. In comparison, keeping super block in first few blocks may become question of availability or wear-leveling trade off. The scan time for super block itself will take lot of time. In fact, in that case we won't need the super block at all. Just scan to find first chained commit block. But this doesn't look like a very good idea. > The super block must be moveable like any other block, though we can > keep it as close to the start of flash as possible. The idea is to get rid of scanning. A fixed place super block can locate movable headers. > Also chaining has a tradeoff. The more chains you need to walk the > closer you get to the point where you are equally bad as a full scan. As artem suggested, chaining should help in minimizing writes to anchor block at fixed location. At first instance it looked promising. But this design also has single point of failure. >> 2. SB PEB at the end. I think this is a very bad idea. Imagine you have >> to do UBIL images for production on the factory. With your design you >> have the following bad drawbacks: >> >> ? a. NAND flash has initial bad blocks, and you do not know how many, >> ? ? ?and where they sit. These may be the last 8 eraseblocks. So, when >> ? ? ?you prepare an image (say, with the ubinize user-space tool), where >> ? ? ?will you put the second SB PEB? >> >> ? b. Currently, UBI/UBIFS images are small. E.g., if you make an >> ? ? ?UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, >> ? ? ?your image will be few megs - it will contain the files, and all >> ? ? ?the needed UBI/UBIFS meta-data. >> >> ? ? ?So now what will be image size for UBIL - 1GiB, and this is bad. >> ? ? ?You then will transfer 1GiB of data to the devices during flashing >> ? ? ?or you will have to invent ways to work around this. Do you need >> ? ? ?these complexities? >> >> I think the second SB PEB should not be at the end. > > I think we do not need a second SB at all. UBI should not depend on > the super block in any way. The super block is an optimization for the > common case - nothing more. > >> 3. Backward-compatibility. In UBIL you removed EC anc VID headers in >> ? ?PEBs. That's fine for optimization purposes. But it has draw-backs: >> >> ? ?a. If any of the UBIL meta-data blocks like SB, CMT or log are >> ? ? ? corrupted - that's it - we are screwed. You cannot anymore >> ? ? ? re-consturct the data by scanning. The robustness goes down. >> >> ? ?c. Backward compatibility - UBI will not be able to attach UBIL >> ? ? ? images. This is not very nice. >> >> So, I think you should keep EC and VID headers in PEBs. And you should >> make the SB/CMT/log blocks to be a new type of UBI volume with >> UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this >> case UBI will attach UBIL volumes just fine. >> >> Then, you can add an _option_ to have no EC/VID headers in PEBs. This >> then can be used for performance, if one wants to sacrifice robustness. >> But this should be the second step. In this case, you will just need to >> put a VID header with UBI_COMPAT_REJECT flag to the first PEB. > > I don't think it's a good idea to kill the EC/VID headers. It not only > violates the backwards compability it also fundamentally weakens UBIs > reliability for no good reason and I doubt that the performance win is > big enough to make it worth. > > The performance gain is at attach time by getting rid of the flash > scan, but not by getting rid of writing the EC/VID headers. These flash headers have some more problems. Like, space wastage in MLC. Alignment problem for byte addressable memory. Backward compatibility is a good idea. But it is possible to implement these features and higher performance by getting rid of them. It seemed a fair trade off to me. But I am open for any better solution. > The logging is a speed up / optimization for the common case, but it > needs to preserve full reconstruction via scanning all eraseblocks and > checking the EC/VID headers. That also allows retrofitting on existing > devices. > > I'd rather see the super block / log volume as a checkpointing > mechanism which provides a snapshot of the EC/VID headers at a given > point and a list of eraseblocks which need to be scanned at attach > time. > > That has two main advantages: > ?1) It limits the number of log writes > ?2) It allows full backward and forward compatibility > > Looking at > http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf > I still see a linear - though less steep - attach time. For the 1GB > flash size it's still 0.8s which is nice progress vs. the 2s for the > non logging case. But that's surprising as one would expect that > logging would provide a more aggressive and non linear gain. > > Just doing the simple math: > > 1GB FLASH with erase block size 128K and page size 2k, that > translates to 8192 erase blocks > > So UBI scans 8192 erase block EC/VID headers in 2 seconds. That > equals to 8192 FLASH pages. > > UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH > pages (or spends the equivivalent time) to achieve the same result. > > That looks wrong. Care to explain ? Very good point. The calculations are confusing me. :-) I need to check this. From brijesh.s.singh at gmail.com Wed May 12 03:14:32 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Wed, 12 May 2010 12:44:32 +0530 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> Message-ID: On Wed, May 12, 2010 at 12:33 PM, Brijesh Singh wrote: > Hi, > > On Wed, May 12, 2010 at 12:47 AM, Thomas Gleixner wrote: >> B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: >> >>> On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: >>> > Hi, >>> > ? I am forwarding you the design document for ubi with log. Please >>> > find the ubil document at >>> > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL >>> > design document.pdf >> >> @Brijesh, thanks for tackling this ! >> >>> Hi guys, >>> >>> I've read the document. Looks very promising. Here some feed-back. >>> >>> 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 >>> erease cycles? Won't the SB PEB wear out very quickly? Why you did not >>> go for the chaining approach which I described in the old JFFS3 design >>> doc? >>> >>> If we do not implement chaining, we should at least design it and make >>> sure UBIL can be extended later so that SB chaining could be added. >> >> The super block needs to be scanned for from the beginning of flash >> anyway due to bad blocks. Putting it into a fixed position (first good >> erase block) is a very bad design decision vs. wear leveling. > > This scan is minimal once the bad blocks are marked bad. Flash driver > generally ?returns error by reading oob area or in ram bbt table. In comparison, > keeping super block in first few blocks may become question of availability or > wear-leveling trade off. The scan time for super block itself will > take lot of time. > In fact, in that case we won't need the super block at all. Just scan > to find first > chained commit block. But this doesn't look like a very good idea. > >> The super block must be moveable like any other block, though we can >> keep it as close to the start of flash as possible. > > The idea is to get rid of scanning. A fixed place super block can > locate movable headers. > >> Also chaining has a tradeoff. The more chains you need to walk the >> closer you get to the point where you are equally bad as a full scan. > > As artem suggested, chaining should help in minimizing writes to > anchor block at fixed > location. At first instance it looked promising. But this design also > has single point of failure. > >>> 2. SB PEB at the end. I think this is a very bad idea. Imagine you have >>> to do UBIL images for production on the factory. With your design you >>> have the following bad drawbacks: >>> >>> ? a. NAND flash has initial bad blocks, and you do not know how many, >>> ? ? ?and where they sit. These may be the last 8 eraseblocks. So, when >>> ? ? ?you prepare an image (say, with the ubinize user-space tool), where >>> ? ? ?will you put the second SB PEB? >>> >>> ? b. Currently, UBI/UBIFS images are small. E.g., if you make an >>> ? ? ?UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, >>> ? ? ?your image will be few megs - it will contain the files, and all >>> ? ? ?the needed UBI/UBIFS meta-data. >>> >>> ? ? ?So now what will be image size for UBIL - 1GiB, and this is bad. >>> ? ? ?You then will transfer 1GiB of data to the devices during flashing >>> ? ? ?or you will have to invent ways to work around this. Do you need >>> ? ? ?these complexities? >>> >>> I think the second SB PEB should not be at the end. >> >> I think we do not need a second SB at all. UBI should not depend on >> the super block in any way. The super block is an optimization for the >> common case - nothing more. >> >>> 3. Backward-compatibility. In UBIL you removed EC anc VID headers in >>> ? ?PEBs. That's fine for optimization purposes. But it has draw-backs: >>> >>> ? ?a. If any of the UBIL meta-data blocks like SB, CMT or log are >>> ? ? ? corrupted - that's it - we are screwed. You cannot anymore >>> ? ? ? re-consturct the data by scanning. The robustness goes down. >>> >>> ? ?c. Backward compatibility - UBI will not be able to attach UBIL >>> ? ? ? images. This is not very nice. >>> >>> So, I think you should keep EC and VID headers in PEBs. And you should >>> make the SB/CMT/log blocks to be a new type of UBI volume with >>> UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this >>> case UBI will attach UBIL volumes just fine. >>> >>> Then, you can add an _option_ to have no EC/VID headers in PEBs. This >>> then can be used for performance, if one wants to sacrifice robustness. >>> But this should be the second step. In this case, you will just need to >>> put a VID header with UBI_COMPAT_REJECT flag to the first PEB. >> >> I don't think it's a good idea to kill the EC/VID headers. It not only >> violates the backwards compability it also fundamentally weakens UBIs >> reliability for no good reason and I doubt that the performance win is >> big enough to make it worth. >> >> The performance gain is at attach time by getting rid of the flash >> scan, but not by getting rid of writing the EC/VID headers. > > These flash headers have some more problems. Like, space wastage in MLC. > Alignment problem for byte addressable memory. Backward compatibility > is a good idea. > But it is possible to implement these features and higher performance > by getting rid of them. > It seemed a fair trade off to me. But I am open for any better solution. > >> The logging is a speed up / optimization for the common case, but it >> needs to preserve full reconstruction via scanning all eraseblocks and >> checking the EC/VID headers. That also allows retrofitting on existing >> devices. >> >> I'd rather see the super block / log volume as a checkpointing >> mechanism which provides a snapshot of the EC/VID headers at a given >> point and a list of eraseblocks which need to be scanned at attach >> time. >> >> That has two main advantages: >> ?1) It limits the number of log writes >> ?2) It allows full backward and forward compatibility >> >> Looking at >> http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf >> I still see a linear - though less steep - attach time. For the 1GB >> flash size it's still 0.8s which is nice progress vs. the 2s for the >> non logging case. But that's surprising as one would expect that >> logging would provide a more aggressive and non linear gain. >> >> Just doing the simple math: >> >> 1GB FLASH with erase block size 128K and page size 2k, that >> translates to 8192 erase blocks >> >> So UBI scans 8192 erase block EC/VID headers in 2 seconds. That >> equals to 8192 FLASH pages. >> >> UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH >> pages (or spends the equivivalent time) to achieve the same result. >> >> That looks wrong. Care to explain ? > Very good point. The calculations are confusing me. :-) I need to check this. Sorry, for email client alignment problem. :( From pazdnikov at prosoft.ural.ru Wed May 12 03:30:07 2010 From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov) Date: Wed, 12 May 2010 13:30:07 +0600 Subject: ubifs became broken on contigous power-fails In-Reply-To: References: Message-ID: <201005121330.07802.pazdnikov@prosoft.ural.ru> recovery proccess of ubi2:dbfs prints ubifs_rcvry_gc_commit: could not find a dirty LEB but we have plenty of free space # df Filesystem Size Used Available Use% Mounted on ubi0:rootfs 13.2M 7.5M 5.7M 57% / tmpfs 4.0K 0 4.0K 0% /dev shm 1.0M 0 1.0M 0% /dev/shm tmpfs 1.0M 8.0K 1016.0K 1% /tmp tmpfs 1.0M 4.0K 1020.0K 0% /root ubi1:logs 11.5M 908.0K 10.0M 8% /var/log ubi1:tmp 13.4M 16.0K 12.7M 0% /usr/local/ecom/tmp ubi0:local 2.1M 64.0K 1.9M 3% /var/local ubi:config 2.0M 68.0K 1.9M 3% /usr/local/ecom/conf ubi2:dbfs 169.1M 36.0M 128.4M 22% /usr/local/ecom/db ubifs/recovery.c: 1044 int ubifs_rcvry_gc_commit(struct ubifs_info *c) { ... err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); if (err) { if (err == -ENOSPC) dbg_err("could not find a dirty LEB"); return err; } ubifs_assert(!(lp.flags & LPROPS_INDEX)); lnum = lp.lnum; Why returns -ENOSPC ? we have enough of free space according to report -- Best regards, Sasha From dedekind1 at gmail.com Wed May 12 03:41:39 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 10:41:39 +0300 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> Message-ID: <1273650099.22706.41.camel@localhost> On Tue, 2010-05-11 at 21:17 +0200, Thomas Gleixner wrote: > B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: > > > On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: > > > Hi, > > > I am forwarding you the design document for ubi with log. Please > > > find the ubil document at > > > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL > > > design document.pdf > > @Brijesh, thanks for tackling this ! > > > Hi guys, > > > > I've read the document. Looks very promising. Here some feed-back. > > > > 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 > > erease cycles? Won't the SB PEB wear out very quickly? Why you did not > > go for the chaining approach which I described in the old JFFS3 design > > doc? > > > > If we do not implement chaining, we should at least design it and make > > sure UBIL can be extended later so that SB chaining could be added. > > The super block needs to be scanned for from the beginning of flash > anyway due to bad blocks. Putting it into a fixed position (first good > erase block) is a very bad design decision vs. wear leveling. > > The super block must be moveable like any other block, though we can > keep it as close to the start of flash as possible. > > Also chaining has a tradeoff. The more chains you need to walk the > closer you get to the point where you are equally bad as a full scan. Well, every new chain member reduces the superblock wear speed by order 2, so I the chain would have 2-4 eraseblocks in most cases, I guess, which is not bad. In the opposite, moving the SB 3-4 eraseblocks further only reduces the load merely by factor 3-4. > > 2. SB PEB at the end. I think this is a very bad idea. Imagine you have > > to do UBIL images for production on the factory. With your design you > > have the following bad drawbacks: > > > > a. NAND flash has initial bad blocks, and you do not know how many, > > and where they sit. These may be the last 8 eraseblocks. So, when > > you prepare an image (say, with the ubinize user-space tool), where > > will you put the second SB PEB? > > > > b. Currently, UBI/UBIFS images are small. E.g., if you make an > > UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, > > your image will be few megs - it will contain the files, and all > > the needed UBI/UBIFS meta-data. > > > > So now what will be image size for UBIL - 1GiB, and this is bad. > > You then will transfer 1GiB of data to the devices during flashing > > or you will have to invent ways to work around this. Do you need > > these complexities? > > > > I think the second SB PEB should not be at the end. > > I think we do not need a second SB at all. UBI should not depend on > the super block in any way. The super block is an optimization for the > common case - nothing more. Yeah, if we preserve the headers we can always fall-back to scanning should something be broken. > > > 3. Backward-compatibility. In UBIL you removed EC anc VID headers in > > PEBs. That's fine for optimization purposes. But it has draw-backs: > > > > a. If any of the UBIL meta-data blocks like SB, CMT or log are > > corrupted - that's it - we are screwed. You cannot anymore > > re-consturct the data by scanning. The robustness goes down. > > > > c. Backward compatibility - UBI will not be able to attach UBIL > > images. This is not very nice. > > > > So, I think you should keep EC and VID headers in PEBs. And you should > > make the SB/CMT/log blocks to be a new type of UBI volume with > > UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this > > case UBI will attach UBIL volumes just fine. > > > > Then, you can add an _option_ to have no EC/VID headers in PEBs. This > > then can be used for performance, if one wants to sacrifice robustness. > > But this should be the second step. In this case, you will just need to > > put a VID header with UBI_COMPAT_REJECT flag to the first PEB. > > I don't think it's a good idea to kill the EC/VID headers. It not only > violates the backwards compability it also fundamentally weakens UBIs > reliability for no good reason and I doubt that the performance win is > big enough to make it worth. > > The performance gain is at attach time by getting rid of the flash > scan, but not by getting rid of writing the EC/VID headers. Well, there are some space savings as well. > > The logging is a speed up / optimization for the common case, but it > needs to preserve full reconstruction via scanning all eraseblocks and > checking the EC/VID headers. That also allows retrofitting on existing > devices. > > I'd rather see the super block / log volume as a checkpointing > mechanism which provides a snapshot of the EC/VID headers at a given > point and a list of eraseblocks which need to be scanned at attach > time. > > > That has two main advantages: > 1) It limits the number of log writes > 2) It allows full backward and forward compatibility I think this is what they do, but they for some reasons removed the headers. If they add them back, it should look like you described. We should preserve the headers. It is always easy to disable them later, if someone needs this for optimization purposes. E.g., we can add an ubi_compat=0 option or something like that. > Looking at > http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf > I still see a linear - though less steep - attach time. For the 1GB > flash size it's still 0.8s which is nice progress vs. the 2s for the > non logging case. But that's surprising as one would expect that > logging would provide a more aggressive and non linear gain. > > Just doing the simple math: > > 1GB FLASH with erase block size 128K and page size 2k, that > translates to 8192 erase blocks > > So UBI scans 8192 erase block EC/VID headers in 2 seconds. That > equals to 8192 FLASH pages. > > UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH > pages (or spends the equivivalent time) to achieve the same result. > > That looks wrong. Care to explain ? I suspect these are implementation issues. I did not look at the code, but I suspect they read whole CMT block and populate the all EB associations at scan time. However, they could populate them lazily, which would optimize things. -- Best Regards, Artem Bityutskiy (????? ????????) From brijesh.s.singh at gmail.com Wed May 12 04:03:39 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Wed, 12 May 2010 13:33:39 +0530 Subject: UBIL design doc In-Reply-To: <1273650099.22706.41.camel@localhost> References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> Message-ID: Hi, On Wed, May 12, 2010 at 1:11 PM, Artem Bityutskiy wrote: > On Tue, 2010-05-11 at 21:17 +0200, Thomas Gleixner wrote: >> B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: >> >> > On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: >> > > Hi, >> > > ? I am forwarding you the design document for ubi with log. Please >> > > find the ubil document at >> > > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL >> > > design document.pdf >> >> @Brijesh, thanks for tackling this ! >> >> > Hi guys, >> > >> > I've read the document. Looks very promising. Here some feed-back. >> > >> > 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 >> > erease cycles? Won't the SB PEB wear out very quickly? Why you did not >> > go for the chaining approach which I described in the old JFFS3 design >> > doc? >> > >> > If we do not implement chaining, we should at least design it and make >> > sure UBIL can be extended later so that SB chaining could be added. >> >> The super block needs to be scanned for from the beginning of flash >> anyway due to bad blocks. Putting it into a fixed position (first good >> erase block) is a very bad design decision vs. wear leveling. >> >> The super block must be moveable like any other block, though we can >> keep it as close to the start of flash as possible. >> >> Also chaining has a tradeoff. The more chains you need to walk the >> closer you get to the point where you are equally bad as a full scan. > > Well, every new chain member reduces the superblock wear speed by order > 2, so I the chain would have 2-4 eraseblocks in most cases, I guess, > which is not bad. > > In the opposite, moving the SB 3-4 eraseblocks further only reduces the > load merely by factor 3-4. > >> > 2. SB PEB at the end. I think this is a very bad idea. Imagine you have >> > to do UBIL images for production on the factory. With your design you >> > have the following bad drawbacks: >> > >> > ? a. NAND flash has initial bad blocks, and you do not know how many, >> > ? ? ?and where they sit. These may be the last 8 eraseblocks. So, when >> > ? ? ?you prepare an image (say, with the ubinize user-space tool), where >> > ? ? ?will you put the second SB PEB? >> > >> > ? b. Currently, UBI/UBIFS images are small. E.g., if you make an >> > ? ? ?UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, >> > ? ? ?your image will be few megs - it will contain the files, and all >> > ? ? ?the needed UBI/UBIFS meta-data. >> > >> > ? ? ?So now what will be image size for UBIL - 1GiB, and this is bad. >> > ? ? ?You then will transfer 1GiB of data to the devices during flashing >> > ? ? ?or you will have to invent ways to work around this. Do you need >> > ? ? ?these complexities? >> > >> > I think the second SB PEB should not be at the end. >> >> I think we do not need a second SB at all. UBI should not depend on >> the super block in any way. The super block is an optimization for the >> common case - nothing more. > > Yeah, if we preserve the headers we can always fall-back to scanning > should something be broken. > >> >> > 3. Backward-compatibility. In UBIL you removed EC anc VID headers in >> > ? ?PEBs. That's fine for optimization purposes. But it has draw-backs: >> > >> > ? ?a. If any of the UBIL meta-data blocks like SB, CMT or log are >> > ? ? ? corrupted - that's it - we are screwed. You cannot anymore >> > ? ? ? re-consturct the data by scanning. The robustness goes down. >> > >> > ? ?c. Backward compatibility - UBI will not be able to attach UBIL >> > ? ? ? images. This is not very nice. >> > >> > So, I think you should keep EC and VID headers in PEBs. And you should >> > make the SB/CMT/log blocks to be a new type of UBI volume with >> > UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this >> > case UBI will attach UBIL volumes just fine. >> > >> > Then, you can add an _option_ to have no EC/VID headers in PEBs. This >> > then can be used for performance, if one wants to sacrifice robustness. >> > But this should be the second step. In this case, you will just need to >> > put a VID header with UBI_COMPAT_REJECT flag to the first PEB. >> >> I don't think it's a good idea to kill the EC/VID headers. It not only >> violates the backwards compability it also fundamentally weakens UBIs >> reliability for no good reason and I doubt that the performance win is >> big enough to make it worth. >> >> The performance gain is at attach time by getting rid of the flash >> scan, but not by getting rid of writing the EC/VID headers. > > Well, there are some space savings as well. > >> >> The logging is a speed up / optimization for the common case, but it >> needs to preserve full reconstruction via scanning all eraseblocks and >> checking the EC/VID headers. That also allows retrofitting on existing >> devices. >> >> I'd rather see the super block / log volume as a checkpointing >> mechanism which provides a snapshot of the EC/VID headers at a given >> point and a list of eraseblocks which need to be scanned at attach >> time. >> >> >> That has two main advantages: >> ?1) It limits the number of log writes >> ?2) It allows full backward and forward compatibility > > I think this is what they do, but they for some reasons removed the > headers. If they add them back, it should look like you described. > > We should preserve the headers. It is always easy to disable them later, > if someone needs this for optimization purposes. E.g., we can add an > ubi_compat=0 option or something like that. > >> Looking at >> http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf >> I still see a linear - though less steep - attach time. For the 1GB >> flash size it's still 0.8s which is nice progress vs. the 2s for the >> non logging case. But that's surprising as one would expect that >> logging would provide a more aggressive and non linear gain. >> >> Just doing the simple math: >> >> 1GB FLASH with erase block size 128K and page size 2k, that >> translates to 8192 erase blocks >> >> So UBI scans 8192 erase block EC/VID headers in 2 seconds. That >> equals to 8192 FLASH pages. >> >> UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH >> pages (or spends the equivivalent time) to achieve the same result. >> >> That looks wrong. Care to explain ? > > I suspect these are implementation issues. I did not look at the code, > but I suspect they read whole CMT block and populate the all EB > associations at scan time. However, they could populate them lazily, > which would optimize things. I am trying to summarize what I have understood. I will send the patches if this is correct. 1) Commit will have ec and vid headers just as any other UBI block. The compat flag helps in backword compatibility, 2)chained sb will locate commit. It will be part of internal volume as well. 3) Commit will be called on unmount. 4) Any unclean un-mount will lead to flash scanning just as UBI. Any thing goes bad, normal scanning becomes recovery. 5) Not sure if log is required in first place. But it could be an option. Is that correct? From maxcir at gmail.com Wed May 12 04:21:12 2010 From: maxcir at gmail.com (massimo cirillo) Date: Wed, 12 May 2010 10:21:12 +0200 Subject: Erase race? In-Reply-To: <1273635175.8881.3.camel@localhost.localdomain> References: <1272373142.7750.5.camel@localhost> <1273635175.8881.3.camel@localhost.localdomain> Message-ID: Hi Jon, I verified some particular error conditions regarding the erase suspend in some nor flash chip. Please tell me the part number of the flash you are using and I will check it. Max 2010/5/12 Artem Bityutskiy : > On Tue, 2010-05-11 at 22:30 -0400, Jon Ringle wrote: >> On Tue, Apr 27, 2010 at 8:59 AM, Artem Bityutskiy wrote: >> > On Tue, 2010-04-20 at 16:24 -0400, Jon Ringle wrote: >> >> On Tue, Apr 13, 2010 at 4:15 PM, Jon Ringle wrote: >> >> > Hi, >> >> > I have a few machines that have UBI and UBIFS on NOR flash that are >> >> > undergoing continuous reboot testing. >> >> > One of them just caught the following failure: >> >> > >> >> > [ ? 51.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) >> >> > [ ? 51.250000] UBI error: ubi_io_write: error -22 while writing 64 >> >> > bytes to PEB 226:0, written 0 bytes >> >> > [ ? 51.270000] UBI error: erase_worker: failed to erase PEB 226, error -22 >> >> > [ ? 51.270000] UBI warning: ubi_ro_mode: switch to read-only mode >> >> > [ ? 51.290000] UBI error: do_work: work failed with error code -22 >> >> > [ ? 51.290000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 >> >> > >> >> > Looking at this it appears that the failure might have been caused due >> >> > to the erase_worker and ubi_io_write occurring out of order... since >> >> > it looks like ubi_io_write was trying to write at offset 0 of the PEB, >> >> > which I imagine would have to be the EC header, which should happen >> >> > after the block is erased. But it doesn't seem to be the case here. >> >> >> >> I had this issue occur again on another system: >> >> [ ? 48.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) >> >> [ ? 48.250000] UBI error: ubi_io_write: error -22 while writing 64 >> >> bytes to PEB 111:0, written 0 bytes >> >> [ ? 48.280000] UBI error: erase_worker: failed to erase PEB 111, error -22 >> >> [ ? 48.280000] UBI warning: ubi_ro_mode: switch to read-only mode >> >> [ ? 48.310000] UBI error: do_work: work failed with error code -22 >> >> [ ? 48.310000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 >> >> >> >> Can anyone comment as to my theory that this is a race condition >> >> between ubi_io_write and erase_worker occurring out of order? >> > >> > Did you debug this further? Any new findings? >> >> I finally got a capture of this with CONFIG_MTD_UBI_DEBUG turned on: >> >> [ ? 61.710000] IXP4XX-Flash.0: buffer write error (status 0xd0) >> [ ? 61.710000] UBI error: ubi_io_write: error -22 while writing 64 >> bytes to PEB 136:0, written 0 bytes >> [ ? 61.740000] [] (unwind_backtrace+0x0/0x170) from >> [] (ubi_io_write+0x1ec/0x214 [ubi]) >> [ ? 61.770000] [] (ubi_io_write+0x1ec/0x214 [ubi]) from >> [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) >> [ ? 61.800000] [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) >> from [] (sync_erase+0xd4/0x128 [ubi]) >> [ ? 61.830000] [] (sync_erase+0xd4/0x128 [ubi]) from >> [] (erase_worker+0x28/0x2d8 [ubi]) >> [ ? 61.860000] [] (erase_worker+0x28/0x2d8 [ubi]) from >> [] (do_work+0x98/0x13c [ubi]) >> [ ? 61.860000] [] (do_work+0x98/0x13c [ubi]) from >> [] (ubi_thread+0xc4/0x158 [ubi]) >> [ ? 61.890000] [] (ubi_thread+0xc4/0x158 [ubi]) from >> [] (kthread+0x7c/0x84) >> [ ? 61.890000] [] (kthread+0x7c/0x84) from [] >> (kernel_thread_exit+0x0/0x8) >> [ ? 61.920000] UBI error: erase_worker: failed to erase PEB 136, error -22 >> [ ? 61.920000] UBI warning: ubi_ro_mode: switch to read-only mode >> [ ? 61.950000] UBI error: do_work: work failed with error code -22 >> [ ? 61.950000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 > > So it is probably not a kind of race you assumed before. Your flash for > some reasons encounters an error, dunno why. > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > From mike at compulab.co.il Wed May 12 04:30:17 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Wed, 12 May 2010 11:30:17 +0300 Subject: [PATCH 3/3] omap3 nand: fix issue in board file to detect the nand In-Reply-To: <1273652243-6303-4-git-send-email-s-ghorai@ti.com> References: <[Sukumar Ghorai ]> <1273652243-6303-1-git-send-email-s-ghorai@ti.com> <1273652243-6303-2-git-send-email-s-ghorai@ti.com> <1273652243-6303-3-git-send-email-s-ghorai@ti.com> <1273652243-6303-4-git-send-email-s-ghorai@ti.com> Message-ID: <4BEA6719.1050400@compulab.co.il> [Sukumar Ghorai wrote: > From: Sukumar Ghorai > > Board file modified to pass the GMPC phys_base address to nand driver. This is > required to adopt the _prob function as in omap2.c > > Signed-off-by: Sukumar Ghorai > --- > arch/arm/mach-omap2/board-cm-t35.c | 10 ++++++++++ > arch/arm/mach-omap2/board-devkit8000.c | 9 +++++++++ > arch/arm/mach-omap2/board-omap3beagle.c | 9 +++++++++ > arch/arm/mach-omap2/board-omap3touchbook.c | 9 +++++++++ > arch/arm/mach-omap2/board-overo.c | 8 ++++++++ > 5 files changed, 45 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c > index fb23122..73a32bd > --- a/arch/arm/mach-omap2/board-cm-t35.c > +++ b/arch/arm/mach-omap2/board-cm-t35.c > @@ -240,6 +240,16 @@ static struct platform_device cm_t35_nand_device = { > > static void __init cm_t35_init_nand(void) > { > + struct device *dev = &cm_t35_nand_device.dev; > + int err = 0; > + > + err = gpmc_cs_request(cm_t35_nand_data.cs, > + NAND_IO_SIZE, &cm_t35_nand_data.phys_base); > + if (err < 0) { > + dev_err(dev, "Cannot request GPMC CS\n"); > + return; > + } > + > if (platform_device_register(&cm_t35_nand_device) < 0) > pr_err("CM-T35: Unable to register NAND device\n"); Why won't you use gpmc_nand_init instead of platform_device_register? With gpmc_nand_init there would be no need to request NAND CS in the board files. Besides, if you convert the boards to use gpmc_nand_init at the first place, it would simplify further patches. > } > diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c > index be50d18..86358e3 > --- a/arch/arm/mach-omap2/board-devkit8000.c > +++ b/arch/arm/mach-omap2/board-devkit8000.c > @@ -578,6 +578,9 @@ static void __init devkit8000_flash_init(void) > u8 cs = 0; > u8 nandcs = GPMC_CS_NUM + 1; > > + struct device *dev = &devkit8000_nand_device.dev; > + int err = 0; > + > /* find out the chip-select on which NAND exists */ > while (cs < GPMC_CS_NUM) { > u32 ret = 0; > @@ -599,6 +602,12 @@ static void __init devkit8000_flash_init(void) > > if (nandcs < GPMC_CS_NUM) { > devkit8000_nand_data.cs = nandcs; > + err = gpmc_cs_request(devkit8000_nand_data.cs, > + NAND_IO_SIZE, &devkit8000_nand_data.phys_base); > + if (err < 0) { > + dev_err(dev, "Cannot request GPMC CS\n"); > + return; > + } > > printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); > if (platform_device_register(&devkit8000_nand_device) < 0) > diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c > index becaebe..d54719d > --- a/arch/arm/mach-omap2/board-omap3beagle.c > +++ b/arch/arm/mach-omap2/board-omap3beagle.c > @@ -374,6 +374,9 @@ static void __init omap3beagle_flash_init(void) > u8 cs = 0; > u8 nandcs = GPMC_CS_NUM + 1; > > + struct device *dev = &omap3beagle_nand_device.dev; > + int err = 0; > + > /* find out the chip-select on which NAND exists */ > while (cs < GPMC_CS_NUM) { > u32 ret = 0; > @@ -395,6 +398,12 @@ static void __init omap3beagle_flash_init(void) > > if (nandcs < GPMC_CS_NUM) { > omap3beagle_nand_data.cs = nandcs; > + err = gpmc_cs_request(omap3beagle_nand_data.cs, > + NAND_IO_SIZE, &omap3beagle_nand_data.phys_base); > + if (err < 0) { > + dev_err(dev, "Cannot request GPMC CS\n"); > + return; > + } > > printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); > if (platform_device_register(&omap3beagle_nand_device) < 0) > diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c > index d6f1b12..088a704 > --- a/arch/arm/mach-omap2/board-omap3touchbook.c > +++ b/arch/arm/mach-omap2/board-omap3touchbook.c > @@ -456,6 +456,9 @@ static void __init omap3touchbook_flash_init(void) > u8 cs = 0; > u8 nandcs = GPMC_CS_NUM + 1; > > + struct device *dev = &omap3touchbook_nand_device.dev; > + int err = 0; > + > /* find out the chip-select on which NAND exists */ > while (cs < GPMC_CS_NUM) { > u32 ret = 0; > @@ -477,6 +480,12 @@ static void __init omap3touchbook_flash_init(void) > > if (nandcs < GPMC_CS_NUM) { > omap3touchbook_nand_data.cs = nandcs; > + err = gpmc_cs_request(omap3touchbook_nand_data.cs, > + NAND_IO_SIZE, &omap3touchbook_nand_data.phys_base); > + if (err < 0) { > + dev_err(dev, "Cannot request GPMC CS\n"); > + return; > + } > > printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); > if (platform_device_register(&omap3touchbook_nand_device) < 0) > diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c > index d843a0a..d6658b5 > --- a/arch/arm/mach-omap2/board-overo.c > +++ b/arch/arm/mach-omap2/board-overo.c > @@ -236,6 +236,8 @@ static void __init overo_flash_init(void) > { > u8 cs = 0; > u8 nandcs = GPMC_CS_NUM + 1; > + struct device *dev = &overo_nand_device.dev; > + int err = 0; > > /* find out the chip-select on which NAND exists */ > while (cs < GPMC_CS_NUM) { > @@ -258,6 +260,12 @@ static void __init overo_flash_init(void) > > if (nandcs < GPMC_CS_NUM) { > overo_nand_data.cs = nandcs; > + err = gpmc_cs_request(overo_nand_data.cs, > + NAND_IO_SIZE, &overo_nand_data.phys_base); > + if (err < 0) { > + dev_err(dev, "Cannot request GPMC CS\n"); > + return; > + } > > printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); > if (platform_device_register(&overo_nand_device) < 0) -- Sincerely yours, Mike. From dedekind1 at gmail.com Wed May 12 04:35:41 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 11:35:41 +0300 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> Message-ID: <1273653341.22706.46.camel@localhost> On Wed, 2010-05-12 at 13:33 +0530, Brijesh Singh wrote: > Hi, > > On Wed, May 12, 2010 at 1:11 PM, Artem Bityutskiy wrote: > > On Tue, 2010-05-11 at 21:17 +0200, Thomas Gleixner wrote: > >> B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: > >> > >> > On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: > >> > > Hi, > >> > > I am forwarding you the design document for ubi with log. Please > >> > > find the ubil document at > >> > > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL > >> > > design document.pdf > >> > >> @Brijesh, thanks for tackling this ! > >> > >> > Hi guys, > >> > > >> > I've read the document. Looks very promising. Here some feed-back. > >> > > >> > 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 > >> > erease cycles? Won't the SB PEB wear out very quickly? Why you did not > >> > go for the chaining approach which I described in the old JFFS3 design > >> > doc? > >> > > >> > If we do not implement chaining, we should at least design it and make > >> > sure UBIL can be extended later so that SB chaining could be added. > >> > >> The super block needs to be scanned for from the beginning of flash > >> anyway due to bad blocks. Putting it into a fixed position (first good > >> erase block) is a very bad design decision vs. wear leveling. > >> > >> The super block must be moveable like any other block, though we can > >> keep it as close to the start of flash as possible. > >> > >> Also chaining has a tradeoff. The more chains you need to walk the > >> closer you get to the point where you are equally bad as a full scan. > > > > Well, every new chain member reduces the superblock wear speed by order > > 2, so I the chain would have 2-4 eraseblocks in most cases, I guess, > > which is not bad. > > > > In the opposite, moving the SB 3-4 eraseblocks further only reduces the > > load merely by factor 3-4. > > > >> > 2. SB PEB at the end. I think this is a very bad idea. Imagine you have > >> > to do UBIL images for production on the factory. With your design you > >> > have the following bad drawbacks: > >> > > >> > a. NAND flash has initial bad blocks, and you do not know how many, > >> > and where they sit. These may be the last 8 eraseblocks. So, when > >> > you prepare an image (say, with the ubinize user-space tool), where > >> > will you put the second SB PEB? > >> > > >> > b. Currently, UBI/UBIFS images are small. E.g., if you make an > >> > UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, > >> > your image will be few megs - it will contain the files, and all > >> > the needed UBI/UBIFS meta-data. > >> > > >> > So now what will be image size for UBIL - 1GiB, and this is bad. > >> > You then will transfer 1GiB of data to the devices during flashing > >> > or you will have to invent ways to work around this. Do you need > >> > these complexities? > >> > > >> > I think the second SB PEB should not be at the end. > >> > >> I think we do not need a second SB at all. UBI should not depend on > >> the super block in any way. The super block is an optimization for the > >> common case - nothing more. > > > > Yeah, if we preserve the headers we can always fall-back to scanning > > should something be broken. > > > >> > >> > 3. Backward-compatibility. In UBIL you removed EC anc VID headers in > >> > PEBs. That's fine for optimization purposes. But it has draw-backs: > >> > > >> > a. If any of the UBIL meta-data blocks like SB, CMT or log are > >> > corrupted - that's it - we are screwed. You cannot anymore > >> > re-consturct the data by scanning. The robustness goes down. > >> > > >> > c. Backward compatibility - UBI will not be able to attach UBIL > >> > images. This is not very nice. > >> > > >> > So, I think you should keep EC and VID headers in PEBs. And you should > >> > make the SB/CMT/log blocks to be a new type of UBI volume with > >> > UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this > >> > case UBI will attach UBIL volumes just fine. > >> > > >> > Then, you can add an _option_ to have no EC/VID headers in PEBs. This > >> > then can be used for performance, if one wants to sacrifice robustness. > >> > But this should be the second step. In this case, you will just need to > >> > put a VID header with UBI_COMPAT_REJECT flag to the first PEB. > >> > >> I don't think it's a good idea to kill the EC/VID headers. It not only > >> violates the backwards compability it also fundamentally weakens UBIs > >> reliability for no good reason and I doubt that the performance win is > >> big enough to make it worth. > >> > >> The performance gain is at attach time by getting rid of the flash > >> scan, but not by getting rid of writing the EC/VID headers. > > > > Well, there are some space savings as well. > > > >> > >> The logging is a speed up / optimization for the common case, but it > >> needs to preserve full reconstruction via scanning all eraseblocks and > >> checking the EC/VID headers. That also allows retrofitting on existing > >> devices. > >> > >> I'd rather see the super block / log volume as a checkpointing > >> mechanism which provides a snapshot of the EC/VID headers at a given > >> point and a list of eraseblocks which need to be scanned at attach > >> time. > >> > >> > >> That has two main advantages: > >> 1) It limits the number of log writes > >> 2) It allows full backward and forward compatibility > > > > I think this is what they do, but they for some reasons removed the > > headers. If they add them back, it should look like you described. > > > > We should preserve the headers. It is always easy to disable them later, > > if someone needs this for optimization purposes. E.g., we can add an > > ubi_compat=0 option or something like that. > > > >> Looking at > >> http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf > >> I still see a linear - though less steep - attach time. For the 1GB > >> flash size it's still 0.8s which is nice progress vs. the 2s for the > >> non logging case. But that's surprising as one would expect that > >> logging would provide a more aggressive and non linear gain. > >> > >> Just doing the simple math: > >> > >> 1GB FLASH with erase block size 128K and page size 2k, that > >> translates to 8192 erase blocks > >> > >> So UBI scans 8192 erase block EC/VID headers in 2 seconds. That > >> equals to 8192 FLASH pages. > >> > >> UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH > >> pages (or spends the equivivalent time) to achieve the same result. > >> > >> That looks wrong. Care to explain ? > > > > I suspect these are implementation issues. I did not look at the code, > > but I suspect they read whole CMT block and populate the all EB > > associations at scan time. However, they could populate them lazily, > > which would optimize things. > I am trying to summarize what I have understood. > I will send the patches if this is correct. > 1) Commit will have ec and vid headers just as any other UBI block. > The compat flag helps in backword compatibility, > 2)chained sb will locate commit. It will be part of internal volume as well. > 3) Commit will be called on unmount. > 4) Any unclean un-mount will lead to flash scanning just as UBI. No! Why you have the log then? Unclean reboots are handled by the log. Scanning happens only when you have _corrupted_ SB, or corrupted cmt, or log. Then you fall-back to scanning. > Any thing goes bad, normal scanning becomes recovery. > 5) Not sure if log is required in first place. But it could be an option. > Is that correct? No, at least I did not suggest you to get rid of the log. It is needed to handle unclean reboots. -- Best Regards, Artem Bityutskiy (????? ????????) From tglx at linutronix.de Wed May 12 05:02:40 2010 From: tglx at linutronix.de (Thomas Gleixner) Date: Wed, 12 May 2010 11:02:40 +0200 (CEST) Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> Message-ID: Brijesh, On Wed, 12 May 2010, Brijesh Singh wrote: > On Wed, May 12, 2010 at 12:47 AM, Thomas Gleixner wrote: > > On Mon, 10 May 2010, Artem Bityutskiy wrote: > >> 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 > >> erease cycles? Won't the SB PEB wear out very quickly? Why you did not > >> go for the chaining approach which I described in the old JFFS3 design > >> doc? > >> > >> If we do not implement chaining, we should at least design it and make > >> sure UBIL can be extended later so that SB chaining could be added. > > > > The super block needs to be scanned for from the beginning of flash > > anyway due to bad blocks. Putting it into a fixed position (first good > > erase block) is a very bad design decision vs. wear leveling. > > This scan is minimal once the bad blocks are marked bad. Flash driver > generally returns error by reading oob area or in ram bbt table. In comparison, > keeping super block in first few blocks may become question of availability or > wear-leveling trade off. The scan time for super block itself will > take lot of time. > In fact, in that case we won't need the super block at all. Just scan > to find first > chained commit block. But this doesn't look like a very good idea. Well, the super block is special. It links to the log block, so that we can move the log block to any place in the flash. So it's going to be a block which is not recycled too often depending on how the log chain works. I don't see why scanning for the super block will take so much time. If we keep it inside of the first N blocks then it's a well defined scan time limit. And you just need to read the first page to find it. > > The super block must be moveable like any other block, though we can > > keep it as close to the start of flash as possible. > > The idea is to get rid of scanning. A fixed place super block can > locate movable headers. Right, but there is a difference between scanning 8k blocks and scanning a low number (16 or 32) blocks. That's in the single digit milliseconds range. So forcing it to a fixed location is just an overoptimization. > > Also chaining has a tradeoff. The more chains you need to walk the > > closer you get to the point where you are equally bad as a full scan. > > As artem suggested, chaining should help in minimizing writes to > anchor block at fixed > location. At first instance it looked promising. But this design also > has single point of failure. Not if you make the super block movable. Then you can create the replacement block before erasing the old super block. So in the worst case you have two super blocks in that scan range and you need to figure out which one is the valid one. No big deal. > > I don't think it's a good idea to kill the EC/VID headers. It not only > > violates the backwards compability it also fundamentally weakens UBIs > > reliability for no good reason and I doubt that the performance win is > > big enough to make it worth. > > > > The performance gain is at attach time by getting rid of the flash > > scan, but not by getting rid of writing the EC/VID headers. > > These flash headers have some more problems. Like, space wastage in MLC. > Alignment problem for byte addressable memory. Backward compatibility > is a good idea. > But it is possible to implement these features and higher performance > by getting rid of them. > It seemed a fair trade off to me. But I am open for any better solution. Well. You can get rid of them, but that needs to be optional. And if you remove them then your log needs to take care of the EC/VID tracking. That means you write at least ECC size long data to the log for every single transaction. IOW, you move the space waste partially from the data blocks to the loging blocks. If you do not, you lose reliability completely, which is not an option at all. Further this will need a careful balance of how many log entries you write before you need to create a compressed snapshot simply because the number of entries is linearely increasing the attach time. Thanks, tglx From tglx at linutronix.de Wed May 12 05:06:22 2010 From: tglx at linutronix.de (Thomas Gleixner) Date: Wed, 12 May 2010 11:06:22 +0200 (CEST) Subject: UBIL design doc In-Reply-To: <1273650099.22706.41.camel@localhost> References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> Message-ID: On Wed, 12 May 2010, Artem Bityutskiy wrote: > On Tue, 2010-05-11 at 21:17 +0200, Thomas Gleixner wrote: > > > > Also chaining has a tradeoff. The more chains you need to walk the > > closer you get to the point where you are equally bad as a full scan. > > Well, every new chain member reduces the superblock wear speed by order > 2, so I the chain would have 2-4 eraseblocks in most cases, I guess, > which is not bad. > > In the opposite, moving the SB 3-4 eraseblocks further only reduces the > load merely by factor 3-4. Right, but having the flexibility of moving the super block in the first 16 or 32 blocks is not going to hurt the attach time significantly. I'm not against the super block and chain design, I merily fight fixed address designs. Thanks, tglx From dedekind1 at gmail.com Wed May 12 05:31:15 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 12:31:15 +0300 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> Message-ID: <1273656675.22706.62.camel@localhost> On Wed, 2010-05-12 at 11:06 +0200, Thomas Gleixner wrote: > On Wed, 12 May 2010, Artem Bityutskiy wrote: > > On Tue, 2010-05-11 at 21:17 +0200, Thomas Gleixner wrote: > > > > > > Also chaining has a tradeoff. The more chains you need to walk the > > > closer you get to the point where you are equally bad as a full scan. > > > > Well, every new chain member reduces the superblock wear speed by order > > 2, so I the chain would have 2-4 eraseblocks in most cases, I guess, > > which is not bad. > > > > In the opposite, moving the SB 3-4 eraseblocks further only reduces the > > load merely by factor 3-4. > > Right, but having the flexibility of moving the super block in the > first 16 or 32 blocks is not going to hurt the attach time > significantly. I'm not against the super block and chain design, I > merily fight fixed address designs. Yeah, I guess this is not a big deal to shift the SB forward a bit if needed. It is not worth discussing further, but to make sure Brijesh is focused on the most important things, I'd like to note that implementation-wise, it is OK to have a constant defined to 1 so far, and later test that everything works just fine when it is something else, and optionally implement the SB searching function. -- Best Regards, Artem Bityutskiy (????? ????????) From brijesh.s.singh at gmail.com Wed May 12 05:46:28 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Wed, 12 May 2010 15:16:28 +0530 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> Message-ID: On Wed, May 12, 2010 at 2:32 PM, Thomas Gleixner wrote: > Brijesh, > > On Wed, 12 May 2010, Brijesh Singh wrote: >> On Wed, May 12, 2010 at 12:47 AM, Thomas Gleixner wrote: >> > On Mon, 10 May 2010, Artem Bityutskiy wrote: >> >> 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 >> >> erease cycles? Won't the SB PEB wear out very quickly? Why you did not >> >> go for the chaining approach which I described in the old JFFS3 design >> >> doc? >> >> >> >> If we do not implement chaining, we should at least design it and make >> >> sure UBIL can be extended later so that SB chaining could be added. >> > >> > The super block needs to be scanned for from the beginning of flash >> > anyway due to bad blocks. Putting it into a fixed position (first good >> > erase block) is a very bad design decision vs. wear leveling. >> >> This scan is minimal once the bad blocks are marked bad. Flash driver >> generally ?returns error by reading oob area or in ram bbt table. In comparison, >> keeping super block in first few blocks may become question of availability or >> wear-leveling trade off. The scan time for super block itself will >> take lot of time. >> In fact, in that case we won't need the super block at all. Just scan >> to find first >> chained commit block. But this doesn't look like a very good idea. > > Well, the super block is special. It links to the log block, so that > we can move the log block to any place in the flash. So it's going to > be a block which is not recycled too often depending on how the log > chain works. > > I don't see why scanning for the super block will take so much > time. If we keep it inside of the first N blocks then it's a well > defined scan time limit. And you just need to read the first page to > find it. > >> > The super block must be moveable like any other block, though we can >> > keep it as close to the start of flash as possible. >> >> The idea is to get rid of scanning. A fixed place super block can >> locate movable headers. > > Right, but there is a difference between scanning 8k blocks and > scanning a low number (16 or 32) blocks. That's in the single digit > milliseconds range. So forcing it to a fixed location is just an > overoptimization. > >> > Also chaining has a tradeoff. The more chains you need to walk the >> > closer you get to the point where you are equally bad as a full scan. >> >> As artem suggested, chaining should help in minimizing writes to >> anchor block at fixed >> location. At first instance it looked promising. But this design also >> has single point of failure. > > Not if you make the super block movable. Then you can create the > replacement block before erasing the old super block. So in the worst > case you have two super blocks in that scan range and you need to > figure out which one is the valid one. No big deal. > >> > I don't think it's a good idea to kill the EC/VID headers. It not only >> > violates the backwards compability it also fundamentally weakens UBIs >> > reliability for no good reason and I doubt that the performance win is >> > big enough to make it worth. >> > >> > The performance gain is at attach time by getting rid of the flash >> > scan, but not by getting rid of writing the EC/VID headers. >> >> These flash headers have some more problems. Like, space wastage in MLC. >> Alignment problem for byte addressable memory. Backward compatibility >> is a good idea. >> But it is possible to implement these features and higher performance >> by getting rid of them. >> It seemed a fair trade off to me. But I am open for any better solution. > > Well. You can get rid of them, but that needs to be optional. > > And if you remove them then your log needs to take care of the EC/VID > tracking. > > That means you write at least ECC size long data to the log for every > single transaction. IOW, you move the space waste partially from the > data blocks to the loging blocks. Right now we are doing this. Writing ECC size long data to log for each update. But we removed EC,VID headers from block. Because they were not needed. Log has all the data.Now, I am trying to get EC,VID headers back as an option. From s-ghorai at ti.com Wed May 12 05:48:36 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Wed, 12 May 2010 15:18:36 +0530 Subject: [PATCH 1/3] omap3: GPMC register definition at common location In-Reply-To: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> Message-ID: <1273657718-12517-2-git-send-email-s-ghorai@ti.com> GPMC register definition move to common place in gpmc.h. Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/gpmc.c | 38 +------------------------------ arch/arm/plat-omap/include/plat/gpmc.h | 36 +++++++++++++++++++++++++++-- drivers/mtd/nand/omap2.c | 14 ++++------- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5bc3ca0..9c77af0 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -28,40 +28,6 @@ #include -/* GPMC register offsets */ -#define GPMC_REVISION 0x00 -#define GPMC_SYSCONFIG 0x10 -#define GPMC_SYSSTATUS 0x14 -#define GPMC_IRQSTATUS 0x18 -#define GPMC_IRQENABLE 0x1c -#define GPMC_TIMEOUT_CONTROL 0x40 -#define GPMC_ERR_ADDRESS 0x44 -#define GPMC_ERR_TYPE 0x48 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 -#define GPMC_PREFETCH_CONFIG1 0x1e0 -#define GPMC_PREFETCH_CONFIG2 0x1e4 -#define GPMC_PREFETCH_CONTROL 0x1ec -#define GPMC_PREFETCH_STATUS 0x1f0 -#define GPMC_ECC_CONFIG 0x1f4 -#define GPMC_ECC_CONTROL 0x1f8 -#define GPMC_ECC_SIZE_CONFIG 0x1fc - -#define GPMC_CS0 0x60 -#define GPMC_CS_SIZE 0x30 - -#define GPMC_MEM_START 0x00000000 -#define GPMC_MEM_END 0x3FFFFFFF -#define BOOT_ROM_SPACE 0x100000 /* 1MB */ - -#define GPMC_CHUNK_SHIFT 24 /* 16 MB */ -#define GPMC_SECTION_SHIFT 28 /* 128 MB */ - -#define PREFETCH_FIFOTHRESHOLD (0x40 << 8) -#define CS_NUM_SHIFT 24 -#define ENABLE_PREFETCH (0x1 << 7) -#define DMA_MPU_MODE 2 - /* Structure to save gpmc cs context */ struct gpmc_cs_config { u32 config1; @@ -112,7 +78,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) { void __iomem *reg_addr; - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; __raw_writel(val, reg_addr); } @@ -120,7 +86,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) { void __iomem *reg_addr; - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; return __raw_readl(reg_addr); } diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 145838a..347d212 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -25,10 +25,40 @@ #define GPMC_CS_NAND_ADDRESS 0x20 #define GPMC_CS_NAND_DATA 0x24 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 +/* GPMC register offsets */ +#define GPMC_REVISION 0x00 +#define GPMC_SYSCONFIG 0x10 +#define GPMC_SYSSTATUS 0x14 +#define GPMC_IRQSTATUS 0x18 +#define GPMC_IRQENABLE 0x1c +#define GPMC_TIMEOUT_CONTROL 0x40 +#define GPMC_ERR_ADDRESS 0x44 +#define GPMC_ERR_TYPE 0x48 +#define GPMC_CONFIG 0x50 +#define GPMC_STATUS 0x54 +#define GPMC_PREFETCH_CONFIG1 0x1e0 +#define GPMC_PREFETCH_CONFIG2 0x1e4 +#define GPMC_PREFETCH_CONTROL 0x1ec +#define GPMC_PREFETCH_STATUS 0x1f0 +#define GPMC_ECC_CONFIG 0x1f4 +#define GPMC_ECC_CONTROL 0x1f8 +#define GPMC_ECC_SIZE_CONFIG 0x1fc +#define GPMC_ECC1_RESULT 0x200 + #define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 +#define GPMC_CS_SIZE 0x30 + +#define GPMC_MEM_START 0x00000000 +#define GPMC_MEM_END 0x3FFFFFFF +#define BOOT_ROM_SPACE 0x100000 /* 1MB */ + +#define GPMC_CHUNK_SHIFT 24 /* 16 MB */ +#define GPMC_SECTION_SHIFT 28 /* 128 MB */ + +#define PREFETCH_FIFOTHRESHOLD (0x40 << 8) +#define CS_NUM_SHIFT 24 +#define ENABLE_PREFETCH (0x1 << 7) +#define DMA_MPU_MODE 2 #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 7545568..258bf06 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -23,12 +23,6 @@ #include #include -#define GPMC_IRQ_STATUS 0x18 -#define GPMC_ECC_CONFIG 0x1F4 -#define GPMC_ECC_CONTROL 0x1F8 -#define GPMC_ECC_SIZE_CONFIG 0x1FC -#define GPMC_ECC1_RESULT 0x200 - #define DRIVER_NAME "omap2-nand" #define NAND_WP_OFF 0 @@ -37,6 +31,7 @@ #define GPMC_BUF_FULL 0x00000001 #define GPMC_BUF_EMPTY 0x00000000 +#ifdef CONFIG_MTD_NAND_OMAP_HWECC #define NAND_Ecc_P1e (1 << 0) #define NAND_Ecc_P2e (1 << 1) #define NAND_Ecc_P4e (1 << 2) @@ -103,6 +98,7 @@ #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */ #ifdef CONFIG_MTD_PARTITIONS static const char *part_probes[] = { "cmdlinepart", NULL }; @@ -854,20 +850,20 @@ static int omap_dev_ready(struct mtd_info *mtd) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS); + unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS); if ((val & 0x100) == 0x100) { /* Clear IRQ Interrupt */ val |= 0x100; val &= ~(0x0); - __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS); + __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS); } else { unsigned int cnt = 0; while (cnt++ < 0x1FF) { if ((val & 0x100) == 0x100) return 0; val = __raw_readl(info->gpmc_baseaddr + - GPMC_IRQ_STATUS); + GPMC_IRQSTATUS); } } From s-ghorai at ti.com Wed May 12 05:48:35 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Wed, 12 May 2010 15:18:35 +0530 Subject: [PATCH 0/3] omap3 nand: cleanup exiting platform related code In-Reply-To: References: Message-ID: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> The following set of patches applies on top of master branch. http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board And these are the patches required to address the following input - 1. The NAND driver needs to stop tinkering with the GPMC registers The omap General Purpose Memory Controller (GPMC) registers are omap specific, and not driver specific. Tinkering with these registers can cause issues with the other devices on the GPMC. 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files Passing hardcoded GPMC virtual addressess is sure way to mess up things. This should all become unnecessary once the NAND drivers stops messing with the GPMC registers directly. Sukumar Ghorai (3): omap3: GPMC register definition at common location omap3 nand: cleanup for not to use GPMC virtual address omap3 nand: fix issue in board file to detect the nand arch/arm/mach-omap2/board-cm-t35.c | 20 +---- arch/arm/mach-omap2/board-devkit8000.c | 25 +------ arch/arm/mach-omap2/board-omap3beagle.c | 24 +----- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------ arch/arm/mach-omap2/board-overo.c | 24 +----- arch/arm/mach-omap2/gpmc.c | 67 +++++----------- arch/arm/plat-omap/include/plat/gpmc.h | 41 ++++++++- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 125 ++++++++++------------------ 9 files changed, 109 insertions(+), 248 deletions(-) From s-ghorai at ti.com Wed May 12 05:48:37 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Wed, 12 May 2010 15:18:37 +0530 Subject: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <1273657718-12517-2-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> <1273657718-12517-2-git-send-email-s-ghorai@ti.com> Message-ID: <1273657718-12517-3-git-send-email-s-ghorai@ti.com> Necessary function added in GPMC module and used by nand driver. This is for not to use GPMC address directly from nand driver. Also it was passing GPMC base address from board files and that is removed. Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/board-cm-t35.c | 4 - arch/arm/mach-omap2/board-devkit8000.c | 9 -- arch/arm/mach-omap2/board-omap3beagle.c | 8 -- arch/arm/mach-omap2/board-omap3touchbook.c | 9 -- arch/arm/mach-omap2/board-overo.c | 7 -- arch/arm/mach-omap2/gpmc.c | 29 ++++--- arch/arm/plat-omap/include/plat/gpmc.h | 5 +- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 117 ++++++++++----------------- 9 files changed, 67 insertions(+), 127 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index e679a2c..fb23122 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -61,8 +61,6 @@ #define SB_T35_SMSC911X_GPIO 65 #define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE) #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include @@ -223,8 +221,6 @@ static struct omap_nand_platform_data cm_t35_nand_data = { .nr_parts = ARRAY_SIZE(cm_t35_nand_partitions), .dma_channel = -1, /* disable DMA in OMAP NAND driver */ .cs = 0, - .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR, - .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT, }; diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 47e3af2..be50d18 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -58,9 +58,6 @@ #include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K #define OMAP_DM9000_GPIO_IRQ 25 @@ -581,8 +578,6 @@ static void __init devkit8000_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -604,10 +599,6 @@ static void __init devkit8000_flash_init(void) if (nandcs < GPMC_CS_NUM) { devkit8000_nand_data.cs = nandcs; - devkit8000_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - devkit8000_nand_data.gpmc_baseaddr = (void *) - (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&devkit8000_nand_device) < 0) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 962d377..becaebe --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -47,9 +47,6 @@ #include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K static struct mtd_partition omap3beagle_nand_partitions[] = { @@ -377,8 +374,6 @@ static void __init omap3beagle_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -400,9 +395,6 @@ static void __init omap3beagle_flash_init(void) if (nandcs < GPMC_CS_NUM) { omap3beagle_nand_data.cs = nandcs; - omap3beagle_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&omap3beagle_nand_device) < 0) diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index 2504d41..d6f1b12 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -54,9 +54,6 @@ #include -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K #define OMAP3_AC_GPIO 136 @@ -459,8 +456,6 @@ static void __init omap3touchbook_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -482,10 +477,6 @@ static void __init omap3touchbook_flash_init(void) if (nandcs < GPMC_CS_NUM) { omap3touchbook_nand_data.cs = nandcs; - omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - omap3touchbook_nand_data.gpmc_baseaddr = - (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&omap3touchbook_nand_device) < 0) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 8848c7c..d843a0a --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -58,8 +58,6 @@ #define OVERO_GPIO_USBH_NRESET 183 #define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 #define OVERO_SMSC911X_CS 5 #define OVERO_SMSC911X_GPIO 176 @@ -239,8 +237,6 @@ static void __init overo_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -262,9 +258,6 @@ static void __init overo_flash_init(void) if (nandcs < GPMC_CS_NUM) { overo_nand_data.cs = nandcs; - overo_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&overo_nand_device) < 0) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 9c77af0..9210e10 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -64,16 +64,32 @@ static void __iomem *gpmc_base; static struct clk *gpmc_l3_clk; -static void gpmc_write_reg(int idx, u32 val) +void gpmc_write_reg(int idx, u32 val) { __raw_writel(val, gpmc_base + idx); } -static u32 gpmc_read_reg(int idx) +u32 gpmc_read_reg(int idx) { return __raw_readl(gpmc_base + idx); } +void gpmc_cs_write_byte(int cs, int idx, u32 val) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; + __raw_writeb(val, reg_addr); +} + +u8 gpmc_cs_read_byte(int cs, int idx) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; + return __raw_readb(reg_addr); +} + void gpmc_cs_write_reg(int cs, int idx, u32 val) { void __iomem *reg_addr; @@ -432,15 +448,6 @@ void gpmc_prefetch_reset(void) } EXPORT_SYMBOL(gpmc_prefetch_reset); -/** - * gpmc_prefetch_status - reads prefetch status of engine - */ -int gpmc_prefetch_status(void) -{ - return gpmc_read_reg(GPMC_PREFETCH_STATUS); -} -EXPORT_SYMBOL(gpmc_prefetch_status); - static void __init gpmc_mem_init(void) { int cs; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 347d212..c1e9807 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -128,8 +128,12 @@ extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns); extern unsigned long gpmc_get_fclk_period(void); +extern void gpmc_write_reg(int idx, u32 val); +extern u32 gpmc_read_reg(int idx); extern void gpmc_cs_write_reg(int cs, int idx, u32 val); extern u32 gpmc_cs_read_reg(int cs, int idx); +extern void gpmc_cs_write_byte(int cs, int idx, u32 val); +extern u8 gpmc_cs_read_byte(int cs, int idx); extern int gpmc_cs_calc_divider(int cs, unsigned int sync_clk); extern int gpmc_cs_set_timings(int cs, const struct gpmc_timings *t); extern int gpmc_cs_request(int cs, unsigned long size, unsigned long *base); @@ -139,7 +143,6 @@ extern int gpmc_cs_reserved(int cs); extern int gpmc_prefetch_enable(int cs, int dma_mode, unsigned int u32_count, int is_write); extern void gpmc_prefetch_reset(void); -extern int gpmc_prefetch_status(void); extern void omap3_gpmc_save_context(void); extern void omap3_gpmc_restore_context(void); extern void gpmc_init(void); diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index f8efd54..6562cd0 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -21,13 +21,11 @@ struct omap_nand_platform_data { int (*dev_ready)(struct omap_nand_platform_data *); int dma_channel; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; int devsize; }; -/* size (4 KiB) for IO mapping */ -#define NAND_IO_SIZE SZ_4K +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) extern int gpmc_nand_init(struct omap_nand_platform_data *d); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 258bf06..f4f6f01 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -135,9 +135,6 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; - void __iomem *nand_pref_fifo_add; struct completion comp; int dma_ch; }; @@ -149,17 +146,14 @@ struct omap_nand_info { */ static void omap_nand_wp(struct mtd_info *mtd, int mode) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); - - unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG); + unsigned long config = gpmc_read_reg(GPMC_CONFIG); if (mode) config &= ~(NAND_WP_BIT); /* WP is ON */ else config |= (NAND_WP_BIT); /* WP is OFF */ - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG)); + gpmc_write_reg(GPMC_CONFIG, config); } /** @@ -177,31 +171,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - switch (ctrl) { - case NAND_CTRL_CHANGE | NAND_CTRL_CLE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_COMMAND; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - case NAND_CTRL_CHANGE | NAND_CTRL_ALE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_ADDRESS; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; + if (cmd != NAND_CMD_NONE) { + if (ctrl & NAND_CLE) { + gpmc_cs_write_byte(info->gpmc_cs, + GPMC_CS_NAND_COMMAND, cmd); - case NAND_CTRL_CHANGE | NAND_NCE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - } + } else if (ctrl & NAND_ALE) { + gpmc_cs_write_byte(info->gpmc_cs, + GPMC_CS_NAND_ADDRESS, cmd); - if (cmd != NAND_CMD_NONE) - __raw_writeb(cmd, info->nand.IO_ADDR_W); + } else /* NAND_NCE */ + gpmc_cs_write_byte(info->gpmc_cs, + GPMC_CS_NAND_DATA, cmd); + } } /** @@ -231,8 +214,9 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) while (len--) { iowrite8(*p++, info->nand.IO_ADDR_W); - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + - GPMC_STATUS) & GPMC_BUF_FULL)); + while (GPMC_BUF_EMPTY == + (gpmc_read_reg(GPMC_STATUS) & GPMC_BUF_FULL)) + ; } } @@ -267,8 +251,8 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) while (len--) { iowrite16(*p++, info->nand.IO_ADDR_W); - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + - GPMC_STATUS) & GPMC_BUF_FULL)) + while (GPMC_BUF_EMPTY == + (gpmc_read_reg(GPMC_STATUS) & GPMC_BUF_FULL)) ; } } @@ -304,9 +288,9 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) omap_read_buf8(mtd, buf, len); } else { do { - pfpw_status = gpmc_prefetch_status(); + pfpw_status = gpmc_read_reg(GPMC_PREFETCH_STATUS); r_count = ((pfpw_status >> 24) & 0x7F) >> 2; - ioread32_rep(info->nand_pref_fifo_add, p, r_count); + ioread32_rep(info->nand.IO_ADDR_R, p, r_count); p += r_count; len -= r_count << 2; } while (len); @@ -347,12 +331,12 @@ static void omap_write_buf_pref(struct mtd_info *mtd, else omap_write_buf8(mtd, buf, len); } else { - pfpw_status = gpmc_prefetch_status(); + pfpw_status = gpmc_read_reg(GPMC_PREFETCH_STATUS); while (pfpw_status & 0x3FFF) { w_count = ((pfpw_status >> 24) & 0x7F) >> 1; for (i = 0; (i < w_count) && len; i++, len -= 2) - iowrite16(*p++, info->nand_pref_fifo_add); - pfpw_status = gpmc_prefetch_status(); + iowrite16(*p++, info->nand.IO_ADDR_W); + pfpw_status = gpmc_read_reg(GPMC_PREFETCH_STATUS); } /* disable and stop the PFPW engine */ @@ -444,7 +428,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, /* setup and start DMA using dma_addr */ wait_for_completion(&info->comp); - while (0x3fff & (prefetch_status = gpmc_prefetch_status())) + while (0x3fff & (prefetch_status = gpmc_read_reg(GPMC_PREFETCH_STATUS))) ; /* disable and stop the PFPW engine */ gpmc_prefetch_reset(); @@ -498,7 +482,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd, omap_write_buf_pref(mtd, buf, len); else /* start transfer in DMA mode */ - omap_nand_dma_transfer(mtd, buf, len, 0x1); + omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); } /** @@ -529,22 +513,21 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len) */ static void omap_hwecc_init(struct mtd_info *mtd) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); struct nand_chip *chip = mtd->priv; unsigned long val = 0x0; /* Read from ECC Control Register */ - val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL); + val = gpmc_read_reg(GPMC_ECC_CONTROL); + /* Clear all ECC | Enable Reg1 */ val = ((0x00000001<<8) | 0x00000001); - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL); + gpmc_write_reg(GPMC_ECC_CONTROL, val); /* Read from ECC Size Config Register */ - val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); /* ECCSIZE1=512 | Select eccResultsize[0-3] */ val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F)); - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); } /** @@ -746,19 +729,14 @@ static int omap_correct_data(struct mtd_info *mtd, u_char *dat, static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u_char *ecc_code) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); unsigned long val = 0x0; - unsigned long reg; /* Start Reading from HW ECC1_Result = 0x200 */ - reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT); - val = __raw_readl(reg); + val = gpmc_read_reg(GPMC_ECC1_RESULT); *ecc_code++ = val; /* P128e, ..., P1e */ *ecc_code++ = val >> 16; /* P128o, ..., P1o */ /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); - reg += 4; return 0; } @@ -774,21 +752,21 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) mtd); struct nand_chip *chip = mtd->priv; unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; - unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG); + unsigned long val = gpmc_read_reg(GPMC_ECC_CONFIG); switch (mode) { case NAND_ECC_READ: - __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); break; case NAND_ECC_READSYN: - __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL); + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); break; case NAND_ECC_WRITE: - __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); break; @@ -798,7 +776,7 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) break; } - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG); + gpmc_write_reg(GPMC_ECC_CONFIG, val); } #endif @@ -827,14 +805,11 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) else timeo += (HZ * 20) / 1000; - this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr + - GPMC_CS_NAND_COMMAND; - this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA; - - __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W); + gpmc_cs_write_byte(info->gpmc_cs, + GPMC_CS_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF)); while (time_before(jiffies, timeo)) { - status = __raw_readb(this->IO_ADDR_R); + status = gpmc_cs_read_byte(info->gpmc_cs, GPMC_CS_NAND_DATA); if (status & NAND_STATUS_READY) break; cond_resched(); @@ -848,22 +823,19 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) */ static int omap_dev_ready(struct mtd_info *mtd) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS); + unsigned int val = gpmc_read_reg(GPMC_IRQSTATUS); if ((val & 0x100) == 0x100) { /* Clear IRQ Interrupt */ val |= 0x100; val &= ~(0x0); - __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS); + gpmc_write_reg(GPMC_IRQSTATUS, val); } else { unsigned int cnt = 0; while (cnt++ < 0x1FF) { if ((val & 0x100) == 0x100) return 0; - val = __raw_readl(info->gpmc_baseaddr + - GPMC_IRQSTATUS); + val = gpmc_read_reg(GPMC_IRQSTATUS); } } @@ -894,8 +866,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->pdev = pdev; info->gpmc_cs = pdata->cs; - info->gpmc_baseaddr = pdata->gpmc_baseaddr; - info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr; info->phys_base = pdata->phys_base; info->mtd.priv = &info->nand; @@ -942,7 +912,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) if (use_prefetch) { /* copy the virtual address of nand base for fifo access */ - info->nand_pref_fifo_add = info->nand.IO_ADDR_R; info->nand.read_buf = omap_read_buf_pref; info->nand.write_buf = omap_write_buf_pref; @@ -1032,7 +1001,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); - iounmap(info->nand_pref_fifo_add); + iounmap(info->nand.IO_ADDR_R); kfree(&info->mtd); return 0; } From s-ghorai at ti.com Wed May 12 05:48:38 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Wed, 12 May 2010 15:18:38 +0530 Subject: [PATCH 3/3] omap3 nand: fix issue in board file to detect the nand In-Reply-To: <1273657718-12517-3-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> <1273657718-12517-2-git-send-email-s-ghorai@ti.com> <1273657718-12517-3-git-send-email-s-ghorai@ti.com> Message-ID: <1273657718-12517-4-git-send-email-s-ghorai@ti.com> Board file modified to pass the GMPC phys_base address to nand driver. This is required to adopt the _prob function as in omap2.c Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/board-cm-t35.c | 16 +--------------- arch/arm/mach-omap2/board-devkit8000.c | 16 +--------------- arch/arm/mach-omap2/board-omap3beagle.c | 16 +--------------- arch/arm/mach-omap2/board-omap3touchbook.c | 16 +--------------- arch/arm/mach-omap2/board-overo.c | 17 +---------------- 5 files changed, 5 insertions(+), 76 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index fb23122..0544294 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -224,23 +224,9 @@ static struct omap_nand_platform_data cm_t35_nand_data = { }; -static struct resource cm_t35_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device cm_t35_nand_device = { - .name = "omap2-nand", - .id = -1, - .num_resources = 1, - .resource = &cm_t35_nand_resource, - .dev = { - .platform_data = &cm_t35_nand_data, - }, -}; - static void __init cm_t35_init_nand(void) { - if (platform_device_register(&cm_t35_nand_device) < 0) + if (gpmc_nand_init(&cm_t35_nand_data) < 0) pr_err("CM-T35: Unable to register NAND device\n"); } #else diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index be50d18..a6fcb48 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -101,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource devkit8000_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device devkit8000_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &devkit8000_nand_data, - }, - .num_resources = 1, - .resource = &devkit8000_nand_resource, -}; - static struct omap2_hsmmc_info mmc[] = { { .mmc = 1, @@ -601,7 +587,7 @@ static void __init devkit8000_flash_init(void) devkit8000_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&devkit8000_nand_device) < 0) + if (gpmc_nand_init(&devkit8000_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index becaebe..bf31b7c --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -89,20 +89,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = { .dev_ready = NULL, }; -static struct resource omap3beagle_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device omap3beagle_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &omap3beagle_nand_data, - }, - .num_resources = 1, - .resource = &omap3beagle_nand_resource, -}; - #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -397,7 +383,7 @@ static void __init omap3beagle_flash_init(void) omap3beagle_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&omap3beagle_nand_device) < 0) + if (gpmc_nand_init(&omap3beagle_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index d6f1b12..e8ad30c --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -103,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = { .dev_ready = NULL, }; -static struct resource omap3touchbook_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device omap3touchbook_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &omap3touchbook_nand_data, - }, - .num_resources = 1, - .resource = &omap3touchbook_nand_resource, -}; - #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -479,7 +465,7 @@ static void __init omap3touchbook_flash_init(void) omap3touchbook_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&omap3touchbook_nand_device) < 0) + if (gpmc_nand_init(&omap3touchbook_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index d843a0a..627edd3 --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -217,21 +217,6 @@ static struct omap_nand_platform_data overo_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource overo_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device overo_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &overo_nand_data, - }, - .num_resources = 1, - .resource = &overo_nand_resource, -}; - - static void __init overo_flash_init(void) { u8 cs = 0; @@ -260,7 +245,7 @@ static void __init overo_flash_init(void) overo_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&overo_nand_device) < 0) + if (gpmc_nand_init(&overo_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } From brijesh.s.singh at gmail.com Wed May 12 05:49:19 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Wed, 12 May 2010 15:19:19 +0530 Subject: UBIL design doc In-Reply-To: <1273653341.22706.46.camel@localhost> References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> <1273653341.22706.46.camel@localhost> Message-ID: On Wed, May 12, 2010 at 2:05 PM, Artem Bityutskiy wrote: > On Wed, 2010-05-12 at 13:33 +0530, Brijesh Singh wrote: >> Hi, >> >> On Wed, May 12, 2010 at 1:11 PM, Artem Bityutskiy wrote: >> > On Tue, 2010-05-11 at 21:17 +0200, Thomas Gleixner wrote: >> >> B1;2005;0cOn Mon, 10 May 2010, Artem Bityutskiy wrote: >> >> >> >> > On Sun, 2010-05-09 at 01:09 +0530, Brijesh Singh wrote: >> >> > > Hi, >> >> > > ? I am forwarding you the design document for ubi with log. Please >> >> > > find the ubil document at >> >> > > http://git.infradead.org/users/brijesh/ubil_results/blob_plain/HEAD:/UBIL >> >> > > design document.pdf >> >> >> >> @Brijesh, thanks for tackling this ! >> >> >> >> > Hi guys, >> >> > >> >> > I've read the document. Looks very promising. Here some feed-back. >> >> > >> >> > 1. SB PEB wear-out. What if the reaseblock lifetime is, say, 10000 >> >> > erease cycles? Won't the SB PEB wear out very quickly? Why you did not >> >> > go for the chaining approach which I described in the old JFFS3 design >> >> > doc? >> >> > >> >> > If we do not implement chaining, we should at least design it and make >> >> > sure UBIL can be extended later so that SB chaining could be added. >> >> >> >> The super block needs to be scanned for from the beginning of flash >> >> anyway due to bad blocks. Putting it into a fixed position (first good >> >> erase block) is a very bad design decision vs. wear leveling. >> >> >> >> The super block must be moveable like any other block, though we can >> >> keep it as close to the start of flash as possible. >> >> >> >> Also chaining has a tradeoff. The more chains you need to walk the >> >> closer you get to the point where you are equally bad as a full scan. >> > >> > Well, every new chain member reduces the superblock wear speed by order >> > 2, so I the chain would have 2-4 eraseblocks in most cases, I guess, >> > which is not bad. >> > >> > In the opposite, moving the SB 3-4 eraseblocks further only reduces the >> > load merely by factor 3-4. >> > >> >> > 2. SB PEB at the end. I think this is a very bad idea. Imagine you have >> >> > to do UBIL images for production on the factory. With your design you >> >> > have the following bad drawbacks: >> >> > >> >> > ? a. NAND flash has initial bad blocks, and you do not know how many, >> >> > ? ? ?and where they sit. These may be the last 8 eraseblocks. So, when >> >> > ? ? ?you prepare an image (say, with the ubinize user-space tool), where >> >> > ? ? ?will you put the second SB PEB? >> >> > >> >> > ? b. Currently, UBI/UBIFS images are small. E.g., if you make an >> >> > ? ? ?UBI/UBIFS image for 1GiB flash, and you have just few KiB of files, >> >> > ? ? ?your image will be few megs - it will contain the files, and all >> >> > ? ? ?the needed UBI/UBIFS meta-data. >> >> > >> >> > ? ? ?So now what will be image size for UBIL - 1GiB, and this is bad. >> >> > ? ? ?You then will transfer 1GiB of data to the devices during flashing >> >> > ? ? ?or you will have to invent ways to work around this. Do you need >> >> > ? ? ?these complexities? >> >> > >> >> > I think the second SB PEB should not be at the end. >> >> >> >> I think we do not need a second SB at all. UBI should not depend on >> >> the super block in any way. The super block is an optimization for the >> >> common case - nothing more. >> > >> > Yeah, if we preserve the headers we can always fall-back to scanning >> > should something be broken. >> > >> >> >> >> > 3. Backward-compatibility. In UBIL you removed EC anc VID headers in >> >> > ? ?PEBs. That's fine for optimization purposes. But it has draw-backs: >> >> > >> >> > ? ?a. If any of the UBIL meta-data blocks like SB, CMT or log are >> >> > ? ? ? corrupted - that's it - we are screwed. You cannot anymore >> >> > ? ? ? re-consturct the data by scanning. The robustness goes down. >> >> > >> >> > ? ?c. Backward compatibility - UBI will not be able to attach UBIL >> >> > ? ? ? images. This is not very nice. >> >> > >> >> > So, I think you should keep EC and VID headers in PEBs. And you should >> >> > make the SB/CMT/log blocks to be a new type of UBI volume with >> >> > UBI_COMPAT_DELETE or UBI_COMPAT_PRESERVE or UBI_COMPAT_RO type. In this >> >> > case UBI will attach UBIL volumes just fine. >> >> > >> >> > Then, you can add an _option_ to have no EC/VID headers in PEBs. This >> >> > then can be used for performance, if one wants to sacrifice robustness. >> >> > But this should be the second step. In this case, you will just need to >> >> > put a VID header with UBI_COMPAT_REJECT flag to the first PEB. >> >> >> >> I don't think it's a good idea to kill the EC/VID headers. It not only >> >> violates the backwards compability it also fundamentally weakens UBIs >> >> reliability for no good reason and I doubt that the performance win is >> >> big enough to make it worth. >> >> >> >> The performance gain is at attach time by getting rid of the flash >> >> scan, but not by getting rid of writing the EC/VID headers. >> > >> > Well, there are some space savings as well. >> > >> >> >> >> The logging is a speed up / optimization for the common case, but it >> >> needs to preserve full reconstruction via scanning all eraseblocks and >> >> checking the EC/VID headers. That also allows retrofitting on existing >> >> devices. >> >> >> >> I'd rather see the super block / log volume as a checkpointing >> >> mechanism which provides a snapshot of the EC/VID headers at a given >> >> point and a list of eraseblocks which need to be scanned at attach >> >> time. >> >> >> >> >> >> That has two main advantages: >> >> ?1) It limits the number of log writes >> >> ?2) It allows full backward and forward compatibility >> > >> > I think this is what they do, but they for some reasons removed the >> > headers. If they add them back, it should look like you described. >> > >> > We should preserve the headers. It is always easy to disable them later, >> > if someone needs this for optimization purposes. E.g., we can add an >> > ubi_compat=0 option or something like that. >> > >> >> Looking at >> >> http://git.infradead.org/users/brijesh/ubil_results/blob/HEAD:/nand_mount_time.pdf >> >> I still see a linear - though less steep - attach time. For the 1GB >> >> flash size it's still 0.8s which is nice progress vs. the 2s for the >> >> non logging case. But that's surprising as one would expect that >> >> logging would provide a more aggressive and non linear gain. >> >> >> >> Just doing the simple math: >> >> >> >> 1GB FLASH with erase block size 128K and page size 2k, that >> >> translates to 8192 erase blocks >> >> >> >> So UBI scans 8192 erase block EC/VID headers in 2 seconds. That >> >> equals to 8192 FLASH pages. >> >> >> >> UBIL needs 0.8 seconds. That means that UBIL still scans ~3236 FLASH >> >> pages (or spends the equivivalent time) to achieve the same result. >> >> >> >> That looks wrong. Care to explain ? >> > >> > I suspect these are implementation issues. I did not look at the code, >> > but I suspect they read whole CMT block and populate the all EB >> > associations at scan time. However, they could populate them lazily, >> > which would optimize things. >> I am trying to summarize what I have understood. >> I will send the patches if this is correct. >> 1) Commit will have ec and vid headers just as any other UBI block. >> The compat flag helps in backword compatibility, >> 2)chained sb will locate commit. It will be part of internal volume as well. >> 3) Commit will be called on unmount. >> 4) Any unclean un-mount will lead to flash scanning just as UBI. > > No! Why you have the log then? Unclean reboots are handled by the log. > > Scanning happens only when you have _corrupted_ SB, or corrupted cmt, or > log. Then you fall-back to scanning. > >> Any thing goes bad, normal scanning becomes recovery. >> 5) Not sure if log is required in first place. But it could be an option. >> Is that correct? > > No, at least I did not suggest you to get rid of the log. It is needed > to handle unclean reboots. Log is written for each EC or VID change. Frequency of log write is same as the frequency of these headers. In case we keep both, there will be one log write penalty per write/erase. So write performance will drop considerably. From dedekind1 at gmail.com Wed May 12 06:01:21 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 13:01:21 +0300 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> <1273653341.22706.46.camel@localhost> Message-ID: <1273658481.22706.73.camel@localhost> On Wed, 2010-05-12 at 15:19 +0530, Brijesh Singh wrote: > >> Any thing goes bad, normal scanning becomes recovery. > >> 5) Not sure if log is required in first place. But it could be an option. > >> Is that correct? > > > > No, at least I did not suggest you to get rid of the log. It is needed > > to handle unclean reboots. > Log is written for each EC or VID change. Yes, I understand. > Frequency of log write is same as > the frequency of these headers. Right. > In case we keep both, there will be one log > write penalty per write/erase. Yes, each time you write to an unmapped LEB, you write the VID header and a log entry. > So write performance will drop considerably. Not sure about 'considerably'. This is to be tested. Keeping the headers means 1 additional write per peb_size bytes, right? Plus just after erase, EC header should be written. But this is the price you pay for robustness and compatibility. But again, it is very easy to switch off headers if this is needed, isn't it? -- Best Regards, Artem Bityutskiy (????? ????????) From arno.steffen at googlemail.com Wed May 12 06:03:32 2010 From: arno.steffen at googlemail.com (Arno Steffen) Date: Wed, 12 May 2010 12:03:32 +0200 Subject: <4>mtd->read(x bytes from y) returned ECC error / Node header CRC failed / READ error In-Reply-To: References: Message-ID: I could solve this issue by changing to kernel 2.6.33 (before 2.6.28). No problems anymore, even on a writeable mounted root-fs. 2010/5/7 Darwin Rambo : >> For the first I have mounted the jffs2 (rootfs) as read only >> (confirmed by a "VFS: Mounted root (jffs2 filesystem) readonly >> message"). >> The behaviour is still the same. So does it makes a difference to set >> WriteProtection? >> The other question - if this is some selfhealing issue (as messages >> dissapear in next boot), why it will not try to heal itself right on >> time? Is it possible to force this? >> I cound't found a fitting option in kernel config (at least not one I >> would understood). > > Sorry, I missed that. My comment was for writable file systems. > From brijesh.s.singh at gmail.com Wed May 12 06:25:17 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Wed, 12 May 2010 15:55:17 +0530 Subject: UBIL design doc In-Reply-To: <1273658481.22706.73.camel@localhost> References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> <1273653341.22706.46.camel@localhost> <1273658481.22706.73.camel@localhost> Message-ID: On Wed, May 12, 2010 at 3:31 PM, Artem Bityutskiy wrote: > On Wed, 2010-05-12 at 15:19 +0530, Brijesh Singh wrote: >> >> Any thing goes bad, normal scanning becomes recovery. >> >> 5) Not sure if log is required in first place. But it could be an option. >> >> Is that correct? >> > >> > No, at least I did not suggest you to get rid of the log. It is needed >> > to handle unclean reboots. >> Log is written for each EC or VID change. > > Yes, I understand. > >> ?Frequency of log write is same as >> the frequency of these headers. > > Right. > >> ?In case we keep both, there will be one log >> write penalty per write/erase. > > Yes, each time you write to an unmapped LEB, you write the VID header > and a log entry. > >> ?So write performance will drop considerably. > > Not sure about 'considerably'. This is to be tested. Keeping the headers > means 1 additional write per peb_size bytes, right? Plus just after > erase, EC header should be written. But this is the price you pay for > robustness and compatibility. > > But again, it is very easy to switch off headers if this is needed, > isn't it? Yes. From eballetbo at gmail.com Wed May 12 06:29:29 2010 From: eballetbo at gmail.com (=?UTF-8?Q?Enric_Balletb=C3=B2_i_Serra?=) Date: Wed, 12 May 2010 12:29:29 +0200 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: Hello, I have a bit of time to investigate more. I have two boards with two different OneNAND chips populated. The first one is a dual Die Plan 4-Gbit (2 dice of 2-Gbit) [ 26.406890] Muxed OneNAND(DDP) 512MB 1.8V 16-bit (0x58) [ 26.412170] OneNAND version = 0x0031 [ 26.415771] Chip support all block unlock [ 26.419830] Chip has 2 plane The second is a single die of 2-Gbit. [ 32.897735] Muxed OneNAND 256MB 1.8V 16-bit (0x40) [ 32.902557] OneNAND version = 0x0031 [ 32.906188] Chip support all block unlock [ 32.910247] Chip has 2 plane As I understand the bit 3 of DEVICE_ID register indicates if package is a single-die or a dual-die, so - Muxed OneNAND(DDP) 512MB 1.8V 16-bit -> device id: 0x58 -> bit 3 is 1 -> dual-die - Muxed OneNAND 256MB 1.8V 16-bit -> device id: 0x40 -> bit 3 is 0 ->single-die The question is, why those devices are reporting 'Chip has 2 plane' ? Sorry if this is a trivial question but I'm not sure about DDP and '2 plane' concepts. Are the same ? Cheers, Enric 2010/5/6 Enric Balletb? i Serra : > Hi, > > 2010/5/6 Kyungmin Park : >> Hi, >> >> What's your chip version? maybe some mis-probe it seems to be probed >> at 4KiB pagesize OneNAND. > > Is a 4-Gbit DDP OneNAND device from Numonyx composed of two 2-Gbit 2KB > page dice stacked together, the device is equipped with two DataRAMs, > and two-plane NAND Flash memory array, > > These two component enables simultaneous program of 4KiB ( > CONFIG_MTD_ONENAND_2X_PROGRAM) > > Cheers, > > Enric > >> >> Thank you, >> Kyungmin Park >> >> On Thu, May 6, 2010 at 8:22 PM, Enric Balletb? i Serra >> wrote: >>> Hi, >>> >>> 2010/5/6 Kyungmin Park : >>>> Hi, >>>> >>>> Can you add this statement at below the code? >>>> printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) >>>> onenand_addr(this, block), ((int) addr >> this->page_shift) & >>>> this->page_mask); >>> >>> Yes, >>> >>> With this code nandtest fails: >>> >>> onenand_base.c >>> >>> 377: ? ? default: >>> ? ? ? ? ? ? ? ?block = onenand_block(this, addr); >>> /* ?(line disabled) ? page = (int) (addr >> this->page_shift); */ >>> ? ? ? ? ? ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >>> this->page_shift; >>> >>> ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, >>> page, (int) >>> ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> >>> this->page_shift) & >>> ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); >>> >>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>> ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; >>> ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ >>> ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) >>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; >>> ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; >>> ? ? ? ? ? ? ? ?} >>> ? ? ? ? ? ? ? ?page &= this->page_mask; >>> ? ? ? ? ? ? ? ?break; >>> >>> >>> --- start log nandtest fail --- >>> # nandtest -l 262144 /dev/mtd3 >>> ECC corrections: 0 >>> ECC failures ? : 0 >>> Bad blocks ? ? : 0 >>> BBT blocks ? ? : 0 >>> 00000000: writing... >>> [ ?243.144287] onenand_command[382] page 0, 2621440, 0 >>> [ ?243.150787] onenand_command[382] page 2, 2621440, 2 >>> [ ?243.156158] onenand_command[382] page 4, 2621440, 4 >>> (...) >>> [ ?243.310729] onenand_command[382] page 60, 2621440, 60 >>> [ ?243.316223] onenand_command[382] page 62, 2621440, 62 >>> [ ?243.322204] onenand_command[382] page 0, 2752512, 0 >>> [ ?243.327636] onenand_command[382] page 2, 2752512, 2 >>> [ ?243.332977] onenand_command[382] page 4, 2752512, 4 >>> (...) >>> [ ?243.487487] onenand_command[382] page 60, 2752512, 60 >>> [ ?243.493041] onenand_command[382] page 62, 2752512, 62 >>> 00000000: reading... >>> [ ?243.498535] onenand_command[382] page 0, 2621440, 0 >>> [ ?243.505249] onenand_wait: ECC error = 0x8488 >>> [ ?243.509552] onenand_command[382] page 1, 2621440, 1 >>> [ ?243.514587] onenand_wait: ECC error = 0x8488 >>> [ ?243.518890] onenand_command[382] page 2, 2621440, 2 >>> (...) >>> [ ?244.089050] onenand_command[382] page 62, 2621440, 62 >>> [ ?244.094268] onenand_wait: ECC error = 0x8448 >>> [ ?244.098602] onenand_command[382] page 63, 2621440, 63 >>> [ ?244.103790] onenand_wait: ECC error = 0x8488 >>> [ ?244.109191] onenand_command[382] page 0, 2752512, 0 >>> [ ?244.114196] onenand_wait: ECC error = 0x8488 >>> [ ?244.118469] onenand_command[382] page 1, 2752512, 1 >>> [ ?244.123535] onenand_wait: ECC error = 0x8488 >>> [ ?244.127838] onenand_command[382] page 2, 2752512, 2 >>> (...) >>> [ ?244.698150] onenand_command[382] page 62, 2752512, 62 >>> [ ?244.703369] onenand_wait: ECC error = 0x8448 >>> [ ?244.707672] onenand_command[382] page 63, 2752512, 63 >>> [ ?244.712890] onenand_wait: ECC error = 0x8488 >>> >>> ECC failed at 00000000 >>> 00000000: checking... >>> compare failed. seed 1804289383 >>> Byte 0x1 is 5a should be da >>> Byte 0x3 is 82 should be 92 >>> Byte 0x4 is 10 should be 1a >>> Byte 0x5 is 21 should be b7 >>> >>> --- end log nandtest fail --- >>> >>> >>> With this other code nandtest pass >>> >>> onenand_base.c >>> >>> 377: ? ? default: >>> ? ? ? ? ? ? ? ?block = onenand_block(this, addr); >>> ? ? ? ? ? ? ? ?page = (int) (addr >> this->page_shift); >>> /* (line disabled) ?page = (int) (addr - onenand_addr(this, block)) >> >>> this->page_shift; */ >>> >>> ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, >>> page, (int) >>> ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> >>> this->page_shift) & >>> ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); >>> >>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>> ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; >>> ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ >>> ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) >>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; >>> ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; >>> ? ? ? ? ? ? ? ?} >>> ? ? ? ? ? ? ? ?page &= this->page_mask; >>> ? ? ? ? ? ? ? ?break; >>> >>> --- start log nandtest pass --- >>> # nandtest -l 262144 /dev/mtd3 >>> ECC corrections: 0 >>> ECC failures ? : 33 >>> Bad blocks ? ? : 0 >>> BBT blocks ? ? : 0 >>> 00000000: writing... >>> [ 2024.624664] onenand_command[382] page 1280, 2621440, 0 >>> [ 2024.631530] onenand_command[382] page 1282, 2621440, 2 >>> [ 2024.637145] onenand_command[382] page 1284, 2621440, 4 >>> (...) >>> [ 2024.796813] onenand_command[382] page 1340, 2621440, 60 >>> [ 2024.802520] onenand_command[382] page 1342, 2621440, 62 >>> [ 2024.808593] onenand_command[382] page 1344, 2752512, 0 >>> [ 2024.814239] onenand_command[382] page 1346, 2752512, 2 >>> (...) >>> [ 2024.979644] onenand_command[382] page 1404, 2752512, 60 >>> [ 2024.985351] onenand_command[382] page 1406, 2752512, 62 >>> 00000000: reading... >>> [ 2024.990997] onenand_command[382] page 1280, 2621440, 0 >>> [ 2024.997985] onenand_command[382] page 1281, 2621440, 1 >>> [ 2025.003295] onenand_command[382] page 1282, 2621440, 2 >>> (...) >>> >>> [ 2025.326782] onenand_command[382] page 1342, 2621440, 62 >>> [ 2025.332214] onenand_command[382] page 1343, 2621440, 63 >>> [ 2025.338592] onenand_command[382] page 1344, 2752512, 0 >>> [ 2025.343811] onenand_command[382] page 1345, 2752512, 1 >>> [ 2025.349151] onenand_command[382] page 1346, 2752512, 2 >>> (...) >>> [ 2025.672576] onenand_command[382] page 1406, 2752512, 62 >>> [ 2025.677978] onenand_command[382] page 1407, 2752512, 63 >>> 00000000: checking... >>> Finished pass 1 successfully >>> --- end log nandtest pass --- >>> >>>> >>>> In my test environment, it displays the correct page number. >>>> (addr - onenand_addr(this, block) >> this->page_shift is same as >>>> '(addr >> this->page_shift) & this->page_mask'. >>>> >>> >>> Looks like page number is wrong ? >>> >>> Cheers, >>> >>> Enric >>> >>>> Thank you, >>>> Kyungmin Park >>>> >>>> On Fri, Apr 30, 2010 at 7:05 PM, Enric Balletb? i Serra >>>> wrote: >>>>> Hello all, >>>>> >>>>> After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: >>>>> Flex-OneNAND support) the onenand support for my device is broken. >>>>> >>>>> Before this commit when I run the nandtest program all is ok >>>>> --- >>>>> # nandtest /dev/mtd3 >>>>> ECC corrections: 0 >>>>> ECC failures ? : 0 >>>>> Bad blocks ? ? : 0 >>>>> BBT blocks ? ? : 0 >>>>> 002c0000: checking... >>>>> Finished pass 1 successfully >>>>> -- >>>>> >>>>> Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest >>>>> fails with: >>>>> --- >>>>> # nandtest /dev/mtd3 >>>>> ECC corrections: 0 >>>>> ECC failures ? : 0 >>>>> Bad blocks ? ? : 0 >>>>> BBT blocks ? ? : 0 >>>>> 00000000: reading... >>>>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>>>> ? ?( ... lots of ECC errors ... ) >>>>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>>>> ECC failed at 00000000 >>>>> 00000000: checking... >>>>> compare failed. seed 1804289383 >>>>> Byte 0x1 is 5a should be da >>>>> Byte 0x3 is 82 should be 92 >>>>> Byte 0x4 is 10 should be 1a >>>>> ? ?( ... ) >>>>> --- >>>>> >>>>> Investigating a little I see a significant difference introduced by >>>>> this patch. In line >>>>> >>>>> 347: ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >>>>> this->page_shift; ? (patch applied) >>>>> >>>>> instead of >>>>> >>>>> 347: ? ? ? ?page = (int) (addr >> this->page_shift); ?(without patch) >>>>> >>>>> I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced >>>>> the line 347 and now works again. Fantastic, but I suspect this is not >>>>> the proper solution (probably this breaks other onenands devices, I >>>>> can't test). >>>>> >>>>> I'm just introducing in OneNAND devices so anyone can help me to >>>>> understand and solve the problem ? Note that my device is a Numonyx >>>>> 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB >>>>> page ) >>>>> >>>>> Thanks in advance, >>>>> >>>>> ///:~Enric >>>>> >>>>> --- >>>>> diff --git a/drivers/mtd/onenand/onenand_base.c >>>>> b/drivers/mtd/onenand/onenand_base.c >>>>> index 081f97d..b1d50a3 100644 >>>>> --- a/drivers/mtd/onenand/onenand_base.c >>>>> +++ b/drivers/mtd/onenand/onenand_base.c >>>>> @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, >>>>> int cmd, loff_t addr, size_t le >>>>> >>>>> ? ? ? ?default: >>>>> ? ? ? ? ? ? ? ?block = (int) onenand_block(this, addr); >>>>> - ? ? ? ? ? ? ? page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; >>>>> + ? ? ? ? ? ? ? page = (int) (addr >> this->page_shift); >>>>> >>>>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>>>> --- >>>>> >>>>> ______________________________________________________ >>>>> Linux MTD discussion mailing list >>>>> http://lists.infradead.org/mailman/listinfo/linux-mtd/ >>>>> >>>> >>> -- >>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >>> the body of a message to majordomo at vger.kernel.org >>> More majordomo info at ?http://vger.kernel.org/majordomo-info.html >>> >> > From muehlfelder at enertex.de Wed May 12 06:48:36 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Wed, 12 May 2010 12:48:36 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <4BE96FD7.7020005@aimvalley.nl> References: <201005031505.18604.muehlfelder@enertex.de> <201005111009.06724.muehlfelder@enertex.de> <4BE96FD7.7020005@aimvalley.nl> Message-ID: <201005121248.36442.muehlfelder@enertex.de> Am Tuesday 11 May 2010 16:55:19 schrieb Norbert van Bolhuis: > Or can you put a kernel image on it beforehand ? are we talking about > deployed systems or to be deployed systems ? Of course the thoughts about UBIFS are only for future systems, that are not deployed yet. Also there is a newer version of the Atmel Sam-ba tool, that fixes the bad blocks problem. But because of the Sam-ba problem it seems to be hard to get a fix done for already deployed systems. > Anyway, if you switch to UBIFS and *can* put the kernel image on UBIFS > fatal bit flips in the uImage on bare NAND don't matter. > On the other hand: fatal bit flips in bootstrap/u-boot/u-boot_env will > still prevent the system to boot. So maybe also refreshing those images is > necessary. This is right. But as long as the kernel Image is about 1.5 MB and all the U-Boot stuff is only about 300 kB it would still increase the security. Furthermore UBIFS will have other advantages (e.g. lower mount times), too. > You need a recent linux kernel and u-boot for them to support UBIFS. > > Note that: if you would upgrade your system with a new u-boot/linux and > UBIFS i.s.o. JFFS2, *everything* on flash will change. If you want to do > this for deployed systems you need a huge upgrade script. This won't be done for deployed systems ;-) > I don't use NAND+UBIFS myself, so I have no experience there. > > The below pointers should have some relevant info though: > > - u-boot home-page: http://www.denx.de/wiki/U-Boot/WebHome > - u-boot mailing list: http://lists.denx.de/pipermail/u-boot/ > - u-boot source code GIT tree: > http://git.denx.de/cgi-bin/gitweb.cgi?p=u-boot.git;a=tree (checkout boards > with NAND and boot-from-NAND support) > - specialized GIT trees for NAND and UBI: > http://www.denx.de/wiki/U-Boot/Custodians Thanks, will have to take a look at it later. But for now it's a higher priority to reduce failure rate in already deployed systems. Regards Thorsten From tglx at linutronix.de Wed May 12 06:58:01 2010 From: tglx at linutronix.de (Thomas Gleixner) Date: Wed, 12 May 2010 12:58:01 +0200 (CEST) Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> <1273653341.22706.46.camel@localhost> Message-ID: On Wed, 12 May 2010, Brijesh Singh wrote: > On Wed, May 12, 2010 at 2:05 PM, Artem Bityutskiy wrote: > > On Wed, 2010-05-12 at 13:33 +0530, Brijesh Singh wrote: > >> 4) Any unclean un-mount will lead to flash scanning just as UBI. > > > > No! Why you have the log then? Unclean reboots are handled by the log. > > > > Scanning happens only when you have _corrupted_ SB, or corrupted cmt, or > > log. Then you fall-back to scanning. > > > >> Any thing goes bad, normal scanning becomes recovery. > >> 5) Not sure if log is required in first place. But it could be an option. > >> Is that correct? > > > > No, at least I did not suggest you to get rid of the log. It is needed > > to handle unclean reboots. > > Log is written for each EC or VID change. Frequency of log write is same as > the frequency of these headers. In case we keep both, there will be one log > write penalty per write/erase. So write performance will drop considerably. True, but the reliability will drop as well. Losing a log block is going to be fatal as there is no way to reconstruct while losing a single block in UBI is not inevitably fatal. Back then when UBI was designed / written we discussed a different approach of avoiding the full flash scan while keeping the reliability intact. Superblock in the first couple of erase blocks which points to a snapshot block. snapshot block(s) contain a compressed EC/VID header snapshot. A defined number of blocks in that snapshot is marked as NEED_SCAN. At the point of creating the snapshot these blocks are empty and belong to the blocks with the lowest erase count. Now when an UBI client (filesystem ...) requests an erase block one of those NEED_SCAN marked blocks is given out. Blocks which are handed back from the client for erasure which are not marked NEED_SCAN are erased and not given out as long as there are still enough empty blocks marked NEED_SCAN available. When we run out of NEED_SCAN marked blocks we write a new snapshot with a new set of NEED_SCAN blocks. So at attach time we read the snapshot and scan the few NEED_SCAN blocks. They are either empty or assigned to a volume. If assigned they can replace an already existing logical erase block reference in the snapshot, so we know that we need to put the original physical erase block into a lazy back ground scan list. With that approach we keep the reliability of UBI untouched with the penalty of scanning a limited number of erase blocks at attach time. That limits the number of writes to the snapshot / log significantly. For devices with a low write frequency that means that the snapshot block can be untouched for a very long time. The speed penalty is constant and does not depend on the number of log entries after the snapshot. Your full log approach is going to slower once the number of log entries is greater than the number of NEED_SCAN marked blocks. If we assume a page read time of 1ms and the number of NEED_SCAN blocks of 64, then we talk about a constant overhead of 64 ms. So lets look at the full picture: Flashsize: 1 GiB Eraseblocksize: 128 KiB Pagesize: 2 KiB Subpagesize: 1 KiB Number of erase blocks: 8192 Snapshot size per block: 16 Byte Full snapshot size: 128 KiB Full snapshot pages: 64 Number of NEED_SCAN blocks: 64 Number of blocks to scan for finding super block(s): 64 So with an assumption of page read time == 1ms the total time of building the initial data structures in RAM is 3 * 64ms. So yes, it _IS_ 3 times the time which we need for your log approach (assumed that the super block is first good block and the number of log entries after the snapshot is 0) So once we agree that a moveable super block is the correct way, the speed advantage is of your log approach is 64ms (still assumed that the number of log entry pages is 0) Now take the log entries into account. Once you have to read 64 pages worth of log entries, which happens in the above example after exaclty 128 entries, the speed advantage is exaclty zero. From that point on it's going to be worse. Thoughts ? tglx From muehlfelder at enertex.de Wed May 12 07:21:07 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Wed, 12 May 2010 13:21:07 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: References: <201005031505.18604.muehlfelder@enertex.de> <201005110959.36213.muehlfelder@enertex.de> Message-ID: <201005121321.07822.muehlfelder@enertex.de> Am Tuesday 11 May 2010 11:35:07 schrieb Ricard Wanderlof: > On Tue, 11 May 2010, Thorsten M?hlfelder wrote: > > But unfortunately the Sam-Ba 2.5 tool has a bug: it uses different bad > > block table structure and Linux refuses to read/write every block, that > > was written by Sam-Ba 2.5 because it recognizes them as bad blocks. > > So for now I have no idea what I can do to reduce the failing rate. > > I don't know if this is a good way, but you could patch your kernel so it > doesn't stop you from erasing/writing badblocks. So the only way to get bad blocks erased (scrubbed) in Linux is to have a patched kernel? This would be a problem, because I don't know any way of getting a new kernel to already deployed systems without deleting the Sam-ba bad blocks before. BTW: Atmel FAQ says the following about it: > SAM-BA v2.6 and NandFlash bad block management > > Question: > SAM-BA v2.6 finds a lot of bad blocks when erasing or programming the > NANDFLASH memory. Is it normal? How should I handle them? > > Answer: > This case usually appears when SAM-BA v2.5 (or older) was used to program > the NandFlash on the AT91SAM9260-EK or AT91SAM9263-EK boards. > > The blocks are not really bad, but data (especially ECC bytes) was written > in the spare area bytes reserved to tag bad blocks. So SAM-BA v2.6 detects > them as bad. To solve this problem and get an empty NandFlash without bad > blocks, follow these steps : > > - launch SAM-BA v2.6 GUI > - in the NANDFLASH tab, select the 'NandFlash Init' script and execute it > - in the TCL shell part of the GUI, type : > '::NANDFLASH::EraseAllNandFlashFull' WARNING : this procedure will erase > all data AND bad block tags too (spare area zones), thus manufacturer bad > block tagging will be lost. > > If you know which blocks were tagged bad by the manufacturer, you can > manually tag them again by typing '::NANDFLASH::TagBadBlock ' > in the SAM-BA TCL shell. So IMHO there are only 2 options: - Within a running Linux remove/erase all bad blocks from beginning of kernel image to end of the partition, test the erased area with nandtest and mark real bad blocks as bad, write the new kernel image to the right address again - Or write some tool, that can distinguish between real bad blocks and the Sam-ba 2.5 created bad blocks, unmark the false bad blocks. But perhaps this is not possible at all. Perhaps somebody knows where I can find detailed information about these "spare area bytes reserved to tag bad blocks"? As far as I understand this is the OOB area, which is 64 bytes on my NAND: /mtd_debug info /dev/mtd0 mtd.type = MTD_NANDFLASH mtd.flags = MTD_CAP_NANDFLASH mtd.size = 10485760 (10M) mtd.erasesize = 131072 (128K) mtd.writesize = 2048 (2K) mtd.oobsize = 64 regions = 0 Is the OOB part of a page or does each page have an extra OOB (2048+64 bytes)? Is the OOB located at the beginning or at the end of each page? Sorry for bothering you with all these questions, Thorsten > Then you could write your > own application which checks for bad blocks in the same way that the > Sam-Ba 2.5 tool does, which would allow you to rewrite everything written > by that tool. > > > At least there is still no board using Samsung flash that has failed and > > I hope all problems are related to the Micron flash. > > Even if you are not using jffs2, mtd will still perform single-bit error > correction thanks the the ECC algorithm, so you need to be unlucky enough > and get two bitflips within a 256 byte region for the system to fail. > > /Ricard From saeed.bishara at gmail.com Wed May 12 07:25:48 2010 From: saeed.bishara at gmail.com (saeed bishara) Date: Wed, 12 May 2010 14:25:48 +0300 Subject: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices In-Reply-To: <1273567389.2209.173.camel@localhost> References: <1273567389.2209.173.camel@localhost> Message-ID: On Tue, May 11, 2010 at 11:43 AM, Artem Bityutskiy wrote: > On Tue, 2010-05-11 at 11:28 +0300, saeed bishara wrote: >> hi, >> ? ?This patch is needed when using >4GiB nand partitions, any idea why >> it has not been merged yet? >> >> saeed >> >> On Fri, Apr 3, 2009 at 11:18 PM, Kevin Cernekee wrote: >> > Use the new kernel ioctls to erase/lock/unlock/readoob/writeoob >4GiB >> > flash devices. >> > >> > Use the new sysfs interface to query device info. >> > >> > Dependencies: >> > >> > "4GiB" extended ioctls: >> > http://lists.infradead.org/pipermail/linux-mtd/2009-April/025122.html >> > >> > Driver model updates 1/2: http://lkml.org/lkml/2009/4/3/477 >> > >> > Optional: Driver model updates 2/2: >> > http://lists.infradead.org/pipermail/linux-mtd/2009-March/025011.html >> > > > Dunno, I did not follow these. Kevin, would you re-send your patches > please? > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > attached updated version of the patch. also, another patch added to make the ubi format use the 64bit erase ioctl. saeed -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-mtd-utils-use-new-64-bit-ioctls-sysfs-tio-support-4G.patch Type: application/octet-stream Size: 44445 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 0002-Fix-the-ubiformat-with-devices-4GiB.patch Type: application/octet-stream Size: 1513 bytes Desc: not available URL: From jon at ringle.org Wed May 12 08:00:48 2010 From: jon at ringle.org (Jon Ringle) Date: Wed, 12 May 2010 08:00:48 -0400 Subject: Erase race? In-Reply-To: References: <1272373142.7750.5.camel@localhost> <1273635175.8881.3.camel@localhost.localdomain> Message-ID: On Wed, May 12, 2010 at 4:21 AM, massimo cirillo wrote: > Hi Jon, > I verified some particular error conditions regarding > the erase suspend in some nor flash chip. > Please tell me the part number of the flash you > are using and I will check it. Thanks. The boards that showed this failure have Intel JS28F256P30T95. However, we are planning on switching to Numonyx JS28F256P30TF due to upcoming obsolescence of the Intel part. Jon From dedekind1 at gmail.com Wed May 12 08:11:29 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 15:11:29 +0300 Subject: [PATCHv4] mtd-utils: use new 64-bit ioctls + sysfs to support >4GiB devices In-Reply-To: References: <1273567389.2209.173.camel@localhost> Message-ID: <1273666289.22706.79.camel@localhost> On Wed, 2010-05-12 at 14:25 +0300, saeed bishara wrote: > attached updated version of the patch. > also, another patch added to make the ubi format use the 64bit erase ioctl. It is better get them from Kevin. -- Best Regards, Artem Bityutskiy (????? ????????) From ricard.wanderlof at axis.com Wed May 12 08:22:19 2010 From: ricard.wanderlof at axis.com (Ricard Wanderlof) Date: Wed, 12 May 2010 14:22:19 +0200 (CEST) Subject: Some questions on bit-flips and JFFS2 In-Reply-To: <201005121321.07822.muehlfelder@enertex.de> References: <201005031505.18604.muehlfelder@enertex.de> <201005110959.36213.muehlfelder@enertex.de> <201005121321.07822.muehlfelder@enertex.de> Message-ID: On Wed, 12 May 2010, Thorsten M?hlfelder wrote: >> I don't know if this is a good way, but you could patch your kernel so it >> doesn't stop you from erasing/writing badblocks. > > So the only way to get bad blocks erased (scrubbed) in Linux is to have a > patched kernel? This would be a problem, because I don't know any way of > getting a new kernel to already deployed systems without deleting the Sam-ba > bad blocks before. Another option would be to write a kernel module that bypasses mtd. But the mtd write routine is very adament about not erasing bad blocks. > So IMHO there are only 2 options: > - Within a running Linux remove/erase all bad blocks from beginning of kernel > image to end of the partition, test the erased area with nandtest and mark > real bad blocks as bad, write the new kernel image to the right address again Testing for bad blocks is something you can't do in practice on a device. At the factory, AFAIK, they perform bad blocks tests while operating the chip at the limits of its specification, to try and catch all blocks which are marginal. Testing if such a block is 'bad' in an existing system most often doesn't give the expected result. On our development boards, it happens sometimes that someone manages to erase the whole flash including bad block markers, we then routinely just assume all blocks are good which works well enough in the lab, although I would never sell a product with a flash that had been erased that way. > - Or write some tool, that can distinguish between real bad blocks and the > Sam-ba 2.5 created bad blocks, unmark the false bad blocks. But perhaps this > is not possible at all. It depends on how exactly Sam-ba 2.5 overwrites the existing bad block markers. > Perhaps somebody knows where I can find detailed information about > these "spare area bytes reserved to tag bad blocks"? As far as I understand The nand flash data sheets from the manufacturers have information both on the memory array layout and how the bad blocks are marked. > Is the OOB part of a page or does each page have an extra OOB (2048+64 bytes)? The OOB (in this case) is an 'extra' 64 bytes per 2048 byte page. > Is the OOB located at the beginning or at the end of each page? Conceptually it is at the end, although it is normally accessed and read in a separate read operation. I think you can perform a sequential read on a nand flash which will read the page + oob in succession. /Ricard -- Ricard Wolf Wanderl?f ricardw(at)axis.com Axis Communications AB, Lund, Sweden www.axis.com Phone +46 46 272 2016 Fax +46 46 13 61 30 From maxcir at gmail.com Wed May 12 08:31:10 2010 From: maxcir at gmail.com (massimo cirillo) Date: Wed, 12 May 2010 14:31:10 +0200 Subject: Erase race? In-Reply-To: References: <1272373142.7750.5.camel@localhost> <1273635175.8881.3.camel@localhost.localdomain> Message-ID: Have you any evidence of erase suspend occurrence ? Could you try to disable erase suspend from cfi_cmdset_0001.c ? To this end, uncomment #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE #define CMDSET0001_DISABLE_WRITE_SUSPEND (they must be defined) at the beginning of the file and repeat your test. Bye 2010/5/12 Jon Ringle : > On Wed, May 12, 2010 at 4:21 AM, massimo cirillo wrote: >> Hi Jon, >> I verified some particular error conditions regarding >> the erase suspend in some nor flash chip. >> Please tell me the part number of the flash you >> are using and I will check it. > > Thanks. The boards that showed this failure have Intel JS28F256P30T95. > However, we are planning on switching to Numonyx JS28F256P30TF due to > upcoming obsolescence of the Intel part. > > Jon > From eballetbo at gmail.com Wed May 12 09:16:34 2010 From: eballetbo at gmail.com (=?UTF-8?Q?Enric_Balletb=C3=B2_i_Serra?=) Date: Wed, 12 May 2010 15:16:34 +0200 Subject: Possible bug in onenand_base ? In-Reply-To: References: Message-ID: I answer to myself. DDP (dual die plane) not implies 'ONENAND_HAS_2PLANE'. A device with a single die can also have '2 planes'. I'm right ? Sorry for these newbie questions, I'm just introducing to OneNAND devices. Cheers, Enric 2010/5/12 Enric Balletb? i Serra : > Hello, > > I have a bit of time to investigate more. > > I have two boards with two different OneNAND chips populated. > > The first one is a dual Die Plan 4-Gbit (2 dice of 2-Gbit) > > [ ? 26.406890] Muxed OneNAND(DDP) 512MB 1.8V 16-bit (0x58) > [ ? 26.412170] OneNAND version = 0x0031 > [ ? 26.415771] Chip support all block unlock > [ ? 26.419830] Chip has 2 plane > > The second is a single die of 2-Gbit. > > [ ? 32.897735] Muxed OneNAND 256MB 1.8V 16-bit (0x40) > [ ? 32.902557] OneNAND version = 0x0031 > [ ? 32.906188] Chip support all block unlock > [ ? 32.910247] Chip has 2 plane > > As I understand the bit 3 of DEVICE_ID register indicates if package > is a single-die or a dual-die, so > > - Muxed OneNAND(DDP) 512MB 1.8V 16-bit -> device id: 0x58 -> bit 3 is > 1 -> dual-die > - Muxed OneNAND 256MB 1.8V 16-bit -> device id: 0x40 -> bit 3 is 0 ->single-die > > The question is, why those devices are reporting 'Chip has 2 plane' ? > > Sorry if this is a trivial question but I'm not sure about DDP and '2 > plane' concepts. Are the same ? > > Cheers, > > Enric > > 2010/5/6 Enric Balletb? i Serra : >> Hi, >> >> 2010/5/6 Kyungmin Park : >>> Hi, >>> >>> What's your chip version? maybe some mis-probe it seems to be probed >>> at 4KiB pagesize OneNAND. >> >> Is a 4-Gbit DDP OneNAND device from Numonyx composed of two 2-Gbit 2KB >> page dice stacked together, the device is equipped with two DataRAMs, >> and two-plane NAND Flash memory array, >> >> These two component enables simultaneous program of 4KiB ( >> CONFIG_MTD_ONENAND_2X_PROGRAM) >> >> Cheers, >> >> Enric >> >>> >>> Thank you, >>> Kyungmin Park >>> >>> On Thu, May 6, 2010 at 8:22 PM, Enric Balletb? i Serra >>> wrote: >>>> Hi, >>>> >>>> 2010/5/6 Kyungmin Park : >>>>> Hi, >>>>> >>>>> Can you add this statement at below the code? >>>>> printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, page, (int) >>>>> onenand_addr(this, block), ((int) addr >> this->page_shift) & >>>>> this->page_mask); >>>> >>>> Yes, >>>> >>>> With this code nandtest fails: >>>> >>>> onenand_base.c >>>> >>>> 377: ? ? default: >>>> ? ? ? ? ? ? ? ?block = onenand_block(this, addr); >>>> /* ?(line disabled) ? page = (int) (addr >> this->page_shift); */ >>>> ? ? ? ? ? ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >>>> this->page_shift; >>>> >>>> ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, >>>> page, (int) >>>> ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> >>>> this->page_shift) & >>>> ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); >>>> >>>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>>> ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; >>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ >>>> ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) >>>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; >>>> ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; >>>> ? ? ? ? ? ? ? ?} >>>> ? ? ? ? ? ? ? ?page &= this->page_mask; >>>> ? ? ? ? ? ? ? ?break; >>>> >>>> >>>> --- start log nandtest fail --- >>>> # nandtest -l 262144 /dev/mtd3 >>>> ECC corrections: 0 >>>> ECC failures ? : 0 >>>> Bad blocks ? ? : 0 >>>> BBT blocks ? ? : 0 >>>> 00000000: writing... >>>> [ ?243.144287] onenand_command[382] page 0, 2621440, 0 >>>> [ ?243.150787] onenand_command[382] page 2, 2621440, 2 >>>> [ ?243.156158] onenand_command[382] page 4, 2621440, 4 >>>> (...) >>>> [ ?243.310729] onenand_command[382] page 60, 2621440, 60 >>>> [ ?243.316223] onenand_command[382] page 62, 2621440, 62 >>>> [ ?243.322204] onenand_command[382] page 0, 2752512, 0 >>>> [ ?243.327636] onenand_command[382] page 2, 2752512, 2 >>>> [ ?243.332977] onenand_command[382] page 4, 2752512, 4 >>>> (...) >>>> [ ?243.487487] onenand_command[382] page 60, 2752512, 60 >>>> [ ?243.493041] onenand_command[382] page 62, 2752512, 62 >>>> 00000000: reading... >>>> [ ?243.498535] onenand_command[382] page 0, 2621440, 0 >>>> [ ?243.505249] onenand_wait: ECC error = 0x8488 >>>> [ ?243.509552] onenand_command[382] page 1, 2621440, 1 >>>> [ ?243.514587] onenand_wait: ECC error = 0x8488 >>>> [ ?243.518890] onenand_command[382] page 2, 2621440, 2 >>>> (...) >>>> [ ?244.089050] onenand_command[382] page 62, 2621440, 62 >>>> [ ?244.094268] onenand_wait: ECC error = 0x8448 >>>> [ ?244.098602] onenand_command[382] page 63, 2621440, 63 >>>> [ ?244.103790] onenand_wait: ECC error = 0x8488 >>>> [ ?244.109191] onenand_command[382] page 0, 2752512, 0 >>>> [ ?244.114196] onenand_wait: ECC error = 0x8488 >>>> [ ?244.118469] onenand_command[382] page 1, 2752512, 1 >>>> [ ?244.123535] onenand_wait: ECC error = 0x8488 >>>> [ ?244.127838] onenand_command[382] page 2, 2752512, 2 >>>> (...) >>>> [ ?244.698150] onenand_command[382] page 62, 2752512, 62 >>>> [ ?244.703369] onenand_wait: ECC error = 0x8448 >>>> [ ?244.707672] onenand_command[382] page 63, 2752512, 63 >>>> [ ?244.712890] onenand_wait: ECC error = 0x8488 >>>> >>>> ECC failed at 00000000 >>>> 00000000: checking... >>>> compare failed. seed 1804289383 >>>> Byte 0x1 is 5a should be da >>>> Byte 0x3 is 82 should be 92 >>>> Byte 0x4 is 10 should be 1a >>>> Byte 0x5 is 21 should be b7 >>>> >>>> --- end log nandtest fail --- >>>> >>>> >>>> With this other code nandtest pass >>>> >>>> onenand_base.c >>>> >>>> 377: ? ? default: >>>> ? ? ? ? ? ? ? ?block = onenand_block(this, addr); >>>> ? ? ? ? ? ? ? ?page = (int) (addr >> this->page_shift); >>>> /* (line disabled) ?page = (int) (addr - onenand_addr(this, block)) >> >>>> this->page_shift; */ >>>> >>>> ? ? ? ? ? ? ? ?printk("%s[%d] page %d, %d, %d\n", __func__, __LINE__, >>>> page, (int) >>>> ? ? ? ? ? ? ? ? ? ? ? ?onenand_addr(this, block), ((int) addr >> >>>> this->page_shift) & >>>> ? ? ? ? ? ? ? ? ? ? ? ?this->page_mask); >>>> >>>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>>> ? ? ? ? ? ? ? ? ? ? ? ?block &= ~1; >>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Is it the odd plane? */ >>>> ? ? ? ? ? ? ? ? ? ? ? ?if (addr & this->writesize) >>>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?block++; >>>> ? ? ? ? ? ? ? ? ? ? ? ?page >>= 1; >>>> ? ? ? ? ? ? ? ?} >>>> ? ? ? ? ? ? ? ?page &= this->page_mask; >>>> ? ? ? ? ? ? ? ?break; >>>> >>>> --- start log nandtest pass --- >>>> # nandtest -l 262144 /dev/mtd3 >>>> ECC corrections: 0 >>>> ECC failures ? : 33 >>>> Bad blocks ? ? : 0 >>>> BBT blocks ? ? : 0 >>>> 00000000: writing... >>>> [ 2024.624664] onenand_command[382] page 1280, 2621440, 0 >>>> [ 2024.631530] onenand_command[382] page 1282, 2621440, 2 >>>> [ 2024.637145] onenand_command[382] page 1284, 2621440, 4 >>>> (...) >>>> [ 2024.796813] onenand_command[382] page 1340, 2621440, 60 >>>> [ 2024.802520] onenand_command[382] page 1342, 2621440, 62 >>>> [ 2024.808593] onenand_command[382] page 1344, 2752512, 0 >>>> [ 2024.814239] onenand_command[382] page 1346, 2752512, 2 >>>> (...) >>>> [ 2024.979644] onenand_command[382] page 1404, 2752512, 60 >>>> [ 2024.985351] onenand_command[382] page 1406, 2752512, 62 >>>> 00000000: reading... >>>> [ 2024.990997] onenand_command[382] page 1280, 2621440, 0 >>>> [ 2024.997985] onenand_command[382] page 1281, 2621440, 1 >>>> [ 2025.003295] onenand_command[382] page 1282, 2621440, 2 >>>> (...) >>>> >>>> [ 2025.326782] onenand_command[382] page 1342, 2621440, 62 >>>> [ 2025.332214] onenand_command[382] page 1343, 2621440, 63 >>>> [ 2025.338592] onenand_command[382] page 1344, 2752512, 0 >>>> [ 2025.343811] onenand_command[382] page 1345, 2752512, 1 >>>> [ 2025.349151] onenand_command[382] page 1346, 2752512, 2 >>>> (...) >>>> [ 2025.672576] onenand_command[382] page 1406, 2752512, 62 >>>> [ 2025.677978] onenand_command[382] page 1407, 2752512, 63 >>>> 00000000: checking... >>>> Finished pass 1 successfully >>>> --- end log nandtest pass --- >>>> >>>>> >>>>> In my test environment, it displays the correct page number. >>>>> (addr - onenand_addr(this, block) >> this->page_shift is same as >>>>> '(addr >> this->page_shift) & this->page_mask'. >>>>> >>>> >>>> Looks like page number is wrong ? >>>> >>>> Cheers, >>>> >>>> Enric >>>> >>>>> Thank you, >>>>> Kyungmin Park >>>>> >>>>> On Fri, Apr 30, 2010 at 7:05 PM, Enric Balletb? i Serra >>>>> wrote: >>>>>> Hello all, >>>>>> >>>>>> After commit 5988af2319781bc8e0ce418affec4e09cfa77907 (mtd: >>>>>> Flex-OneNAND support) the onenand support for my device is broken. >>>>>> >>>>>> Before this commit when I run the nandtest program all is ok >>>>>> --- >>>>>> # nandtest /dev/mtd3 >>>>>> ECC corrections: 0 >>>>>> ECC failures ? : 0 >>>>>> Bad blocks ? ? : 0 >>>>>> BBT blocks ? ? : 0 >>>>>> 002c0000: checking... >>>>>> Finished pass 1 successfully >>>>>> -- >>>>>> >>>>>> Introduced commit 5988af2319781bc8e0ce418affec4e09cfa7790 the nandtest >>>>>> fails with: >>>>>> --- >>>>>> # nandtest /dev/mtd3 >>>>>> ECC corrections: 0 >>>>>> ECC failures ? : 0 >>>>>> Bad blocks ? ? : 0 >>>>>> BBT blocks ? ? : 0 >>>>>> 00000000: reading... >>>>>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>>>>> ? ?( ... lots of ECC errors ... ) >>>>>> [ ?299.092041] onenand_wait: ECC error = 0x8488 >>>>>> ECC failed at 00000000 >>>>>> 00000000: checking... >>>>>> compare failed. seed 1804289383 >>>>>> Byte 0x1 is 5a should be da >>>>>> Byte 0x3 is 82 should be 92 >>>>>> Byte 0x4 is 10 should be 1a >>>>>> ? ?( ... ) >>>>>> --- >>>>>> >>>>>> Investigating a little I see a significant difference introduced by >>>>>> this patch. In line >>>>>> >>>>>> 347: ? ? ? ?page = (int) (addr - onenand_addr(this, block)) >> >>>>>> this->page_shift; ? (patch applied) >>>>>> >>>>>> instead of >>>>>> >>>>>> 347: ? ? ? ?page = (int) (addr >> this->page_shift); ?(without patch) >>>>>> >>>>>> I applied commit 5988af2319781bc8e0ce418affec4e09cfa7790 and replaced >>>>>> the line 347 and now works again. Fantastic, but I suspect this is not >>>>>> the proper solution (probably this breaks other onenands devices, I >>>>>> can't test). >>>>>> >>>>>> I'm just introducing in OneNAND devices so anyone can help me to >>>>>> understand and solve the problem ? Note that my device is a Numonyx >>>>>> 4-Gbit DDP (DUAL DIE PLAN) OneNAND flash memory ( 2 dice of 2Gb, 2KB >>>>>> page ) >>>>>> >>>>>> Thanks in advance, >>>>>> >>>>>> ///:~Enric >>>>>> >>>>>> --- >>>>>> diff --git a/drivers/mtd/onenand/onenand_base.c >>>>>> b/drivers/mtd/onenand/onenand_base.c >>>>>> index 081f97d..b1d50a3 100644 >>>>>> --- a/drivers/mtd/onenand/onenand_base.c >>>>>> +++ b/drivers/mtd/onenand/onenand_base.c >>>>>> @@ -344,7 +344,7 @@ static int onenand_command(struct mtd_info *mtd, >>>>>> int cmd, loff_t addr, size_t le >>>>>> >>>>>> ? ? ? ?default: >>>>>> ? ? ? ? ? ? ? ?block = (int) onenand_block(this, addr); >>>>>> - ? ? ? ? ? ? ? page = (int) (addr - onenand_addr(this, block)) >> this->page_shift; >>>>>> + ? ? ? ? ? ? ? page = (int) (addr >> this->page_shift); >>>>>> >>>>>> ? ? ? ? ? ? ? ?if (ONENAND_IS_2PLANE(this)) { >>>>>> ? ? ? ? ? ? ? ? ? ? ? ?/* Make the even block number */ >>>>>> --- >>>>>> >>>>>> ______________________________________________________ >>>>>> Linux MTD discussion mailing list >>>>>> http://lists.infradead.org/mailman/listinfo/linux-mtd/ >>>>>> >>>>> >>>> -- >>>> To unsubscribe from this list: send the line "unsubscribe linux-omap" in >>>> the body of a message to majordomo at vger.kernel.org >>>> More majordomo info at ?http://vger.kernel.org/majordomo-info.html >>>> >>> >> > From PeterHuewe at gmx.de Wed May 12 18:06:54 2010 From: PeterHuewe at gmx.de (Peter Huewe) Date: Thu, 13 May 2010 00:06:54 +0200 Subject: [PATCH] mtd: Move function mtd_to_flctl to fix build failure Message-ID: <201005130006.54616.PeterHuewe@gmx.de> From: Peter Huewe This patch fixes a build failure[1] by simply moving the function mtd_to_flctl beneath the definition of sh_flctl which it uses. BF introduced by patch 'mtd/nand/sh_flctl: Replace the dangerous mtd_to_flctl macro' (67026418) Signed-off-by: Peter Huewe --- KernelVersion: linux-next of 20100512 References: [1] http://kisskb.ellerman.id.au/kisskb/buildresult/2601986/ include/linux/mtd/sh_flctl.h | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/include/linux/mtd/sh_flctl.h b/include/linux/mtd/sh_flctl.h index 178b5c2..d7b686a 100644 --- a/include/linux/mtd/sh_flctl.h +++ b/include/linux/mtd/sh_flctl.h @@ -93,11 +93,6 @@ #define INIT_FL4ECCRESULT_VAL 0x03FF03FF #define LOOP_TIMEOUT_MAX 0x00010000 -static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo) -{ - return container_of(mtdinfo, struct sh_flctl, mtd); -} - struct sh_flctl { struct mtd_info mtd; struct nand_chip chip; @@ -128,4 +123,9 @@ struct sh_flctl_platform_data { unsigned has_hwecc:1; }; +static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo) +{ + return container_of(mtdinfo, struct sh_flctl, mtd); +} + #endif /* __SH_FLCTL_H__ */ -- 1.6.4.4 From hartleys at visionengravers.com Wed May 12 19:13:45 2010 From: hartleys at visionengravers.com (H Hartley Sweeten) Date: Wed, 12 May 2010 18:13:45 -0500 Subject: Question about flash_info utility Message-ID: <0D753D10438DA54287A00B0270842697636EF69B4A@AUSP01VMBX24.collaborationhost.net> Hello all, I'm trying to finalize my flash on a new product and have a question about the mtd utilities, specifically the 'flash_info' utility. When my system boots I get this as part of the boot messages: physmap platform flash device: 04000000 at 60000000 physmap-flash.0: Found 1 x16 devices at 0x0 in 16-bit bank physmap-flash.0: Found an alias at 0x2000000 for the chip at 0x0 Intel/Sharp Extended Query Table at 0x010A Intel/Sharp Extended Query Table at 0x010A Intel/Sharp Extended Query Table at 0x010A Intel/Sharp Extended Query Table at 0x010A Intel/Sharp Extended Query Table at 0x010A Using buffer write method Using auto-unlock on power-up/resume cfi_cmdset_0001: Erase suspend on write enabled erase region 0: offset=0x0,size=0x20000,blocks=255 erase region 1: offset=0x1fe0000,size=0x8000,blocks=4 cmdlinepart partition parsing not available Searching for RedBoot partition table in physmap-flash.0 at offset 0x1fe0000 4 RedBoot partitions found on MTD device physmap-flash.0 Creating 4 MTD partitions on "physmap-flash.0": 0x000000000000-0x000000040000 : "RedBoot" 0x000000040000-0x000001fe0000 : "unallocated" 0x000001fe0000-0x000001ff8000 : "FIS directory" 0x000001ff8000-0x000002000000 : "RedBoot config" And /proc/mtd shows: / # cat /proc/mtd dev: size erasesize name mtd0: 00040000 00020000 "RedBoot" mtd1: 01fa0000 00020000 "unallocated" mtd2: 00018000 00008000 "FIS directory" mtd3: 00008000 00008000 "RedBoot config" But when I run the 'flash_info' utility on mtd[0-3] I get: / # flash_info /dev/mtd0 Device /dev/mtd0 has 0 erase regions / # flash_info /dev/mtd1 Device /dev/mtd1 has 0 erase regions / # flash_info /dev/mtd2 Device /dev/mtd2 has 0 erase regions / # flash_info /dev/mtd3 Device /dev/mtd3 has 0 erase regions Based on the erasesize they should be 2, 253, 3, and 1. The 'mtd_debug' utility does appear to show the correct information: / # mtd_debug info /dev/mtd0 mtd.type = MTD_NORFLASH mtd.flags = MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_STUPID_LOCK mtd.size = 262144 (256K) mtd.erasesize = 131072 (128K) mtd.writesize = 1 mtd.oobsize = 0 regions = 0 / # mtd_debug info /dev/mtd1 mtd.type = MTD_NORFLASH mtd.flags = MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_STUPID_LOCK mtd.size = 33161216 (31M) mtd.erasesize = 131072 (128K) mtd.writesize = 1 mtd.oobsize = 0 regions = 0 / # mtd_debug info /dev/mtd2 mtd.type = MTD_NORFLASH mtd.flags = MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_STUPID_LOCK mtd.size = 98304 (96K) mtd.erasesize = 32768 (32K) mtd.writesize = 1 mtd.oobsize = 0 regions = 0 / # mtd_debug info /dev/mtd3 mtd.type = MTD_NORFLASH mtd.flags = MTD_WRITEABLE | MTD_BIT_WRITEABLE | MTD_STUPID_LOCK mtd.size = 32768 (32K) mtd.erasesize = 32768 (32K) mtd.writesize = 1 mtd.oobsize = 0 regions = 0 Any ideas what's wrong? Regards, Hartley From hartleys at visionengravers.com Wed May 12 19:23:10 2010 From: hartleys at visionengravers.com (H Hartley Sweeten) Date: Wed, 12 May 2010 18:23:10 -0500 Subject: Question about flash_info utility In-Reply-To: <0D753D10438DA54287A00B0270842697636EF69B4A@AUSP01VMBX24.collaborationhost.net> References: <0D753D10438DA54287A00B0270842697636EF69B4A@AUSP01VMBX24.collaborationhost.net> Message-ID: <0D753D10438DA54287A00B0270842697636EF69B58@AUSP01VMBX24.collaborationhost.net> On Wednesday, May 12, 2010 4:14 PM, H Hartley Sweeten wrote: > Hello all, > > I'm trying to finalize my flash on a new product and have a > question about the mtd utilities, specifically the 'flash_info' > utility. Oops... Misunderstood what flash_info is reporting. Since all my mtd nodes exist in uniform erase block regions I guess the "0 erase regions" result is appropriate. Maybe the message should be changed to reflect this? Regards, Hartley From cernekee at gmail.com Wed May 12 22:22:57 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Wed, 12 May 2010 19:22:57 -0700 Subject: [PATCH v5 1/3] mtd-utils: update to latest mtd-abi.h from kernel.org Message-ID: Signed-off-by: Kevin Cernekee --- include/mtd/mtd-abi.h | 89 ++++++++++++++++++++++++++++-------------------- 1 files changed, 52 insertions(+), 37 deletions(-) diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index 86defe1..c6954ed 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -1,23 +1,35 @@ /* - * $Id: mtd-abi.h,v 1.13 2005/11/07 11:14:56 gleixner Exp $ - * * Portions of MTD ABI definition which are shared by kernel and user space */ #ifndef __MTD_ABI_H__ #define __MTD_ABI_H__ +#include + struct erase_info_user { - uint32_t start; - uint32_t length; + __u32 start; + __u32 length; +}; + +struct erase_info_user64 { + __u64 start; + __u64 length; }; struct mtd_oob_buf { - uint32_t start; - uint32_t length; + __u32 start; + __u32 length; unsigned char *ptr; }; +struct mtd_oob_buf64 { + __u64 start; + __u32 pad; + __u32 length; + __u64 usr_ptr; +}; + #define MTD_ABSENT 0 #define MTD_RAM 1 #define MTD_ROM 2 @@ -29,7 +41,7 @@ struct mtd_oob_buf { #define MTD_WRITEABLE 0x400 /* Device is writeable */ #define MTD_BIT_WRITEABLE 0x800 /* Single bits can be flipped */ #define MTD_NO_ERASE 0x1000 /* No erase necessary */ -#define MTD_STUPID_LOCK 0x2000 /* Always locked after reset */ +#define MTD_POWERUP_LOCK 0x2000 /* Always locked after reset */ // Some common devices / combinations of capabilities #define MTD_CAP_ROM 0 @@ -50,30 +62,30 @@ struct mtd_oob_buf { #define MTD_OTP_USER 2 struct mtd_info_user { - uint8_t type; - uint32_t flags; - uint32_t size; // Total size of the MTD - uint32_t erasesize; - uint32_t writesize; - uint32_t oobsize; // Amount of OOB data per block (e.g. 16) + __u8 type; + __u32 flags; + __u32 size; // Total size of the MTD + __u32 erasesize; + __u32 writesize; + __u32 oobsize; // Amount of OOB data per block (e.g. 16) /* The below two fields are obsolete and broken, do not use them * (TODO: remove at some point) */ - uint32_t ecctype; - uint32_t eccsize; + __u32 ecctype; + __u32 eccsize; }; struct region_info_user { - uint32_t offset; /* At which this region starts, + __u32 offset; /* At which this region starts, * from the beginning of the MTD */ - uint32_t erasesize; /* For this region */ - uint32_t numblocks; /* Number of blocks in this region */ - uint32_t regionindex; + __u32 erasesize; /* For this region */ + __u32 numblocks; /* Number of blocks in this region */ + __u32 regionindex; }; struct otp_info { - uint32_t start; - uint32_t length; - uint32_t locked; + __u32 start; + __u32 length; + __u32 locked; }; #define MEMGETINFO _IOR('M', 1, struct mtd_info_user) @@ -86,8 +98,8 @@ struct otp_info { #define MEMGETREGIONINFO _IOWR('M', 8, struct region_info_user) #define MEMSETOOBSEL _IOW('M', 9, struct nand_oobinfo) #define MEMGETOOBSEL _IOR('M', 10, struct nand_oobinfo) -#define MEMGETBADBLOCK _IOW('M', 11, loff_t) -#define MEMSETBADBLOCK _IOW('M', 12, loff_t) +#define MEMGETBADBLOCK _IOW('M', 11, __kernel_loff_t) +#define MEMSETBADBLOCK _IOW('M', 12, __kernel_loff_t) #define OTPSELECT _IOR('M', 13, int) #define OTPGETREGIONCOUNT _IOW('M', 14, int) #define OTPGETREGIONINFO _IOW('M', 15, struct otp_info) @@ -95,21 +107,24 @@ struct otp_info { #define ECCGETLAYOUT _IOR('M', 17, struct nand_ecclayout) #define ECCGETSTATS _IOR('M', 18, struct mtd_ecc_stats) #define MTDFILEMODE _IO('M', 19) +#define MEMERASE64 _IOW('M', 20, struct erase_info_user64) +#define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) +#define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) /* * Obsolete legacy interface. Keep it in order not to break userspace * interfaces */ struct nand_oobinfo { - uint32_t useecc; - uint32_t eccbytes; - uint32_t oobfree[8][2]; - uint32_t eccpos[32]; + __u32 useecc; + __u32 eccbytes; + __u32 oobfree[8][2]; + __u32 eccpos[32]; }; struct nand_oobfree { - uint32_t offset; - uint32_t length; + __u32 offset; + __u32 length; }; #define MTD_MAX_OOBFREE_ENTRIES 8 @@ -118,9 +133,9 @@ struct nand_oobfree { * diagnosis and to allow creation of raw images */ struct nand_ecclayout { - uint32_t eccbytes; - uint32_t eccpos[64]; - uint32_t oobavail; + __u32 eccbytes; + __u32 eccpos[64]; + __u32 oobavail; struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES]; }; @@ -133,10 +148,10 @@ struct nand_ecclayout { * @bbtblocks: number of blocks reserved for bad block tables */ struct mtd_ecc_stats { - uint32_t corrected; - uint32_t failed; - uint32_t badblocks; - uint32_t bbtblocks; + __u32 corrected; + __u32 failed; + __u32 badblocks; + __u32 bbtblocks; }; /* -- 1.6.5 From cernekee at gmail.com Wed May 12 22:24:30 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Wed, 12 May 2010 19:24:30 -0700 Subject: [PATCH v5 3/3] mtd-utils: clean up compiler warnings In-Reply-To: References: Message-ID: <4b38adf0a5ec5a3a1c7ef85f64585cfee66c1921@localhost.localdomain> Seen on gcc 4.2.4 IA32: flashcp.c:255:2: warning: #warning "Check for smaller erase regions" nftl_format.c:214: warning: assignment discards qualifiers from pointer target type nftl_format.c:219: warning: assignment discards qualifiers from pointer target type serve_image.c:129: warning: format ???%ld??? expects type ???long int???, but argument 3 has type ???__off64_t??? fec.c:120: warning: initialization discards qualifiers from pointer target type fec.c:417: warning: passing argument 2 of ???my_malloc??? discards qualifiers from pointer target type recv_image.c:164: warning: comparison of unsigned expression < 0 is always false recv_image.c:59: warning: ???start_seq??? may be used uninitialized in this function recv_image.c:56: warning: ???fec??? may be used uninitialized in this function recv_image.c:49: warning: ???image_crc??? may be used uninitialized in this function sumtool.c:112: warning: initialization discards qualifiers from pointer target type sumtool.c:115: warning: initialization discards qualifiers from pointer target type mkfs.ubifs.c:1171: warning: format ???%lu??? expects type ???long unsigned int???, but argument 4 has type ???ino_t??? mkfs.ubifs.c:1171: warning: format ???%lu??? expects type ???long unsigned int???, but argument 6 has type ???ino_t??? Signed-off-by: Kevin Cernekee --- fec.c | 6 +++--- mkfs.ubifs/mkfs.ubifs.c | 4 ++-- nftl_format.c | 3 ++- recv_image.c | 8 ++++---- serve_image.c | 5 +++-- sumtool.c | 4 ++-- 6 files changed, 16 insertions(+), 14 deletions(-) diff --git a/fec.c b/fec.c index 6d9020f..bee371e 100644 --- a/fec.c +++ b/fec.c @@ -114,7 +114,7 @@ typedef unsigned short gf; * Primitive polynomials - see Lin & Costello, Appendix A, * and Lee & Messerschmitt, p. 453. */ -static char *allPp[] = { /* GF_BITS polynomial */ +static const char *allPp[] = { /* GF_BITS polynomial */ NULL, /* 0 no code */ NULL, /* 1 no code */ "111", /* 2 1+x+x^2 */ @@ -226,7 +226,7 @@ gf_mul(x,y) * one place. */ static void * -my_malloc(int sz, char *err_string) +my_malloc(int sz, const char *err_string) { void *p = malloc( sz ); if (p == NULL) { @@ -247,7 +247,7 @@ generate_gf(void) { int i; gf mask; - char *Pp = allPp[GF_BITS] ; + const char *Pp = allPp[GF_BITS] ; mask = 1; /* x ** 0 = 1 */ gf_exp[GF_BITS] = 0; /* will be updated at the end of the 1st loop */ diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c index e4b4e3c..4d1971c 100644 --- a/mkfs.ubifs/mkfs.ubifs.c +++ b/mkfs.ubifs/mkfs.ubifs.c @@ -1168,8 +1168,8 @@ static int add_dent_node(ino_t dir_inum, const char *name, ino_t inum, char *kname; int len; - dbg_msg(3, "%s ino %lu type %u dir ino %lu", name, inum, - (unsigned)type, dir_inum); + dbg_msg(3, "%s ino %lu type %u dir ino %lu", name, (unsigned long)inum, + (unsigned)type, (unsigned long)dir_inum); memset(dent, 0, UBIFS_DENT_NODE_SZ); dname.name = (void *)name; diff --git a/nftl_format.c b/nftl_format.c index 42949a0..167098a 100644 --- a/nftl_format.c +++ b/nftl_format.c @@ -202,7 +202,8 @@ int main(int argc, char **argv) long MediaUnitOff1 = 0, MediaUnitOff2 = 0; unsigned char oobbuf[16]; struct mtd_oob_buf oob = {0, 16, oobbuf}; - char *mtddevice, *nftl; + char *mtddevice; + const char *nftl; int c, do_inftl = 0, do_bbt = 0; diff --git a/recv_image.c b/recv_image.c index d65aa2a..6ff0bce 100644 --- a/recv_image.c +++ b/recv_image.c @@ -39,24 +39,24 @@ int main(int argc, char **argv) struct addrinfo *runp; int ret; int sock; - size_t len; + ssize_t len; int flfd; struct mtd_info_user meminfo; unsigned char *eb_buf, *decode_buf, **src_pkts; int nr_blocks = 0; int pkts_per_block; int block_nr = -1; - uint32_t image_crc; + uint32_t image_crc = 0; int total_pkts = 0; int ignored_pkts = 0; loff_t mtdoffset = 0; int badcrcs = 0; int duplicates = 0; int file_mode = 0; - struct fec_parms *fec; + struct fec_parms *fec = NULL; int i; struct eraseblock *eraseblocks = NULL; - uint32_t start_seq; + uint32_t start_seq = 0; struct timeval start, now; unsigned long fec_time = 0, flash_time = 0, crc_time = 0, rflash_time = 0, erase_time = 0, net_time = 0; diff --git a/serve_image.c b/serve_image.c index adb4869..292e7f6 100644 --- a/serve_image.c +++ b/serve_image.c @@ -125,8 +125,9 @@ int main(int argc, char **argv) } if (st.st_size % erasesize) { - fprintf(stderr, "Image size %ld bytes is not a multiple of erasesize %d bytes\n", - st.st_size, erasesize); + fprintf(stderr, "Image size %lld bytes is not a multiple " + "of erasesize %d bytes\n", + (long long)st.st_size, erasesize); exit(1); } image = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, rfd, 0); diff --git a/sumtool.c b/sumtool.c index 6bb7168..9a2029f 100644 --- a/sumtool.c +++ b/sumtool.c @@ -88,7 +88,7 @@ static struct option long_options[] = { {NULL, 0, NULL, 0} }; -static char *helptext = +static const char *helptext = "Usage: sumtool [OPTIONS] -i inputfile -o outputfile\n\n" "Convert the input JFFS2 image to a summarized JFFS2 image\n" "Summary makes mounting faster - if summary support enabled in your kernel\n\n" @@ -112,7 +112,7 @@ static char *helptext = " eraseblock\n\n"; -static char *revtext = "$Revision: 1.9 $"; +static const char *revtext = "$Revision: 1.9 $"; static unsigned char ffbuf[16] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, -- 1.6.5 From cernekee at gmail.com Wed May 12 22:23:42 2010 From: cernekee at gmail.com (Kevin Cernekee) Date: Wed, 12 May 2010 19:23:42 -0700 Subject: [PATCH v5 2/3] mtd-utils: support >4GiB devices In-Reply-To: References: Message-ID: <5e05b5a05a30b2dc2035b87a60bb82f3137174cb@localhost.localdomain> This patch updates the following programs to handle >4GiB flash devices: flash_erase flash_eraseall flashcp mtd_debug nanddump nandtest nandwrite It also lays the groundwork for >4GiB support in: flash_lock flash_unlock The latter two utilities would require MEMLOCK64 / MEMUNLOCK64 functionality on the kernel side (currently unimplemented). For now they still use MEMLOCK / MEMUNLOCK and cannot access blocks above 4GiB. By default, the compatibility layer (mtd_ioctl.c) will attempt to use the MTD sysfs interface and MEM*64 ioctls in 2.6.31+. It will fall back to the older ABI if it determines that the running kernel does not support the new calls. Signed-off-by: Kevin Cernekee --- Makefile | 19 +++- flash_erase.c | 59 ++++++---- flash_eraseall.c | 31 +++-- flash_lock.c | 21 ++-- flash_unlock.c | 9 +- flashcp.c | 22 ++-- mtd_debug.c | 114 ++++++++++--------- mtd_ioctl.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++ mtd_ioctl.h | 39 ++++++ nanddump.c | 23 +++-- nandtest.c | 35 +++--- nandwrite.c | 60 +++++----- 13 files changed, 570 insertions(+), 171 deletions(-) create mode 100644 mtd_ioctl.c create mode 100644 mtd_ioctl.h diff --git a/Makefile b/Makefile index 577634f..5bf1292 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,24 @@ $(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\ LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS) LDLIBS_mkfs.jffs2 = -lz -llzo2 -$(BUILDDIR)/flash_eraseall: $(BUILDDIR)/crc32.o $(BUILDDIR)/flash_eraseall.o +$(BUILDDIR)/flash_eraseall: $(BUILDDIR)/crc32.o $(BUILDDIR)/flash_eraseall.o \ + $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/flash_erase: $(BUILDDIR)/flash_erase.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/nandwrite: $(BUILDDIR)/nandwrite.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/nandtest: $(BUILDDIR)/nandtest.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/nanddump: $(BUILDDIR)/nanddump.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/flashcp: $(BUILDDIR)/flashcp.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/flash_lock: $(BUILDDIR)/flash_lock.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/flash_unlock: $(BUILDDIR)/flash_unlock.o $(BUILDDIR)/mtd_ioctl.o + +$(BUILDDIR)/mtd_debug: $(BUILDDIR)/mtd_debug.o $(BUILDDIR)/mtd_ioctl.o $(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS) diff --git a/flash_erase.c b/flash_erase.c index fdf9918..f689cf5 100644 --- a/flash_erase.c +++ b/flash_erase.c @@ -11,22 +11,25 @@ #include #include #include +#include "mtd_ioctl.h" -int region_erase(int Fd, int start, int count, int unlock, int regcount) +int region_erase(int Fd, long long start, int count, int unlock, int regcount) { int i, j; - region_info_t * reginfo; + region_info64_t * reginfo; reginfo = calloc(regcount, sizeof(region_info_t)); for(i = 0; i < regcount; i++) { reginfo[i].regionindex = i; - if(ioctl(Fd,MEMGETREGIONINFO,&(reginfo[i])) != 0) + if(mtd_ioctl_getregioninfo(Fd,&(reginfo[i])) != 0) return 8; else - printf("Region %d is at %d of %d sector and with sector " - "size %x\n", i, reginfo[i].offset, reginfo[i].numblocks, + printf("Region %d is at %lld of %d sector and with sector " + "size %x\n", i, + (unsigned long long)reginfo[i].offset, + reginfo[i].numblocks, reginfo[i].erasesize); } @@ -34,7 +37,7 @@ int region_erase(int Fd, int start, int count, int unlock, int regcount) for(i = 0; i < regcount; i++) { //Loop through the regions - region_info_t * r = &(reginfo[i]); + region_info64_t * r = &(reginfo[i]); if((start >= reginfo[i].offset) && (start < (r->offset + r->numblocks*r->erasesize))) @@ -43,7 +46,7 @@ int region_erase(int Fd, int start, int count, int unlock, int regcount) if(i >= regcount) { - printf("Starting offset %x not within chip.\n", start); + printf("Starting offset %llx not within chip.\n", start); return 8; } @@ -52,25 +55,28 @@ int region_erase(int Fd, int start, int count, int unlock, int regcount) for(j = 0; (j < count)&&(i < regcount); j++) { - erase_info_t erase; - region_info_t * r = &(reginfo[i]); + erase_info64_t erase; + region_info64_t * r = &(reginfo[i]); + + memset(&erase, 0, sizeof(erase)); erase.start = start; erase.length = r->erasesize; if(unlock != 0) { //Unlock the sector first. - if(ioctl(Fd, MEMUNLOCK, &erase) != 0) + if(mtd_ioctl_unlock(Fd, &erase) != 0) { perror("\nMTD Unlock failure"); close(Fd); return 8; } } - printf("\rPerforming Flash Erase of length %u at offset 0x%x", - erase.length, erase.start); + printf("\rPerforming Flash Erase of length %llu at offset 0x%llx", + (unsigned long long)erase.length, + (unsigned long long)erase.start); fflush(stdout); - if(ioctl(Fd, MEMERASE, &erase) != 0) + if(mtd_ioctl_erase(Fd, &erase) != 0) { perror("\nMTD Erase failure"); close(Fd); @@ -91,28 +97,31 @@ int region_erase(int Fd, int start, int count, int unlock, int regcount) return 0; } -int non_region_erase(int Fd, int start, int count, int unlock) +int non_region_erase(int Fd, long long start, int count, int unlock) { - mtd_info_t meminfo; + mtd_info64_t meminfo; - if (ioctl(Fd,MEMGETINFO,&meminfo) == 0) + if (mtd_ioctl_getinfo(Fd,&meminfo) == 0) { - erase_info_t erase; + erase_info64_t erase; - erase.start = start; + memset(&erase, 0, sizeof(erase)); + erase.start = start; erase.length = meminfo.erasesize; for (; count > 0; count--) { - printf("\rPerforming Flash Erase of length %u at offset 0x%x", - erase.length, erase.start); + printf("\rPerforming Flash Erase of length %llu at offset 0x%llx", + (unsigned long long)erase.length, + (unsigned long long)erase.start); fflush(stdout); if(unlock != 0) { //Unlock the sector first. - printf("\rPerforming Flash unlock at offset 0x%x",erase.start); - if(ioctl(Fd, MEMUNLOCK, &erase) != 0) + printf("\rPerforming Flash unlock at offset 0x%llx", + (unsigned long long)erase.start); + if(mtd_ioctl_unlock(Fd, &erase) != 0) { perror("\nMTD Unlock failure"); close(Fd); @@ -120,7 +129,7 @@ int non_region_erase(int Fd, int start, int count, int unlock) } } - if (ioctl(Fd,MEMERASE,&erase) != 0) + if (mtd_ioctl_erase(Fd,&erase) != 0) { perror("\nMTD Erase failure"); close(Fd); @@ -137,7 +146,7 @@ int main(int argc,char *argv[]) { int regcount; int Fd; - int start; + long long start; int count; int unlock; int res = 0; @@ -149,7 +158,7 @@ int main(int argc,char *argv[]) } if (argc > 2) - start = strtol(argv[2], NULL, 0); + start = strtoll(argv[2], NULL, 0); else start = 0; diff --git a/flash_eraseall.c b/flash_eraseall.c index a22fc49..8f44570 100644 --- a/flash_eraseall.c +++ b/flash_eraseall.c @@ -36,6 +36,7 @@ #include #include #include "crc32.h" +#include "mtd_ioctl.h" #include #include @@ -49,7 +50,7 @@ static int quiet; /* true -- don't output progress */ static int jffs2; // format for jffs2 usage static void process_options (int argc, char *argv[]); -void show_progress (mtd_info_t *meminfo, erase_info_t *erase); +void show_progress (mtd_info64_t *meminfo, erase_info64_t *erase); static void display_help (void); static void display_version (void); static struct jffs2_unknown_node cleanmarker; @@ -57,9 +58,9 @@ int target_endian = __BYTE_ORDER; int main (int argc, char *argv[]) { - mtd_info_t meminfo; + mtd_info64_t meminfo; int fd, clmpos = 0, clmlen = 8; - erase_info_t erase; + erase_info64_t erase; int isNAND, bbtest = 1; process_options(argc, argv); @@ -70,11 +71,12 @@ int main (int argc, char *argv[]) } - if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { + if (mtd_ioctl_getinfo(fd, &meminfo) != 0) { fprintf(stderr, "%s: %s: unable to get MTD device info\n", exe_name, mtd_device); return 1; } + memset(&erase, 0, sizeof(erase)); erase.length = meminfo.erasesize; isNAND = meminfo.type == MTD_NANDFLASH ? 1 : 0; @@ -130,7 +132,8 @@ int main (int argc, char *argv[]) int ret = ioctl(fd, MEMGETBADBLOCK, &offset); if (ret > 0) { if (!quiet) - printf ("\nSkipping bad block at 0x%08x\n", erase.start); + printf ("\nSkipping bad block at 0x%08llx\n", + (unsigned long long)erase.start); continue; } else if (ret < 0) { if (errno == EOPNOTSUPP) { @@ -149,7 +152,7 @@ int main (int argc, char *argv[]) if (!quiet) show_progress(&meminfo, &erase); - if (ioctl(fd, MEMERASE, &erase) != 0) { + if (mtd_ioctl_erase(fd, &erase) != 0) { fprintf(stderr, "\n%s: %s: MTD Erase failure: %s\n", exe_name, mtd_device, strerror(errno)); continue; } @@ -160,11 +163,12 @@ int main (int argc, char *argv[]) /* write cleanmarker */ if (isNAND) { - struct mtd_oob_buf oob; - oob.ptr = (unsigned char *) &cleanmarker; + struct mtd_oob_buf64 oob; + memset(&oob, 0, sizeof(oob)); + oob.usr_ptr = (uintptr_t) &cleanmarker; oob.start = erase.start + clmpos; oob.length = clmlen; - if (ioctl (fd, MEMWRITEOOB, &oob) != 0) { + if (mtd_ioctl_writeoob(fd, &oob) != 0) { fprintf(stderr, "\n%s: %s: MTD writeoob failure: %s\n", exe_name, mtd_device, strerror(errno)); continue; } @@ -179,7 +183,8 @@ int main (int argc, char *argv[]) } } if (!quiet) - printf (" Cleanmarker written at %x.", erase.start); + printf (" Cleanmarker written at %llx.", + (unsigned long long)erase.start); } if (!quiet) { show_progress(&meminfo, &erase); @@ -250,10 +255,10 @@ void process_options (int argc, char *argv[]) mtd_device = argv[optind]; } -void show_progress (mtd_info_t *meminfo, erase_info_t *erase) +void show_progress (mtd_info64_t *meminfo, erase_info64_t *erase) { - printf("\rErasing %d Kibyte @ %x -- %2llu %% complete.", - meminfo->erasesize / 1024, erase->start, + printf("\rErasing %d Kibyte @ %llx -- %2llu %% complete.", + meminfo->erasesize / 1024, (unsigned long long)erase->start, (unsigned long long) erase->start * 100 / meminfo->size); fflush(stdout); } diff --git a/flash_lock.c b/flash_lock.c index 37f2ad3..a8a8241 100644 --- a/flash_lock.c +++ b/flash_lock.c @@ -15,14 +15,15 @@ #include #include +#include "mtd_ioctl.h" int main(int argc, char *argv[]) { int fd; - struct mtd_info_user mtdInfo; - struct erase_info_user mtdLockInfo; - int num_sectors; - int ofs; + struct mtd_info_user64 mtdInfo; + struct erase_info_user64 mtdLockInfo; + long long num_sectors; + long long ofs; /* * Parse command line options @@ -45,17 +46,17 @@ int main(int argc, char *argv[]) exit(1); } - if(ioctl(fd, MEMGETINFO, &mtdInfo)) + if(mtd_ioctl_getinfo(fd, &mtdInfo)) { fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]); close(fd); exit(1); } - sscanf(argv[2], "%x",&ofs); - sscanf(argv[3], "%d",&num_sectors); + sscanf(argv[2], "%llx",&ofs); + sscanf(argv[3], "%lld",&num_sectors); if(ofs > mtdInfo.size - mtdInfo.erasesize) { - fprintf(stderr, "%x is beyond device size %x\n",ofs,(unsigned int)(mtdInfo.size - mtdInfo.erasesize)); + fprintf(stderr, "%llx is beyond device size %llx\n",ofs,(unsigned long long)(mtdInfo.size - mtdInfo.erasesize)); exit(1); } @@ -65,14 +66,14 @@ int main(int argc, char *argv[]) else { if(num_sectors > mtdInfo.size/mtdInfo.erasesize) { - fprintf(stderr, "%d are too many sectors, device only has %d\n",num_sectors,(int)(mtdInfo.size/mtdInfo.erasesize)); + fprintf(stderr, "%lld are too many sectors, device only has %lld\n",num_sectors,(long long)(mtdInfo.size/mtdInfo.erasesize)); exit(1); } } mtdLockInfo.start = ofs; mtdLockInfo.length = (num_sectors - 1) * mtdInfo.erasesize; - if(ioctl(fd, MEMLOCK, &mtdLockInfo)) + if(mtd_ioctl_lock(fd, &mtdLockInfo)) { fprintf(stderr, "Could not lock MTD device: %s\n", argv[1]); close(fd); diff --git a/flash_unlock.c b/flash_unlock.c index 3969453..9921996 100644 --- a/flash_unlock.c +++ b/flash_unlock.c @@ -15,12 +15,13 @@ #include #include +#include "mtd_ioctl.h" int main(int argc, char *argv[]) { int fd; - struct mtd_info_user mtdInfo; - struct erase_info_user mtdLockInfo; + struct mtd_info_user64 mtdInfo; + struct erase_info_user64 mtdLockInfo; int count; /* @@ -44,7 +45,7 @@ int main(int argc, char *argv[]) exit(1); } - if(ioctl(fd, MEMGETINFO, &mtdInfo)) + if(mtd_ioctl_getinfo(fd, &mtdInfo)) { fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]); close(fd); @@ -63,7 +64,7 @@ int main(int argc, char *argv[]) mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize; } - if(ioctl(fd, MEMUNLOCK, &mtdLockInfo)) + if(mtd_ioctl_unlock(fd, &mtdLockInfo)) { fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]); close(fd); diff --git a/flashcp.c b/flashcp.c index 8775022..d9bab84 100644 --- a/flashcp.c +++ b/flashcp.c @@ -40,6 +40,7 @@ #include #include #include +#include "mtd_ioctl.h" typedef int bool; #define true 1 @@ -169,8 +170,8 @@ int main (int argc,char *argv[]) int i,flags = FLAG_NONE; ssize_t result; size_t size,written; - struct mtd_info_user mtd; - struct erase_info_user erase; + struct mtd_info_user64 mtd; + struct erase_info_user64 erase; struct stat filestat; unsigned char src[BUFSIZE],dest[BUFSIZE]; @@ -226,7 +227,7 @@ int main (int argc,char *argv[]) /* get some info about the flash device */ dev_fd = safe_open (device,O_SYNC | O_RDWR); - if (ioctl (dev_fd,MEMGETINFO,&mtd) < 0) + if (mtd_ioctl_getinfo (dev_fd,&mtd) < 0) { DEBUG("ioctl(): %m\n"); log_printf (LOG_ERROR,"This doesn't seem to be a valid MTD flash device!\n"); @@ -254,6 +255,7 @@ int main (int argc,char *argv[]) #warning "Check for smaller erase regions" + memset(&erase, 0, sizeof(erase)); erase.start = 0; erase.length = (filestat.st_size + mtd.erasesize - 1) / mtd.erasesize; erase.length *= mtd.erasesize; @@ -261,18 +263,18 @@ int main (int argc,char *argv[]) if (flags & FLAG_VERBOSE) { /* if the user wants verbose output, erase 1 block at a time and show him/her what's going on */ - int blocks = erase.length / mtd.erasesize; + long long blocks = erase.length / mtd.erasesize; erase.length = mtd.erasesize; log_printf (LOG_NORMAL,"Erasing blocks: 0/%d (0%%)",blocks); for (i = 1; i <= blocks; i++) { log_printf (LOG_NORMAL,"\rErasing blocks: %d/%d (%d%%)",i,blocks,PERCENTAGE (i,blocks)); - if (ioctl (dev_fd,MEMERASE,&erase) < 0) + if (mtd_ioctl_erase (dev_fd, &erase) < 0) { log_printf (LOG_NORMAL,"\n"); log_printf (LOG_ERROR, - "While erasing blocks 0x%.8x-0x%.8x on %s: %m\n", - (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device); + "While erasing blocks 0x%.8llx-0x%.8llx on %s: %m\n", + erase.start, (erase.start + erase.length),device); exit (EXIT_FAILURE); } erase.start += mtd.erasesize; @@ -282,11 +284,11 @@ int main (int argc,char *argv[]) else { /* if not, erase the whole chunk in one shot */ - if (ioctl (dev_fd,MEMERASE,&erase) < 0) + if (mtd_ioctl_erase (dev_fd, &erase) < 0) { log_printf (LOG_ERROR, - "While erasing blocks from 0x%.8x-0x%.8x on %s: %m\n", - (unsigned int) erase.start,(unsigned int) (erase.start + erase.length),device); + "While erasing blocks from 0x%.8llx-0x%.8llx on %s: %m\n", + erase.start, (erase.start + erase.length),device); exit (EXIT_FAILURE); } } diff --git a/mtd_debug.c b/mtd_debug.c index 49a4567..1020fe2 100644 --- a/mtd_debug.c +++ b/mtd_debug.c @@ -37,28 +37,13 @@ #include #include #include - -/* - * MEMGETINFO - */ -static int getmeminfo (int fd,struct mtd_info_user *mtd) -{ - return (ioctl (fd,MEMGETINFO,mtd)); -} - -/* - * MEMERASE - */ -static int memerase (int fd,struct erase_info_user *erase) -{ - return (ioctl (fd,MEMERASE,erase)); -} +#include "mtd_ioctl.h" /* * MEMGETREGIONCOUNT - * MEMGETREGIONINFO + * MEMGETREGIONINFO64 */ -static int getregions (int fd,struct region_info_user *regions,int *n) +static int getregions (int fd,struct region_info_user64 *regions,int *n) { int i,err; err = ioctl (fd,MEMGETREGIONCOUNT,n); @@ -66,44 +51,48 @@ static int getregions (int fd,struct region_info_user *regions,int *n) for (i = 0; i < *n; i++) { regions[i].regionindex = i; - err = ioctl (fd,MEMGETREGIONINFO,®ions[i]); + err = mtd_ioctl_getregioninfo (fd,®ions[i]); if (err) return (err); } return (0); } -int erase_flash (int fd,u_int32_t offset,u_int32_t bytes) +int erase_flash (int fd,u_int64_t offset,u_int64_t bytes) { int err; - struct erase_info_user erase; + struct erase_info_user64 erase; + + memset(&erase, 0, sizeof(erase)); erase.start = offset; erase.length = bytes; - err = memerase (fd,&erase); + + err = mtd_ioctl_erase (fd,&erase); if (err < 0) { perror ("MEMERASE"); return (1); } - fprintf (stderr,"Erased %d bytes from address 0x%.8x in flash\n",bytes,offset); + fprintf (stderr,"Erased %lld bytes from address 0x%.8llx in flash\n", + (unsigned long long)bytes, (unsigned long long)offset); return (0); } -void printsize (u_int32_t x) +void printsize (u_int64_t x) { int i; static const char *flags = "KMGT"; - printf ("%u ",x); + printf ("%llu ", (unsigned long long)x); for (i = 0; x >= 1024 && flags[i] != '\0'; i++) x /= 1024; i--; - if (i >= 0) printf ("(%u%c)",x,flags[i]); + if (i >= 0) printf ("(%llu%c)",(unsigned long long)x,flags[i]); } -int flash_to_file (int fd,u_int32_t offset,size_t len,const char *filename) +int flash_to_file (int fd, off_t offset,size_t len,const char *filename) { u_int8_t *buf = NULL; int outfd,err; - int size = len * sizeof (u_int8_t); - int n = len; + size_t size = len * sizeof (u_int8_t); + size_t n = len; if (offset != lseek (fd,offset,SEEK_SET)) { @@ -121,10 +110,12 @@ retry: if ((buf = (u_int8_t *) malloc (size)) == NULL) { #define BUF_SIZE (64 * 1024 * sizeof (u_int8_t)) - fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__, size); + fprintf (stderr, "%s: malloc(%#x)\n", __FUNCTION__, + (unsigned int)size); if (size != BUF_SIZE) { size = BUF_SIZE; - fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size); + fprintf (stderr, "%s: trying buffer size %#x\n", + __FUNCTION__, (unsigned int)size); goto retry; } perror ("malloc()"); @@ -136,20 +127,25 @@ retry: err = read (fd,buf,size); if (err < 0) { - fprintf (stderr, "%s: read, size %#x, n %#x\n", __FUNCTION__, size, n); + fprintf (stderr, "%s: read, size %#x, n %#x\n", + __FUNCTION__, (unsigned int)size, + (unsigned int)n); perror ("read()"); goto err2; } err = write (outfd,buf,size); if (err < 0) { - fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n); + fprintf (stderr, "%s: write, size %#x, n %#x\n", + __FUNCTION__, (unsigned int)size, + (unsigned int)n); perror ("write()"); goto err2; } if (err != size) { - fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n",filename,err,size); + fprintf (stderr,"Couldn't copy entire buffer to %s. (%d/%d bytes copied)\n", + filename,err,(int)size); goto err2; } n -= size; @@ -158,7 +154,8 @@ retry: if (buf != NULL) free (buf); close (outfd); - printf ("Copied %d bytes from address 0x%.8x in flash to %s\n",len,offset,filename); + printf ("Copied %d bytes from address 0x%.8llx in flash to %s\n", + (int)len,(unsigned long long)offset,filename); return (0); err2: @@ -170,13 +167,13 @@ err0: return (1); } -int file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char *filename) +int file_to_flash (int fd, off_t offset, size_t len,const char *filename) { u_int8_t *buf = NULL; FILE *fp; int err; - int size = len * sizeof (u_int8_t); - int n = len; + size_t size = len * sizeof (u_int8_t); + size_t n = len; if (offset != lseek (fd,offset,SEEK_SET)) { @@ -191,10 +188,12 @@ int file_to_flash (int fd,u_int32_t offset,u_int32_t len,const char *filename) retry: if ((buf = (u_int8_t *) malloc (size)) == NULL) { - fprintf (stderr, "%s: malloc(%#x) failed\n", __FUNCTION__, size); + fprintf (stderr, "%s: malloc(%#x) failed\n", + __FUNCTION__, (int)size); if (size != BUF_SIZE) { size = BUF_SIZE; - fprintf (stderr, "%s: trying buffer size %#x\n", __FUNCTION__, size); + fprintf (stderr, "%s: trying buffer size %#x\n", + __FUNCTION__, (int)size); goto retry; } perror ("malloc()"); @@ -206,7 +205,9 @@ retry: size = n; if (fread (buf,size,1,fp) != 1 || ferror (fp)) { - fprintf (stderr, "%s: fread, size %#x, n %#x\n", __FUNCTION__, size, n); + fprintf (stderr, "%s: fread, size %#x, n %#x\n", + __FUNCTION__, (unsigned int)size, + (unsigned int)n); perror ("fread()"); free (buf); fclose (fp); @@ -215,7 +216,9 @@ retry: err = write (fd,buf,size); if (err < 0) { - fprintf (stderr, "%s: write, size %#x, n %#x\n", __FUNCTION__, size, n); + fprintf (stderr, "%s: write, size %#x, n %#x\n", + __FUNCTION__, (unsigned int)size, + (unsigned int)n); perror ("write()"); free (buf); fclose (fp); @@ -227,23 +230,26 @@ retry: if (buf != NULL) free (buf); fclose (fp); - printf ("Copied %d bytes from %s to address 0x%.8x in flash\n",len,filename,offset); + printf ("Copied %d bytes from %s to address 0x%.8llx in flash\n", + (int)len,filename,(unsigned long long)offset); return (0); } int showinfo (int fd) { int i,err,n; - struct mtd_info_user mtd; - static struct region_info_user region[1024]; + struct mtd_info_user64 mtd; + static struct region_info_user64 region[1024]; - err = getmeminfo (fd,&mtd); + err = mtd_ioctl_getinfo (fd,&mtd); if (err < 0) { - perror ("MEMGETINFO"); + perror ("MEMGETINFO64"); return (1); } + memset(region, 0, sizeof(region)); + err = getregions (fd,region,&n); if (err < 0) { @@ -301,7 +307,7 @@ int showinfo (int fd) { "MTD_WRITEABLE", MTD_WRITEABLE }, { "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE }, { "MTD_NO_ERASE", MTD_NO_ERASE }, - { "MTD_STUPID_LOCK", MTD_STUPID_LOCK }, + { "MTD_POWERUP_LOCK", MTD_POWERUP_LOCK }, { NULL, -1 } }; for (i = 0; flags[i].name != NULL; i++) @@ -309,7 +315,7 @@ int showinfo (int fd) { if (first) { - printf (flags[i].name); + printf ("%s", flags[i].name); first = 0; } else printf (" | %s",flags[i].name); @@ -335,9 +341,9 @@ int showinfo (int fd) for (i = 0; i < n; i++) { - printf ("region[%d].offset = 0x%.8x\n" + printf ("region[%d].offset = 0x%.8llx\n" "region[%d].erasesize = ", - i,region[i].offset,i); + i,(unsigned long long)region[i].offset,i); printsize (region[i].erasesize); printf ("\nregion[%d].numblocks = %d\n" "region[%d].regionindex = %d\n", @@ -399,13 +405,13 @@ int main (int argc,char *argv[]) showinfo (fd); break; case OPT_READ: - err = flash_to_file (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0),argv[5]); + err = flash_to_file (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0),argv[5]); break; case OPT_WRITE: - err = file_to_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0),argv[5]); + err = file_to_flash (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0),argv[5]); break; case OPT_ERASE: - err = erase_flash (fd,strtol (argv[3],NULL,0),strtol (argv[4],NULL,0)); + err = erase_flash (fd,strtoll (argv[3],NULL,0),strtoll (argv[4],NULL,0)); break; } diff --git a/mtd_ioctl.c b/mtd_ioctl.c new file mode 100644 index 0000000..d19dcd3 --- /dev/null +++ b/mtd_ioctl.c @@ -0,0 +1,307 @@ +/* + * mtd_ioctl.c - backward compatibility wrappers for MTD ioctls + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mtd_ioctl.h" + +#define BUF_LEN 64 + +static int use_old_abi = 0; + +static int try_new_ioctl(int fd, unsigned int cmd, unsigned long arg, int *retp) +{ + int ret; + + if(use_old_abi) + return(0); + ret = ioctl(fd, cmd, arg); + if((ret < 0) && (errno == ENOTTY)) { + use_old_abi = 1; + return(0); + } + *retp = ret; + return(1); +} + +/** + * mkpath - compose full path from 2 given components. + * @path: the first component + * @name: the second component + * + * This function returns the resulting path in case of success and %NULL in + * case of failure. + */ +static char *mkpath(const char *path, const char *name) +{ + char *n; + int len1 = strlen(path); + int len2 = strlen(name); + + n = malloc(len1 + len2 + 2); + if (!n) { + return NULL; + } + + memcpy(n, path, len1); + if (n[len1 - 1] != '/') + n[len1++] = '/'; + + memcpy(n + len1, name, len2 + 1); + return n; +} + +/** + * read_data - read data from a file. + * @file: the file to read from + * @buf: the buffer to read to + * @buf_len: buffer length + * + * This function returns number of read bytes in case of success and %-1 in + * case of failure. Note, if the file contains more then @buf_len bytes of + * date, this function fails with %EINVAL error code. + */ +static int sysfs_get_str(const char *prefix, const char *element, + char *buf, int buf_len) +{ + int fd, rd, tmp, tmp1; + char *file = mkpath(prefix, element), *sep; + + if(! file) + return -1; + + fd = open(file, O_RDONLY); + if (fd == -1) { + free(file); + return -1; + } + + rd = read(fd, buf, buf_len); + if (rd == -1) { + goto out_error; + } + + /* Make sure all data is read */ + tmp1 = read(fd, &tmp, 1); + if (tmp1 == 1) { + goto out_error; + } + if (tmp1) { + errno = EINVAL; + goto out_error; + } + + if (close(fd)) { + rd = -1; + } + + sep = index(buf, '\n'); + if(sep) + *sep = 0; + else + buf[buf_len - 1] = 0; + + free(file); + return rd; + +out_error: + close(fd); + free(file); + return -1; +} + +static int sysfs_get_ull(const char *prefix, const char *element, + unsigned long long *out) +{ + int ret; + char buf[BUF_LEN]; + + ret = sysfs_get_str(prefix, element, buf, BUF_LEN); + if(ret <= 0) + return(ret); + + if(sscanf(buf, "0x%llx", out) == 1) + return(0); + + if(sscanf(buf, "%llu", out) == 1) + return(0); + + return(-1); +} + +int mtd_ioctl_getinfo(int fd, struct mtd_info_user64 *arg) +{ + int ret; + struct mtd_info_user oldarg; + struct stat st; + char prefix[BUF_LEN], str[BUF_LEN]; + unsigned long long tmp; + + if((fstat(fd, &st) < 0) || !S_ISCHR(st.st_mode)) + return(-1); + + snprintf(prefix, BUF_LEN, "/sys/class/mtd/mtd%d/", + minor(st.st_rdev) >> 1); + + if(sysfs_get_str(prefix, "type", str, BUF_LEN) > 0) { + if(strcasecmp(str, "absent") == 0) + arg->type = MTD_ABSENT; + else if(strcasecmp(str, "ram") == 0) + arg->type = MTD_RAM; + else if(strcasecmp(str, "rom") == 0) + arg->type = MTD_ROM; + else if(strcasecmp(str, "nor") == 0) + arg->type = MTD_NORFLASH; + else if(strcasecmp(str, "nand") == 0) + arg->type = MTD_NANDFLASH; + else if(strcasecmp(str, "dataflash") == 0) + arg->type = MTD_DATAFLASH; + else if(strcasecmp(str, "ubi") == 0) + arg->type = MTD_UBIVOLUME; + else + return(-1); + + if(sysfs_get_ull(prefix, "flags", &tmp) != 0) + return(-1); + arg->flags = tmp; + + if(sysfs_get_ull(prefix, "size", &tmp) != 0) + return(-1); + arg->size = tmp; + + if(sysfs_get_ull(prefix, "erasesize", &tmp) != 0) + return(-1); + arg->erasesize = tmp; + + if(sysfs_get_ull(prefix, "writesize", &tmp) != 0) + return(-1); + arg->writesize = tmp; + + if(sysfs_get_ull(prefix, "oobsize", &tmp) != 0) + return(-1); + arg->oobsize = tmp; + + return(0); + } + + ret = ioctl(fd, MEMGETINFO, (unsigned long)&oldarg); + if(ret < 0) + return(ret); + + arg->type = oldarg.type; + arg->flags = oldarg.flags; + arg->size = oldarg.size; + arg->erasesize = oldarg.erasesize; + arg->writesize = oldarg.writesize; + arg->oobsize = oldarg.oobsize; + + return(ret); +} + +int mtd_ioctl_erase(int fd, struct erase_info_user64 *arg) +{ + int ret; + struct erase_info_user oldarg; + + if(try_new_ioctl(fd, MEMERASE64, (unsigned long)arg, &ret) != 0) + return(ret); + + oldarg.start = arg->start; + oldarg.length = arg->length; + + return(ioctl(fd, MEMERASE, (unsigned long)&oldarg)); +} + +int mtd_ioctl_writeoob(int fd, struct mtd_oob_buf64 *arg) +{ + int ret; + struct mtd_oob_buf oldarg; + + if(try_new_ioctl(fd, MEMWRITEOOB64, (unsigned long)arg, &ret) != 0) + return(ret); + + oldarg.start = arg->start; + oldarg.length = arg->length; + oldarg.ptr = (void *)(uintptr_t)arg->usr_ptr; + + ret = ioctl(fd, MEMWRITEOOB, (unsigned long)&oldarg); + + arg->length = oldarg.length; + return(ret); +} + +int mtd_ioctl_readoob(int fd, struct mtd_oob_buf64 *arg) +{ + int ret; + struct mtd_oob_buf oldarg; + + if(try_new_ioctl(fd, MEMREADOOB64, (unsigned long)arg, &ret) != 0) + return(ret); + + oldarg.start = arg->start; + oldarg.length = arg->length; + oldarg.ptr = (void *)(uintptr_t)arg->usr_ptr; + + ret = ioctl(fd, MEMREADOOB, (unsigned long)&oldarg); + + /* old ABI puts returned length in "start" */ + arg->length = oldarg.start; + return(ret); +} + +int mtd_ioctl_lock(int fd, struct erase_info_user64 *arg) +{ + struct erase_info_user oldarg; +#ifdef MEMLOCK64 + int ret; + + if(try_new_ioctl(fd, MEMLOCK64, (unsigned long)arg, &ret) != 0) + return(ret); +#endif + + oldarg.start = arg->start; + oldarg.length = arg->length; + + return(ioctl(fd, MEMLOCK, (unsigned long)&oldarg)); +} + +int mtd_ioctl_unlock(int fd, struct erase_info_user64 *arg) +{ + struct erase_info_user oldarg; +#ifdef MEMUNLOCK64 + int ret; + + if(try_new_ioctl(fd, MEMUNLOCK64, (unsigned long)arg, &ret) != 0) + return(ret); +#endif + + oldarg.start = arg->start; + oldarg.length = arg->length; + + return(ioctl(fd, MEMUNLOCK, (unsigned long)&oldarg)); +} + +int mtd_ioctl_getregioninfo(int fd, struct region_info_user64 *arg) +{ + int ret; + struct region_info_user oldarg; + + oldarg.regionindex = arg->regionindex; + + ret = ioctl(fd, MEMGETREGIONINFO, (unsigned long)&oldarg); + + arg->offset = oldarg.offset; + arg->erasesize = oldarg.erasesize; + arg->numblocks = oldarg.numblocks; + + return(ret); +} diff --git a/mtd_ioctl.h b/mtd_ioctl.h new file mode 100644 index 0000000..a479793 --- /dev/null +++ b/mtd_ioctl.h @@ -0,0 +1,39 @@ +/* + * mtd_ioctl.h - backward compatibility wrappers for MTD ioctls + */ + +#ifndef _MTD_IOCTL_H +#define _MTD_IOCTL_H + +#include + +struct region_info_user64 { + uint64_t offset; /* At which this region starts, + * from the beginning of the MTD */ + uint32_t erasesize; /* For this region */ + uint32_t numblocks; /* Number of blocks in this region */ + uint32_t regionindex; +}; + +struct mtd_info_user64 { + uint32_t type; + uint32_t flags; + uint64_t size; /* Total size of the MTD */ + uint32_t erasesize; + uint32_t writesize; + uint32_t oobsize; /* OOB bytes per page (e.g. 16) */ +}; + +typedef struct mtd_info_user64 mtd_info64_t; +typedef struct region_info_user64 region_info64_t; +typedef struct erase_info_user64 erase_info64_t; + +int mtd_ioctl_getinfo(int fd, struct mtd_info_user64 *arg); +int mtd_ioctl_erase(int fd, struct erase_info_user64 *arg); +int mtd_ioctl_writeoob(int fd, struct mtd_oob_buf64 *arg); +int mtd_ioctl_readoob(int fd, struct mtd_oob_buf64 *arg); +int mtd_ioctl_lock(int fd, struct erase_info_user64 *arg); +int mtd_ioctl_unlock(int fd, struct erase_info_user64 *arg); +int mtd_ioctl_getregioninfo(int fd, struct region_info_user64 *arg); + +#endif /* !_MTD_IOCTL_H */ diff --git a/nanddump.c b/nanddump.c index ae0e425..6f101d2 100644 --- a/nanddump.c +++ b/nanddump.c @@ -29,6 +29,7 @@ #include #include +#include "mtd_ioctl.h" #define PROGRAM "nanddump" #define VERSION "$Revision: 1.29 $" @@ -182,11 +183,15 @@ static unsigned char oobbuf[128]; */ int main(int argc, char * const argv[]) { - unsigned long ofs, end_addr = 0; + unsigned long long ofs, end_addr = 0; unsigned long long blockstart = 1; int ret, i, fd, ofd, bs, badblock = 0; - struct mtd_oob_buf oob = {0, 16, oobbuf}; - mtd_info_t meminfo; + struct mtd_oob_buf64 oob = { + .start = 0, + .length = 16, + .usr_ptr = (uintptr_t)oobbuf, + }; + mtd_info64_t meminfo; char pretty_buf[80]; int oobinfochanged = 0 ; struct nand_oobinfo old_oobinfo; @@ -202,8 +207,8 @@ int main(int argc, char * const argv[]) } /* Fill in MTD device capability structure */ - if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { - perror("MEMGETINFO"); + if (mtd_ioctl_getinfo(fd, &meminfo) != 0) { + perror("MEMGETINFO64"); close(fd); exit (EXIT_FAILURE); } @@ -322,11 +327,11 @@ int main(int argc, char * const argv[]) } if (stat1.failed != stat2.failed) fprintf(stderr, "ECC: %d uncorrectable bitflip(s)" - " at offset 0x%08lx\n", + " at offset 0x%08llx\n", stat2.failed - stat1.failed, ofs); if (stat1.corrected != stat2.corrected) fprintf(stderr, "ECC: %d corrected bitflip(s) at" - " offset 0x%08lx\n", + " offset 0x%08llx\n", stat2.corrected - stat1.corrected, ofs); stat1 = stat2; } @@ -361,8 +366,8 @@ int main(int argc, char * const argv[]) } else { /* Read OOB data and exit on failure */ oob.start = ofs; - if (ioctl(fd, MEMREADOOB, &oob) != 0) { - perror("ioctl(MEMREADOOB)"); + if (mtd_ioctl_readoob(fd, &oob) != 0) { + perror("ioctl(MEMREADOOB64)"); goto closeall; } } diff --git a/nandtest.c b/nandtest.c index e31e28a..ef31130 100644 --- a/nandtest.c +++ b/nandtest.c @@ -14,6 +14,7 @@ #include #include "mtd/mtd-user.h" +#include "mtd_ioctl.h" void usage(void) { @@ -28,7 +29,7 @@ void usage(void) exit(1); } -struct mtd_info_user meminfo; +struct mtd_info_user64 meminfo; struct mtd_ecc_stats oldstats, newstats; int fd; int markbad=0; @@ -36,26 +37,28 @@ int seed; int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf) { - struct erase_info_user er; + struct erase_info_user64 er; ssize_t len; int i; - printf("\r%08x: erasing... ", (unsigned)ofs); + printf("\r%08llx: erasing... ", ofs); fflush(stdout); + memset(&er, 0, sizeof(er)); + er.start = ofs; er.length = meminfo.erasesize; - if (ioctl(fd, MEMERASE, &er)) { - perror("MEMERASE"); + if (mtd_ioctl_erase(fd, &er)) { + perror("MEMERASE64"); if (markbad) { - printf("Mark block bad at %08lx\n", (long)ofs); + printf("Mark block bad at %08llx\n", ofs); ioctl(fd, MEMSETBADBLOCK, &ofs); } return 1; } - printf("\r%08x: writing...", (unsigned)ofs); + printf("\r%08llx: writing...", ofs); fflush(stdout); len = pwrite(fd, data, meminfo.erasesize, ofs); @@ -132,8 +135,8 @@ int main(int argc, char **argv) int pass; int nr_passes = 1; int keep_contents = 0; - uint32_t offset = 0; - uint32_t length = -1; + uint64_t offset = 0; + uint64_t length = -1; for (;;) { static const char *short_options="hkl:mo:p:s:"; @@ -175,11 +178,11 @@ int main(int argc, char **argv) break; case 'o': - offset = atol(optarg); + offset = atoll(optarg); break; case 'l': - length = strtol(optarg, NULL, 0); + length = strtoll(optarg, NULL, 0); break; } @@ -193,8 +196,8 @@ int main(int argc, char **argv) exit(1); } - if (ioctl(fd, MEMGETINFO, &meminfo)) { - perror("MEMGETINFO"); + if (mtd_ioctl_getinfo(fd, &meminfo)) { + perror("MEMGETINFO64"); close(fd); exit(1); } @@ -203,17 +206,17 @@ int main(int argc, char **argv) length = meminfo.size; if (offset % meminfo.erasesize) { - fprintf(stderr, "Offset %x not multiple of erase size %x\n", + fprintf(stderr, "Offset %llx not multiple of erase size %x\n", offset, meminfo.erasesize); exit(1); } if (length % meminfo.erasesize) { - fprintf(stderr, "Length %x not multiple of erase size %x\n", + fprintf(stderr, "Length %llx not multiple of erase size %x\n", length, meminfo.erasesize); exit(1); } if (length + offset > meminfo.size) { - fprintf(stderr, "Length %x + offset %x exceeds device size %x\n", + fprintf(stderr, "Length %llx + offset %llx exceeds device size %llx\n", length, offset, meminfo.size); exit(1); } diff --git a/nandwrite.c b/nandwrite.c index b77edd6..9684b95 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -38,6 +38,7 @@ #include #include "mtd/mtd-user.h" +#include "mtd_ioctl.h" #define PROGRAM "nandwrite" #define VERSION "$Revision: 1.32 $" @@ -107,7 +108,7 @@ static void display_version (void) static const char *standard_input = "-"; static const char *mtd_device, *img; -static int mtdoffset = 0; +static long long mtdoffset = 0; static bool quiet = false; static bool writeoob = false; static bool autoplace = false; @@ -188,7 +189,7 @@ static void process_options (int argc, char * const argv[]) pad = true; break; case 's': - mtdoffset = strtol (optarg, NULL, 0); + mtdoffset = strtoll (optarg, NULL, 0); break; case 'b': blockalign = atoi (optarg); @@ -200,7 +201,7 @@ static void process_options (int argc, char * const argv[]) } if (mtdoffset < 0) { - fprintf(stderr, "Can't specify a negative device offset `%d'\n", + fprintf(stderr, "Can't specify a negative device offset `%lld'\n", mtdoffset); exit (EXIT_FAILURE); } @@ -246,9 +247,9 @@ int main(int argc, char * const argv[]) int ifd = -1; int imglen = 0, pagelen; bool baderaseblock = false; - int blockstart = -1; - struct mtd_info_user meminfo; - struct mtd_oob_buf oob; + long long blockstart = -1; + struct mtd_info_user64 meminfo; + struct mtd_oob_buf64 oob; loff_t offs; int ret; int oobinfochanged = 0; @@ -280,8 +281,8 @@ int main(int argc, char * const argv[]) } /* Fill in MTD device capability structure */ - if (ioctl(fd, MEMGETINFO, &meminfo) != 0) { - perror("MEMGETINFO"); + if (mtd_ioctl_getinfo(fd, &meminfo) != 0) { + perror("MEMGETINFO64"); close(fd); exit (EXIT_FAILURE); } @@ -377,8 +378,9 @@ int main(int argc, char * const argv[]) } } + memset(&oob, 0, sizeof(oob)); oob.length = meminfo.oobsize; - oob.ptr = noecc ? oobreadbuf : oobbuf; + oob.usr_ptr = (uintptr_t)(noecc ? oobreadbuf : oobbuf); /* Determine if we are reading from standard input or from a file. */ if (strcmp(img, standard_input) == 0) { @@ -421,8 +423,9 @@ int main(int argc, char * const argv[]) // Check, if length fits into device if ( ((imglen / pagelen) * meminfo.writesize) > (meminfo.size - mtdoffset)) { - fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %u bytes\n", - imglen, pagelen, meminfo.writesize, meminfo.size); + fprintf (stderr, "Image %d bytes, NAND page %d bytes, OOB area %u bytes, device size %llu bytes\n", + imglen, pagelen, meminfo.writesize, + (unsigned long long)meminfo.size); perror ("Input file does not fit into device"); goto closeall; } @@ -467,7 +470,7 @@ int main(int argc, char * const argv[]) baderaseblock = false; if (!quiet) - fprintf (stdout, "Writing data to block %d at offset 0x%x\n", + fprintf (stdout, "Writing data to block %lld at offset 0x%llx\n", blockstart / meminfo.erasesize, blockstart); /* Check all the blocks in an erase block for bad blocks */ @@ -479,9 +482,10 @@ int main(int argc, char * const argv[]) if (ret == 1) { baderaseblock = true; if (!quiet) - fprintf (stderr, "Bad block at %x, %u block(s) " - "from %x will be skipped\n", - (int) offs, blockalign, blockstart); + fprintf (stderr, "Bad block at %llx, %u block(s) " + "from %llx will be skipped\n", + (unsigned long long)offs, + blockalign, blockstart); } if (baderaseblock) { @@ -580,7 +584,7 @@ int main(int argc, char * const argv[]) } if (noecc) { - oob.ptr = oobreadbuf; + oob.usr_ptr = (uintptr_t)oobreadbuf; } else { int i, start, len; /* @@ -610,15 +614,15 @@ int main(int argc, char * const argv[]) } /* Write OOB data first, as ecc will be placed in there*/ oob.start = mtdoffset; - if (ioctl(fd, MEMWRITEOOB, &oob) != 0) { - perror ("ioctl(MEMWRITEOOB)"); + if (mtd_ioctl_writeoob(fd, &oob) != 0) { + perror ("ioctl(MEMWRITEOOB64)"); goto closeall; } } /* Write out the Page data */ if (pwrite(fd, writebuf, meminfo.writesize, mtdoffset) != meminfo.writesize) { - erase_info_t erase; + erase_info64_t erase; if (errno != EIO) { perror("pwrite"); @@ -628,21 +632,21 @@ int main(int argc, char * const argv[]) /* Must rewind to blockstart if we can */ writebuf = filebuf; + memset(&erase, 0, sizeof(erase)); erase.start = blockstart; erase.length = meminfo.erasesize; - fprintf(stderr, "Erasing failed write from %08lx-%08lx\n", - (long)erase.start, (long)erase.start+erase.length-1); - if (ioctl(fd, MEMERASE, &erase) != 0) { - int errno_tmp = errno; - perror("MEMERASE"); - if (errno_tmp != EIO) { - goto closeall; - } + fprintf(stderr, "Erasing failed write from %08llx-%08llx\n", + (unsigned long long)erase.start, + (unsigned long long)(erase.start+erase.length-1)); + if (mtd_ioctl_erase(fd, &erase) != 0) { + perror("MEMERASE64"); + goto closeall; } if (markbad) { loff_t bad_addr = mtdoffset & (~(meminfo.erasesize / blockalign) + 1); - fprintf(stderr, "Marking block at %08lx bad\n", (long)bad_addr); + fprintf(stderr, "Marking block at %08llx bad\n", + (unsigned long long)bad_addr); if (ioctl(fd, MEMSETBADBLOCK, &bad_addr)) { perror("MEMSETBADBLOCK"); goto closeall; -- 1.6.5 From mike at compulab.co.il Thu May 13 02:15:47 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Thu, 13 May 2010 09:15:47 +0300 Subject: [PATCH 1/3] omap3: GPMC register definition at common location In-Reply-To: <1273657718-12517-2-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> <1273657718-12517-2-git-send-email-s-ghorai@ti.com> Message-ID: <4BEB9913.2000303@compulab.co.il> Sukumar Ghorai wrote: > GPMC register definition move to common place in gpmc.h. > > Signed-off-by: Sukumar Ghorai Looks Ok to me, just minor comments > --- > arch/arm/mach-omap2/gpmc.c | 38 +------------------------------ > arch/arm/plat-omap/include/plat/gpmc.h | 36 +++++++++++++++++++++++++++-- > drivers/mtd/nand/omap2.c | 14 ++++------- > 3 files changed, 40 insertions(+), 48 deletions(-) > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > index 5bc3ca0..9c77af0 > --- a/arch/arm/mach-omap2/gpmc.c > +++ b/arch/arm/mach-omap2/gpmc.c > @@ -28,40 +28,6 @@ > > #include > > -/* GPMC register offsets */ > -#define GPMC_REVISION 0x00 > -#define GPMC_SYSCONFIG 0x10 > -#define GPMC_SYSSTATUS 0x14 > -#define GPMC_IRQSTATUS 0x18 > -#define GPMC_IRQENABLE 0x1c > -#define GPMC_TIMEOUT_CONTROL 0x40 > -#define GPMC_ERR_ADDRESS 0x44 > -#define GPMC_ERR_TYPE 0x48 > -#define GPMC_CONFIG 0x50 > -#define GPMC_STATUS 0x54 > -#define GPMC_PREFETCH_CONFIG1 0x1e0 > -#define GPMC_PREFETCH_CONFIG2 0x1e4 > -#define GPMC_PREFETCH_CONTROL 0x1ec > -#define GPMC_PREFETCH_STATUS 0x1f0 > -#define GPMC_ECC_CONFIG 0x1f4 > -#define GPMC_ECC_CONTROL 0x1f8 > -#define GPMC_ECC_SIZE_CONFIG 0x1fc > - > -#define GPMC_CS0 0x60 > -#define GPMC_CS_SIZE 0x30 > - > -#define GPMC_MEM_START 0x00000000 > -#define GPMC_MEM_END 0x3FFFFFFF > -#define BOOT_ROM_SPACE 0x100000 /* 1MB */ > - > -#define GPMC_CHUNK_SHIFT 24 /* 16 MB */ > -#define GPMC_SECTION_SHIFT 28 /* 128 MB */ > - > -#define PREFETCH_FIFOTHRESHOLD (0x40 << 8) > -#define CS_NUM_SHIFT 24 > -#define ENABLE_PREFETCH (0x1 << 7) > -#define DMA_MPU_MODE 2 > - > /* Structure to save gpmc cs context */ > struct gpmc_cs_config { > u32 config1; > @@ -112,7 +78,7 @@ void gpmc_cs_write_reg(int cs, int idx, u32 val) > { > void __iomem *reg_addr; > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > __raw_writel(val, reg_addr); > } > > @@ -120,7 +86,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > { > void __iomem *reg_addr; > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > return __raw_readl(reg_addr); > } > > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h > index 145838a..347d212 100644 > --- a/arch/arm/plat-omap/include/plat/gpmc.h > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > @@ -25,10 +25,40 @@ > #define GPMC_CS_NAND_ADDRESS 0x20 > #define GPMC_CS_NAND_DATA 0x24 > > -#define GPMC_CONFIG 0x50 > -#define GPMC_STATUS 0x54 > +/* GPMC register offsets */ > +#define GPMC_REVISION 0x00 > +#define GPMC_SYSCONFIG 0x10 > +#define GPMC_SYSSTATUS 0x14 > +#define GPMC_IRQSTATUS 0x18 > +#define GPMC_IRQENABLE 0x1c > +#define GPMC_TIMEOUT_CONTROL 0x40 > +#define GPMC_ERR_ADDRESS 0x44 > +#define GPMC_ERR_TYPE 0x48 > +#define GPMC_CONFIG 0x50 > +#define GPMC_STATUS 0x54 > +#define GPMC_PREFETCH_CONFIG1 0x1e0 > +#define GPMC_PREFETCH_CONFIG2 0x1e4 > +#define GPMC_PREFETCH_CONTROL 0x1ec > +#define GPMC_PREFETCH_STATUS 0x1f0 > +#define GPMC_ECC_CONFIG 0x1f4 > +#define GPMC_ECC_CONTROL 0x1f8 > +#define GPMC_ECC_SIZE_CONFIG 0x1fc > +#define GPMC_ECC1_RESULT 0x200 > + > #define GPMC_CS0_BASE 0x60 > -#define GPMC_CS_SIZE 0x30 > +#define GPMC_CS_SIZE 0x30 > + > +#define GPMC_MEM_START 0x00000000 > +#define GPMC_MEM_END 0x3FFFFFFF > +#define BOOT_ROM_SPACE 0x100000 /* 1MB */ > + > +#define GPMC_CHUNK_SHIFT 24 /* 16 MB */ > +#define GPMC_SECTION_SHIFT 28 /* 128 MB */ > + > +#define PREFETCH_FIFOTHRESHOLD (0x40 << 8) > +#define CS_NUM_SHIFT 24 > +#define ENABLE_PREFETCH (0x1 << 7) > +#define DMA_MPU_MODE 2 > > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > index 7545568..258bf06 > --- a/drivers/mtd/nand/omap2.c > +++ b/drivers/mtd/nand/omap2.c > @@ -23,12 +23,6 @@ > #include > #include > > -#define GPMC_IRQ_STATUS 0x18 > -#define GPMC_ECC_CONFIG 0x1F4 > -#define GPMC_ECC_CONTROL 0x1F8 > -#define GPMC_ECC_SIZE_CONFIG 0x1FC > -#define GPMC_ECC1_RESULT 0x200 > - > #define DRIVER_NAME "omap2-nand" > > #define NAND_WP_OFF 0 > @@ -37,6 +31,7 @@ > #define GPMC_BUF_FULL 0x00000001 > #define GPMC_BUF_EMPTY 0x00000000 > > +#ifdef CONFIG_MTD_NAND_OMAP_HWECC This change does not seem related to the patch subject. > #define NAND_Ecc_P1e (1 << 0) > #define NAND_Ecc_P2e (1 << 1) > #define NAND_Ecc_P4e (1 << 2) > @@ -103,6 +98,7 @@ > > #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) > #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) > +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */ > > #ifdef CONFIG_MTD_PARTITIONS > static const char *part_probes[] = { "cmdlinepart", NULL }; > @@ -854,20 +850,20 @@ static int omap_dev_ready(struct mtd_info *mtd) > { > struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, > mtd); > - unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS); > + unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQSTATUS); > > if ((val & 0x100) == 0x100) { > /* Clear IRQ Interrupt */ > val |= 0x100; > val &= ~(0x0); > - __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS); > + __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQSTATUS); > } else { > unsigned int cnt = 0; > while (cnt++ < 0x1FF) { > if ((val & 0x100) == 0x100) > return 0; > val = __raw_readl(info->gpmc_baseaddr + > - GPMC_IRQ_STATUS); > + GPMC_IRQSTATUS); > } > } > -- Sincerely yours, Mike. From brijesh.s.singh at gmail.com Thu May 13 03:10:13 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Thu, 13 May 2010 12:40:13 +0530 Subject: UBIL design doc In-Reply-To: References: <1273475736.2209.88.camel@localhost> <1273650099.22706.41.camel@localhost> <1273653341.22706.46.camel@localhost> Message-ID: Hi Thomas, Thanks for the idea. It looked impressive. On Wed, May 12, 2010 at 4:28 PM, Thomas Gleixner wrote: > On Wed, 12 May 2010, Brijesh Singh wrote: >> On Wed, May 12, 2010 at 2:05 PM, Artem Bityutskiy wrote: >> > On Wed, 2010-05-12 at 13:33 +0530, Brijesh Singh wrote: >> >> 4) Any unclean un-mount will lead to flash scanning just as UBI. >> > >> > No! Why you have the log then? Unclean reboots are handled by the log. >> > >> > Scanning happens only when you have _corrupted_ SB, or corrupted cmt, or >> > log. Then you fall-back to scanning. >> > >> >> Any thing goes bad, normal scanning becomes recovery. >> >> 5) Not sure if log is required in first place. But it could be an option. >> >> Is that correct? >> > >> > No, at least I did not suggest you to get rid of the log. It is needed >> > to handle unclean reboots. >> >> Log is written for each EC or VID change. Frequency of log write is same as >> the frequency of these headers. In case we keep both, there will be one log >> write penalty per write/erase. So write performance will drop considerably. > > True, but the reliability will drop as well. Losing a log block is > going to be fatal as there is no way to reconstruct while losing a > single block in UBI is not inevitably fatal. > > Back then when UBI was designed / written we discussed a different > approach of avoiding the full flash scan while keeping the reliability > intact. > > Superblock in the first couple of erase blocks which points to a > snapshot block. snapshot block(s) contain a compressed EC/VID header > snapshot. A defined number of blocks in that snapshot is marked as > NEED_SCAN. At the point of creating the snapshot these blocks are > empty and belong to the blocks with the lowest erase count. > > Now when an UBI client (filesystem ...) requests an erase block one of > those NEED_SCAN marked blocks is given out. Blocks which are handed > back from the client for erasure which are not marked NEED_SCAN are > erased and not given out as long as there are still enough empty > blocks marked NEED_SCAN available. When we run out of NEED_SCAN marked > blocks we write a new snapshot with a new set of NEED_SCAN blocks. This is compromise with wear-leveling.Also, erasing a block will write EC to flash. We won't be able to erase any of no NEED_SCAN blocks. Only NEED_SCAN blocks can be erased after the snapshot is written. So wear-leveling thread will be inactive. Problems: 1)What if a block which is not NEED_SCAN block, is unmapped, how do we erase it? We can't. 2)What if wear-leveling threshold is hit? How to move blocks? > So at attach time we read the snapshot and scan the few NEED_SCAN > blocks. They are either empty or assigned to a volume. If assigned > they can replace an already existing logical erase block reference in > the snapshot, so we know that we need to put the original physical > erase block into a lazy back ground scan list. > > With that approach we keep the reliability of UBI untouched with the > penalty of scanning a limited number of erase blocks at attach time. > > That limits the number of writes to the snapshot / log > significantly. For devices with a low write frequency that means that > the snapshot block can be untouched for a very long time. > > The speed penalty is constant and does not depend on the number of log > entries after the snapshot. > > Your full log approach is going to slower once the number of log > entries is greater than the number of NEED_SCAN marked blocks. > > If we assume a page read time of 1ms and the number of NEED_SCAN > blocks of 64, then we talk about a constant overhead of 64 ms. > > So lets look at the full picture: > > Flashsize: ? ? ? ? ? ? ? ? ? 1 GiB > Eraseblocksize: ? ? ? ? ? ?128 KiB > Pagesize: ? ? ? ? ? ? ? ? ? ?2 KiB > Subpagesize: ? ? ? ? ? ? ? ? 1 KiB > Number of erase blocks: ? 8192 > > Snapshot size per block: ? ?16 Byte > Full snapshot size: ? ? ? ?128 KiB > Full snapshot pages: ? ? ? ?64 > > Number of NEED_SCAN blocks: 64 > > Number of blocks to scan > for finding super block(s): 64 > > So with an assumption of page read time == 1ms the total time of > building the initial data structures in RAM is 3 * 64ms. > > So yes, it _IS_ 3 times the time which we need for your log approach > (assumed that the super block is first good block and the number of > log entries after the snapshot is 0) > > So once we agree that a moveable super block is the correct way, the > speed advantage is of your log approach is 64ms (still assumed that > the number of log entry pages is 0) > > Now take the log entries into account. Once you have to read 64 pages > worth of log entries, which happens in the above example after exaclty > 128 entries, the speed advantage is exaclty zero. From that point on > it's going to be worse. > > Thoughts ? It is getting complicated. Should we fix back word compatibility first and then can come to these optimization? From pazdnikov at prosoft.ural.ru Thu May 13 04:08:01 2010 From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov) Date: Thu, 13 May 2010 14:08:01 +0600 Subject: ubifs became broken on contigous power-fails In-Reply-To: <201005121330.07802.pazdnikov@prosoft.ural.ru> References: <201005121330.07802.pazdnikov@prosoft.ural.ru> Message-ID: <201005131408.01573.pazdnikov@prosoft.ural.ru> We've separated EC and VID headers to different pages, setuped 4 devices on test run. -- Best regards, Sasha From linux at dominikbrodowski.net Thu May 13 06:00:01 2010 From: linux at dominikbrodowski.net (Dominik Brodowski) Date: Thu, 13 May 2010 12:00:01 +0200 Subject: [PATCH 4/4] pcmciamtd: add another ID In-Reply-To: <20100513095749.GA25909@comet.dominikbrodowski.net> References: <20100513095749.GA25909@comet.dominikbrodowski.net> Message-ID: <1273744801-26318-4-git-send-email-linux@dominikbrodowski.net> Reported-by: Komuro Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/pcmciamtd.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 050aa8e..c4aacbf 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -747,6 +747,7 @@ static struct pcmcia_device_id pcmciamtd_ids[] = { PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965), + PCMCIA_DEVICE_PROD_ID12("PRETEC", " 2MB SRAM CARD", 0xebf91155, 0x805360ca), PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05), -- 1.6.3.3 From linux at dominikbrodowski.net Thu May 13 05:57:49 2010 From: linux at dominikbrodowski.net (Dominik Brodowski) Date: Thu, 13 May 2010 11:57:49 +0200 Subject: [git pull] pcmciamtd fixes Message-ID: <20100513095749.GA25909@comet.dominikbrodowski.net> David, Alexander Kurz spent quite some time to fix pcmciamtd to not only build again, but to actually work on some cards he owns. In addition, there are a few more PCMCIA IDs to report, and Julia Lawall reported and fixed an use-after-free bug in pcmciamtd. Could you pick up these patches and pull from git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6.git pcmciamtd please? Alteranatively, I can push these changes (post-2.6.34) upstream via PCMCIA, if you prefer me to take them. I'll send the patches to the MTD and PCMCIA lists for a final(?) round of review. Thanks & Best, Dominik Alexander Kurz (2): pcmciamtd: fixing obvious errors pcmciamtd: coding style cleanups Dominik Brodowski (1): pcmciamtd: add another ID Julia Lawall (1): drivers/mtd/maps: Eliminate use after free drivers/mtd/maps/Kconfig | 2 +- drivers/mtd/maps/pcmciamtd.c | 80 ++++++++++++++++++++++++------------------ 2 files changed, 47 insertions(+), 35 deletions(-) From linux at dominikbrodowski.net Thu May 13 05:59:58 2010 From: linux at dominikbrodowski.net (Dominik Brodowski) Date: Thu, 13 May 2010 11:59:58 +0200 Subject: [PATCH 1/4] drivers/mtd/maps: Eliminate use after free In-Reply-To: <20100513095749.GA25909@comet.dominikbrodowski.net> References: <20100513095749.GA25909@comet.dominikbrodowski.net> Message-ID: <1273744801-26318-1-git-send-email-linux@dominikbrodowski.net> From: Julia Lawall Moved the debugging message before the call to map_destroy, which frees its argument. The message is also slightly changed to reflect its new position. A simplified version of the semantic patch that finds this problem is as follows: (http://coccinelle.lip6.fr/) // @@ expression E,E2; @@ del_mtd_device(E) ... ( E = E2 | * E ) // Signed-off-by: Julia Lawall Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/pcmciamtd.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 689d6a7..81159d7 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -692,8 +692,8 @@ static void pcmciamtd_detach(struct pcmcia_device *link) if(dev->mtd_info) { del_mtd_device(dev->mtd_info); + info("mtd%d: Removing", dev->mtd_info->index); map_destroy(dev->mtd_info); - info("mtd%d: Removed", dev->mtd_info->index); } pcmciamtd_release(link); -- 1.6.3.3 From linux at dominikbrodowski.net Thu May 13 06:00:00 2010 From: linux at dominikbrodowski.net (Dominik Brodowski) Date: Thu, 13 May 2010 12:00:00 +0200 Subject: [PATCH 3/4] pcmciamtd: coding style cleanups In-Reply-To: <20100513095749.GA25909@comet.dominikbrodowski.net> References: <20100513095749.GA25909@comet.dominikbrodowski.net> Message-ID: <1273744801-26318-3-git-send-email-linux@dominikbrodowski.net> From: Alexander Kurz Signed-off-by: Alexander Kurz Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/pcmciamtd.c | 55 +++++++++++++++++++++++++---------------- 1 files changed, 33 insertions(+), 22 deletions(-) diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 915b64e..050aa8e 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -40,10 +40,7 @@ MODULE_PARM_DESC(debug, "Set Debug Level 0=quiet, 5=noisy"); static const int debug = 0; #endif -#define err(format, arg...) printk(KERN_ERR "pcmciamtd: " format "\n" , ## arg) #define info(format, arg...) printk(KERN_INFO "pcmciamtd: " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING "pcmciamtd: " format "\n" , ## arg) - #define DRIVER_DESC "PCMCIA Flash memory card driver" @@ -100,7 +97,9 @@ module_param(mem_type, int, 0); MODULE_PARM_DESC(mem_type, "Set Memory type (0=Flash, 1=RAM, 2=ROM, default=0)"); -/* read/write{8,16} copy_{from,to} routines with window remapping to access whole card */ +/* read/write{8,16} copy_{from,to} routines with window remapping + * to access whole card + */ static caddr_t remap_window(struct map_info *map, unsigned long to) { struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; @@ -245,7 +244,8 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) return d; d.x[0] = readb(win_base + ofs); - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, win_base + ofs, d.x[0]); + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", + ofs, win_base + ofs, d.x[0]); return d; } @@ -259,7 +259,8 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs) return d; d.x[0] = readw(win_base + ofs); - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, win_base + ofs, d.x[0]); + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", + ofs, win_base + ofs, d.x[0]); return d; } @@ -283,7 +284,8 @@ static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr) if(DEV_REMOVED(map)) return; - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", adr, win_base + adr, d.x[0]); + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", + adr, win_base + adr, d.x[0]); writeb(d.x[0], win_base + adr); } @@ -295,7 +297,8 @@ static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr) if(DEV_REMOVED(map)) return; - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", adr, win_base + adr, d.x[0]); + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", + adr, win_base + adr, d.x[0]); writew(d.x[0], win_base + adr); } @@ -376,7 +379,8 @@ static int pcmciamtd_cistpl_jedec(struct pcmcia_device *p_dev, if (!pcmcia_parse_tuple(tuple, &parse)) { cistpl_jedec_t *t = &parse.jedec; for (i = 0; i < t->nid; i++) - DEBUG(2, "JEDEC: 0x%02x 0x%02x", t->id[i].mfr, t->id[i].info); + DEBUG(2, "JEDEC: 0x%02x 0x%02x", + t->id[i].mfr, t->id[i].info); } return -ENOSPC; } @@ -477,7 +481,8 @@ static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev } DEBUG(1, "Device: Size: %lu Width:%d Name: %s", - dev->pcmcia_map.size, dev->pcmcia_map.bankwidth << 3, dev->mtd_name); + dev->pcmcia_map.size, + dev->pcmcia_map.bankwidth << 3, dev->mtd_name); } @@ -513,9 +518,11 @@ static int pcmciamtd_config(struct pcmcia_device *link) if(setvpp == 1) dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp; - /* Request a memory window for PCMCIA. Some architeures can map windows upto the maximum - that PCMCIA can support (64MiB) - this is ideal and we aim for a window the size of the - whole card - otherwise we try smaller windows until we succeed */ + /* Request a memory window for PCMCIA. Some architeures can map windows + * upto the maximum that PCMCIA can support (64MiB) - this is ideal and + * we aim for a window the size of the whole card - otherwise we try + * smaller windows until we succeed + */ req.Attributes = WIN_MEMORY_TYPE_CM | WIN_ENABLE; req.Attributes |= (dev->pcmcia_map.bankwidth == 1) ? WIN_DATA_WIDTH_8 : WIN_DATA_WIDTH_16; @@ -543,7 +550,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) DEBUG(2, "dev->win_size = %d", dev->win_size); if(!dev->win_size) { - err("Cant allocate memory window"); + dev_err(&dev->p_dev->dev, "Cannot allocate memory window\n"); pcmciamtd_release(link); return -ENODEV; } @@ -553,7 +560,8 @@ static int pcmciamtd_config(struct pcmcia_device *link) DEBUG(2, "window handle = 0x%8.8lx", (unsigned long)link->win); dev->win_base = ioremap(req.Base, req.Size); if(!dev->win_base) { - err("ioremap(%lu, %u) failed", req.Base, req.Size); + dev_err(&dev->p_dev->dev, "ioremap(%lu, %u) failed\n", + req.Base, req.Size); pcmciamtd_release(link); return -ENODEV; } @@ -600,7 +608,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) } if(!mtd) { - DEBUG(1, "Cant find an MTD"); + DEBUG(1, "Can not find an MTD"); pcmciamtd_release(link); return -ENODEV; } @@ -611,8 +619,9 @@ static int pcmciamtd_config(struct pcmcia_device *link) if(new_name) { int size = 0; char unit = ' '; - /* Since we are using a default name, make it better by adding in the - size */ + /* Since we are using a default name, make it better by adding + * in the size + */ if(mtd->size < 1048576) { /* <1MiB in size, show size in KiB */ size = mtd->size >> 10; unit = 'K'; @@ -642,16 +651,17 @@ static int pcmciamtd_config(struct pcmcia_device *link) if(add_mtd_device(mtd)) { map_destroy(mtd); dev->mtd_info = NULL; - err("Couldnt register MTD device"); + dev_err(&dev->p_dev->dev, + "Could not register the MTD device\n"); pcmciamtd_release(link); return -ENODEV; } snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); - info("mtd%d: %s", mtd->index, mtd->name); + dev_info(&dev->p_dev->dev, "mtd%d: %s\n", mtd->index, mtd->name); link->dev_node = &dev->node; return 0; - err("CS Error, exiting"); + dev_err(&dev->p_dev->dev, "CS Error, exiting\n"); pcmciamtd_release(link); return -ENODEV; } @@ -690,7 +700,8 @@ static void pcmciamtd_detach(struct pcmcia_device *link) if(dev->mtd_info) { del_mtd_device(dev->mtd_info); - info("mtd%d: Removing", dev->mtd_info->index); + dev_info(&dev->p_dev->dev, "mtd%d: Removing\n", + dev->mtd_info->index); map_destroy(dev->mtd_info); } -- 1.6.3.3 From linux at dominikbrodowski.net Thu May 13 05:59:59 2010 From: linux at dominikbrodowski.net (Dominik Brodowski) Date: Thu, 13 May 2010 11:59:59 +0200 Subject: [PATCH 2/4] pcmciamtd: fixing obvious errors In-Reply-To: <20100513095749.GA25909@comet.dominikbrodowski.net> References: <20100513095749.GA25909@comet.dominikbrodowski.net> Message-ID: <1273744801-26318-2-git-send-email-linux@dominikbrodowski.net> From: Alexander Kurz After fixing the obvious errors, the driver will now compile again on v2.6.34-rc3. First tests with two 4MB flash cards including erase- and write test with one of the cards where successful. Also, add two new PCMCIA_DEVICE_PROD_IDs. [linux at dominikbrodowski.net: clean up commit message] Signed-off-by: Alexander Kurz Signed-off-by: Dominik Brodowski --- drivers/mtd/maps/Kconfig | 2 +- drivers/mtd/maps/pcmciamtd.c | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index aa2807d..f22bc9f 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -435,7 +435,7 @@ config MTD_PCI config MTD_PCMCIA tristate "PCMCIA MTD driver" - depends on PCMCIA && MTD_COMPLEX_MAPPINGS && BROKEN + depends on PCMCIA && MTD_COMPLEX_MAPPINGS help Map driver for accessing PCMCIA linear flash memory cards. These cards are usually around 4-16MiB in size. This does not include diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 81159d7..915b64e 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -137,7 +137,7 @@ static map_word pcmcia_read8_remap(struct map_info *map, unsigned long ofs) return d; d.x[0] = readb(addr); - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, addr, d.x[0]); + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, addr, d.x[0]); return d; } @@ -152,7 +152,7 @@ static map_word pcmcia_read16_remap(struct map_info *map, unsigned long ofs) return d; d.x[0] = readw(addr); - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, addr, d.x[0]); + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, addr, d.x[0]); return d; } @@ -190,7 +190,7 @@ static void pcmcia_write8_remap(struct map_info *map, map_word d, unsigned long if(!addr) return; - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, addr, d.x[0]); + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", adr, addr, d.x[0]); writeb(d.x[0], addr); } @@ -201,7 +201,7 @@ static void pcmcia_write16_remap(struct map_info *map, map_word d, unsigned long if(!addr) return; - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, addr, d.x[0]); + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", adr, addr, d.x[0]); writew(d.x[0], addr); } @@ -245,7 +245,7 @@ static map_word pcmcia_read8(struct map_info *map, unsigned long ofs) return d; d.x[0] = readb(win_base + ofs); - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02x", ofs, win_base + ofs, d.x[0]); + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%02lx", ofs, win_base + ofs, d.x[0]); return d; } @@ -259,7 +259,7 @@ static map_word pcmcia_read16(struct map_info *map, unsigned long ofs) return d; d.x[0] = readw(win_base + ofs); - DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04x", ofs, win_base + ofs, d.x[0]); + DEBUG(3, "ofs = 0x%08lx (%p) data = 0x%04lx", ofs, win_base + ofs, d.x[0]); return d; } @@ -276,27 +276,27 @@ static void pcmcia_copy_from(struct map_info *map, void *to, unsigned long from, } -static void pcmcia_write8(struct map_info *map, u8 d, unsigned long adr) +static void pcmcia_write8(struct map_info *map, map_word d, unsigned long adr) { caddr_t win_base = (caddr_t)map->map_priv_2; if(DEV_REMOVED(map)) return; - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02x", adr, win_base + adr, d); - writeb(d, win_base + adr); + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%02lx", adr, win_base + adr, d.x[0]); + writeb(d.x[0], win_base + adr); } -static void pcmcia_write16(struct map_info *map, u16 d, unsigned long adr) +static void pcmcia_write16(struct map_info *map, map_word d, unsigned long adr) { caddr_t win_base = (caddr_t)map->map_priv_2; if(DEV_REMOVED(map)) return; - DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04x", adr, win_base + adr, d); - writew(d, win_base + adr); + DEBUG(3, "adr = 0x%08lx (%p) data = 0x%04lx", adr, win_base + adr, d.x[0]); + writew(d.x[0], win_base + adr); } @@ -432,7 +432,7 @@ static int pcmciamtd_cistpl_geo(struct pcmcia_device *p_dev, } -static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *link, int *new_name) +static void card_settings(struct pcmciamtd_dev *dev, struct pcmcia_device *p_dev, int *new_name) { int i; @@ -490,7 +490,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) { struct pcmciamtd_dev *dev = link->priv; struct mtd_info *mtd = NULL; - cs_status_t status; win_req_t req; int ret; int i; @@ -565,7 +564,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) dev->pcmcia_map.map_priv_1 = (unsigned long)dev; dev->pcmcia_map.map_priv_2 = (unsigned long)link->win; - dev->vpp = (vpp) ? vpp : link->socket.socket.Vpp; + dev->vpp = (vpp) ? vpp : link->socket->socket.Vpp; link->conf.Attributes = 0; if(setvpp == 2) { link->conf.Vpp = dev->vpp; @@ -652,7 +651,6 @@ static int pcmciamtd_config(struct pcmcia_device *link) link->dev_node = &dev->node; return 0; - failed: err("CS Error, exiting"); pcmciamtd_release(link); return -ENODEV; @@ -737,8 +735,10 @@ static struct pcmcia_device_id pcmciamtd_ids[] = { PCMCIA_DEVICE_PROD_ID12("intel", "VALUE SERIES 100 ", 0x40ade711, 0xdf8506d8), PCMCIA_DEVICE_PROD_ID12("KINGMAX TECHNOLOGY INC.", "SRAM 256K Bytes", 0x54d0c69c, 0xad12c29c), PCMCIA_DEVICE_PROD_ID12("Maxtor", "MAXFL MobileMax Flash Memory Card", 0xb68968c8, 0x2dfb47b0), + PCMCIA_DEVICE_PROD_ID123("M-Systems", "M-SYS Flash Memory Card", "(c) M-Systems", 0x7ed2ad87, 0x675dc3fb, 0x7aef3965), PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB101EN20", 0xf9876baf, 0xad0b207b), PCMCIA_DEVICE_PROD_ID12("SEIKO EPSON", "WWB513EN20", 0xf9876baf, 0xe8d884ad), + PCMCIA_DEVICE_PROD_ID12("SMART Modular Technologies", " 4MB FLASH Card", 0x96fd8277, 0x737a5b05), PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-3000", 0x05ddca47, 0xe7d67bca), PCMCIA_DEVICE_PROD_ID12("Starfish, Inc.", "REX-4100", 0x05ddca47, 0x7bc32944), /* the following was commented out in pcmcia-cs-3.2.7 */ -- 1.6.3.3 From dedekind1 at gmail.com Thu May 13 06:11:11 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 13 May 2010 13:11:11 +0300 Subject: [PATCH v5 2/3] mtd-utils: support >4GiB devices In-Reply-To: <5e05b5a05a30b2dc2035b87a60bb82f3137174cb@localhost.localdomain> References: <5e05b5a05a30b2dc2035b87a60bb82f3137174cb@localhost.localdomain> Message-ID: <1273745471.22706.163.camel@localhost> On Wed, 2010-05-12 at 19:23 -0700, Kevin Cernekee wrote: > This patch updates the following programs to handle >4GiB flash devices: > > flash_erase > flash_eraseall > flashcp > mtd_debug > nanddump > nandtest > nandwrite > > It also lays the groundwork for >4GiB support in: > > flash_lock > flash_unlock > > The latter two utilities would require MEMLOCK64 / MEMUNLOCK64 > functionality on the kernel side (currently unimplemented). For now > they still use MEMLOCK / MEMUNLOCK and cannot access blocks above 4GiB. > > By default, the compatibility layer (mtd_ioctl.c) will attempt to use > the MTD sysfs interface and MEM*64 ioctls in 2.6.31+. It will fall back > to the older ABI if it determines that the running kernel does not > support the new calls. > > Signed-off-by: Kevin Cernekee > --- > Makefile | 19 +++- > flash_erase.c | 59 ++++++---- > flash_eraseall.c | 31 +++-- > flash_lock.c | 21 ++-- > flash_unlock.c | 9 +- > flashcp.c | 22 ++-- > mtd_debug.c | 114 ++++++++++--------- > mtd_ioctl.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++ > mtd_ioctl.h | 39 ++++++ > nanddump.c | 23 +++-- > nandtest.c | 35 +++--- > nandwrite.c | 60 +++++----- > 13 files changed, 570 insertions(+), 171 deletions(-) > create mode 100644 mtd_ioctl.c > create mode 100644 mtd_ioctl.h Any chance to extend and use mtd-utils/ubi-utils/src/libmtd.c instead of mtd_ioctl.c? -- Best Regards, Artem Bityutskiy (????? ????????) From jon at ringle.org Thu May 13 09:23:01 2010 From: jon at ringle.org (Jon Ringle) Date: Thu, 13 May 2010 09:23:01 -0400 Subject: Erase race? In-Reply-To: References: <1272373142.7750.5.camel@localhost> <1273635175.8881.3.camel@localhost.localdomain> Message-ID: On Wed, May 12, 2010 at 8:31 AM, massimo cirillo wrote: > Have you any evidence of erase suspend occurrence ? How do I know if erase suspend occurs? > Could you try to disable erase suspend from cfi_cmdset_0001.c ? > To this end, uncomment > #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE > #define CMDSET0001_DISABLE_WRITE_SUSPEND > (they must be defined) at the beginning of the file and repeat > your test. Thanks. I will try this, however, since the problem is infrequent and I don't know how to make the problem happen more reliably, it will take some time to verify that this fixes the issue. Jon From tony at atomide.com Thu May 13 11:41:03 2010 From: tony at atomide.com (Tony Lindgren) Date: Thu, 13 May 2010 08:41:03 -0700 Subject: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <1273657718-12517-3-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> <1273657718-12517-2-git-send-email-s-ghorai@ti.com> <1273657718-12517-3-git-send-email-s-ghorai@ti.com> Message-ID: <20100513154103.GI29368@atomide.com> * Sukumar Ghorai [100512 02:43]: > --- a/arch/arm/mach-omap2/gpmc.c > +++ b/arch/arm/mach-omap2/gpmc.c > @@ -64,16 +64,32 @@ static void __iomem *gpmc_base; > > static struct clk *gpmc_l3_clk; > > -static void gpmc_write_reg(int idx, u32 val) > +void gpmc_write_reg(int idx, u32 val) > { > __raw_writel(val, gpmc_base + idx); > } > > -static u32 gpmc_read_reg(int idx) > +u32 gpmc_read_reg(int idx) > { > return __raw_readl(gpmc_base + idx); > } > > +void gpmc_cs_write_byte(int cs, int idx, u32 val) > +{ > + void __iomem *reg_addr; > + > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > + __raw_writeb(val, reg_addr); > +} > + > +u8 gpmc_cs_read_byte(int cs, int idx) > +{ > + void __iomem *reg_addr; > + > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > + return __raw_readb(reg_addr); > +} > + This will not improve the situation unfortunately. We for sure don't want to export functions to mess with the GPMC registers all over the place. > @@ -432,15 +448,6 @@ void gpmc_prefetch_reset(void) > } > EXPORT_SYMBOL(gpmc_prefetch_reset); > > -/** > - * gpmc_prefetch_status - reads prefetch status of engine > - */ > -int gpmc_prefetch_status(void) > -{ > - return gpmc_read_reg(GPMC_PREFETCH_STATUS); > -} > -EXPORT_SYMBOL(gpmc_prefetch_status); > - And we don't want to remove GPMC functions like this, instead we need to implement more functions like this for the platform init code to use. Regards, Tony From tony at atomide.com Thu May 13 11:41:59 2010 From: tony at atomide.com (Tony Lindgren) Date: Thu, 13 May 2010 08:41:59 -0700 Subject: [PATCH 1/3] omap3: GPMC register definition at common location In-Reply-To: <1273657718-12517-2-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> <1273657718-12517-2-git-send-email-s-ghorai@ti.com> Message-ID: <20100513154158.GJ29368@atomide.com> * Sukumar Ghorai [100512 02:43]: > --- a/arch/arm/plat-omap/include/plat/gpmc.h > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > @@ -25,10 +25,40 @@ > #define GPMC_CS_NAND_ADDRESS 0x20 > #define GPMC_CS_NAND_DATA 0x24 > > -#define GPMC_CONFIG 0x50 > -#define GPMC_STATUS 0x54 > +/* GPMC register offsets */ > +#define GPMC_REVISION 0x00 > +#define GPMC_SYSCONFIG 0x10 > +#define GPMC_SYSSTATUS 0x14 > +#define GPMC_IRQSTATUS 0x18 > +#define GPMC_IRQENABLE 0x1c > +#define GPMC_TIMEOUT_CONTROL 0x40 > +#define GPMC_ERR_ADDRESS 0x44 > +#define GPMC_ERR_TYPE 0x48 > +#define GPMC_CONFIG 0x50 > +#define GPMC_STATUS 0x54 > +#define GPMC_PREFETCH_CONFIG1 0x1e0 > +#define GPMC_PREFETCH_CONFIG2 0x1e4 > +#define GPMC_PREFETCH_CONTROL 0x1ec > +#define GPMC_PREFETCH_STATUS 0x1f0 > +#define GPMC_ECC_CONFIG 0x1f4 > +#define GPMC_ECC_CONTROL 0x1f8 > +#define GPMC_ECC_SIZE_CONFIG 0x1fc > +#define GPMC_ECC1_RESULT 0x200 ... No thanks, that will just make the situation worse leading into all the drivers messing with the GPMC registers. Tony From tony at atomide.com Thu May 13 11:44:23 2010 From: tony at atomide.com (Tony Lindgren) Date: Thu, 13 May 2010 08:44:23 -0700 Subject: [PATCH 0/3] omap3 nand: cleanup exiting platform related code In-Reply-To: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> Message-ID: <20100513154423.GK29368@atomide.com> * Sukumar Ghorai [100512 02:43]: > The following set of patches applies on top of master branch. > http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git > Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board > > And these are the patches required to address the following input - > 1. The NAND driver needs to stop tinkering with the GPMC registers > The omap General Purpose Memory Controller (GPMC) registers are omap > specific, and not driver specific. Tinkering with these registers can > cause issues with the other devices on the GPMC. > > 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files > Passing hardcoded GPMC virtual addressess is sure way to mess up things. > This should all become unnecessary once the NAND drivers stops messing > with the GPMC registers directly. Thanks for working on this. I've made some comments to you patches to do what's listed above. Instead of exporting the GPMC registers, you should create new functions into gpmc.c for the nand platform init code to use. Regards, Tony From dwmw2 at infradead.org Thu May 13 13:16:58 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Thu, 13 May 2010 18:16:58 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> Message-ID: <1273771018.12840.7077.camel@macbook.infradead.org> On Sat, 2010-03-20 at 11:03 +0100, Joakim Tjernlund wrote: > Erasing blocks is a form of GC and therefore it should live in the > GC task. By moving it there two problems will be solved: > 1) unmounting will not hang until all pending blocks has > been erased. > 2) Erasing can be paused by sending a SIGSTOP to the GC thread which > allowes for time critical tasks to work in peace. > > Since erasing now is in the GC thread, erases should trigger > the GC task instead. > wbuf.c still wants to flush its buffer via write_super so > invent jffs2_dirty_trigger() and use that in wbuf. > Remove surplus call to jffs2_erase_pending_trigger() in erase.c > and remove jffs2_garbage_collect_trigger() from write_super as > of now write_super() should only commit dirty data to disk. > > Signed-off-by: Joakim Tjernlund > --- The only callers of jffs2_erase_pending_blocks() now call it with a 'count' argument of 1. So perhaps it's now misnamed and the 's' and the extra argument should be dropped? I don't much like the calculation you've added to the end of that function either, which really ought to be under locks (even though right now I suspect it doesn't hurt). Why recalculate that at all, though -- why not keep a 'ret' variable which defaults to 0 but is set to 1 just before the 'goto done' which is the only way out of the function where the return value should be non-zero anyway? I've always been very careful to keep the GC thread as an _optimisation_. It looks like this will still work, because the actual erase will get done from jffs2_reserve_space()... but that'll only erase blocks immediately when we actually need them. Before, we were erasing them in advance. I suppose that's OK though. -- dwmw2 From rpjday at crashcourse.ca Thu May 13 14:27:39 2010 From: rpjday at crashcourse.ca (Robert P. J. Day) Date: Thu, 13 May 2010 14:27:39 -0400 (EDT) Subject: simplifying the linux MTD Kconfig/Makefile structure In-Reply-To: <1272024346.6917.10.camel@localhost> References: <1272024346.6917.10.camel@localhost> Message-ID: On Fri, 23 Apr 2010, Artem Bityutskiy wrote: > On Tue, 2010-03-30 at 08:29 -0400, Robert P. J. Day wrote: > > it seems like the various Kconfigs and Makefiles related to MTD > > could be tightened up a bit. for instance, in drivers/mtd/Makefile: > > > > obj-$(CONFIG_MTD_UBI) += ubi/ > > > > but given that selection, it's kind of redundant to then have > > drivers/mtd/ubi/Makefile start with: > > > > obj-$(CONFIG_MTD_UBI) += ubi.o > > > > is it not? why not just "obj-y"? > > > > along those lines, again from drivers/mtd/Makefile: > > > > obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ > > > > obj-$(CONFIG_MTD_UBI) += ubi/ > > > > why not be consistent and have: > > > > obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ > > > > obj-$(CONFIG_MTD_UBI) += ubi/ > > obj-$(CONFIG_MTD_TESTS) += tests/ > > > > which would *massively* simplify drivers/mtd/tests/Makefile, would it > > not? > > > > i can submit some patches if there's any interest. i suspect some > > of the other directories could be similarly tidied up. > > Sounds like a reasonable clean-up to me. sorry for the delay, either i or a local buddy will take care of this and submit patches to the list. rday -- ======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA Linux Consulting, Training and Kernel Pedantry. Web page: http://crashcourse.ca Twitter: http://twitter.com/rpjday ======================================================================== From s-ghorai at ti.com Thu May 13 14:48:13 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Fri, 14 May 2010 00:18:13 +0530 Subject: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <20100513154103.GI29368@atomide.com> References: <1273657718-12517-1-git-send-email-s-ghorai@ti.com> <1273657718-12517-2-git-send-email-s-ghorai@ti.com> <1273657718-12517-3-git-send-email-s-ghorai@ti.com> <20100513154103.GI29368@atomide.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FB10F@dbde02.ent.ti.com> Tony, > -----Original Message----- > From: Tony Lindgren [mailto:tony at atomide.com] > Sent: 2010-05-13 21:11 > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; > sakoman at gmail.com; mike at compulab.co.il; Artem.Bityutskiy at nokia.com > Subject: Re: [PATCH 2/3] omap3 nand: cleanup for not to use GPMC virtual > address > > * Sukumar Ghorai [100512 02:43]: > > --- a/arch/arm/mach-omap2/gpmc.c > > +++ b/arch/arm/mach-omap2/gpmc.c > > @@ -64,16 +64,32 @@ static void __iomem *gpmc_base; > > > > static struct clk *gpmc_l3_clk; > > > > -static void gpmc_write_reg(int idx, u32 val) > > +void gpmc_write_reg(int idx, u32 val) > > { > > __raw_writel(val, gpmc_base + idx); > > } > > > > -static u32 gpmc_read_reg(int idx) > > +u32 gpmc_read_reg(int idx) > > { > > return __raw_readl(gpmc_base + idx); > > } > > > > +void gpmc_cs_write_byte(int cs, int idx, u32 val) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > + __raw_writeb(val, reg_addr); > > +} > > + > > +u8 gpmc_cs_read_byte(int cs, int idx) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > + return __raw_readb(reg_addr); > > +} > > + > > This will not improve the situation unfortunately. > We for sure don't want to export functions to mess > with the GPMC registers all over the place. > > > @@ -432,15 +448,6 @@ void gpmc_prefetch_reset(void) > > } > > EXPORT_SYMBOL(gpmc_prefetch_reset); > > > > -/** > > - * gpmc_prefetch_status - reads prefetch status of engine > > - */ > > -int gpmc_prefetch_status(void) > > -{ > > - return gpmc_read_reg(GPMC_PREFETCH_STATUS); > > -} > > -EXPORT_SYMBOL(gpmc_prefetch_status); > > - > > And we don't want to remove GPMC functions like this, > instead we need to implement more functions like this > for the platform init code to use. [Ghorai] 1. NAND IO address needed by core NAND driver. So we can't move that access to GMPC. 2. And is it ok if we add functions as below and all need to be as EXPORT_SYMBOL too? get_gpmc_status() get_gpmc_irq_status() set_gpmc_irq_status() set_gpmc_irq_enable() get_gpmc_config set_gpmc_config get_gpmc_status() get_gpmc_prefetch_config() gpmc_prefetch_status set_gpmc_ecc_config set_gpmc_ecc_contol set_gpmc_ecc_size get_gpmc_ecc_result Regards, Sukumar > Regards, > > Tony From julia at diku.dk Thu May 13 16:07:46 2010 From: julia at diku.dk (Julia Lawall) Date: Thu, 13 May 2010 22:07:46 +0200 (CEST) Subject: [PATCH 20/20] drivers/mtd/nand: Use kzalloc Message-ID: From: Julia Lawall Use kzalloc rather than the combination of kmalloc and memset. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,size,flags; statement S; @@ -x = kmalloc(size,flags); +x = kzalloc(size,flags); if (x == NULL) S -memset(x, 0, size); // Signed-off-by: Julia Lawall --- drivers/mtd/nand/s3c2410.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff -u -p a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -929,14 +929,13 @@ static int s3c24xx_nand_probe(struct pla pr_debug("s3c2410_nand_probe(%p)\n", pdev); - info = kmalloc(sizeof(*info), GFP_KERNEL); + info = kzalloc(sizeof(*info), GFP_KERNEL); if (info == NULL) { dev_err(&pdev->dev, "no memory for flash info\n"); err = -ENOMEM; goto exit_error; } - memset(info, 0, sizeof(*info)); platform_set_drvdata(pdev, info); spin_lock_init(&info->controller.lock); @@ -994,15 +993,13 @@ static int s3c24xx_nand_probe(struct pla /* allocate our information */ size = nr_sets * sizeof(*info->mtds); - info->mtds = kmalloc(size, GFP_KERNEL); + info->mtds = kzalloc(size, GFP_KERNEL); if (info->mtds == NULL) { dev_err(&pdev->dev, "failed to allocate mtd storage\n"); err = -ENOMEM; goto exit_error; } - memset(info->mtds, 0, size); - /* initialise all possible chips */ nmtd = info->mtds; From julia at diku.dk Thu May 13 16:03:15 2010 From: julia at diku.dk (Julia Lawall) Date: Thu, 13 May 2010 22:03:15 +0200 (CEST) Subject: [PATCH 12/20] drivers/mtd: Use kzalloc Message-ID: From: Julia Lawall Use kzalloc rather than the combination of kmalloc and memset. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression x,size,flags; statement S; @@ -x = kmalloc(size,flags); +x = kzalloc(size,flags); if (x == NULL) S -memset(x, 0, size); // Signed-off-by: Julia Lawall --- drivers/mtd/lpddr/qinfo_probe.c | 7 ++----- drivers/mtd/maps/ixp2000.c | 3 +-- drivers/mtd/maps/ixp4xx.c | 3 +-- drivers/mtd/maps/pxa2xx-flash.c | 3 +-- drivers/mtd/tests/mtd_pagetest.c | 3 +-- drivers/mtd/tests/mtd_readtest.c | 3 +-- drivers/mtd/tests/mtd_speedtest.c | 3 +-- drivers/mtd/tests/mtd_stresstest.c | 3 +-- drivers/mtd/tests/mtd_subpagetest.c | 3 +-- 9 files changed, 10 insertions(+), 21 deletions(-) diff -u -p a/drivers/mtd/lpddr/qinfo_probe.c b/drivers/mtd/lpddr/qinfo_probe.c --- a/drivers/mtd/lpddr/qinfo_probe.c +++ b/drivers/mtd/lpddr/qinfo_probe.c @@ -134,13 +134,12 @@ out: static int lpddr_chip_setup(struct map_info *map, struct lpddr_private *lpddr) { - lpddr->qinfo = kmalloc(sizeof(struct qinfo_chip), GFP_KERNEL); + lpddr->qinfo = kzalloc(sizeof(struct qinfo_chip), GFP_KERNEL); if (!lpddr->qinfo) { printk(KERN_WARNING "%s: no memory for LPDDR qinfo structure\n", map->name); return 0; } - memset(lpddr->qinfo, 0, sizeof(struct qinfo_chip)); /* Get the ManuID */ lpddr->ManufactId = CMDVAL(map_read(map, map->pfow_base + PFOW_MANUFACTURER_ID)); @@ -185,13 +184,11 @@ static struct lpddr_private *lpddr_probe lpddr.numchips = 1; numvirtchips = lpddr.numchips * lpddr.qinfo->HWPartsNum; - retlpddr = kmalloc(sizeof(struct lpddr_private) + + retlpddr = kzalloc(sizeof(struct lpddr_private) + numvirtchips * sizeof(struct flchip), GFP_KERNEL); if (!retlpddr) return NULL; - memset(retlpddr, 0, sizeof(struct lpddr_private) + - numvirtchips * sizeof(struct flchip)); memcpy(retlpddr, &lpddr, sizeof(struct lpddr_private)); retlpddr->numchips = numvirtchips; diff -u -p a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c --- a/drivers/mtd/maps/ixp2000.c +++ b/drivers/mtd/maps/ixp2000.c @@ -165,12 +165,11 @@ static int ixp2000_flash_probe(struct pl return -EIO; } - info = kmalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL); + info = kzalloc(sizeof(struct ixp2000_flash_info), GFP_KERNEL); if(!info) { err = -ENOMEM; goto Error; } - memset(info, 0, sizeof(struct ixp2000_flash_info)); platform_set_drvdata(dev, info); diff -u -p a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -196,12 +196,11 @@ static int ixp4xx_flash_probe(struct pla return err; } - info = kmalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL); + info = kzalloc(sizeof(struct ixp4xx_flash_info), GFP_KERNEL); if(!info) { err = -ENOMEM; goto Error; } - memset(info, 0, sizeof(struct ixp4xx_flash_info)); platform_set_drvdata(dev, info); diff -u -p a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -63,11 +63,10 @@ static int __init pxa2xx_flash_probe(str if (!res) return -ENODEV; - info = kmalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL); + info = kzalloc(sizeof(struct pxa2xx_flash_info), GFP_KERNEL); if (!info) return -ENOMEM; - memset(info, 0, sizeof(struct pxa2xx_flash_info)); info->map.name = (char *) flash->name; info->map.bankwidth = flash->width; info->map.phys = res->start; diff -u -p a/drivers/mtd/tests/mtd_pagetest.c b/drivers/mtd/tests/mtd_pagetest.c --- a/drivers/mtd/tests/mtd_pagetest.c +++ b/drivers/mtd/tests/mtd_pagetest.c @@ -480,12 +480,11 @@ static int scan_for_bad_eraseblocks(void { int i, bad = 0; - bbt = kmalloc(ebcnt, GFP_KERNEL); + bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { printk(PRINT_PREF "error: cannot allocate memory\n"); return -ENOMEM; } - memset(bbt, 0 , ebcnt); printk(PRINT_PREF "scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { diff -u -p a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c --- a/drivers/mtd/tests/mtd_readtest.c +++ b/drivers/mtd/tests/mtd_readtest.c @@ -141,12 +141,11 @@ static int scan_for_bad_eraseblocks(void { int i, bad = 0; - bbt = kmalloc(ebcnt, GFP_KERNEL); + bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { printk(PRINT_PREF "error: cannot allocate memory\n"); return -ENOMEM; } - memset(bbt, 0 , ebcnt); /* NOR flash does not implement block_isbad */ if (mtd->block_isbad == NULL) diff -u -p a/drivers/mtd/tests/mtd_speedtest.c b/drivers/mtd/tests/mtd_speedtest.c --- a/drivers/mtd/tests/mtd_speedtest.c +++ b/drivers/mtd/tests/mtd_speedtest.c @@ -295,12 +295,11 @@ static int scan_for_bad_eraseblocks(void { int i, bad = 0; - bbt = kmalloc(ebcnt, GFP_KERNEL); + bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { printk(PRINT_PREF "error: cannot allocate memory\n"); return -ENOMEM; } - memset(bbt, 0 , ebcnt); /* NOR flash does not implement block_isbad */ if (mtd->block_isbad == NULL) diff -u -p a/drivers/mtd/tests/mtd_stresstest.c b/drivers/mtd/tests/mtd_stresstest.c --- a/drivers/mtd/tests/mtd_stresstest.c +++ b/drivers/mtd/tests/mtd_stresstest.c @@ -221,12 +221,11 @@ static int scan_for_bad_eraseblocks(void { int i, bad = 0; - bbt = kmalloc(ebcnt, GFP_KERNEL); + bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { printk(PRINT_PREF "error: cannot allocate memory\n"); return -ENOMEM; } - memset(bbt, 0 , ebcnt); /* NOR flash does not implement block_isbad */ if (mtd->block_isbad == NULL) diff -u -p a/drivers/mtd/tests/mtd_subpagetest.c b/drivers/mtd/tests/mtd_subpagetest.c --- a/drivers/mtd/tests/mtd_subpagetest.c +++ b/drivers/mtd/tests/mtd_subpagetest.c @@ -354,12 +354,11 @@ static int scan_for_bad_eraseblocks(void { int i, bad = 0; - bbt = kmalloc(ebcnt, GFP_KERNEL); + bbt = kzalloc(ebcnt, GFP_KERNEL); if (!bbt) { printk(PRINT_PREF "error: cannot allocate memory\n"); return -ENOMEM; } - memset(bbt, 0 , ebcnt); printk(PRINT_PREF "scanning for bad eraseblocks\n"); for (i = 0; i < ebcnt; ++i) { From dwmw2 at infradead.org Thu May 13 19:06:58 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 00:06:58 +0100 Subject: [PATCH] mtd: cfi_cmdset_0001: Fix max timeout for locking operations In-Reply-To: <4B8834FB.2070004@netinsight.net> References: <4B8834FB.2070004@netinsight.net> Message-ID: <1273792018.9999.268.camel@macbook.infradead.org> On Fri, 2010-02-26 at 21:54 +0100, Anders Grafstr?m wrote: > The max timeout is currently too short for some flash chips. > This patch increases it to 10 seconds. The typical timeout > remains unchanged (the tick period, 1000000/HZ). > > Specification change #11 in '5 Volt Intel StrataFlash Memory Specification Update' > (297848-15) specifies an increase of Clear Block Lock-Bit Time Max to 7 sec. > This is contradicted by the table in Specification Change #8 which says .70 sec > but a 10 sec timeout doesn't hurt so play it safe. > > Signed-off-by: Anders Grafstr?m > --- > drivers/mtd/chips/cfi_cmdset_0001.c | 2 +- > 1 files changed, 1 insertions(+), 1 deletions(-) > > diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c > index 9253043..83e4ae2 100644 > --- a/drivers/mtd/chips/cfi_cmdset_0001.c > +++ b/drivers/mtd/chips/cfi_cmdset_0001.c > @@ -2077,7 +2077,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip > */ > udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; > > - ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100); > + ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * HZ * 10); I don't see how this makes any sense. What is the _unit_ of the argument you're changing? Is it ?s, is it ticks? You aren't just changing the value here; you're actually changing the units. The dimensional analysis doesn't make sense. AFAICT this really is supposed to be ?s, so multiplying by HZ has to be wrong. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 19:36:20 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 00:36:20 +0100 Subject: [PATCH] [MTD] physmap: remove physmap_flash_shutdown() method. In-Reply-To: <1268400366-14802-1-git-send-email-vzapolskiy@gmail.com> References: <1268400366-14802-1-git-send-email-vzapolskiy@gmail.com> Message-ID: <1273793780.9999.359.camel@macbook.infradead.org> On Fri, 2010-03-12 at 16:26 +0300, Vladimir Zapolskiy wrote: > physmap driver operates with cfi, jedec, qinfo and map_rom compliant > chips. None of interface drivers for all these chips uses actual > suspend and resume chip operations, but correspondent two methods only > change flash chip state in drivers' internal state machines, and for > Intel chips save/restore block locks is done. > > To operate with boards with Intel flash chips where RP# pin is not > asserted on reset there is an already implemented mechanism of reboot > notifiers, and on reboot the flash moves into defined "read array" > state. > > If CONFIG_PM kernel option is enabled, then physmap_flash_shutdown() > method is called after reboot notifier work, and save/restore block > locks operations disturb the chip from default "read array" state, > thus if the flash is a bootable one, board cann't be booted from it > after reset. I think this is the wrong approach. We should instead remove the reboot notifier, and keep the shutdown() method called through the map driver, which is in the right place in the power management tree. I'd much rather see a patch which does that. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 19:50:29 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 00:50:29 +0100 Subject: [PATCH 1/2] mtdpart: memory accessor interface for MTD layer In-Reply-To: <1268772081-6534-1-git-send-email-khilman@deeprootsystems.com> References: <1268772081-6534-1-git-send-email-khilman@deeprootsystems.com> Message-ID: <1273794629.9999.412.camel@macbook.infradead.org> On Tue, 2010-03-16 at 13:41 -0700, Kevin Hilman wrote: > From: Sudhakar Rajashekhara > > This patch implements memory accessor interface in the MTD > layer which enables the kernel to access flash data. > > This patch adds two new members to the mtd_partition structure, > a function handler which will be called during setup of the > partition and an argument to be passed to this setup function. Ick. I don't mind providing the mtd_macc_{read,write} helper functions, although they should work on generic MTD devices not just on partitions. But do we really have to do the callout to arbitrary functions from _within_ the core MTD code... why can't we do that in the board driver? -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 20:19:39 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 01:19:39 +0100 Subject: [PATCH v5 5/9] [MTD] remove bogus warning about missing boot bank location In-Reply-To: <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> References: <20100424155751.14723.46761.stgit@shiryu.yomgui.biz> <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> Message-ID: <1273796379.9999.509.camel@macbook.infradead.org> On Sat, 2010-04-24 at 17:58 +0200, Guillaume LECERF wrote: > From: Uwe Kleine-K?nig > > After the deleted block bootloc is only used once as follows: > > if (bootloc == 3 && something_else) { > ... > > So setting bootloc = 2 doesn't change anything. Taking that the > warning is wrong and missleading. > > Signed-off-by: Uwe Kleine-K?nig > Signed-off-by: Guillaume LECERF > Acked-by: Christopher Moore The warning should be preserved for invalid values, or values we don't support. I don't think it's correct to just remove it. Looking at the latest datasheet, it looks like values of 0x04 or 0x05 are acceptable, meaning "Uniform, bottom WP protect" and "Uniform, top WP protect" respectively. Zero is acceptable only for pre-CFI 1.1 devices, and in that case it says "refer to device ID code for Top/Bottom boot version of AM29LV160 or AM29LV116". But perhaps we should just probe such devices using the JEDEC mode anyway. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 20:44:48 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 01:44:48 +0100 Subject: [PATCH 1/2] mtd/chips: add SST39WF160x NOR-flashes In-Reply-To: <1272334774-17019-1-git-send-email-w.sang@pengutronix.de> References: <1272334774-17019-1-git-send-email-w.sang@pengutronix.de> Message-ID: <1273797888.9999.591.camel@macbook.infradead.org> On Tue, 2010-04-27 at 04:19 +0200, Wolfram Sang wrote: > Due to a broken CFI, they have to be added to jedec_probe. > > Signed-off-by: Wolfram Sang > Cc: Artem Bityutskiy > Cc: David Woodhouse > --- > > Sadly, those two cannot be detected using Guillaume's SST-patchset. Why not? Guillaume has patches which add quirks for specific SST chips; what is fundamentally different about these chips that means you can't take the same approach? > drivers/mtd/chips/jedec_probe.c | 30 ++++++++++++++++++++++++++++++ > 1 files changed, 30 insertions(+), 0 deletions(-) > > diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c > index 8db1148..6850b23 100644 > --- a/drivers/mtd/chips/jedec_probe.c > +++ b/drivers/mtd/chips/jedec_probe.c > @@ -166,6 +166,8 @@ > #define SST39LF160 0x2782 > #define SST39VF1601 0x234b > #define SST39VF3201 0x235b > +#define SST39WF1601 0x274b > +#define SST39WF1602 0x274a > #define SST39LF512 0x00D4 > #define SST39LF010 0x00D5 > #define SST39LF020 0x00D6 > @@ -1529,6 +1531,34 @@ static const struct amd_flash_info jedec_table[] = { > ERASEINFO(0x1000,256) > } > }, { > + /* CFI is broken: reports AMD_STD, but needs custom uaddr */ > + .mfr_id = MANUFACTURER_SST, > + .dev_id = SST39WF1601, > + .name = "SST 39WF1601", > + .devtypes = CFI_DEVICETYPE_X16, > + .uaddr = MTD_UADDR_0xAAAA_0x5555, > + .dev_size = SIZE_2MiB, > + .cmd_set = P_ID_AMD_STD, > + .nr_regions = 2, > + .regions = { > + ERASEINFO(0x1000,256), > + ERASEINFO(0x1000,256) > + } > + }, { > + /* CFI is broken: reports AMD_STD, but needs custom uaddr */ > + .mfr_id = MANUFACTURER_SST, > + .dev_id = SST39WF1602, > + .name = "SST 39WF1602", > + .devtypes = CFI_DEVICETYPE_X16, > + .uaddr = MTD_UADDR_0xAAAA_0x5555, > + .dev_size = SIZE_2MiB, > + .cmd_set = P_ID_AMD_STD, > + .nr_regions = 2, > + .regions = { > + ERASEINFO(0x1000,256), > + ERASEINFO(0x1000,256) > + } > + }, { > .mfr_id = MANUFACTURER_SST, /* should be CFI */ > .dev_id = SST39VF3201, > .name = "SST 39VF3201", -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 21:04:34 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 02:04:34 +0100 Subject: [PATCH v4] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1273074054-11849-1-git-send-email-kirill@shutemov.name> References: <1273074054-11849-1-git-send-email-kirill@shutemov.name> Message-ID: <1273799074.9999.653.camel@macbook.infradead.org> On Wed, 2010-05-05 at 18:40 +0300, Kirill A. Shutemov wrote: > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > backing device of device node inode, since file->f_mapping is equal to > inode->i_mapping (see __dentry_open() in fs/open.c). > > Let's introduce separate inode for MTD device with appropriate backing > device. I hate the fact that we have to do this -- is it really the only option? Is it _just_ for the backing_device_info? Can't that be done differently? > @@ -85,11 +88,27 @@ static int mtd_open(struct inode *inode, struct file *file) > goto out; > } > > - if (mtd->backing_dev_info) > - file->f_mapping->backing_dev_info = mtd->backing_dev_info; > + if (!mtd->inode) { > + mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); I believe that would be a race condition, if it wasn't for the BKL. And what happens when you close the chardevice and call iput() on the inode so it's destroyed, and then you re-open the device? You never set mtd->inode = NULL, so won't it now try to igrab a stale pointer? You won't have seen this in your testing unless you made it prune the icache between the close and open calls. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From w.sang at pengutronix.de Thu May 13 21:20:23 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Fri, 14 May 2010 03:20:23 +0200 Subject: [PATCH 1/2] mtd/chips: add SST39WF160x NOR-flashes In-Reply-To: <1273797888.9999.591.camel@macbook.infradead.org> References: <1272334774-17019-1-git-send-email-w.sang@pengutronix.de> <1273797888.9999.591.camel@macbook.infradead.org> Message-ID: <20100514012023.GA30794@pengutronix.de> On Fri, May 14, 2010 at 01:44:48AM +0100, David Woodhouse wrote: > On Tue, 2010-04-27 at 04:19 +0200, Wolfram Sang wrote: > > Due to a broken CFI, they have to be added to jedec_probe. > > > > Signed-off-by: Wolfram Sang > > Cc: Artem Bityutskiy > > Cc: David Woodhouse > > --- > > > > Sadly, those two cannot be detected using Guillaume's SST-patchset. > > Why not? Guillaume has patches which add quirks for specific SST chips; > what is fundamentally different about these chips that means you can't > take the same approach? See his patch 3/8. He introduces: +#define P_ID_SST_OLD 0x0701 so, he can then do: + if (cfi->cfiq->P_ID == P_ID_SST_OLD) { + addr_unlock1 = 0x5555; + addr_unlock2 = 0x2AAA; + } + Only after that, he can query for more CFI-information/product ID and apply the quirks. My flashes don't have P_ID_SST_OLD, sadly, but P_ID_AMD_STD. Still, unlike other AMD_STD-flashes, my flashes need their custom unlock address. I couldn't find a way to distinguish this from the standard case with the regular unlock addresses. Kind regards, Wolfram -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: Digital signature URL: From dwmw2 at infradead.org Thu May 13 21:28:41 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 02:28:41 +0100 Subject: [PATCH 1/2] mtd/chips: add SST39WF160x NOR-flashes In-Reply-To: <20100514012023.GA30794@pengutronix.de> References: <1272334774-17019-1-git-send-email-w.sang@pengutronix.de> <1273797888.9999.591.camel@macbook.infradead.org> <20100514012023.GA30794@pengutronix.de> Message-ID: <1273800521.9999.726.camel@macbook.infradead.org> On Fri, 2010-05-14 at 03:20 +0200, Wolfram Sang wrote: > My flashes don't have P_ID_SST_OLD, sadly, but P_ID_AMD_STD. Still, unlike > other AMD_STD-flashes, my flashes need their custom unlock address. I couldn't > find a way to distinguish this from the standard case with the regular unlock > addresses. Makes sense; thanks for the clarification. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 22:24:50 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 03:24:50 +0100 Subject: [git pull] pcmciamtd fixes In-Reply-To: <20100513095749.GA25909@comet.dominikbrodowski.net> References: <20100513095749.GA25909@comet.dominikbrodowski.net> Message-ID: <1273803890.9999.866.camel@macbook.infradead.org> On Thu, 2010-05-13 at 11:57 +0200, Dominik Brodowski wrote: > Alexander Kurz spent quite some time to fix pcmciamtd to not only build > again, but to actually work on some cards he owns. In addition, there are a > few more PCMCIA IDs to report, and Julia Lawall reported and fixed an > use-after-free bug in pcmciamtd. Could you pick up these patches and pull > from I already had Julia's patch; I've picked up the other three. Thanks. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Thu May 13 22:32:44 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 03:32:44 +0100 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: References: Message-ID: <1273804364.9999.881.camel@macbook.infradead.org> On Thu, 2010-05-06 at 05:12 -0400, Haojian Zhuang wrote: > From c81c53e24bbbe29ab4bf9767d24de8c45a4470b9 Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Thu, 6 May 2010 10:42:13 +0800 > Subject: [PATCH] pxa3xx_nand: add cmdline part parser support > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > drivers/mtd/nand/pxa3xx_nand.c | 26 ++++++++++++++++++++++++-- > 1 files changed, 24 insertions(+), 2 deletions(-) This conflicts with commit bff3c10d369440bc87ba612b45ba2777d2bf017f. Some of the other patches in this sequence don't apply cleanly to the current mtd-2.6.git tree either; please could you refresh? -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From haojian.zhuang at gmail.com Fri May 14 02:08:56 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:08:56 +0800 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: <1273804364.9999.881.camel@macbook.infradead.org> References: <1273804364.9999.881.camel@macbook.infradead.org> Message-ID: On Fri, May 14, 2010 at 10:32 AM, David Woodhouse wrote: > On Thu, 2010-05-06 at 05:12 -0400, Haojian Zhuang wrote: >> From c81c53e24bbbe29ab4bf9767d24de8c45a4470b9 Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Thu, 6 May 2010 10:42:13 +0800 >> Subject: [PATCH] pxa3xx_nand: add cmdline part parser support >> >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?drivers/mtd/nand/pxa3xx_nand.c | ? 26 ++++++++++++++++++++++++-- >> ?1 files changed, 24 insertions(+), 2 deletions(-) > > This conflicts with commit bff3c10d369440bc87ba612b45ba2777d2bf017f. > > Some of the other patches in this sequence don't apply cleanly to the > current mtd-2.6.git tree either; please could you refresh? > New patches are rebased for mtd-2.6 master branch. There're contained in another mail loop. Thanks Haojian From haojian.zhuang at gmail.com Fri May 14 02:11:47 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:11:47 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:12:42 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:12:42 +0800 Subject: [PATCH 02/20] mtd: pxa3xx_nand: introduce common timing to reduce read id times Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:13:32 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:13:32 +0800 Subject: [PATCH 03/20] mtd: pxa3xx_nand: remove the flash info in driver structure Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:14:22 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:14:22 +0800 Subject: [PATCH 04/20] mtd: pxa3xx_nand: make scan procedure more clear Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:15:11 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:15:11 +0800 Subject: [PATCH 05/20] mtd: pxa3xx_nand: rework irq logic Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:16:00 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:16:00 +0800 Subject: [PATCH 06/20] mtd: pxa3xx_nand: unify prepare command Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:16:44 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:16:44 +0800 Subject: [PATCH 07/20] mtd: pxa3xx_nand: mtd scan id process could be defined by driver itself Message-ID: From leiwen at marvell.com Wed May 5 21:48:30 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 09:48:30 +0800 Subject: [PATCH] mtd: pxa3xx_nand: mtd scan id process could be Message-ID: defined by driver itself Different NAND driver may require its unique detection. For pxa3xx_nand, it use its self id database to get the necessary info. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 257 +++++++++++++++++++++++++++++----------- 1 files changed, 185 insertions(+), 72 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 854adad..7a8ff38 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -255,6 +255,8 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, }, }; +static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; + #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) #define NDTR0_tWH(c) (min((c), 7) << 11) @@ -893,37 +895,6 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) return 0; } -static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, - const struct pxa3xx_nand_platform_data *pdata) -{ - const struct pxa3xx_nand_flash *f; - uint32_t id = -1; - int i; - - if (pdata->keep_config) - if (pxa3xx_nand_detect_config(info) == 0) - return 0; - - f = &builtin_flash_types[0]; - pxa3xx_nand_config_flash(info, f); - pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); - id = *((uint16_t *)(info->data_buff)); - - for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { - f = &builtin_flash_types[i]; - if (f->chip_id == id) { - dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); - pxa3xx_nand_config_flash(info, f); - return 0; - } - } - - dev_warn(&info->pdev->dev, - "failed to detect configured nand flash; found %04x instead of\n", - id); - return -ENODEV; -} - /* the maximum possible buffer size for large page with OOB data * is: 2048 + 64 = 2112 bytes, allocate a page here for both the * data buffer and the DMA descriptor @@ -980,41 +951,174 @@ static struct nand_ecclayout hw_largepage_ecclayout = { .oobfree = { {2, 38} } }; -static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, - struct pxa3xx_nand_info *info) +static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, uint8_t *buf, int page) +{ + struct pxa3xx_nand_info *info = mtd->priv; + + chip->read_buf(mtd, buf, mtd->writesize); + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + + if (info->retcode == ERR_SBERR) { + switch (info->use_ecc) { + case 1: + mtd->ecc_stats.corrected ++; + break; + + case 0: + default: + break; + } + } + else if (info->retcode == ERR_DBERR) { + int buf_blank; + + buf_blank = is_buf_blank(buf, mtd->writesize); + if (!buf_blank) + mtd->ecc_stats.failed++; + } + + return 0; +} + +static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, + struct nand_chip *chip, const uint8_t *buf) +{ + chip->write_buf(mtd, buf, mtd->writesize); + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); +} + +static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page) { - struct nand_chip *this = &info->nand_chip; - - this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; - - this->waitfunc = pxa3xx_nand_waitfunc; - this->select_chip = pxa3xx_nand_select_chip; - this->dev_ready = pxa3xx_nand_dev_ready; - this->cmdfunc = pxa3xx_nand_cmdfunc; - this->read_word = pxa3xx_nand_read_word; - this->read_byte = pxa3xx_nand_read_byte; - this->read_buf = pxa3xx_nand_read_buf; - this->write_buf = pxa3xx_nand_write_buf; - this->verify_buf = pxa3xx_nand_verify_buf; - - this->ecc.mode = NAND_ECC_HW; - this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; - this->ecc.calculate = pxa3xx_nand_ecc_calculate; - this->ecc.correct = pxa3xx_nand_ecc_correct; - this->ecc.size = info->page_size; - - if (info->page_size == 2048) - this->ecc.layout = &hw_largepage_ecclayout; + struct nand_chip *chip = mtd->priv; + /* Send commands to erase a block */ + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); +} + +static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) +{ + struct mtd_info *mtd = info->mtd; + struct nand_chip *chip = mtd->priv; + + /* use the common timing to make a try */ + pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); + chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); + if (info->state & STATE_READY) + return 1; else - this->ecc.layout = &hw_smallpage_ecclayout; + return 0; +} + +static int pxa3xx_nand_scan(struct mtd_info *mtd) +{ + struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_flash *f; + struct nand_chip *chip = mtd->priv; + uint32_t id = -1; + int i, ret; - this->chip_delay = 25; + ret = pxa3xx_nand_sensing(info); + if (!ret) { + kfree(mtd); + info->mtd = NULL; + printk(KERN_INFO "There is no nand chip on cs 0!\n"); + + return -EINVAL; + } + + chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); + if (id != 0) + printk(KERN_INFO "Detect a flash id %x\n", id); + else { + kfree(mtd); + info->mtd = NULL; + printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); + + return -EINVAL; + } + + for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { + + f = &builtin_flash_types[i]; + + /* find the chip in default list */ + if (f->chip_id == id) { + pxa3xx_nand_config_flash(info, f); + chip->cellinfo = info->data_buff[2]; + mtd->writesize = f->page_size; + mtd->writesize_shift = ffs(mtd->writesize) - 1; + mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; + mtd->oobsize = mtd->writesize / 32; + mtd->erasesize = f->page_size * f->page_per_block; + mtd->erasesize_shift = ffs(mtd->erasesize) - 1; + mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; + + mtd->name = mtd_names[0]; + break; + } + } + + if (i == ARRAY_SIZE(builtin_flash_types)) { + kfree(mtd); + info->mtd = NULL; + printk(KERN_ERR "ERROR!! flash not defined!!!\n"); + + return -EINVAL; + } + + chip->ecc.mode = NAND_ECC_HW; + chip->ecc.size = f->page_size; + if (f->page_size == 2048) + chip->ecc.layout = &hw_largepage_ecclayout; + else + chip->ecc.layout = &hw_smallpage_ecclayout; + + chip->chipsize = (uint64_t)f->num_blocks * \ + f->page_per_block * \ + f->page_size; + + chip->chip_shift = ffs(chip->chipsize) - 1; + mtd->size = chip->chipsize; + + /* Calculate the address shift from the page size */ + chip->page_shift = ffs(mtd->writesize) - 1; + chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; + chip->numchips = 1; + chip->chip_delay = 25; + chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1; + + /* Set the bad block position */ + chip->badblockpos = mtd->writesize > 512 ? + NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; + + chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; + chip->options |= NAND_NO_AUTOINCR; + chip->options |= NAND_NO_READRDY; + chip->options |= NAND_USE_FLASH_BBT; + + return nand_scan_tail(mtd); +} + +static int pxa3xx_nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct nand_chip *chip = mtd->priv; + int block; + + block = (int)(ofs >> chip->bbt_erase_shift); + chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); + return nand_update_bbt(mtd, ofs); +} + +static int pxa3xx_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) +{ + return 0; } static int alloc_nand_resource(struct platform_device *pdev) { - struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; struct pxa3xx_nand_info *info; + struct nand_chip *chip; struct mtd_info *mtd; struct resource *r; int ret, irq; @@ -1027,12 +1131,31 @@ static int alloc_nand_resource(struct platform_device *pdev) } info = (struct pxa3xx_nand_info *)(&mtd[1]); + chip = (struct nand_chip *)(&mtd[1]); info->pdev = pdev; - - mtd->priv = info; info->mtd = mtd; + mtd->priv = info; mtd->owner = THIS_MODULE; + chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; + chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->ecc.hwctl = pxa3xx_nand_ecc_hwctl; + chip->ecc.calculate = pxa3xx_nand_ecc_calculate; + chip->ecc.correct = pxa3xx_nand_ecc_correct; + chip->waitfunc = pxa3xx_nand_waitfunc; + chip->select_chip = pxa3xx_nand_select_chip; + chip->dev_ready = pxa3xx_nand_dev_ready; + chip->cmdfunc = pxa3xx_nand_cmdfunc; + chip->read_word = pxa3xx_nand_read_word; + chip->read_byte = pxa3xx_nand_read_byte; + chip->read_buf = pxa3xx_nand_read_buf; + chip->write_buf = pxa3xx_nand_write_buf; + chip->verify_buf = pxa3xx_nand_verify_buf; + chip->block_markbad = pxa3xx_nand_default_block_markbad; + chip->block_bad = pxa3xx_nand_block_bad; + chip->scan_bbt = nand_default_bbt; + chip->erase_cmd = pxa3xx_nand_erase_cmd; + info->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(info->clk)) { dev_err(&pdev->dev, "failed to get nand clock\n"); @@ -1100,21 +1223,11 @@ static int alloc_nand_resource(struct platform_device *pdev) goto fail_free_buf; } - ret = pxa3xx_nand_detect_flash(info, pdata); - if (ret) { - dev_err(&pdev->dev, "failed to detect flash\n"); - ret = -ENODEV; - goto fail_free_irq; - } - - pxa3xx_nand_init_mtd(mtd, info); platform_set_drvdata(pdev, info); - return 0; -fail_free_irq: - free_irq(irq, info); fail_free_buf: + free_irq(irq, info); if (use_dma) { pxa_free_dma(info->data_dma_ch); dma_free_coherent(&pdev->dev, info->data_buff_size, @@ -1182,7 +1295,7 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) return ret; info = platform_get_drvdata(pdev); - if (nand_scan(info->mtd, 1)) { + if (pxa3xx_nand_scan(info->mtd)) { dev_err(&pdev->dev, "failed to scan nand\n"); pxa3xx_nand_remove(pdev); return -ENODEV; -- 1.5.6.5 From moore at free.fr Fri May 14 02:17:13 2010 From: moore at free.fr (Chris Moore) Date: Fri, 14 May 2010 08:17:13 +0200 Subject: [PATCH v5 5/9] [MTD] remove bogus warning about missing boot bank location In-Reply-To: <1273796379.9999.509.camel@macbook.infradead.org> References: <20100424155751.14723.46761.stgit@shiryu.yomgui.biz> <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> <1273796379.9999.509.camel@macbook.infradead.org> Message-ID: <4BECEAE9.2030008@free.fr> Le 14/05/2010 02:19, David Woodhouse a ?crit : > On Sat, 2010-04-24 at 17:58 +0200, Guillaume LECERF wrote: > >> From: Uwe Kleine-K?nig >> >> After the deleted block bootloc is only used once as follows: >> >> if (bootloc == 3&& something_else) { >> ... >> >> So setting bootloc = 2 doesn't change anything. Taking that the >> warning is wrong and missleading. >> >> Signed-off-by: Uwe Kleine-K?nig >> Signed-off-by: Guillaume LECERF >> Acked-by: Christopher Moore >> > The warning should be preserved for invalid values, or values we don't > support. I don't think it's correct to just remove it. > > But, David, the only effect of this code is to print an *erroneous* message. The message says "Assuming top" but sets bootloc to bottom (2) :( See this thread: http://thread.gmane.org/gmane.linux.drivers.mtd/22176 Remark: this would be even clearer if the bootloc values were macros instead of 2, 3, ... If you really want to keep the message then it must at least be changed to "Assuming bottom". Cheers, Chris From haojian.zhuang at gmail.com Fri May 14 02:17:29 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:17:29 +0800 Subject: [PATCH 08/20] mtd: pxa3xx_nand: remove detect configure function Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:18:13 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:18:13 +0800 Subject: [PATCH 09/20] mtd: pxa3xx_nand: add two chip select Message-ID: From leiwen at marvell.com Fri May 14 01:27:20 2010 From: leiwen at marvell.com (Lei Wen) Date: Fri, 14 May 2010 13:27:20 +0800 Subject: [PATCH] mtd: pxa3xx_nand: add two chip select Message-ID: Current pxa3xx_nand controller has two chip select which both be workable. This patch enable this feature. Update platform driver to support this feature. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- arch/arm/mach-mmp/aspenite.c | 4 +- arch/arm/mach-mmp/avengers_lite.c | 51 ++ arch/arm/mach-pxa/cm-x300.c | 4 +- arch/arm/mach-pxa/colibri-pxa3xx.c | 4 +- arch/arm/mach-pxa/littleton.c | 4 +- arch/arm/mach-pxa/mxm8x10.c | 8 +- arch/arm/mach-pxa/raumfeld.c | 4 +- arch/arm/mach-pxa/zylonite.c | 4 +- arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 5 +- drivers/mtd/nand/pxa3xx_nand.c | 674 ++++++++++++++------------ 10 files changed, 422 insertions(+), 340 deletions(-) diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c index a2d307e..c55c904 100644 --- a/arch/arm/mach-mmp/aspenite.c +++ b/arch/arm/mach-mmp/aspenite.c @@ -119,8 +119,8 @@ static struct mtd_partition aspenite_nand_partitions[] = { static struct pxa3xx_nand_platform_data aspenite_nand_info = { .enable_arbiter = 1, - .parts = aspenite_nand_partitions, - .nr_parts = ARRAY_SIZE(aspenite_nand_partitions), + .parts[0] = aspenite_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(aspenite_nand_partitions), }; static void __init common_init(void) diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c index 8c3fa5d..8a2883f 100644 --- a/arch/arm/mach-mmp/avengers_lite.c +++ b/arch/arm/mach-mmp/avengers_lite.c @@ -32,12 +32,63 @@ static unsigned long avengers_lite_pin_config_V16F[] __initdata = { GPIO89_UART2_RXD, }; +static struct mtd_partition avengers_nand_partitions_0[] = { + { + .name = "bootloader", + .offset = 0, + .size = SZ_1M, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "kernel", + .offset = MTDPART_OFS_APPEND, + .size = (SZ_2M + SZ_1M), + }, { + .name = "mass0", + .offset = MTDPART_OFS_APPEND, + .size = SZ_48M, + } +}; + +static struct mtd_partition avengers_nand_partitions_1[] = { + { + .name = "reserved", + .offset = 0, + .size = SZ_2M, + .mask_flags = MTD_WRITEABLE, + }, { + .name = "filesystem", + .offset = MTDPART_OFS_APPEND, + .size = SZ_512M, + }, { + .name = "mass1", + .offset = MTDPART_OFS_APPEND, + .size = SZ_16M, + }, { + .name = "mass2", + .offset = MTDPART_OFS_APPEND, + .size = SZ_256M, + } +}; + +static struct pxa3xx_nand_platform_data avengers_nand_info; +static void __init avengers_init_flash(void) +{ + avengers_nand_info.parts[0] = avengers_nand_partitions_0; + avengers_nand_info.nr_parts[0] = ARRAY_SIZE(avengers_nand_partitions_0); + avengers_nand_info.parts[1] = avengers_nand_partitions_1; + avengers_nand_info.nr_parts[1] = ARRAY_SIZE(avengers_nand_partitions_1); + avengers_nand_info.enable_arbiter = 1; + avengers_nand_info.naked_cmd_support = 1; + pxa168_add_nand(&avengers_nand_info); +} + static void __init avengers_lite_init(void) { mfp_config(ARRAY_AND_SIZE(avengers_lite_pin_config_V16F)); /* on-chip devices */ pxa168_add_uart(2); + avengers_init_flash(); } MACHINE_START(AVENGERS_LITE, "PXA168 Avengers lite Development Platform") diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c index d37cfa1..696cfea 100644 --- a/arch/arm/mach-pxa/cm-x300.c +++ b/arch/arm/mach-pxa/cm-x300.c @@ -416,8 +416,8 @@ static struct mtd_partition cm_x300_nand_partitions[] = { static struct pxa3xx_nand_platform_data cm_x300_nand_info = { .enable_arbiter = 1, .keep_config = 1, - .parts = cm_x300_nand_partitions, - .nr_parts = ARRAY_SIZE(cm_x300_nand_partitions), + .parts[0] = cm_x300_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(cm_x300_nand_partitions), }; static void __init cm_x300_init_nand(void) diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c index e6c0a22..6c0fcf7 100644 --- a/arch/arm/mach-pxa/colibri-pxa3xx.c +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c @@ -188,8 +188,8 @@ static struct mtd_partition colibri_nand_partitions[] = { static struct pxa3xx_nand_platform_data colibri_nand_info = { .enable_arbiter = 1, .keep_config = 1, - .parts = colibri_nand_partitions, - .nr_parts = ARRAY_SIZE(colibri_nand_partitions), + .parts[0] = colibri_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(colibri_nand_partitions), }; void __init colibri_pxa3xx_init_nand(void) diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c index fa527b2..a643735 100644 --- a/arch/arm/mach-pxa/littleton.c +++ b/arch/arm/mach-pxa/littleton.c @@ -326,8 +326,8 @@ static struct mtd_partition littleton_nand_partitions[] = { static struct pxa3xx_nand_platform_data littleton_nand_info = { .enable_arbiter = 1, - .parts = littleton_nand_partitions, - .nr_parts = ARRAY_SIZE(littleton_nand_partitions), + .parts[0] = littleton_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(littleton_nand_partitions), }; static void __init littleton_init_nand(void) diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c index 8c9c6f0..922c445 100644 --- a/arch/arm/mach-pxa/mxm8x10.c +++ b/arch/arm/mach-pxa/mxm8x10.c @@ -389,10 +389,10 @@ static struct mtd_partition mxm_8x10_nand_partitions[] = { }; static struct pxa3xx_nand_platform_data mxm_8x10_nand_info = { - .enable_arbiter = 1, - .keep_config = 1, - .parts = mxm_8x10_nand_partitions, - .nr_parts = ARRAY_SIZE(mxm_8x10_nand_partitions) + .enable_arbiter = 1, + .keep_config = 1, + .parts[0] = mxm_8x10_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(mxm_8x10_nand_partitions) }; static void __init mxm_8x10_nand_init(void) diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c index d12667b..a7aec23 100644 --- a/arch/arm/mach-pxa/raumfeld.c +++ b/arch/arm/mach-pxa/raumfeld.c @@ -350,8 +350,8 @@ static struct mtd_partition raumfeld_nand_partitions[] = { static struct pxa3xx_nand_platform_data raumfeld_nand_info = { .enable_arbiter = 1, .keep_config = 1, - .parts = raumfeld_nand_partitions, - .nr_parts = ARRAY_SIZE(raumfeld_nand_partitions), + .parts[0] = raumfeld_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(raumfeld_nand_partitions), }; /** diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c index 2b4043c..bcc3850 100644 --- a/arch/arm/mach-pxa/zylonite.c +++ b/arch/arm/mach-pxa/zylonite.c @@ -356,8 +356,8 @@ static struct mtd_partition zylonite_nand_partitions[] = { static struct pxa3xx_nand_platform_data zylonite_nand_info = { .enable_arbiter = 1, - .parts = zylonite_nand_partitions, - .nr_parts = ARRAY_SIZE(zylonite_nand_partitions), + .parts[0] = zylonite_nand_partitions, + .nr_parts[0] = ARRAY_SIZE(zylonite_nand_partitions), }; static void __init zylonite_init_nand(void) diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h index c494f68..76ebd21 100644 --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h @@ -4,6 +4,7 @@ #include #include +#define NUM_CHIP_SELECT (2) struct pxa3xx_nand_platform_data { /* the data flash bus is shared between the Static Memory @@ -15,8 +16,8 @@ struct pxa3xx_nand_platform_data { /* allow platform code to keep OBM/bootloader defined NFC config */ int keep_config; - const struct mtd_partition *parts; - unsigned int nr_parts; + const struct mtd_partition *parts[NUM_CHIP_SELECT]; + unsigned int nr_parts[NUM_CHIP_SELECT]; }; extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2c7f925..f8b16be 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -98,6 +98,8 @@ #define nand_readl(info, off) \ __raw_readl((info)->mmio_base + (off)) +#define get_mtd_by_info(info) \ + (struct mtd_info *)((void *)info - sizeof(struct mtd_info)) /* error code and state */ enum { @@ -158,60 +160,62 @@ struct pxa3xx_nand_flash { struct pxa3xx_nand_info { struct nand_chip nand_chip; - struct platform_device *pdev; - - struct clk *clk; - void __iomem *mmio_base; - unsigned long mmio_phys; - - unsigned int buf_start; - unsigned int buf_count; - - struct mtd_info *mtd; - /* DMA information */ - int drcmr_dat; - int drcmr_cmd; - + uint32_t page_size; /* page size of attached chip */ unsigned char *data_buff; unsigned char *oob_buff; + uint32_t buf_start; + uint32_t buf_count; + + /* dma related */ + int data_dma_ch; dma_addr_t data_buff_phys; - size_t data_buff_size; - int data_dma_ch; - struct pxa_dma_desc *data_desc; dma_addr_t data_desc_addr; + struct pxa_dma_desc *data_desc; + uint8_t chip_select; + uint8_t use_ecc; /* use HW ECC ? */ - uint32_t reg_ndcr; - - /* saved column/page_addr during CMD_SEQIN */ - int seqin_column; - int seqin_page_addr; + /* calculated from pxa3xx_nand_flash data */ + uint8_t col_addr_cycles; + uint8_t row_addr_cycles; + uint8_t read_id_bytes; - /* relate to the command */ - unsigned int state; + /* cached register value */ + uint32_t reg_ndcr; + uint32_t ndtr0cs0; + uint32_t ndtr1cs0; + uint32_t ndcb0; + uint32_t ndcb1; + uint32_t ndcb2; - int use_ecc; /* use HW ECC ? */ - int use_dma; /* use DMA ? */ + void *nand_data; +}; - unsigned int page_size; /* page size of attached chip */ - unsigned int data_size; /* data size in FIFO */ - int retcode; +struct pxa3xx_nand { + struct clk *clk; + void __iomem *mmio_base; + unsigned long mmio_phys; + struct nand_hw_control controller; struct completion cmd_complete; + struct platform_device *pdev; - /* generated NDCBx register values */ - uint32_t ndcb0; - uint32_t ndcb1; - uint32_t ndcb2; + uint8_t chip_select; + uint8_t use_ecc; + uint8_t use_dma; + uint8_t wait_mode; - /* timing calcuted from setting */ - uint32_t ndtr0cs0; - uint32_t ndtr1cs0; + /* relate to the command */ + uint32_t state; + uint32_t command; + uint16_t data_size; /* data size in FIFO */ + uint16_t oob_size; + uint32_t bad_count; + uint32_t retcode; - /* calculated from pxa3xx_nand_flash data */ - size_t oob_size; - size_t read_id_bytes; + /* DMA information */ + uint32_t drcmr_dat; + uint32_t drcmr_cmd; - unsigned int col_addr_cycles; - unsigned int row_addr_cycles; + struct pxa3xx_nand_info *info[NUM_CHIP_SELECT]; }; static int use_dma = 1; @@ -240,6 +244,7 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0, 0, 0, 0, 0, 0, { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, }, { 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, { 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, +{ 0xd3ec, 128, 2048, 8, 8, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, { 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, { 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, { 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, @@ -248,7 +253,7 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, 60, 10, }, }, }; -static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; +static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; #define NDTR0_tCH(c) (min((c), 7) << 19) #define NDTR0_tCS(c) (min((c), 7) << 16) @@ -281,9 +286,11 @@ static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_timing *t) { - unsigned long nand_clk = clk_get_rate(info->clk); + struct pxa3xx_nand *nand = info->nand_data; + unsigned long nand_clk; uint32_t ndtr0, ndtr1; + nand_clk = clk_get_rate(nand->clk); ndtr0 = NDTR0_tCH(ns2cycle(t->tCH, nand_clk)) | NDTR0_tCS(ns2cycle(t->tCS, nand_clk)) | NDTR0_tWH(ns2cycle(t->tWH, nand_clk)) | @@ -297,25 +304,26 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, info->ndtr0cs0 = ndtr0; info->ndtr1cs0 = ndtr1; - nand_writel(info, NDTR0CS0, ndtr0); - nand_writel(info, NDTR1CS0, ndtr1); + nand_writel(nand, NDTR0CS0, ndtr0); + nand_writel(nand, NDTR1CS0, ndtr1); } static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) { + struct pxa3xx_nand *nand = info->nand_data; int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; - info->data_size = info->page_size; + nand->data_size = info->page_size; if (!oob_enable) { - info->oob_size = 0; + nand->oob_size = 0; return; } switch (info->page_size) { case 2048: - info->oob_size = (info->use_ecc) ? 40 : 64; + nand->oob_size = (nand->use_ecc) ? 40 : 64; break; case 512: - info->oob_size = (info->use_ecc) ? 8 : 16; + nand->oob_size = (nand->use_ecc) ? 8 : 16; break; } } @@ -326,22 +334,24 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) * We enable all the interrupt at the same time, and * let pxa3xx_nand_irq to handle all logic. */ -static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) +static void pxa3xx_nand_start(struct pxa3xx_nand *nand) { + struct pxa3xx_nand_info *info; uint32_t ndcr; + info = nand->info[nand->chip_select]; ndcr = info->reg_ndcr; - ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; - ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR; + ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0; + ndcr |= nand->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR; ndcr |= NDCR_ND_RUN; /* clear status bits and run */ - nand_writel(info, NDCR, 0); - nand_writel(info, NDSR, NDSR_MASK); - nand_writel(info, NDCR, ndcr); + nand_writel(nand, NDCR, 0); + nand_writel(nand, NDSR, NDSR_MASK); + nand_writel(nand, NDCR, ndcr); } -static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) +static void pxa3xx_nand_stop(struct pxa3xx_nand *nand) { uint32_t ndcr; int timeout = NAND_STOP_DELAY; @@ -349,146 +359,152 @@ static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) /* wait RUN bit in NDCR become 0 */ do { /* clear status bits */ - nand_writel(info, NDSR, NDSR_MASK); - ndcr = nand_readl(info, NDCR); + nand_writel(nand, NDSR, NDSR_MASK); + ndcr = nand_readl(nand, NDCR); udelay(1); } while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0)); if (timeout <= 0) { ndcr &= ~(NDCR_ND_RUN); - nand_writel(info, NDCR, ndcr); + nand_writel(nand, NDCR, ndcr); } } -static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) +static void enable_int(struct pxa3xx_nand *nand, uint32_t int_mask) { uint32_t ndcr; - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~int_mask); + ndcr = nand_readl(nand, NDCR); + nand_writel(nand, NDCR, ndcr & ~int_mask); } -static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) +static void disable_int(struct pxa3xx_nand *nand, uint32_t int_mask) { uint32_t ndcr; - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr | int_mask); + ndcr = nand_readl(nand, NDCR); + nand_writel(nand, NDCR, ndcr | int_mask); } -static void handle_data_pio(struct pxa3xx_nand_info *info) +static void handle_data_pio(struct pxa3xx_nand *nand) { - if (info->state & STATE_IS_WRITE) { - __raw_writesl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); - if (info->oob_size > 0) - __raw_writesl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; + + if (nand->state & STATE_IS_WRITE) { + __raw_writesl(nand->mmio_base + NDDB, info->data_buff, + DIV_ROUND_UP(nand->data_size, 4)); + if (nand->oob_size > 0) + __raw_writesl(nand->mmio_base + NDDB, info->oob_buff, + DIV_ROUND_UP(nand->oob_size, 4)); } else { - __raw_readsl(info->mmio_base + NDDB, info->data_buff, - DIV_ROUND_UP(info->data_size, 4)); - if (info->oob_size > 0) - __raw_readsl(info->mmio_base + NDDB, info->oob_buff, - DIV_ROUND_UP(info->oob_size, 4)); + __raw_readsl(nand->mmio_base + NDDB, info->data_buff, + DIV_ROUND_UP(nand->data_size, 4)); + if (nand->oob_size > 0) + __raw_readsl(nand->mmio_base + NDDB, info->oob_buff, + DIV_ROUND_UP(nand->oob_size, 4)); } } -static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) +static void start_data_dma(struct pxa3xx_nand *nand, int dir_out) { + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; struct pxa_dma_desc *desc = info->data_desc; - int dma_len = ALIGN(info->data_size + info->oob_size, 32); + int dma_len = ALIGN(nand->data_size + nand->oob_size, 32); desc->ddadr = DDADR_STOP; desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; if (dir_out) { desc->dsadr = info->data_buff_phys; - desc->dtadr = info->mmio_phys + NDDB; + desc->dtadr = nand->mmio_phys + NDDB; desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG; } else { desc->dtadr = info->data_buff_phys; - desc->dsadr = info->mmio_phys + NDDB; + desc->dsadr = nand->mmio_phys + NDDB; desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; } - DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; + DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; DDADR(info->data_dma_ch) = info->data_desc_addr; DCSR(info->data_dma_ch) |= DCSR_RUN; } static void pxa3xx_nand_data_dma_irq(int channel, void *data) { - struct pxa3xx_nand_info *info = data; + struct pxa3xx_nand *nand = data; uint32_t dcsr; dcsr = DCSR(channel); DCSR(channel) = dcsr; if (dcsr & DCSR_BUSERR) { - info->retcode = ERR_DMABUSERR; + nand->retcode = ERR_DMABUSERR; } - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); + enable_int(nand, NDCR_INT_MASK); + nand_writel(nand, NDSR, NDSR_WRDREQ | NDSR_RDDREQ); } static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { - struct pxa3xx_nand_info *info = devid; - unsigned int status, is_completed = 0; + struct pxa3xx_nand *nand = devid; + struct pxa3xx_nand_info *info; + unsigned int status, is_completed = 0, cs; + unsigned int ready, cmd_done, page_done, badblock_detect; - status = nand_readl(info, NDSR); + cs = nand->chip_select; + ready = (cs) ? NDSR_RDY : NDSR_FLASH_RDY; + cmd_done = (cs) ? NDSR_CS1_CMDD : NDSR_CS0_CMDD; + page_done = (cs) ? NDSR_CS1_PAGED : NDSR_CS0_PAGED; + badblock_detect = (cs) ? NDSR_CS1_BBD : NDSR_CS0_BBD; + info = nand->info[cs]; + status = nand_readl(nand, NDSR); if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; + nand->retcode = ERR_DBERR; if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; + nand->retcode = ERR_SBERR; if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { - info->state |= STATE_DATA_PROCESSING; + nand->state |= STATE_DATA_PROCESSING; /* whether use dma to transfer data */ - if (info->use_dma) { - disable_int(info, NDSR_WRDREQ); - start_data_dma(info, 0); + if (nand->use_dma) { + disable_int(nand, NDCR_INT_MASK); + start_data_dma(nand, nand->state & STATE_IS_WRITE); goto NORMAL_IRQ_EXIT; } else - handle_data_pio(info); + handle_data_pio(nand); - info->state |= STATE_DATA_DONE; + nand->state |= STATE_DATA_DONE; } - if (status & NDSR_CS0_CMDD) { - info->state |= STATE_CMD_DONE; + if (status & cmd_done) { + nand->state |= STATE_CMD_DONE; is_completed = 1; } - if (status & NDSR_FLASH_RDY) - info->state |= STATE_READY; - if (status & NDSR_CS0_PAGED) - info->state |= STATE_PAGE_DONE; + if (status & ready) + nand->state |= STATE_READY; + if (status & page_done) + nand->state |= STATE_PAGE_DONE; if (status & NDSR_WRCMDREQ) { - nand_writel(info, NDSR, NDSR_WRCMDREQ); + nand_writel(nand, NDSR, NDSR_WRCMDREQ); status &= ~NDSR_WRCMDREQ; - info->state |= STATE_CMD_WAIT_DONE; - nand_writel(info, NDCB0, info->ndcb0); - nand_writel(info, NDCB0, info->ndcb1); - nand_writel(info, NDCB0, info->ndcb2); + nand->state |= STATE_CMD_WAIT_DONE; + nand_writel(nand, NDCB0, info->ndcb0); + nand_writel(nand, NDCB0, info->ndcb1); + nand_writel(nand, NDCB0, info->ndcb2); } /* clear NDSR to let the controller exit the IRQ */ - nand_writel(info, NDSR, status); + nand_writel(nand, NDSR, status); if (is_completed) - complete(&info->cmd_complete); + complete(&nand->cmd_complete); NORMAL_IRQ_EXIT: return IRQ_HANDLED; } -static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) -{ - struct pxa3xx_nand_info *info = mtd->priv; - return (nand_readl(info, NDSR) & NDSR_RDY) ? 1 : 0; -} - static inline int is_buf_blank(uint8_t *buf, size_t len) { for (; len > 0; len--) @@ -497,29 +513,36 @@ static inline int is_buf_blank(uint8_t *buf, size_t len) return 1; } -static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, +static int prepare_command_pool(struct pxa3xx_nand *nand, int command, uint16_t column, int page_addr) { uint16_t cmd; int addr_cycle, exec_cmd, ndcb0; - struct mtd_info *mtd = info->mtd; + struct mtd_info *mtd; + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; - ndcb0 = 0; + mtd = get_mtd_by_info(info); + ndcb0 = (nand->chip_select) ? NDCB0_CSEL : 0;; addr_cycle = 0; exec_cmd = 1; /* reset data and oob column point to handle data */ info->buf_start = 0; info->buf_count = 0; - info->oob_size = 0; - info->use_ecc = 0; + info->ndcb0 = ndcb0; + nand->data_size = 0; + nand->oob_size = 0; + nand->use_ecc = 0; + nand->use_dma = 0; + nand->state = 0; switch (command) { case NAND_CMD_READ0: case NAND_CMD_PAGEPROG: - info->use_ecc = 1; + nand->use_ecc = info->use_ecc; case NAND_CMD_READOOB: pxa3xx_set_datasize(info); + nand->use_dma = use_dma; break; case NAND_CMD_SEQIN: exec_cmd = 0; @@ -530,7 +553,6 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, break; } - info->ndcb0 = ndcb0; addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles); @@ -584,7 +606,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, } cmd = cmdset.program; - info->state |= STATE_IS_WRITE; + nand->state |= STATE_IS_WRITE; info->ndcb0 |= NDCB0_CMD_TYPE(0x1) | NDCB0_AUTO_RS | NDCB0_ST_ROW_EN @@ -600,7 +622,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | NDCB0_ADDR_CYC(1) | cmd; - info->data_size = 8; + nand->data_size = 8; break; case NAND_CMD_STATUS: @@ -610,7 +632,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command, | NDCB0_ADDR_CYC(1) | cmd; - info->data_size = 8; + nand->data_size = 8; break; case NAND_CMD_ERASE1: @@ -648,6 +670,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; int ret, exec_cmd; /* if this is a x16 device ,then convert the input @@ -657,21 +680,28 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, if (info->reg_ndcr & NDCR_DWIDTH_M) column /= 2; - exec_cmd = prepare_command_pool(info, command, column, page_addr); + /* reset timing */ + if (nand->chip_select != info->chip_select) { + nand->chip_select = info->chip_select; + nand_writel(nand, NDTR0CS0, info->ndtr0cs0); + nand_writel(nand, NDTR1CS0, info->ndtr1cs0); + } + + exec_cmd = prepare_command_pool(nand, command, column, page_addr); if (exec_cmd) { - init_completion(&info->cmd_complete); - info->state |= STATE_CMD_PREPARED; - pxa3xx_nand_start(info); + init_completion(&nand->cmd_complete); + nand->state |= STATE_CMD_PREPARED; + pxa3xx_nand_start(nand); - ret = wait_for_completion_timeout(&info->cmd_complete, + ret = wait_for_completion_timeout(&nand->cmd_complete, CHIP_DELAY_TIMEOUT); if (!ret) { printk(KERN_ERR "Wait time out!!!\n"); } /* Stop State Machine for next command cycle */ - pxa3xx_nand_stop(info); - disable_int(info, NDCR_INT_MASK); - info->state &= ~STATE_CMD_PREPARED; + pxa3xx_nand_stop(nand); + disable_int(nand, NDCR_INT_MASK); + nand->state &= ~STATE_CMD_PREPARED; } } @@ -732,10 +762,11 @@ static void pxa3xx_nand_select_chip(struct mtd_info *mtd, int chip) static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) { struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; /* pxa3xx_nand_send_command has waited for command complete */ if (this->state == FL_WRITING || this->state == FL_ERASING) { - if (info->retcode == ERR_NONE) + if (nand->retcode == ERR_NONE) return 0; else { /* @@ -749,48 +780,17 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return 0; } -static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode) -{ - return; -} - -static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd, - const uint8_t *dat, uint8_t *ecc_code) -{ - return 0; -} - -static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, - uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc) -{ - struct pxa3xx_nand_info *info = mtd->priv; - /* - * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we - * consider it as a ecc error which will tell the caller the - * read fail We have distinguish all the errors, but the - * nand_read_ecc only check this function return value - * - * Corrected (single-bit) errors must also be noted. - */ - if (info->retcode == ERR_SBERR) - return 1; - else if (info->retcode != ERR_NONE) - return -1; - - return 0; -} - static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_flash *f) { - struct platform_device *pdev = info->pdev; + struct pxa3xx_nand *nand = info->nand_data; + struct platform_device *pdev = nand->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; uint32_t ndcr = 0; /* calculate flash information */ info->page_size = f->page_size; info->oob_buff = info->data_buff + f->page_size; - info->oob_size = (f->page_size == 2048) ? 64 : 16; info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; /* calculate addressing information */ @@ -823,41 +823,6 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, */ #define MAX_BUFF_SIZE PAGE_SIZE -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info) -{ - struct platform_device *pdev = info->pdev; - int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); - - if (use_dma == 0) { - info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); - if (info->data_buff == NULL) - return -ENOMEM; - return 0; - } - - info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, - &info->data_buff_phys, GFP_KERNEL); - if (info->data_buff == NULL) { - dev_err(&pdev->dev, "failed to allocate dma buffer\n"); - return -ENOMEM; - } - - info->data_buff_size = MAX_BUFF_SIZE; - info->data_desc = (void *)info->data_buff + data_desc_offset; - info->data_desc_addr = info->data_buff_phys + data_desc_offset; - - info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW, - pxa3xx_nand_data_dma_irq, info); - if (info->data_dma_ch < 0) { - dev_err(&pdev->dev, "failed to request data dma\n"); - dma_free_coherent(&pdev->dev, info->data_buff_size, - info->data_buff, info->data_buff_phys); - return info->data_dma_ch; - } - - return 0; -} - static struct nand_ecclayout hw_smallpage_ecclayout = { .eccbytes = 6, .eccpos = {8, 9, 10, 11, 12, 13 }, @@ -873,26 +838,50 @@ static struct nand_ecclayout hw_largepage_ecclayout = { .oobfree = { {2, 38} } }; +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs) +{ + struct pxa3xx_nand *nand; + struct mtd_info *mtd; + + if (!info) + return; + + nand = info->nand_data; + if (use_dma) { + if (info->data_dma_ch >= 0) + pxa_free_dma(info->data_dma_ch); + if (info->data_buff) + dma_free_coherent(&nand->pdev->dev, MAX_BUFF_SIZE, + info->data_buff, info->data_buff_phys); + } else { + if (info->data_buff) + kfree(info->data_buff); + } + mtd = get_mtd_by_info(info); + kfree(mtd); + nand->info[cs] = NULL; +} + static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, uint8_t *buf, int page) { struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); - if (info->retcode == ERR_SBERR) { - switch (info->use_ecc) { + if (nand->retcode == ERR_SBERR) { + switch (nand->use_ecc) { case 1: - mtd->ecc_stats.corrected ++; + mtd->ecc_stats.corrected++; break; case 0: default: break; } - } - else if (info->retcode == ERR_DBERR) { + } else if (nand->retcode == ERR_DBERR) { int buf_blank; buf_blank = is_buf_blank(buf, mtd->writesize); @@ -912,20 +901,18 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page) { - struct nand_chip *chip = mtd->priv; /* Send commands to erase a block */ - chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); + pxa3xx_nand_cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); } -static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) +static int pxa3xx_nand_sensing(struct pxa3xx_nand *nand) { - struct mtd_info *mtd = info->mtd; - struct nand_chip *chip = mtd->priv; - + struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; + struct mtd_info *mtd = get_mtd_by_info(info); /* use the common timing to make a try */ pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); - chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); - if (info->state & STATE_READY) + pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0); + if (nand->state & STATE_READY) return 1; else return 0; @@ -933,29 +920,29 @@ static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) static int pxa3xx_nand_scan(struct mtd_info *mtd) { - struct pxa3xx_nand_info *info = mtd->priv; struct pxa3xx_nand_flash *f; + struct pxa3xx_nand_info *info = mtd->priv; struct nand_chip *chip = mtd->priv; + struct pxa3xx_nand *nand = info->nand_data; uint32_t id = -1; int i, ret; - ret = pxa3xx_nand_sensing(info); + nand->chip_select = info->chip_select; + ret = pxa3xx_nand_sensing(nand); if (!ret) { - kfree(mtd); - info->mtd = NULL; - printk(KERN_INFO "There is no nand chip on cs 0!\n"); + pr_info("There is no nand chip on cs %d!\n", info->chip_select); + free_cs_resource(info, nand->chip_select); return -EINVAL; } - chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); + pxa3xx_nand_cmdfunc(mtd, NAND_CMD_READID, 0, 0); id = *((uint16_t *)(info->data_buff)); if (id != 0) - printk(KERN_INFO "Detect a flash id %x\n", id); + pr_info("Detect a flash id %x on cs %d\n", id, nand->chip_select); else { - kfree(mtd); - info->mtd = NULL; - printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); + pr_warning("Read out ID 0, potential timing set wrong!!\n"); + free_cs_resource(info, nand->chip_select); return -EINVAL; } @@ -976,15 +963,14 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) mtd->erasesize_shift = ffs(mtd->erasesize) - 1; mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; - mtd->name = mtd_names[0]; + mtd->name = mtd_names[nand->chip_select]; break; } } if (i == ARRAY_SIZE(builtin_flash_types)) { - kfree(mtd); - info->mtd = NULL; printk(KERN_ERR "ERROR!! flash not defined!!!\n"); + free_cs_resource(info, nand->chip_select); return -EINVAL; } @@ -1007,7 +993,6 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd) chip->page_shift = ffs(mtd->writesize) - 1; chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; chip->numchips = 1; - chip->chip_delay = 25; chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1; /* Set the bad block position */ @@ -1041,50 +1026,26 @@ static int alloc_nand_resource(struct platform_device *pdev) { struct pxa3xx_nand_info *info; struct nand_chip *chip; + struct pxa3xx_nand *nand; struct mtd_info *mtd; struct resource *r; - int ret, irq; + int ret, irq, cs; + int data_desc_offset = MAX_BUFF_SIZE - sizeof(struct pxa_dma_desc); - mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), - GFP_KERNEL); - if (!mtd) { + nand = kzalloc(sizeof(struct pxa3xx_nand), GFP_KERNEL); + if (!nand) { dev_err(&pdev->dev, "failed to allocate memory\n"); return -ENOMEM; } - info = (struct pxa3xx_nand_info *)(&mtd[1]); - chip = (struct nand_chip *)(&mtd[1]); - info->pdev = pdev; - info->mtd = mtd; - mtd->priv = info; - mtd->owner = THIS_MODULE; - - chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; - chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; - chip->ecc.hwctl = pxa3xx_nand_ecc_hwctl; - chip->ecc.calculate = pxa3xx_nand_ecc_calculate; - chip->ecc.correct = pxa3xx_nand_ecc_correct; - chip->waitfunc = pxa3xx_nand_waitfunc; - chip->select_chip = pxa3xx_nand_select_chip; - chip->dev_ready = pxa3xx_nand_dev_ready; - chip->cmdfunc = pxa3xx_nand_cmdfunc; - chip->read_word = pxa3xx_nand_read_word; - chip->read_byte = pxa3xx_nand_read_byte; - chip->read_buf = pxa3xx_nand_read_buf; - chip->write_buf = pxa3xx_nand_write_buf; - chip->verify_buf = pxa3xx_nand_verify_buf; - chip->block_markbad = pxa3xx_nand_default_block_markbad; - chip->block_bad = pxa3xx_nand_block_bad; - chip->scan_bbt = nand_default_bbt; - chip->erase_cmd = pxa3xx_nand_erase_cmd; - - info->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(info->clk)) { + nand->pdev = pdev; + nand->clk = clk_get(&pdev->dev, NULL); + if (IS_ERR(nand->clk)) { dev_err(&pdev->dev, "failed to get nand clock\n"); - ret = PTR_ERR(info->clk); - goto fail_free_mtd; + ret = PTR_ERR(nand->clk); + goto fail_alloc; } - clk_enable(info->clk); + clk_enable(nand->clk); r = platform_get_resource(pdev, IORESOURCE_DMA, 0); if (r == NULL) { @@ -1092,7 +1053,7 @@ static int alloc_nand_resource(struct platform_device *pdev) ret = -ENXIO; goto fail_put_clk; } - info->drcmr_dat = r->start; + nand->drcmr_dat = r->start; r = platform_get_resource(pdev, IORESOURCE_DMA, 1); if (r == NULL) { @@ -1100,14 +1061,7 @@ static int alloc_nand_resource(struct platform_device *pdev) ret = -ENXIO; goto fail_put_clk; } - info->drcmr_cmd = r->start; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) { - dev_err(&pdev->dev, "no IRQ resource defined\n"); - ret = -ENXIO; - goto fail_put_clk; - } + nand->drcmr_cmd = r->start; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (r == NULL) { @@ -1123,80 +1077,145 @@ static int alloc_nand_resource(struct platform_device *pdev) goto fail_put_clk; } - info->mmio_base = ioremap(r->start, resource_size(r)); - if (info->mmio_base == NULL) { + nand->mmio_base = ioremap(r->start, resource_size(r)); + if (nand->mmio_base == NULL) { dev_err(&pdev->dev, "ioremap() failed\n"); ret = -ENODEV; goto fail_free_res; } - info->mmio_phys = r->start; - - ret = pxa3xx_nand_init_buff(info); - if (ret) - goto fail_free_io; + nand->mmio_phys = r->start; /* initialize all interrupts to be disabled */ - disable_int(info, NDSR_MASK); + disable_int(nand, NDSR_MASK); + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "no IRQ resource defined\n"); + ret = -ENXIO; + goto fail_put_clk; + } ret = request_irq(irq, pxa3xx_nand_irq, IRQF_DISABLED, - pdev->name, info); + pdev->name, nand); if (ret < 0) { dev_err(&pdev->dev, "failed to request IRQ\n"); - goto fail_free_buf; + ret = -ENXIO; + goto fail_free_irq; } - platform_set_drvdata(pdev, info); + platform_set_drvdata(pdev, nand); + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + mtd = kzalloc(sizeof(struct mtd_info) + + sizeof(struct pxa3xx_nand_info), + GFP_KERNEL); + if (!mtd) { + dev_err(&pdev->dev, "failed to allocate memory\n"); + ret = -ENOMEM; + goto fail_free_irq; + } + + info = (struct pxa3xx_nand_info *)(&mtd[1]); + info->nand_data = nand; + info->chip_select = cs; + mtd->priv = info; + mtd->owner = THIS_MODULE; + nand->info[cs] = info; + + chip = (struct nand_chip *)(&mtd[1]); + chip->controller = &nand->controller; + chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; + chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->waitfunc = pxa3xx_nand_waitfunc; + chip->select_chip = pxa3xx_nand_select_chip; + chip->cmdfunc = pxa3xx_nand_cmdfunc; + chip->read_word = pxa3xx_nand_read_word; + chip->read_byte = pxa3xx_nand_read_byte; + chip->read_buf = pxa3xx_nand_read_buf; + chip->write_buf = pxa3xx_nand_write_buf; + chip->verify_buf = pxa3xx_nand_verify_buf; + chip->block_markbad = pxa3xx_nand_default_block_markbad; + chip->block_bad = pxa3xx_nand_block_bad; + chip->scan_bbt = nand_default_bbt; + chip->erase_cmd = pxa3xx_nand_erase_cmd; + + if (use_dma == 0) { + info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL); + if (info->data_buff == NULL) { + ret = -ENOMEM; + goto fail_free_buf; + } + continue; + } + + info->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE, + &info->data_buff_phys, GFP_KERNEL); + if (info->data_buff == NULL) { + dev_err(&pdev->dev, "failed to allocate dma buffer\n"); + ret = -ENOMEM; + goto fail_free_buf; + } + + info->data_desc = (void *)info->data_buff + data_desc_offset; + info->data_desc_addr = info->data_buff_phys + data_desc_offset; + info->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW, + pxa3xx_nand_data_dma_irq, nand); + if (info->data_dma_ch < 0) { + dev_err(&pdev->dev, "failed to request data dma\n"); + ret = -ENXIO; + goto fail_free_buf; + } + } + + spin_lock_init(&nand->controller.lock); + init_waitqueue_head(&nand->controller.wq); return 0; fail_free_buf: - free_irq(irq, info); - if (use_dma) { - pxa_free_dma(info->data_dma_ch); - dma_free_coherent(&pdev->dev, info->data_buff_size, - info->data_buff, info->data_buff_phys); - } else - kfree(info->data_buff); -fail_free_io: - iounmap(info->mmio_base); + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + info = nand->info[cs]; + free_cs_resource(info, cs); + } +fail_free_irq: + free_irq(irq, nand); + iounmap(nand->mmio_base); fail_free_res: release_mem_region(r->start, resource_size(r)); fail_put_clk: - clk_disable(info->clk); - clk_put(info->clk); -fail_free_mtd: - kfree(mtd); + clk_disable(nand->clk); + clk_put(nand->clk); +fail_alloc: + kfree(nand); return ret; } static int pxa3xx_nand_remove(struct platform_device *pdev) { - struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); - struct mtd_info *mtd = info->mtd; + struct pxa3xx_nand *nand = platform_get_drvdata(pdev); + struct pxa3xx_nand_info *info; + struct mtd_info *mtd; struct resource *r; - int irq; + int irq, cs; platform_set_drvdata(pdev, NULL); - del_mtd_device(mtd); - del_mtd_partitions(mtd); irq = platform_get_irq(pdev, 0); if (irq >= 0) - free_irq(irq, info); - if (use_dma) { - pxa_free_dma(info->data_dma_ch); - dma_free_writecombine(&pdev->dev, info->data_buff_size, - info->data_buff, info->data_buff_phys); - } else - kfree(info->data_buff); + free_irq(irq, nand); - iounmap(info->mmio_base); + iounmap(nand->mmio_base); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(r->start, resource_size(r)); - - clk_disable(info->clk); - clk_put(info->clk); - - kfree(mtd); + clk_disable(nand->clk); + clk_put(nand->clk); + + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + info = nand->info[cs]; + if (!info) + continue; + mtd = get_mtd_by_info(info); + del_mtd_partitions(mtd); + del_mtd_device(mtd); + free_cs_resource(info, cs); + } return 0; } @@ -1204,7 +1223,9 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) { struct pxa3xx_nand_platform_data *pdata; struct pxa3xx_nand_info *info; - int ret; + struct pxa3xx_nand *nand; + struct mtd_info *mtd; + int ret, cs, probe_success = 0; pdata = pdev->dev.platform_data; if (!pdata) { @@ -1216,14 +1237,23 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) if (ret) return ret; - info = platform_get_drvdata(pdev); - if (pxa3xx_nand_scan(info->mtd)) { - dev_err(&pdev->dev, "failed to scan nand\n"); - pxa3xx_nand_remove(pdev); - return -ENODEV; + nand = platform_get_drvdata(pdev); + for (cs = 0; cs < NUM_CHIP_SELECT; cs++) { + info = nand->info[cs]; + mtd = get_mtd_by_info(info); + if (pxa3xx_nand_scan(mtd)) { + dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs); + continue; + } + ret = add_mtd_partitions(mtd, pdata->parts[cs], + pdata->nr_parts[cs]); + if (!ret) + probe_success = 1; } - return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); + if (!probe_success) + pxa3xx_nand_remove(pdev); + return ret; } #ifdef CONFIG_PM -- 1.5.6.5 From haojian.zhuang at gmail.com Fri May 14 02:18:52 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:18:52 +0800 Subject: [PATCH 10/20] mtd: pxa3xx_nand: add bch ecc support Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:19:35 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:19:35 +0800 Subject: [PATCH 11/20] mtd: pxa3xx_nand: add debug messege Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:20:16 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:20:16 +0800 Subject: [PATCH 12/20] mtd: pxa3xx_nand: enable 4k page operation Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:20:57 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:20:57 +0800 Subject: [PATCH 13/20] mtd: pxa3xx_nand: show the real time used by the controller Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:21:31 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:21:31 +0800 Subject: [PATCH 14/20] mtd: pxa3xx_nand: add polling mode support Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:22:12 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:22:12 +0800 Subject: [PATCH 15/20] mmp: add nand support to mmp2 Message-ID: From leiwen at marvell.com Fri May 14 01:30:21 2010 From: leiwen at marvell.com (Lei Wen) Date: Fri, 14 May 2010 13:30:21 +0800 Subject: [PATCH] mmp: add nand support to mmp2 Message-ID: Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- arch/arm/mach-mmp/include/mach/mmp2.h | 6 ++++ arch/arm/mach-mmp/jasper.c | 53 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h index 459f3be..5d706ed 100644 --- a/arch/arm/mach-mmp/include/mach/mmp2.h +++ b/arch/arm/mach-mmp/include/mach/mmp2.h @@ -4,6 +4,7 @@ #include #include #include +#include extern struct pxa_device_desc mmp2_device_uart1; extern struct pxa_device_desc mmp2_device_uart2; @@ -15,6 +16,7 @@ extern struct pxa_device_desc mmp2_device_twsi3; extern struct pxa_device_desc mmp2_device_twsi4; extern struct pxa_device_desc mmp2_device_twsi5; extern struct pxa_device_desc mmp2_device_twsi6; +extern struct pxa_device_desc mmp2_device_nand; static inline int mmp2_add_uart(int id) { @@ -56,5 +58,9 @@ static inline int mmp2_add_twsi(int id, struct i2c_pxa_platform_data *data, return pxa_register_device(d, data, sizeof(*data)); } +static inline int mmp2_add_nand(struct pxa3xx_nand_platform_data *data) +{ + return pxa_register_device(&mmp2_device_nand, data, sizeof(*data)); +} #endif /* __ASM_MACH_MMP2_H */ diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c index cfd4d66..80a571e 100644 --- a/arch/arm/mach-mmp/jasper.c +++ b/arch/arm/mach-mmp/jasper.c @@ -58,8 +58,60 @@ static unsigned long jasper_pin_config[] __initdata = { GPIO149_ND_CLE, GPIO112_ND_RDY0, GPIO160_ND_RDY1, + GPIO154_SMC_IRQ, }; +static struct mtd_partition jasper_nand_partitions[] = { + [0] = { + .name = "Bootloader", + .offset = 0, + .size = 0x100000, + .mask_flags = MTD_WRITEABLE, + }, + [1] = { + .name = "Reserve", + .offset = 0x100000, + .size = 0x080000, + }, + [2] = { + .name = "Reserve", + .offset = 0x180000, + .size = 0x800000, + .mask_flags = MTD_WRITEABLE, + }, + [3] = { + .name = "Kernel", + .offset = 0x980000, + .size = 0x300000, + .mask_flags = MTD_WRITEABLE, + }, + [4] = { + .name = "system", + .offset = 0x0c80000, + .size = 0x7000000, + }, + [5] = { + .name = "userdata", + .offset = 0x7c80000, + .size = 0x7000000, + }, + [6] = { + .name = "filesystem", + .offset = 0x0ec80000, + .size = MTDPART_SIZ_FULL, + } +}; + +static struct pxa3xx_nand_platform_data jasper_nand_info; +static void __init jasper_init_flash(void) +{ + jasper_nand_info.parts[0] = jasper_nand_partitions; + jasper_nand_info.nr_parts[0] = ARRAY_SIZE(jasper_nand_partitions); + jasper_nand_info.enable_arbiter = 1; + jasper_nand_info.naked_cmd_support = 1; + mmp2_add_nand(&jasper_nand_info); +} + static void __init jasper_init(void) { mfp_config(ARRAY_AND_SIZE(jasper_pin_config)); @@ -67,6 +119,7 @@ static void __init jasper_init(void) /* on-chip devices */ mmp2_add_uart(1); mmp2_add_uart(3); + jasper_init_flash(); } MACHINE_START(MARVELL_JASPER, "Jasper Development Platform") -- 1.5.6.5 From haojian.zhuang at gmail.com Fri May 14 02:22:59 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:22:59 +0800 Subject: [PATCH 16/20] mtd: pxa3xx_nand: fix reset timeout on mmp2 Message-ID: From haojian.zhuang at gmail.com Fri May 14 02:23:42 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:23:42 +0800 Subject: [PATCH 17/20] mtd: pxa3xx_nand: add cmdline part parser support Message-ID: From leiwen at marvell.com Wed May 5 22:42:13 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 10:42:13 +0800 Subject: [PATCH] mtd: pxa3xx_nand: add cmdline part parser support Message-ID: Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 26 ++++++++++++++++++++++++-- 1 files changed, 24 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 2eebd20..793b64c 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -349,6 +349,9 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0, 10, 35, 15, 25, 15, 25, 25000, 0, 60, 10, }, }, }; +#ifdef CONFIG_MTD_CMDLINE_PARTS +static const char *part_probes[] = { "cmdlinepart", NULL }; +#endif static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; /* convert nano-seconds to nand flash controller clock cycles */ @@ -1726,6 +1729,10 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) struct pxa3xx_nand *nand; struct mtd_info *mtd; int ret, cs, probe_success = 0; +#ifdef CONFIG_MTD_PARTITIONS + struct mtd_partition *partitions = NULL; + int num_part = 0; +#endif pdata = pdev->dev.platform_data; if (!pdata) { @@ -1747,8 +1754,23 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs); continue; } - ret = add_mtd_partitions(mtd, pdata->parts[cs], - pdata->nr_parts[cs]); + mtd->name = mtd_names[cs]; +#ifdef CONFIG_MTD_PARTITIONS +#ifdef CONFIG_MTD_CMDLINE_PARTS + num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0); +#endif + if (num_part <= 0) { + num_part = pdata->nr_parts[cs]; + partitions = pdata->parts[cs]; + } + + if (partitions && num_part > 0) + ret = add_mtd_partitions(mtd, partitions, num_part); + else + ret = add_mtd_device(mtd); +#else + ret = add_mtd_device(mtd); +#endif if (!ret) probe_success = 1; } -- 1.5.6.5 From haojian.zhuang at gmail.com Fri May 14 02:24:22 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:24:22 +0800 Subject: [PATCH 18/20] mmp: refresh nand timing Message-ID: From leiwen at marvell.com Fri May 14 01:31:04 2010 From: leiwen at marvell.com (Lei Wen) Date: Fri, 14 May 2010 13:31:04 +0800 Subject: [PATCH] mmp: refresh nand timing Message-ID: Update the NAND clock of PXA168. And adjust the nand timing configuration. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- arch/arm/configs/pxa168_defconfig | 98 ++++++++++++++++++++++++++++++++++++- arch/arm/mach-mmp/pxa168.c | 2 +- drivers/mtd/nand/pxa3xx_nand.c | 5 +- 3 files changed, 99 insertions(+), 6 deletions(-) diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig index 113511f..909bbfa 100644 --- a/arch/arm/configs/pxa168_defconfig +++ b/arch/arm/configs/pxa168_defconfig @@ -301,7 +301,7 @@ CONFIG_ALIGNMENT_TRAP=y # CONFIG_ZBOOT_ROM_TEXT=0x0 CONFIG_ZBOOT_ROM_BSS=0x0 -CONFIG_CMDLINE="root=/dev/nfs rootfstype=nfs nfsroot=192.168.2.100:/nfsroot/ ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M" +CONFIG_CMDLINE="root=/dev/mtdblock4 rootfstype=jffs2 ip=192.168.2.101:192.168.2.100::255.255.255.0::eth0:on console=ttyS0,115200 mem=128M" # CONFIG_XIP_KERNEL is not set # CONFIG_KEXEC is not set @@ -438,7 +438,89 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set +CONFIG_MTD=y +# CONFIG_MTD_DEBUG is not set +# CONFIG_MTD_TESTS is not set +# CONFIG_MTD_CONCAT is not set +CONFIG_MTD_PARTITIONS=y +# CONFIG_MTD_REDBOOT_PARTS is not set +CONFIG_MTD_CMDLINE_PARTS=y +# CONFIG_MTD_AFS_PARTS is not set +# CONFIG_MTD_AR7_PARTS is not set + +# +# User Modules And Translation Layers +# +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +# CONFIG_FTL is not set +# CONFIG_NFTL is not set +# CONFIG_INFTL is not set +# CONFIG_RFD_FTL is not set +# CONFIG_SSFDC is not set +# CONFIG_MTD_OOPS is not set + +# +# RAM/ROM/Flash chip drivers +# +# CONFIG_MTD_CFI is not set +# CONFIG_MTD_JEDECPROBE is not set +CONFIG_MTD_MAP_BANK_WIDTH_1=y +CONFIG_MTD_MAP_BANK_WIDTH_2=y +CONFIG_MTD_MAP_BANK_WIDTH_4=y +# CONFIG_MTD_MAP_BANK_WIDTH_8 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_16 is not set +# CONFIG_MTD_MAP_BANK_WIDTH_32 is not set +CONFIG_MTD_CFI_I1=y +CONFIG_MTD_CFI_I2=y +# CONFIG_MTD_CFI_I4 is not set +# CONFIG_MTD_CFI_I8 is not set +# CONFIG_MTD_RAM is not set +# CONFIG_MTD_ROM is not set +# CONFIG_MTD_ABSENT is not set + +# +# Mapping drivers for chip access +# +# CONFIG_MTD_COMPLEX_MAPPINGS is not set +# CONFIG_MTD_PLATRAM is not set + +# +# Self-contained MTD device drivers +# +# CONFIG_MTD_SLRAM is not set +# CONFIG_MTD_PHRAM is not set +# CONFIG_MTD_MTDRAM is not set +# CONFIG_MTD_BLOCK2MTD is not set + +# +# Disk-On-Chip Device Drivers +# +# CONFIG_MTD_DOC2000 is not set +# CONFIG_MTD_DOC2001 is not set +# CONFIG_MTD_DOC2001PLUS is not set +CONFIG_MTD_NAND=y +# CONFIG_MTD_NAND_VERIFY_WRITE is not set +# CONFIG_MTD_NAND_ECC_SMC is not set +# CONFIG_MTD_NAND_MUSEUM_IDS is not set +# CONFIG_MTD_NAND_GPIO is not set +CONFIG_MTD_NAND_IDS=y +# CONFIG_MTD_NAND_DISKONCHIP is not set +CONFIG_MTD_NAND_PXA3xx=y +# CONFIG_MTD_NAND_NANDSIM is not set +# CONFIG_MTD_NAND_PLATFORM is not set +# CONFIG_MTD_ONENAND is not set + +# +# LPDDR flash memory drivers +# +# CONFIG_MTD_LPDDR is not set + +# +# UBI - Unsorted block images +# +# CONFIG_MTD_UBI is not set # CONFIG_PARPORT is not set # CONFIG_BLK_DEV is not set # CONFIG_MISC_DEVICES is not set @@ -720,6 +802,18 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_BEFS_FS is not set # CONFIG_BFS_FS is not set # CONFIG_EFS_FS is not set +CONFIG_JFFS2_FS=y +CONFIG_JFFS2_FS_DEBUG=0 +CONFIG_JFFS2_FS_WRITEBUFFER=y +# CONFIG_JFFS2_FS_WBUF_VERIFY is not set +# CONFIG_JFFS2_SUMMARY is not set +# CONFIG_JFFS2_FS_XATTR is not set +# CONFIG_JFFS2_COMPRESSION_OPTIONS is not set +CONFIG_JFFS2_ZLIB=y +# CONFIG_JFFS2_LZO is not set +CONFIG_JFFS2_RTIME=y +# CONFIG_JFFS2_RUBIN is not set +# CONFIG_LOGFS is not set CONFIG_CRAMFS=y # CONFIG_SQUASHFS is not set # CONFIG_VXFS_FS is not set diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c index 1873c82..0ee09cf 100644 --- a/arch/arm/mach-mmp/pxa168.c +++ b/arch/arm/mach-mmp/pxa168.c @@ -73,7 +73,7 @@ static APBC_CLK(pwm2, PXA168_PWM2, 1, 13000000); static APBC_CLK(pwm3, PXA168_PWM3, 1, 13000000); static APBC_CLK(pwm4, PXA168_PWM4, 1, 13000000); -static APMU_CLK(nand, NAND, 0x01db, 208000000); +static APMU_CLK(nand, NAND, 0x019b, 156000000); /* device and clock bindings */ static struct clk_lookup pxa168_clkregs[] = { diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 793b64c..7c871af 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -330,11 +330,11 @@ static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { { 0x46ec, 32, 512, 16, 16, ECC_HAMMIN, 4096, \ { 0, 10, 0, 20, 40, 30, 40, 11123, 0, 110, 10, }, }, { 0xdaec, 64, 2048, 8, 8, ECC_HAMMIN, 2048, \ - { 0, 10, 0, 20, 40, 30, 40, 11123, 0, 110, 10, }, }, + { 0, 10, 0, 20, 40, 30, 40, 25000, 0, 110, 10, }, }, { 0xd3ec, 128, 2048, 8, 8, ECC_BCH, 4096, \ { 0, 10, 0, 20, 40, 30, 40, 11123, 0, 110, 10, }, }, { 0xd7ec, 128, 4096, 8, 8, ECC_BCH, 8192, \ - { 0, 10, 0, 20, 40, 30, 40, 25000, 0, 110, 10, }, }, + { 200, 10, 15, 10, 12, 10, 8, 60000, 20, 75, 10, }, }, { 0xa12c, 64, 2048, 8, 8, ECC_HAMMIN, 1024, \ { 0, 10, 25, 15, 25, 15, 30, 25000, 0, 60, 10, }, }, { 0xb12c, 64, 2048, 16, 16, ECC_HAMMIN, 1024, \ @@ -509,7 +509,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, | NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); - nand_writel(nand, NDTR0CS0, ndtr0); nand_writel(nand, NDTR1CS0, ndtr1); nand_writel(nand, NDREDEL, 0x0); -- 1.5.6.5 From haojian.zhuang at gmail.com Fri May 14 02:25:03 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:25:03 +0800 Subject: [PATCH 19/20] mtd: pxa3xx_nand: reimplment read oob command to increase performance Message-ID: From leiwen at marvell.com Wed May 5 22:43:57 2010 From: leiwen at marvell.com (Lei Wen) Date: Thu, 6 May 2010 10:43:57 +0800 Subject: [PATCH] mtd: pxa3xx_nand: reimplment read oob command to Message-ID: increase performance For read oob command only care about the spare area part, we truly need not to transfer all page data to the controller side. By random data out, we could do the naked read first to let one page data transfer from NAND chip to its internal ram. Then we use random data out command to change the offset to the start of oob part. After all this, we toggle only oob size of RE# to the controller side. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 122 ++++++++++++++++++++++++++++++---------- 1 files changed, 92 insertions(+), 30 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 7c871af..2e1c8b6 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -129,6 +129,7 @@ #define NDCB0_CMD_XTYPE_MASK (0x7 << 29) #define NDCB0_CMD_XTYPE(x) (((x) << 29) & NDCB0_CMD_XTYPE_MASK) +#define NDCB0_LEN_OVRD (0x1 << 28) #define NDCB0_ST_ROW_EN (0x1 << 26) #define NDCB0_AUTO_RS (0x1 << 25) #define NDCB0_CSEL (0x1 << 24) @@ -257,8 +258,9 @@ struct pxa3xx_nand_info { uint8_t total_cmds; uint8_t wait_ready[CMD_POOL_SIZE]; uint32_t ndcb0[CMD_POOL_SIZE]; - uint32_t ndcb1; - uint32_t ndcb2; + uint32_t ndcb1[CMD_POOL_SIZE]; + uint32_t ndcb2[CMD_POOL_SIZE]; + uint32_t ndcb3[CMD_POOL_SIZE]; uint32_t reg_ndcr; uint32_t ndtr0cs0; uint32_t ndtr1cs0; @@ -646,9 +648,9 @@ static void nand_error_dump(struct pxa3xx_nand *nand) printk(KERN_ERR "Totally %d command for sending\n", info->total_cmds); for (i = 0; i < info->total_cmds; i ++) - printk(KERN_ERR "NDCB0:%d: %x\n", - i, info->ndcb0[i]); - printk(KERN_ERR "NDCB1: %x; NDCB2 %x\n", info->ndcb1, info->ndcb2); + printk(KERN_ERR "==%d: NDCB0 %x, NDCB1 %x, NDCB2 %x, NDCB3 %x\n", + i, info->ndcb0[i], info->ndcb1[i], + info->ndcb2[i], info->ndcb3[i]); printk(KERN_ERR "\nRegister DUMPing ##############\n"); printk(KERN_ERR "NDCR %x\n" @@ -775,7 +777,7 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand) { struct pxa3xx_nand_info *info; - unsigned int status, is_completed = 0, cs, cmd_seqs, ndcb1, ndcb2; + unsigned int status, is_completed = 0, cs, cmd_seqs; unsigned int ready, cmd_done, page_done, badblock_detect; cs = nand->chip_select; @@ -842,24 +844,20 @@ static int pxa3xx_nand_transaction(struct pxa3xx_nand *nand) nand_writel(nand, NDSR, NDSR_WRCMDREQ); if (cmd_seqs < info->total_cmds) { - info->cmd_seqs ++; - if (cmd_seqs == 0) { - ndcb1 = info->ndcb1; - ndcb2 = info->ndcb2; - } - else { - ndcb1 = 0; - ndcb2 = 0; - } + info->cmd_seqs++; nand->state &= ~STATE_MASK; nand->state |= STATE_CMD_WAIT_DONE; nand_writel(nand, NDCB0, info->ndcb0[cmd_seqs]); - nand_writel(nand, NDCB0, ndcb1); - nand_writel(nand, NDCB0, ndcb2); - DBG_NAND(printk("\tndcb0 %x ndcb1 %x ndcb2 %x\n", - info->ndcb0[cmd_seqs], ndcb1, ndcb2)); - } - else + nand_writel(nand, NDCB0, info->ndcb1[cmd_seqs]); + nand_writel(nand, NDCB0, info->ndcb2[cmd_seqs]); + if (info->ndcb0[cmd_seqs] & NDCB0_LEN_OVRD) + nand_writel(nand, NDCB0, info->ndcb3[cmd_seqs]); + DBG_NAND(printk("\tndcb0 %x ndcb1 %x ndcb2 %x, ndcb3 %x\n", + info->ndcb0[cmd_seqs], + info->ndcb1[cmd_seqs], + info->ndcb2[cmd_seqs], + info->ndcb3[cmd_seqs])); + } else is_completed = 1; } @@ -938,6 +936,7 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, case NAND_CMD_PAGEPROG: nand->use_ecc = info->use_ecc; case NAND_CMD_READOOB: + case NAND_CMD_RNDOUT: pxa3xx_set_datasize(info); nand->use_dma = use_dma; chunks = info->page_size / nand->data_size; @@ -946,8 +945,8 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, exec_cmd = 0; break; default: - info->ndcb1 = 0; - info->ndcb2 = 0; + info->ndcb1[0] = 0; + info->ndcb2[0] = 0; break; } @@ -1005,26 +1004,73 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, case NAND_CMD_SEQIN: /* small page addr setting */ if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) { - info->ndcb1 = ((page_addr & 0xFFFFFF) << 8) + info->ndcb1[0] = ((page_addr & 0xFFFFFF) << 8) | (column & 0xFF); - info->ndcb2 = 0; + info->ndcb2[0] = 0; } else { - info->ndcb1 = ((page_addr & 0xFFFF) << 16) + info->ndcb1[0] = ((page_addr & 0xFFFF) << 16) | (column & 0xFFFF); if (page_addr & 0xFF0000) - info->ndcb2 = (page_addr & 0xFF0000) >> 16; + info->ndcb2[0] = (page_addr & 0xFF0000) >> 16; else - info->ndcb2 = 0; + info->ndcb2[0] = 0; } + for (i = 1; i <=chunks; i ++) { + info->ndcb1[i] = info->ndcb1[0]; + info->ndcb2[i] = info->ndcb2[0]; + } info->buf_count = mtd->writesize + mtd->oobsize; memset(info->data_buff, 0xFF, info->buf_count); break; + case NAND_CMD_RNDOUT: + /* current RNDOUT only support 2k nand */ + if (info->page_size > PAGE_CHUNK_SIZE) + BUG(); + + cmd = cmdset.read1; + info->total_cmds = 3; + info->ndcb0[0] |= NDCB0_CMD_XTYPE(0x6) + | NDCB0_CMD_TYPE(0) + | NDCB0_DBC + | NDCB0_NC + | addr_cycle + | cmd; + + info->ndcb0[1] |= NDCB0_CMD_XTYPE(0x6) + | NDCB0_CMD_TYPE(0) + | NDCB0_DBC + | NDCB0_NC + | NDCB0_ADDR_CYC(info->col_addr_cycles) + | (NAND_CMD_RNDOUTSTART << 8) + | NAND_CMD_RNDOUT; + + info->ndcb0[2] |= NDCB0_CMD_XTYPE(0x5) + | NDCB0_LEN_OVRD; + + info->ndcb1[0] = ((page_addr & 0xFFFF) << 16) + | (column & 0xFFFF); + info->ndcb1[1] = mtd->writesize; + info->ndcb1[2] = 0; + + if (page_addr & 0xFF0000) + info->ndcb2[0] = (page_addr & 0xFF0000) >> 16; + else + info->ndcb2[0] = 0; + info->ndcb2[1] = info->ndcb2[2] = 0; + info->ndcb3[0] = info->ndcb3[1] = 0; + info->ndcb3[2] = mtd->oobsize; + info->buf_count = mtd->oobsize; + info->wait_ready[1] = 1; + nand->data_size = mtd->oobsize; + nand->oob_size = 0; + break; + case NAND_CMD_PAGEPROG: if (is_buf_blank(info->data_buff, (mtd->writesize + mtd->oobsize))) { exec_cmd = 0; @@ -1096,8 +1142,8 @@ static int prepare_command_pool(struct pxa3xx_nand *nand, int command, | NDCB0_ADDR_CYC(3) | NDCB0_DBC | cmd; - info->ndcb1 = page_addr; - info->ndcb2 = 0; + info->ndcb1[0] = page_addr; + info->ndcb2[0] = 0; break; case NAND_CMD_RESET: @@ -1245,6 +1291,21 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this) return 0; } +static int pxa3xx_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip, + int page, int sndcmd) +{ + struct pxa3xx_nand_info *info = (struct pxa3xx_nand_info *)chip; + if (sndcmd) { + if ((info->page_size <= PAGE_CHUNK_SIZE) && naked_cmd_support) + chip->cmdfunc(mtd, NAND_CMD_RNDOUT, 0, page); + else + chip->cmdfunc(mtd, NAND_CMD_READOOB, 0, page); + sndcmd = 0; + } + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); + return sndcmd; +} + static void pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, struct pxa3xx_nand_flash *f, int show_timing) { @@ -1626,6 +1687,7 @@ static int alloc_nand_resource(struct platform_device *pdev) chip->controller = &nand->controller; chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; + chip->ecc.read_oob = pxa3xx_nand_read_oob; chip->waitfunc = pxa3xx_nand_waitfunc; chip->select_chip = pxa3xx_nand_select_chip; chip->cmdfunc = pxa3xx_nand_cmdfunc; -- 1.5.6.5 From haojian.zhuang at gmail.com Fri May 14 02:25:47 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 14:25:47 +0800 Subject: [PATCH 20/20] mtd: pxa3xx_nand: fix power management support Message-ID: From dwmw2 at infradead.org Fri May 14 03:54:02 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 08:54:02 +0100 Subject: [PATCH v5 5/9] [MTD] remove bogus warning about missing boot bank location In-Reply-To: <4BECEAE9.2030008@free.fr> References: <20100424155751.14723.46761.stgit@shiryu.yomgui.biz> <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> <1273796379.9999.509.camel@macbook.infradead.org> <4BECEAE9.2030008@free.fr> Message-ID: <1273823642.9999.1528.camel@macbook.infradead.org> On Fri, 2010-05-14 at 08:17 +0200, Chris Moore wrote: > Le 14/05/2010 02:19, David Woodhouse a ?crit : > > On Sat, 2010-04-24 at 17:58 +0200, Guillaume LECERF wrote: > > > >> From: Uwe Kleine-K?nig > >> > >> After the deleted block bootloc is only used once as follows: > >> > >> if (bootloc == 3&& something_else) { > >> ... > >> > >> So setting bootloc = 2 doesn't change anything. Taking that the > >> warning is wrong and missleading. > >> > >> Signed-off-by: Uwe Kleine-K?nig > >> Signed-off-by: Guillaume LECERF > >> Acked-by: Christopher Moore > >> > > The warning should be preserved for invalid values, or values we don't > > support. I don't think it's correct to just remove it. > > > > > > But, David, the only effect of this code is to print an *erroneous* message. > The message says "Assuming top" but sets bootloc to bottom (2) :( > See this thread: http://thread.gmane.org/gmane.linux.drivers.mtd/22176 > Remark: this would be even clearer if the bootloc values were macros > instead of 2, 3, ... > > If you really want to keep the message then it must at least be changed > to "Assuming bottom". http://git.infradead.org/mtd-2.6.git/commitdiff/412da2f6 -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From glecerf at gmail.com Fri May 14 04:09:44 2010 From: glecerf at gmail.com (Guillaume LECERF) Date: Fri, 14 May 2010 10:09:44 +0200 Subject: [PATCH v5 5/9] [MTD] remove bogus warning about missing boot bank location In-Reply-To: <1273823642.9999.1528.camel@macbook.infradead.org> References: <20100424155751.14723.46761.stgit@shiryu.yomgui.biz> <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> <1273796379.9999.509.camel@macbook.infradead.org> <4BECEAE9.2030008@free.fr> <1273823642.9999.1528.camel@macbook.infradead.org> Message-ID: 2010/5/14 David Woodhouse : > http://git.infradead.org/mtd-2.6.git/commitdiff/412da2f6 Thanks David. One thing I noted : + if ((bootloc < 2) || (bootloc > 5)) { + printk(KERN_WARNING "%s: CFI contains unrecognised boot " + "bank location (%d). Assuming bottom.\n", + bootloc, map->name); I think bootloc and map->name need to be swapped to match the printk pattern order (%s first then %d). -- Guillaume LECERF GeeXboX developer - www.geexbox.org From dwmw2 at infradead.org Fri May 14 04:15:32 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 09:15:32 +0100 Subject: [PATCH v5 5/9] [MTD] remove bogus warning about missing boot bank location In-Reply-To: References: <20100424155751.14723.46761.stgit@shiryu.yomgui.biz> <20100424155812.14723.66554.stgit@shiryu.yomgui.biz> <1273796379.9999.509.camel@macbook.infradead.org> <4BECEAE9.2030008@free.fr> <1273823642.9999.1528.camel@macbook.infradead.org> Message-ID: <1273824932.9999.1578.camel@macbook.infradead.org> On Fri, 2010-05-14 at 10:09 +0200, Guillaume LECERF wrote: > I think bootloc and map->name need to be swapped to match the printk > pattern order (%s first then %d). Doh. Fixed; thanks. -- dwmw2 From dwmw2 at infradead.org Fri May 14 04:16:11 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 09:16:11 +0100 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: References: <1273804364.9999.881.camel@macbook.infradead.org> Message-ID: <1273824971.9999.1582.camel@macbook.infradead.org> On Fri, 2010-05-14 at 14:08 +0800, Haojian Zhuang wrote: > On Fri, May 14, 2010 at 10:32 AM, David Woodhouse wrote: > > On Thu, 2010-05-06 at 05:12 -0400, Haojian Zhuang wrote: > >> From c81c53e24bbbe29ab4bf9767d24de8c45a4470b9 Mon Sep 17 00:00:00 2001 > >> From: Lei Wen > >> Date: Thu, 6 May 2010 10:42:13 +0800 > >> Subject: [PATCH] pxa3xx_nand: add cmdline part parser support > >> > >> Signed-off-by: Lei Wen > >> Signed-off-by: Haojian Zhuang > >> --- > >> drivers/mtd/nand/pxa3xx_nand.c | 26 ++++++++++++++++++++++++-- > >> 1 files changed, 24 insertions(+), 2 deletions(-) > > > > This conflicts with commit bff3c10d369440bc87ba612b45ba2777d2bf017f. > > > > Some of the other patches in this sequence don't apply cleanly to the > > current mtd-2.6.git tree either; please could you refresh? > > > > New patches are rebased for mtd-2.6 master branch. There're contained > in another mail loop. Hm, please test these by sending to yourself first, saving the patches and checking that they apply. [dwmw2 at macbook mtd-2.6]$ git describe HEAD v2.6.34-rc7-142-gf6b173c [dwmw2 at macbook mtd-2.6]$ for a in `seq -w 1 20` ; do echo Patch $a ; patch -p1 < pxa$a.patch ; done Patch 01 patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h patching file drivers/mtd/nand/Kconfig patching file drivers/mtd/nand/pxa3xx_nand.c patch: **** malformed patch at line 203: transfering to/from NAND HW"); Patch 02 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 225. patch: **** malformed patch at line 96: pxa3xx_nand_info *info, Patch 03 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 succeeded at 117 (offset -35 lines). Hunk #2 succeeded at 130 (offset -35 lines). Hunk #3 succeeded at 149 (offset -35 lines). Hunk #4 succeeded at 159 (offset -35 lines). patch: **** malformed patch at line 116: pxa3xx_nand_info *info, Patch 04 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 succeeded at 126 (offset -34 lines). Hunk #2 FAILED at 1097. patch: **** malformed patch at line 106: platform_device *pdev) Patch 05 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #4 succeeded at 108 with fuzz 1. patch: **** malformed patch at line 130: pxa3xx_nand_info *info, Patch 06 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 28. Hunk #2 succeeded at 74 (offset -4 lines). Hunk #3 FAILED at 335. Hunk #4 FAILED at 364. Hunk #5 FAILED at 556. patch: **** malformed patch at line 391: *mtd, unsigned command, Patch 07 patching file drivers/mtd/nand/pxa3xx_nand.c patch: **** malformed patch at line 78: builtin_flash_types[] = { Patch 08 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 218. patch: **** malformed patch at line 97: pxa3xx_nand_info *info, Patch 09 patching file arch/arm/mach-mmp/aspenite.c patching file arch/arm/mach-mmp/avengers_lite.c patch: **** malformed patch at line 104: avengers_lite_pin_config_V16F[] __initdata = { Patch 10 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 29. Hunk #2 succeeded at 36 (offset -2 lines). Hunk #3 succeeded at 89 (offset -6 lines). Hunk #4 FAILED at 132. Hunk #5 FAILED at 159. Hunk #6 FAILED at 182. patch: **** malformed patch at line 164: 60, 10, }, }, Patch 11 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 30. Hunk #2 FAILED at 411. Hunk #3 FAILED at 456. patch: **** malformed patch at line 107: *nand, int dir_out) Patch 12 patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h Hunk #1 succeeded at 12 with fuzz 2 (offset -1 lines). patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 30. Hunk #2 FAILED at 45. Hunk #3 FAILED at 59. Hunk #4 FAILED at 89. Hunk #5 succeeded at 93 with fuzz 2 (offset -46 lines). Hunk #6 FAILED at 154. Hunk #7 FAILED at 186. Hunk #8 FAILED at 209. patch: **** malformed patch at line 222: using naked command set"); Patch 13 patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h Hunk #1 succeeded at 14 with fuzz 2 (offset -1 lines). patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 succeeded at 60 with fuzz 2 (offset -30 lines). Hunk #2 FAILED at 187. Hunk #3 FAILED at 194. Hunk #4 FAILED at 275. patch: **** malformed patch at line 215: long nand_clk) Patch 14 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 26. Hunk #2 FAILED at 298. 2 out of 2 hunks FAILED -- saving rejects to file drivers/mtd/nand/pxa3xx_nand.c.rej Patch 15 patching file arch/arm/mach-mmp/include/mach/mmp2.h patch: **** malformed patch at line 92: i2c_pxa_platform_data *data, Patch 16 patching file drivers/mtd/nand/pxa3xx_nand.c patch: **** malformed patch at line 80: pxa3xx_nand *nand, int command, Patch 17 patching file drivers/mtd/nand/pxa3xx_nand.c patch: **** malformed patch at line 74: builtin_flash_types[] = { Patch 18 patching file arch/arm/configs/pxa168_defconfig patch: **** malformed patch at line 82: nfsroot=192.168.2.100:/nfsroot/ Patch 19 patching file drivers/mtd/nand/pxa3xx_nand.c Hunk #1 FAILED at 129. Hunk #2 FAILED at 257. Hunk #3 FAILED at 646. patch: **** malformed patch at line 119: void *data) Patch 20 patching file drivers/mtd/nand/pxa3xx_nand.c patch: **** malformed patch at line 74: platform_device *pdev) -- dwmw2 From mkl at pengutronix.de Fri May 14 04:20:13 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Fri, 14 May 2010 10:20:13 +0200 Subject: [PATCH 11/20] mtd: pxa3xx_nand: add debug messege In-Reply-To: References: Message-ID: <4BED07BD.7090403@pengutronix.de> Haojian Zhuang wrote: >>From 10e0c31fac5a8ebeb314d609cea24351097b1aae Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Tue, 30 Mar 2010 20:58:58 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: add debug messege > > Add debug messege to those key route to help find out problem. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > drivers/mtd/nand/pxa3xx_nand.c | 23 ++++++++++++++++++++++- > 1 files changed, 22 insertions(+), 1 deletions(-) > > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index fb1af4c..0674b52 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -30,6 +30,12 @@ > #define NAND_STOP_DELAY (2 * HZ/50) > #define PAGE_CHUNK_SIZE (2048) > #define BCH_THRESHOLD (8) > +#undef PXA3XX_NAND_DEBUG > +#ifdef PXA3XX_NAND_DEBUG > +#define DBG_NAND(x) do{x;}while(0) > +#else > +#define DBG_NAND(x) > +#endif If you really need to get this in mainline, try using pr_debug() for this, add #if PXA3XX_NAND_DEBUG #define DEBUG #endif to activate debugging. > > /* registers and bit definitions */ > #define NDCR (0x00) /* Control register */ > @@ -411,6 +417,8 @@ static void pxa3xx_nand_start(struct pxa3xx_nand *nand) > } > > /* clear status bits and run */ > + DBG_NAND(printk("@@@ndcr set: %x, ndeccctrl set %x\n", > + ndcr, ndeccctrl)); > nand_writel(nand, NDCR, 0); > nand_writel(nand, NDECCCTRL, ndeccctrl); > nand_writel(nand, NDSR, NDSR_MASK); > @@ -456,6 +464,8 @@ static void handle_data_pio(struct pxa3xx_nand *nand) > { > struct pxa3xx_nand_info *info = nand->info[nand->chip_select]; > > + DBG_NAND(printk("data size %x, oob size %x\n", > + nand->data_size, nand->oob_size)); > if (nand->state & STATE_IS_WRITE) { > __raw_writesl(nand->mmio_base + NDDB, info->data_buff, > DIV_ROUND_UP(nand->data_size, 4)); > @@ -492,6 +502,8 @@ static void start_data_dma(struct pxa3xx_nand > *nand, int dir_out) > desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC; > } > > + DBG_NAND(printk("DMA START:DMA dcmd %x, dsadr %x, dtadr %x, len %x\n", > + desc->dcmd, desc->dsadr, desc->dtadr, dma_len)); > DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch; > DDADR(info->data_dma_ch) = info->data_desc_addr; > DCSR(info->data_dma_ch) |= DCSR_RUN; > @@ -505,6 +517,7 @@ static void pxa3xx_nand_data_dma_irq(int channel, > void *data) > dcsr = DCSR(channel); > DCSR(channel) = dcsr; > > + DBG_NAND(printk("DMA IRQ: dcsr %x\n", dcsr)); > if (dcsr & DCSR_BUSERR) { > nand->retcode = ERR_DMABUSERR; > } > @@ -528,6 +541,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) > info = nand->info[cs]; > > status = nand_readl(nand, NDSR); > + DBG_NAND(if (status != 0) > + printk("\t\tstatus %x, cs %x\n", status, cs)); > nand->bad_count = (status & NDSR_ERR_CNT_MASK) >> 16; > if (status & NDSR_DBERR) > nand->retcode = ERR_DBERR; > @@ -562,6 +577,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) > nand_writel(nand, NDCB0, info->ndcb0); > nand_writel(nand, NDCB0, info->ndcb1); > nand_writel(nand, NDCB0, info->ndcb2); > + DBG_NAND(printk("\tndcb0 %x ndcb1 %x ndcb2 %x\n", > + info->ndcb0, info->ndcb1, info->ndcb2)); > } > > /* clear NDSR to let the controller exit the IRQ */ > @@ -754,6 +771,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > nand_writel(nand, NDTR1CS0, info->ndtr1cs0); > } > > + DBG_NAND(printk("command %x, page %x\n", command, page_addr)); > exec_cmd = prepare_command_pool(nand, command, column, page_addr); > if (exec_cmd) { > init_completion(&nand->cmd_complete); > @@ -940,6 +958,7 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, > chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); > > if (nand->retcode == ERR_SBERR) { > + DBG_NAND(printk("###correctable error detected\n");); > switch (nand->use_ecc) { > case ECC_BCH: > if (nand->bad_count > BCH_THRESHOLD) > @@ -956,8 +975,10 @@ static int pxa3xx_nand_read_page_hwecc(struct > mtd_info *mtd, > int buf_blank; > > buf_blank = is_buf_blank(buf, mtd->writesize); > - if (!buf_blank) > + if (!buf_blank) { > + DBG_NAND(printk("###uncorrectable error!!!\n")); > mtd->ecc_stats.failed++; > + } > } > > return 0; -- Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 260 bytes Desc: OpenPGP digital signature URL: From david.woodhouse at intel.com Fri May 14 04:35:19 2010 From: david.woodhouse at intel.com (David Woodhouse) Date: Fri, 14 May 2010 09:35:19 +0100 Subject: [PATCH 11/20] mtd: pxa3xx_nand: add debug messege In-Reply-To: <4BED07BD.7090403@pengutronix.de> References: <4BED07BD.7090403@pengutronix.de> Message-ID: <1273826119.9999.1634.camel@macbook.infradead.org> On Fri, 2010-05-14 at 09:20 +0100, Marc Kleine-Budde wrote: > > If you really need to get this in mainline, try using pr_debug() for > this, add > > #if PXA3XX_NAND_DEBUG > #define DEBUG > #endif > > to activate debugging. I _wish_ we could have a per-device 'debug' flag, and dev_dbg() would work based on that. We should also be able to compile it out completely, of course. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From daniel at caiaq.de Fri May 14 04:41:49 2010 From: daniel at caiaq.de (Daniel Mack) Date: Fri, 14 May 2010 10:41:49 +0200 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: <1273824971.9999.1582.camel@macbook.infradead.org> References: <1273804364.9999.881.camel@macbook.infradead.org> <1273824971.9999.1582.camel@macbook.infradead.org> Message-ID: <20100514084149.GJ30801@buzzloop.caiaq.de> On Fri, May 14, 2010 at 09:16:11AM +0100, David Woodhouse wrote: > On Fri, 2010-05-14 at 14:08 +0800, Haojian Zhuang wrote: > > New patches are rebased for mtd-2.6 master branch. There're contained > > in another mail loop. > > Hm, please test these by sending to yourself first, saving the patches > and checking that they apply. > > [dwmw2 at macbook mtd-2.6]$ git describe HEAD > v2.6.34-rc7-142-gf6b173c > > [dwmw2 at macbook mtd-2.6]$ for a in `seq -w 1 20` ; do echo Patch $a ; patch -p1 < pxa$a.patch ; done > Patch 01 > patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > patching file drivers/mtd/nand/Kconfig > patching file drivers/mtd/nand/pxa3xx_nand.c > patch: **** malformed patch at line 203: transfering to/from NAND HW"); Jep, they're line-wrapped, just like the version before. Haojian, you can avoid this to happen by using 'git send-email'. Thanks, Daniel From joakim.tjernlund at transmode.se Fri May 14 06:10:57 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Fri, 14 May 2010 12:10:57 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1273771018.12840.7077.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/13 19:16:58: > > On Sat, 2010-03-20 at 11:03 +0100, Joakim Tjernlund wrote: > > Erasing blocks is a form of GC and therefore it should live in the > > GC task. By moving it there two problems will be solved: > > 1) unmounting will not hang until all pending blocks has > > been erased. > > 2) Erasing can be paused by sending a SIGSTOP to the GC thread which > > allowes for time critical tasks to work in peace. > > > > Since erasing now is in the GC thread, erases should trigger > > the GC task instead. > > wbuf.c still wants to flush its buffer via write_super so > > invent jffs2_dirty_trigger() and use that in wbuf. > > Remove surplus call to jffs2_erase_pending_trigger() in erase.c > > and remove jffs2_garbage_collect_trigger() from write_super as > > of now write_super() should only commit dirty data to disk. > > > > Signed-off-by: Joakim Tjernlund > > --- > uhh, I wrote this patch almost 2 months ago, can't remember the details but I do my best. > The only callers of jffs2_erase_pending_blocks() now call it with a > 'count' argument of 1. So perhaps it's now misnamed and the 's' and the > extra argument should be dropped? I didn't want to change to much and who knows, maybe someone wants to erase more than one block in the future. Removing the count could be an add on patch once this patch has proven itself. > > I don't much like the calculation you've added to the end of that > function either, which really ought to be under locks (even though right > now I suspect it doesn't hurt). Why recalculate that at all, though -- Why does a simple list test need locks? > why not keep a 'ret' variable which defaults to 0 but is set to 1 just > before the 'goto done' which is the only way out of the function where > the return value should be non-zero anyway? That would not be the same, would it? One wants to know if the lists are empty AFTER erasing count blocks. I guess I could move the list empty check before goto done, but that would not really change anything. > > I've always been very careful to keep the GC thread as an > _optimisation_. It looks like this will still work, because the actual > erase will get done from jffs2_reserve_space()... but that'll only erase > blocks immediately when we actually need them. Before, we were erasing > them in advance. I suppose that's OK though. yes, I think so too. From dwmw2 at infradead.org Fri May 14 06:35:04 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Fri, 14 May 2010 11:35:04 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> Message-ID: <1273833304.9999.1994.camel@macbook.infradead.org> On Fri, 2010-05-14 at 12:10 +0200, Joakim Tjernlund wrote: > The only callers of jffs2_erase_pending_blocks() now call it with a > > 'count' argument of 1. So perhaps it's now misnamed and the 's' and the > > extra argument should be dropped? > > I didn't want to change to much and who knows, maybe someone wants > to erase more than one block in the future. Removing the > count could be an add on patch once this patch has proven itself. Yeah, that makes some sense. > > I don't much like the calculation you've added to the end of that > > function either, which really ought to be under locks (even though right > > now I suspect it doesn't hurt). Why recalculate that at all, though -- > > Why does a simple list test need locks? Because it's not just about the test itself. It's also about the memory barriers. Some other CPU could have changed the list (under locks) but unless you have the memory barrier which is implicit in the spinlock, you might see old data. > > why not keep a 'ret' variable which defaults to 0 but is set to 1 just > > before the 'goto done' which is the only way out of the function where > > the return value should be non-zero anyway? > > That would not be the same, would it? One wants to know if the lists > are empty AFTER erasing count blocks. Hm, does one? There's precisely one place we use this return value, in the GC thread. Can you explain the logic of what you were doing there? It looks like you really wanted it to return a flag saying whether it actually _did_ anything or not. And if it did, that's your work for this GC wakeup and you don't call jffs2_garbage_collect_pass(). Why are you returning a value which tells whether there's more work to do? > I guess I could move the list empty > check before goto done, but that would not really change anything. Ah, yes. Instead of setting ret=1 at the 'goto done', you'd actually do the test somewhere there too, before dropping the locks. Assuming that this really is the return value you need to return, rather than a simple 'work_done' flag. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From haojian.zhuang at gmail.com Fri May 14 06:56:44 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Fri, 14 May 2010 18:56:44 +0800 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: <20100514084149.GJ30801@buzzloop.caiaq.de> References: <1273804364.9999.881.camel@macbook.infradead.org> <1273824971.9999.1582.camel@macbook.infradead.org> <20100514084149.GJ30801@buzzloop.caiaq.de> Message-ID: On Fri, May 14, 2010 at 4:41 PM, Daniel Mack wrote: > On Fri, May 14, 2010 at 09:16:11AM +0100, David Woodhouse wrote: >> On Fri, 2010-05-14 at 14:08 +0800, Haojian Zhuang wrote: >> > New patches are rebased for mtd-2.6 master branch. There're contained >> > in another mail loop. >> >> Hm, please test these by sending to yourself first, saving the patches >> and checking that they apply. >> >> [dwmw2 at macbook mtd-2.6]$ git describe HEAD >> v2.6.34-rc7-142-gf6b173c >> >> [dwmw2 at macbook mtd-2.6]$ for a in `seq -w 1 20` ; do echo Patch $a ; patch -p1 < pxa$a.patch ; done >> Patch 01 >> patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >> patching file drivers/mtd/nand/Kconfig >> patching file drivers/mtd/nand/pxa3xx_nand.c >> patch: **** malformed patch at line 203: transfering to/from NAND HW"); > > Jep, they're line-wrapped, just like the version before. > > Haojian, you can avoid this to happen by using 'git send-email'. > > Thanks, > Daniel > Now I attach these patches directly. Only 0011 patch is changed to using dev_dbg for debug print. Daniel, Thanks for your advice. Best Regards Haojian -------------- next part -------------- A non-text attachment was scrubbed... Name: nand_update_mtd2.6.tgz Type: application/x-gzip Size: 43854 bytes Desc: not available URL: From mkl at pengutronix.de Fri May 14 07:09:00 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Fri, 14 May 2010 13:09:00 +0200 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: Message-ID: <4BED2F4C.8040300@pengutronix.de> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hello Haojian, Haojian Zhuang wrote: >>From 16057e690aa4a2fd8a9c07c70ab48ffc2f76204f Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Sat, 20 Mar 2010 19:01:23 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: refuse the flash definition get from platform > > For current usage, it is little reason to use a platform defined flash info > for the flash detection. Flash timing through platform should be the same. > And allow multiple platform to define the same flash chip would be a waste. > > Also condense the flash definition way in the c file to simplify adding a > new chip. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang NACK, see inline > --- > arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 40 ---- > drivers/mtd/nand/Kconfig | 7 - > drivers/mtd/nand/pxa3xx_nand.c | 262 ++++++-------------------- > 3 files changed, 60 insertions(+), 249 deletions(-) > > diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > index 3478eae..c494f68 100644 > --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > @@ -4,43 +4,6 @@ > #include > #include > > -struct pxa3xx_nand_timing { > - unsigned int tCH; /* Enable signal hold time */ > - unsigned int tCS; /* Enable signal setup time */ > - unsigned int tWH; /* ND_nWE high duration */ > - unsigned int tWP; /* ND_nWE pulse time */ > - unsigned int tRH; /* ND_nRE high duration */ > - unsigned int tRP; /* ND_nRE pulse width */ > - unsigned int tR; /* ND_nWE high to ND_nRE low for read */ > - unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */ > - unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ > -}; > - > -struct pxa3xx_nand_cmdset { > - uint16_t read1; > - uint16_t read2; > - uint16_t program; > - uint16_t read_status; > - uint16_t read_id; > - uint16_t erase; > - uint16_t reset; > - uint16_t lock; > - uint16_t unlock; > - uint16_t lock_status; > -}; > - > -struct pxa3xx_nand_flash { > - const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ > - const struct pxa3xx_nand_cmdset *cmdset; > - > - uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ > - uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ > - uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ > - uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ > - uint32_t num_blocks; /* Number of physical blocks in Flash */ > - uint32_t chip_id; > -}; > - > struct pxa3xx_nand_platform_data { > > /* the data flash bus is shared between the Static Memory > @@ -54,9 +17,6 @@ struct pxa3xx_nand_platform_data { > > const struct mtd_partition *parts; > unsigned int nr_parts; > - > - const struct pxa3xx_nand_flash * flash; > - size_t num_flash; > }; > > extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig > index 98a04b3..9a35d92 100644 > --- a/drivers/mtd/nand/Kconfig > +++ b/drivers/mtd/nand/Kconfig > @@ -399,13 +399,6 @@ config MTD_NAND_PXA3xx > This enables the driver for the NAND flash device found on > PXA3xx processors > > -config MTD_NAND_PXA3xx_BUILTIN > - bool "Use builtin definitions for some NAND chips (deprecated)" > - depends on MTD_NAND_PXA3xx > - help > - This enables builtin definitions for some NAND chips. This > - is deprecated in favor of platform specific data. > - > config MTD_NAND_CM_X270 > tristate "Support for NAND Flash on CM-X270 modules" > depends on MTD_NAND && MACH_ARMCORE > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index e02fa4f..da40b9a 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -113,6 +113,41 @@ enum { > STATE_PIO_WRITING, > }; > > +struct pxa3xx_nand_timing { > + uint32_t tCH; /* Enable signal hold time */ > + uint32_t tCS; /* Enable signal setup time */ > + uint32_t tWH; /* ND_nWE high duration */ > + uint32_t tWP; /* ND_nWE pulse time */ > + uint32_t tRH; /* ND_nRE high duration */ > + uint32_t tRP; /* ND_nRE pulse width */ > + uint32_t tAR; /* ND_ALE low to ND_nRE low delay */ > + uint32_t tWHR; /* ND_nWE high to ND_nRE low for status read */ > + uint32_t tR; /* ND_nWE high to ND_nRE low for read */ > +}; > + > +struct pxa3xx_nand_cmdset { > + uint16_t read1; > + uint16_t read2; > + uint16_t program; > + uint16_t read_status; > + uint16_t read_id; > + uint16_t erase; > + uint16_t reset; > + uint16_t lock; > + uint16_t unlock; > + uint16_t lock_status; > +}; > + > +struct pxa3xx_nand_flash { > + uint32_t chip_id; > + uint16_t page_per_block; /* Pages per block (PG_PER_BLK) */ > + uint16_t page_size; /* Page size in bytes (PAGE_SZ) */ > + uint8_t flash_width; /* Width of Flash memory (DWIDTH_M) */ > + uint8_t dfc_width; /* Width of flash controller(DWIDTH_C) */ > + uint32_t num_blocks; /* Number of physical blocks in Flash */ > + struct pxa3xx_nand_timing timing; /* NAND Flash timing */ > +}; > + > struct pxa3xx_nand_info { > struct nand_chip nand_chip; > > @@ -177,20 +212,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data > transfering to/from NAND HW"); > static struct pxa3xx_nand_timing default_timing; > static struct pxa3xx_nand_flash default_flash; > > -static struct pxa3xx_nand_cmdset smallpage_cmdset = { > - .read1 = 0x0000, > - .read2 = 0x0050, > - .program = 0x1080, > - .read_status = 0x0070, > - .read_id = 0x0090, > - .erase = 0xD060, > - .reset = 0x00FF, > - .lock = 0x002A, > - .unlock = 0x2423, > - .lock_status = 0x007A, > -}; > - > -static struct pxa3xx_nand_cmdset largepage_cmdset = { > +const static struct pxa3xx_nand_cmdset cmdset = { > .read1 = 0x3000, > .read2 = 0x0050, > .program = 0x1080, > @@ -203,143 +225,17 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = { > .lock_status = 0x007A, > }; > > -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN > -static struct pxa3xx_nand_timing samsung512MbX16_timing = { > - .tCH = 10, > - .tCS = 0, > - .tWH = 20, > - .tWP = 40, > - .tRH = 30, > - .tRP = 40, > - .tR = 11123, > - .tWHR = 110, > - .tAR = 10, > -}; > - > -static struct pxa3xx_nand_flash samsung512MbX16 = { > - .timing = &samsung512MbX16_timing, > - .cmdset = &smallpage_cmdset, > - .page_per_block = 32, > - .page_size = 512, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 4096, > - .chip_id = 0x46ec, > -}; > - > -static struct pxa3xx_nand_flash samsung2GbX8 = { > - .timing = &samsung512MbX16_timing, > - .cmdset = &smallpage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 2048, > - .chip_id = 0xdaec, > -}; > - > -static struct pxa3xx_nand_flash samsung32GbX8 = { > - .timing = &samsung512MbX16_timing, > - .cmdset = &smallpage_cmdset, > - .page_per_block = 128, > - .page_size = 4096, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 8192, > - .chip_id = 0xd7ec, > +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { > +{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, > +{ 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, > 60, 10, }, }, > +{ 0xdc2c, 64, 2048, 8, 8, 4096, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, > +{ 0xcc2c, 64, 2048, 16, 16, 4096, { 10, 25, 15, 25, 15, 30, 25000, > 60, 10, }, }, > +{ 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, > 60, 10, }, }, > }; > > -static struct pxa3xx_nand_timing micron_timing = { > - .tCH = 10, > - .tCS = 25, > - .tWH = 15, > - .tWP = 25, > - .tRH = 15, > - .tRP = 30, > - .tR = 25000, > - .tWHR = 60, > - .tAR = 10, > -}; > - > -static struct pxa3xx_nand_flash micron1GbX8 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 1024, > - .chip_id = 0xa12c, > -}; > - > -static struct pxa3xx_nand_flash micron1GbX16 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 1024, > - .chip_id = 0xb12c, > -}; > - > -static struct pxa3xx_nand_flash micron4GbX8 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 4096, > - .chip_id = 0xdc2c, > -}; > - > -static struct pxa3xx_nand_flash micron4GbX16 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 4096, > - .chip_id = 0xcc2c, > -}; > - > -static struct pxa3xx_nand_timing stm2GbX16_timing = { > - .tCH = 10, > - .tCS = 35, > - .tWH = 15, > - .tWP = 25, > - .tRH = 15, > - .tRP = 25, > - .tR = 25000, > - .tWHR = 60, > - .tAR = 10, > -}; > - > -static struct pxa3xx_nand_flash stm2GbX16 = { > - .timing = &stm2GbX16_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 2048, > - .chip_id = 0xba20, > -}; > - > -static struct pxa3xx_nand_flash *builtin_flash_types[] = { > - &samsung512MbX16, > - &samsung2GbX8, > - &samsung32GbX8, > - µn1GbX8, > - µn1GbX16, > - µn4GbX8, > - µn4GbX16, > - &stm2GbX16, > -}; > -#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ > - > #define NDTR0_tCH(c) (min((c), 7) << 19) > #define NDTR0_tCS(c) (min((c), 7) << 16) > #define NDTR0_tWH(c) (min((c), 7) << 11) > @@ -412,7 +308,6 @@ static int prepare_read_prog_cmd(struct > pxa3xx_nand_info *info, > uint16_t cmd, int column, int page_addr) > { > const struct pxa3xx_nand_flash *f = info->flash_info; > - const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; > > /* calculate data size */ > switch (f->page_size) { > @@ -445,7 +340,7 @@ static int prepare_read_prog_cmd(struct > pxa3xx_nand_info *info, > */ > info->ndcb1 = page_addr << 8; > > - if (cmd == cmdset->program) > + if (cmd == cmdset.program) > info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; > > return 0; > @@ -463,20 +358,18 @@ static int prepare_erase_cmd(struct > pxa3xx_nand_info *info, > > static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) > { > - const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; > - > info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); > info->ndcb1 = 0; > info->ndcb2 = 0; > > - if (cmd == cmdset->read_id) { > + if (cmd == cmdset.read_id) { > info->ndcb0 |= NDCB0_CMD_TYPE(3); > info->data_size = 8; > - } else if (cmd == cmdset->read_status) { > + } else if (cmd == cmdset.read_status) { > info->ndcb0 |= NDCB0_CMD_TYPE(4); > info->data_size = 8; > - } else if (cmd == cmdset->reset || cmd == cmdset->lock || > - cmd == cmdset->unlock) { > + } else if (cmd == cmdset.reset || cmd == cmdset.lock || > + cmd == cmdset.unlock) { > info->ndcb0 |= NDCB0_CMD_TYPE(5); > } else > return -EINVAL; > @@ -700,8 +593,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > int column, int page_addr) > { > struct pxa3xx_nand_info *info = mtd->priv; > - const struct pxa3xx_nand_flash *flash_info = info->flash_info; > - const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; > int ret; > > info->use_dma = (use_dma) ? 1 : 0; > @@ -718,7 +609,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > info->buf_start = mtd->writesize + column; > memset(info->data_buff, 0xFF, info->buf_count); > > - if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) > + if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); > @@ -735,7 +626,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > info->buf_count = mtd->writesize + mtd->oobsize; > memset(info->data_buff, 0xFF, info->buf_count); > > - if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) > + if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); > @@ -761,14 +652,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > case NAND_CMD_PAGEPROG: > info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; > > - if (prepare_read_prog_cmd(info, cmdset->program, > + if (prepare_read_prog_cmd(info, cmdset.program, > info->seqin_column, info->seqin_page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); > break; > case NAND_CMD_ERASE1: > - if (prepare_erase_cmd(info, cmdset->erase, page_addr)) > + if (prepare_erase_cmd(info, cmdset.erase, page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); > @@ -783,13 +674,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > info->read_id_bytes : 1; > > if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? > - cmdset->read_id : cmdset->read_status)) > + cmdset.read_id : cmdset.read_status)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); > break; > case NAND_CMD_RESET: > - if (prepare_other_cmd(info, cmdset->reset)) > + if (prepare_other_cmd(info, cmdset.reset)) > break; > > ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); > @@ -925,12 +816,10 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, > > static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) > { > - const struct pxa3xx_nand_flash *f = info->flash_info; > - const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; > uint32_t ndcr; > uint8_t id_buff[8]; > > - if (prepare_other_cmd(info, cmdset->read_id)) { > + if (prepare_other_cmd(info, cmdset.read_id)) { > printk(KERN_ERR "failed to prepare command\n"); > return -EINVAL; > } > @@ -991,7 +880,7 @@ static int pxa3xx_nand_config_flash(struct > pxa3xx_nand_info *info, > > info->reg_ndcr = ndcr; > > - pxa3xx_nand_set_timing(info, f->timing); > + pxa3xx_nand_set_timing(info, &f->timing); > info->flash_info = f; > return 0; > } > @@ -1027,11 +916,6 @@ static int pxa3xx_nand_detect_config(struct > pxa3xx_nand_info *info) > default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; > default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; > > - if (default_flash.page_size == 2048) > - default_flash.cmdset = &largepage_cmdset; > - else > - default_flash.cmdset = &smallpage_cmdset; > - > /* set info fields needed to __readid */ > info->flash_info = &default_flash; > info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; > @@ -1067,7 +951,7 @@ static int pxa3xx_nand_detect_config(struct > pxa3xx_nand_info *info) > info->row_addr_cycles = 2; > > pxa3xx_nand_detect_timing(info, &default_timing); > - default_flash.timing = &default_timing; > + memcpy(&default_flash.timing, &default_timing, sizeof(default_timing)); > > return 0; > } > @@ -1083,23 +967,9 @@ static int pxa3xx_nand_detect_flash(struct > pxa3xx_nand_info *info, > if (pxa3xx_nand_detect_config(info) == 0) > return 0; > > - for (i = 0; inum_flash; ++i) { > - f = pdata->flash + i; > - > - if (pxa3xx_nand_config_flash(info, f)) > - continue; > - > - if (__readid(info, &id)) > - continue; > - > - if (id == f->chip_id) > - return 0; > - } > - > -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN > for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { > > - f = builtin_flash_types[i]; > + f = &builtin_flash_types[i]; > > if (pxa3xx_nand_config_flash(info, f)) > continue; > @@ -1110,7 +980,6 @@ static int pxa3xx_nand_detect_flash(struct > pxa3xx_nand_info *info, > if (id == f->chip_id) > return 0; > } > -#endif > > dev_warn(&info->pdev->dev, > "failed to detect configured nand flash; found %04x instead of\n", > @@ -1320,17 +1189,6 @@ static int pxa3xx_nand_probe(struct > platform_device *pdev) > goto fail_free_irq; > } > > - if (mtd_has_cmdlinepart()) { > - static const char *probes[] = { "cmdlinepart", NULL }; > - struct mtd_partition *parts; > - int nr_parts; > - > - nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); > - > - if (nr_parts) > - return add_mtd_partitions(mtd, parts, nr_parts); > - } > - Why are you removing this? It already works, has the same functionality as your patch 17 and works without ugly defines. Please don't remove this and drop your patch 17 > return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); > > fail_free_irq: cheers Marc - -- Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkvtL0wACgkQjTAFq1RaXHOWgACdFRMRw1ywiDYcm1CqYKgJErUu NX8AoIHPVxVPVLB+U9l6c0Umk4nGbdH4 =0Dv/ -----END PGP SIGNATURE----- From mkl at pengutronix.de Fri May 14 07:09:57 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Fri, 14 May 2010 13:09:57 +0200 Subject: [PATCH 17/20] mtd: pxa3xx_nand: add cmdline part parser support In-Reply-To: References: Message-ID: <4BED2F85.9080004@pengutronix.de> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Haojian Zhuang wrote: >>From aeab6a19eeb5ff8715ba16497124fae539641e46 Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Thu, 6 May 2010 10:42:13 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: add cmdline part parser support > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang NACK, you remove already working cmdline support in you patch 1. Please drop this patch. cheers, Marc > --- > drivers/mtd/nand/pxa3xx_nand.c | 26 ++++++++++++++++++++++++-- > 1 files changed, 24 insertions(+), 2 deletions(-) > > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index 2eebd20..793b64c 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -349,6 +349,9 @@ static struct pxa3xx_nand_flash __devinitdata > builtin_flash_types[] = { > { 0, 10, 35, 15, 25, 15, 25, 25000, 0, 60, 10, }, }, > }; > > +#ifdef CONFIG_MTD_CMDLINE_PARTS > +static const char *part_probes[] = { "cmdlinepart", NULL }; > +#endif > static const char *mtd_names[] = {"pxa3xx_nand-0", "pxa3xx_nand-1", NULL}; > > /* convert nano-seconds to nand flash controller clock cycles */ > @@ -1726,6 +1729,10 @@ static int __devinit pxa3xx_nand_probe(struct > platform_device *pdev) > struct pxa3xx_nand *nand; > struct mtd_info *mtd; > int ret, cs, probe_success = 0; > +#ifdef CONFIG_MTD_PARTITIONS > + struct mtd_partition *partitions = NULL; > + int num_part = 0; > +#endif > > pdata = pdev->dev.platform_data; > if (!pdata) { > @@ -1747,8 +1754,23 @@ static int __devinit pxa3xx_nand_probe(struct > platform_device *pdev) > dev_err(&pdev->dev, "failed to scan cs#%d nand\n", cs); > continue; > } > - ret = add_mtd_partitions(mtd, pdata->parts[cs], > - pdata->nr_parts[cs]); > + mtd->name = mtd_names[cs]; > +#ifdef CONFIG_MTD_PARTITIONS > +#ifdef CONFIG_MTD_CMDLINE_PARTS > + num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0); > +#endif > + if (num_part <= 0) { > + num_part = pdata->nr_parts[cs]; > + partitions = pdata->parts[cs]; > + } > + > + if (partitions && num_part > 0) > + ret = add_mtd_partitions(mtd, partitions, num_part); > + else > + ret = add_mtd_device(mtd); > +#else > + ret = add_mtd_device(mtd); > +#endif > if (!ret) > probe_success = 1; > } - -- Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iEYEARECAAYFAkvtL4UACgkQjTAFq1RaXHNwjQCfS/U6+ZQoq8J/CpNpurWppigf PNIAn2jzOk/bi2XjTMCP4M1nDFkX87Er =4//G -----END PGP SIGNATURE----- From mkl at pengutronix.de Fri May 14 07:11:12 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Fri, 14 May 2010 13:11:12 +0200 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: References: <1273804364.9999.881.camel@macbook.infradead.org> <1273824971.9999.1582.camel@macbook.infradead.org> <20100514084149.GJ30801@buzzloop.caiaq.de> Message-ID: <4BED2FD0.5010308@pengutronix.de> Haojian Zhuang wrote: > On Fri, May 14, 2010 at 4:41 PM, Daniel Mack wrote: >> On Fri, May 14, 2010 at 09:16:11AM +0100, David Woodhouse wrote: >>> On Fri, 2010-05-14 at 14:08 +0800, Haojian Zhuang wrote: >>>> New patches are rebased for mtd-2.6 master branch. There're contained >>>> in another mail loop. >>> Hm, please test these by sending to yourself first, saving the patches >>> and checking that they apply. >>> >>> [dwmw2 at macbook mtd-2.6]$ git describe HEAD >>> v2.6.34-rc7-142-gf6b173c >>> >>> [dwmw2 at macbook mtd-2.6]$ for a in `seq -w 1 20` ; do echo Patch $a ; patch -p1 < pxa$a.patch ; done >>> Patch 01 >>> patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >>> patching file drivers/mtd/nand/Kconfig >>> patching file drivers/mtd/nand/pxa3xx_nand.c >>> patch: **** malformed patch at line 203: transfering to/from NAND HW"); >> Jep, they're line-wrapped, just like the version before. >> >> Haojian, you can avoid this to happen by using 'git send-email'. >> >> Thanks, >> Daniel >> > > Now I attach these patches directly. Only 0011 patch is changed to > using dev_dbg for debug print. I NACK patches 1 and 17. See my reply to these individual patches. Cheers, Marc -- Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 260 bytes Desc: OpenPGP digital signature URL: From joakim.tjernlund at transmode.se Fri May 14 07:07:05 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Fri, 14 May 2010 13:07:05 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1273833304.9999.1994.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/14 12:35:04: > > On Fri, 2010-05-14 at 12:10 +0200, Joakim Tjernlund wrote: > > The only callers of jffs2_erase_pending_blocks() now call it with a > > > 'count' argument of 1. So perhaps it's now misnamed and the 's' and the > > > extra argument should be dropped? > > > > I didn't want to change to much and who knows, maybe someone wants > > to erase more than one block in the future. Removing the > > count could be an add on patch once this patch has proven itself. > > Yeah, that makes some sense. > > > > I don't much like the calculation you've added to the end of that > > > function either, which really ought to be under locks (even though right > > > now I suspect it doesn't hurt). Why recalculate that at all, though -- > > > > Why does a simple list test need locks? > > Because it's not just about the test itself. It's also about the memory > barriers. Some other CPU could have changed the list (under locks) but > unless you have the memory barrier which is implicit in the spinlock, > you might see old data. old data doesn't matter here I think. > > > > why not keep a 'ret' variable which defaults to 0 but is set to 1 just > > > before the 'goto done' which is the only way out of the function where > > > the return value should be non-zero anyway? > > > > That would not be the same, would it? One wants to know if the lists > > are empty AFTER erasing count blocks. > > Hm, does one? There's precisely one place we use this return value, in > the GC thread. Can you explain the logic of what you were doing there? Sure, return 1 if there are more blocks left in the list after erasing count. That way the caller knows if there are any block left to erase. > It looks like you really wanted it to return a flag saying whether it > actually _did_ anything or not. And if it did, that's your work for this > GC wakeup and you don't call jffs2_garbage_collect_pass(). Why are you > returning a value which tells whether there's more work to do? hmm, I guess the simpler method like you suggested would work too. Details are a bit fuzzy now. > > > I guess I could move the list empty > > check before goto done, but that would not really change anything. > > Ah, yes. Instead of setting ret=1 at the 'goto done', you'd actually do > the test somewhere there too, before dropping the locks. Assuming that > this really is the return value you need to return, rather than a simple > 'work_done' flag. From joakim.tjernlund at transmode.se Fri May 14 08:12:03 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Fri, 14 May 2010 14:12:03 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> Message-ID: > > David Woodhouse wrote on 2010/05/14 12:35:04: > > > > On Fri, 2010-05-14 at 12:10 +0200, Joakim Tjernlund wrote: > > > The only callers of jffs2_erase_pending_blocks() now call it with a > > > > 'count' argument of 1. So perhaps it's now misnamed and the 's' and the > > > > extra argument should be dropped? > > > > > > I didn't want to change to much and who knows, maybe someone wants > > > to erase more than one block in the future. Removing the > > > count could be an add on patch once this patch has proven itself. > > > > Yeah, that makes some sense. > > > > > > I don't much like the calculation you've added to the end of that > > > > function either, which really ought to be under locks (even though right > > > > now I suspect it doesn't hurt). Why recalculate that at all, though -- > > > > > > Why does a simple list test need locks? > > > > Because it's not just about the test itself. It's also about the memory > > barriers. Some other CPU could have changed the list (under locks) but > > unless you have the memory barrier which is implicit in the spinlock, > > you might see old data. > > old data doesn't matter here I think. > > > > > > > why not keep a 'ret' variable which defaults to 0 but is set to 1 just > > > > before the 'goto done' which is the only way out of the function where > > > > the return value should be non-zero anyway? > > > > > > That would not be the same, would it? One wants to know if the lists > > > are empty AFTER erasing count blocks. > > > > Hm, does one? There's precisely one place we use this return value, in > > the GC thread. Can you explain the logic of what you were doing there? > > Sure, return 1 if there are more blocks left in the list after > erasing count. That way the caller knows if there are any block left > to erase. > > > It looks like you really wanted it to return a flag saying whether it > > actually _did_ anything or not. And if it did, that's your work for this > > GC wakeup and you don't call jffs2_garbage_collect_pass(). Why are you > > returning a value which tells whether there's more work to do? > > hmm, I guess the simpler method like you suggested would work too. > Details are a bit fuzzy now. > > > > > > I guess I could move the list empty > > > check before goto done, but that would not really change anything. > > > > Ah, yes. Instead of setting ret=1 at the 'goto done', you'd actually do > > the test somewhere there too, before dropping the locks. Assuming that > > this really is the return value you need to return, rather than a simple > > 'work_done' flag. How about this then? I have changed jffs2_erase_pending_blocks() to use the simpler work_done flag: From s-ghorai at ti.com Fri May 14 11:23:09 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Fri, 14 May 2010 20:53:09 +0530 Subject: [PATCH v2 0/2] omap3 nand: cleanup exiting platform related code In-Reply-To: References: Message-ID: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> v2: The following set of patches applies on top of master branch. http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board And these are the patches required to address the following input - 1. The NAND driver needs to stop tinkering with the GPMC registers The omap General Purpose Memory Controller (GPMC) registers are omap specific, and not driver specific. Tinkering with these registers can cause issues with the other devices on the GPMC. 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files Passing hardcoded GPMC virtual addressess is sure way to mess up things. This should all become unnecessary once the NAND drivers stops messing with the GPMC registers directly. v1: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28164.html Sukumar Ghorai (2): omap3 nand: cleanup for not to use GPMC virtual address omap3 nand: fix issue in board file to detect the nand arch/arm/mach-omap2/board-cm-t35.c | 20 +--- arch/arm/mach-omap2/board-devkit8000.c | 25 +--- arch/arm/mach-omap2/board-omap3beagle.c | 24 +--- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +--- arch/arm/mach-omap2/board-overo.c | 24 +--- arch/arm/mach-omap2/gpmc-nand.c | 38 ++---- arch/arm/mach-omap2/gpmc-onenand.c | 2 +- arch/arm/mach-omap2/gpmc.c | 244 ++++++++++++++++++++++++---- arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 190 ++++++---------------- 11 files changed, 306 insertions(+), 328 deletions(-) From s-ghorai at ti.com Fri May 14 11:23:11 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Fri, 14 May 2010 20:53:11 +0530 Subject: [PATCH v2 2/2] omap3 nand: fix issue in board file to detect the nand In-Reply-To: <1273850591-19040-2-git-send-email-s-ghorai@ti.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> Message-ID: <1273850591-19040-3-git-send-email-s-ghorai@ti.com> Board file modified to pass the GMPC phys_base address to nand driver. This is required to adopt the _prob function as in omap2.c Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/board-cm-t35.c | 16 +--------------- arch/arm/mach-omap2/board-devkit8000.c | 16 +--------------- arch/arm/mach-omap2/board-omap3beagle.c | 16 +--------------- arch/arm/mach-omap2/board-omap3touchbook.c | 16 +--------------- arch/arm/mach-omap2/board-overo.c | 17 +---------------- 5 files changed, 5 insertions(+), 76 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index fb23122..0544294 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -224,23 +224,9 @@ static struct omap_nand_platform_data cm_t35_nand_data = { }; -static struct resource cm_t35_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device cm_t35_nand_device = { - .name = "omap2-nand", - .id = -1, - .num_resources = 1, - .resource = &cm_t35_nand_resource, - .dev = { - .platform_data = &cm_t35_nand_data, - }, -}; - static void __init cm_t35_init_nand(void) { - if (platform_device_register(&cm_t35_nand_device) < 0) + if (gpmc_nand_init(&cm_t35_nand_data) < 0) pr_err("CM-T35: Unable to register NAND device\n"); } #else diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index ca4e409..9a8135d --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -101,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource devkit8000_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device devkit8000_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &devkit8000_nand_data, - }, - .num_resources = 1, - .resource = &devkit8000_nand_resource, -}; - static struct omap2_hsmmc_info mmc[] = { { .mmc = 1, @@ -601,7 +587,7 @@ static void __init devkit8000_flash_init(void) devkit8000_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&devkit8000_nand_device) < 0) + if (gpmc_nand_init(&devkit8000_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index becaebe..bf31b7c --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -89,20 +89,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = { .dev_ready = NULL, }; -static struct resource omap3beagle_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device omap3beagle_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &omap3beagle_nand_data, - }, - .num_resources = 1, - .resource = &omap3beagle_nand_resource, -}; - #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -397,7 +383,7 @@ static void __init omap3beagle_flash_init(void) omap3beagle_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&omap3beagle_nand_device) < 0) + if (gpmc_nand_init(&omap3beagle_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index d6f1b12..e8ad30c --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -103,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = { .dev_ready = NULL, }; -static struct resource omap3touchbook_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device omap3touchbook_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &omap3touchbook_nand_data, - }, - .num_resources = 1, - .resource = &omap3touchbook_nand_resource, -}; - #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -479,7 +465,7 @@ static void __init omap3touchbook_flash_init(void) omap3touchbook_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&omap3touchbook_nand_device) < 0) + if (gpmc_nand_init(&omap3touchbook_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index bf2ec32..cddc7ad --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -229,21 +229,6 @@ static struct omap_nand_platform_data overo_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource overo_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device overo_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &overo_nand_data, - }, - .num_resources = 1, - .resource = &overo_nand_resource, -}; - - static void __init overo_flash_init(void) { u8 cs = 0; @@ -272,7 +257,7 @@ static void __init overo_flash_init(void) overo_nand_data.cs = nandcs; printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&overo_nand_device) < 0) + if (gpmc_nand_init(&overo_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } From s-ghorai at ti.com Fri May 14 11:23:10 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Fri, 14 May 2010 20:53:10 +0530 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> Message-ID: <1273850591-19040-2-git-send-email-s-ghorai@ti.com> Necessary function added in GPMC module and used by nand driver. This is for not to use GPMC address directly from nand driver. Also it was passing GPMC base address from board files and that is removed. Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/board-cm-t35.c | 4 - arch/arm/mach-omap2/board-devkit8000.c | 9 - arch/arm/mach-omap2/board-omap3beagle.c | 8 - arch/arm/mach-omap2/board-omap3touchbook.c | 9 - arch/arm/mach-omap2/board-overo.c | 7 - arch/arm/mach-omap2/gpmc-nand.c | 38 ++---- arch/arm/mach-omap2/gpmc-onenand.c | 2 +- arch/arm/mach-omap2/gpmc.c | 244 ++++++++++++++++++++++++---- arch/arm/plat-omap/include/plat/gpmc.h | 36 ++++- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 190 ++++++---------------- 11 files changed, 301 insertions(+), 252 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index f4e8063..87bed2a --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -61,8 +61,6 @@ #define SB_T35_SMSC911X_GPIO 65 #define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE) #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include @@ -223,8 +221,6 @@ static struct omap_nand_platform_data cm_t35_nand_data = { .nr_parts = ARRAY_SIZE(cm_t35_nand_partitions), .dma_channel = -1, /* disable DMA in OMAP NAND driver */ .cs = 0, - .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR, - .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT, }; diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6d910df..ef9b677 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -58,9 +58,6 @@ #include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K #define OMAP_DM9000_GPIO_IRQ 25 @@ -581,8 +578,6 @@ static void __init devkit8000_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -604,10 +599,6 @@ static void __init devkit8000_flash_init(void) if (nandcs < GPMC_CS_NUM) { devkit8000_nand_data.cs = nandcs; - devkit8000_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - devkit8000_nand_data.gpmc_baseaddr = (void *) - (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&devkit8000_nand_device) < 0) diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 5df89f6..e90dd2a --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -47,9 +47,6 @@ #include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K static struct mtd_partition omap3beagle_nand_partitions[] = { @@ -377,8 +374,6 @@ static void __init omap3beagle_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -400,9 +395,6 @@ static void __init omap3beagle_flash_init(void) if (nandcs < GPMC_CS_NUM) { omap3beagle_nand_data.cs = nandcs; - omap3beagle_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&omap3beagle_nand_device) < 0) diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index c59050d..4a6c984 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -54,9 +54,6 @@ #include -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K #define OMAP3_AC_GPIO 136 @@ -459,8 +456,6 @@ static void __init omap3touchbook_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -482,10 +477,6 @@ static void __init omap3touchbook_flash_init(void) if (nandcs < GPMC_CS_NUM) { omap3touchbook_nand_data.cs = nandcs; - omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - omap3touchbook_nand_data.gpmc_baseaddr = - (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&omap3touchbook_nand_device) < 0) diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 24b32d7..a9151fb --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -58,8 +58,6 @@ #define OVERO_GPIO_USBH_NRESET 183 #define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 #define OVERO_SMSC911X_CS 5 #define OVERO_SMSC911X_GPIO 176 @@ -251,8 +249,6 @@ static void __init overo_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -274,9 +270,6 @@ static void __init overo_flash_init(void) if (nandcs < GPMC_CS_NUM) { overo_nand_data.cs = nandcs; - overo_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); if (platform_device_register(&overo_nand_device) < 0) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index e57fb29..8aa74be --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -19,8 +19,6 @@ #include #include -#define WR_RD_PIN_MONITORING 0x00600000 - static struct omap_nand_platform_data *gpmc_nand_data; static struct resource gpmc_nand_resource = { @@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void) t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle); /* Configure GPMC */ - gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1, - GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) | - GPMC_CONFIG1_DEVICETYPE_NAND); - + gpmc_hwcontrol(1, gpmc_nand_data->cs, + GPMC_CONFIG_DEV_SIZE, gpmc_nand_data->devsize, NULL); + gpmc_hwcontrol(1, gpmc_nand_data->cs, + GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND, NULL); err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); if (err) return err; @@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void) return 0; } -static int gpmc_nand_setup(void) -{ - struct device *dev = &gpmc_nand_device.dev; - - /* Set timings in GPMC */ - if (omap2_nand_gpmc_retime() < 0) { - dev_err(dev, "Unable to set gpmc timings\n"); - return -EINVAL; - } - - return 0; -} - int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data) { - unsigned int val; int err = 0; struct device *dev = &gpmc_nand_device.dev; gpmc_nand_data = _nand_data; - gpmc_nand_data->nand_setup = gpmc_nand_setup; + gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime; gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, @@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data) return err; } - err = gpmc_nand_setup(); + /* Set timings in GPMC */ + err = omap2_nand_gpmc_retime(); if (err < 0) { - dev_err(dev, "NAND platform setup failed: %d\n", err); + dev_err(dev, "Unable to set gpmc timings: %d\n", err); return err; } /* Enable RD PIN Monitoring Reg */ if (gpmc_nand_data->dev_ready) { - val = gpmc_cs_read_reg(gpmc_nand_data->cs, - GPMC_CS_CONFIG1); - val |= WR_RD_PIN_MONITORING; - gpmc_cs_write_reg(gpmc_nand_data->cs, - GPMC_CS_CONFIG1, val); + gpmc_hwcontrol(1, gpmc_nand_data->cs, + GPMC_CONFIG_RDY_BSY, 1, NULL); } err = platform_device_register(&gpmc_nand_device); diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c index 7bb6922..5d66817 --- a/arch/arm/mach-omap2/gpmc-onenand.c +++ b/arch/arm/mach-omap2/gpmc-onenand.c @@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, (GPMC_CONFIG1_WAIT_READ_MON | GPMC_CONFIG1_WAIT_PIN_SEL(0))) | GPMC_CONFIG1_DEVICESIZE_16 | - GPMC_CONFIG1_DEVICETYPE_NOR | + GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) | GPMC_CONFIG1_MUXADDDATA); err = gpmc_cs_set_timings(cs, &t); diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5bc3ca0..a3fd1ed --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -29,27 +29,27 @@ #include /* GPMC register offsets */ -#define GPMC_REVISION 0x00 -#define GPMC_SYSCONFIG 0x10 -#define GPMC_SYSSTATUS 0x14 -#define GPMC_IRQSTATUS 0x18 -#define GPMC_IRQENABLE 0x1c -#define GPMC_TIMEOUT_CONTROL 0x40 -#define GPMC_ERR_ADDRESS 0x44 -#define GPMC_ERR_TYPE 0x48 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 -#define GPMC_PREFETCH_CONFIG1 0x1e0 -#define GPMC_PREFETCH_CONFIG2 0x1e4 -#define GPMC_PREFETCH_CONTROL 0x1ec -#define GPMC_PREFETCH_STATUS 0x1f0 -#define GPMC_ECC_CONFIG 0x1f4 -#define GPMC_ECC_CONTROL 0x1f8 -#define GPMC_ECC_SIZE_CONFIG 0x1fc - -#define GPMC_CS0 0x60 -#define GPMC_CS_SIZE 0x30 - +#define GPMC_REVISION 0x00 +#define GPMC_SYSCONFIG 0x10 +#define GPMC_SYSSTATUS 0x14 +#define GPMC_IRQSTATUS 0x18 +#define GPMC_IRQENABLE 0x1c +#define GPMC_TIMEOUT_CONTROL 0x40 +#define GPMC_ERR_ADDRESS 0x44 +#define GPMC_ERR_TYPE 0x48 +#define GPMC_CONFIG 0x50 +#define GPMC_STATUS 0x54 +#define GPMC_PREFETCH_CONFIG1 0x1e0 +#define GPMC_PREFETCH_CONFIG2 0x1e4 +#define GPMC_PREFETCH_CONTROL 0x1ec +#define GPMC_PREFETCH_STATUS 0x1f0 +#define GPMC_ECC_CONFIG 0x1f4 +#define GPMC_ECC_CONTROL 0x1f8 +#define GPMC_ECC_SIZE_CONFIG 0x1fc +#define GPMC_ECC1_RESULT 0x200 + +#define GPMC_CS0_BASE 0x60 +#define GPMC_CS_SIZE 0x30 #define GPMC_MEM_START 0x00000000 #define GPMC_MEM_END 0x3FFFFFFF #define BOOT_ROM_SPACE 0x100000 /* 1MB */ @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx) return __raw_readl(gpmc_base + idx); } +static void gpmc_cs_write_byte(int cs, int idx, u8 val) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; + __raw_writeb(val, reg_addr); +} + +static u8 gpmc_cs_read_byte(int cs, int idx) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; + return __raw_readb(reg_addr); +} + void gpmc_cs_write_reg(int cs, int idx, u32 val) { void __iomem *reg_addr; - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; __raw_writel(val, reg_addr); } @@ -120,7 +136,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) { void __iomem *reg_addr; - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; return __raw_readl(reg_addr); } @@ -419,6 +435,96 @@ void gpmc_cs_free(int cs) EXPORT_SYMBOL(gpmc_cs_free); /** + * gpmc_hwcontrol - hardware specific access (read/ write) to control + * @write: need 1 for configure; 0 for reading the complete register + * @cs: chip select number + * @cmd: Command type + * @wval: value/information to write + * @rval: pointer to get the value back + */ +int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval) +{ + u32 reg = 0; + u32 regval = 0; + + switch (cmd) { + + case GPMC_GET_SET_STATUS: + reg = GPMC_STATUS; + if (write) + gpmc_write_reg(GPMC_STATUS, regval); + break; + + case GPMC_GET_SET_IRQ_STATUS: + reg = GPMC_IRQSTATUS; + if (write) + gpmc_write_reg(GPMC_IRQSTATUS, regval); + break; + + case GPMC_GET_PREF_STATUS: + reg = GPMC_PREFETCH_STATUS; + break; + + case GPMC_CONFIG_WP: + reg = GPMC_CONFIG; + regval = gpmc_read_reg(GPMC_CONFIG); + if (wval) + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ + else + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */ + gpmc_write_reg(reg, regval); + break; + + case GPMC_CONFIG_RDY_BSY: + #define WR_RD_PIN_MONITORING 0x00600000 + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + regval |= WR_RD_PIN_MONITORING; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); + break; + + case GPMC_CONFIG_DEV_SIZE: + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + regval |= GPMC_CONFIG1_DEVICESIZE(wval); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); + break; + + case GPMC_CONFIG_DEV_TYPE: + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + regval |= GPMC_CONFIG1_DEVICETYPE(wval); + if (wval == GPMC_DEVICETYPE_NOR) + regval |= GPMC_CONFIG1_MUXADDDATA; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); + break; + + case GPMC_NAND_COMMAND: + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); + break; + + case GPMC_NAND_ADDRESS: + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); + break; + + case GPMC_NAND_DATA: + if (write) + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); + else + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); + break; + + default: + dump_stack(); + printk(KERN_ERR "not supported\n"); + return -1; + } + + if (!write && reg) + *rval = gpmc_read_reg(reg); + + return 0; +} +EXPORT_SYMBOL(gpmc_hwcontrol); + +/** * gpmc_prefetch_enable - configures and starts prefetch transfer * @cs: nand cs (chip select) number * @dma_mode: dma mode enable (1) or disable (0) @@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void) } EXPORT_SYMBOL(gpmc_prefetch_reset); -/** - * gpmc_prefetch_status - reads prefetch status of engine - */ -int gpmc_prefetch_status(void) -{ - return gpmc_read_reg(GPMC_PREFETCH_STATUS); -} -EXPORT_SYMBOL(gpmc_prefetch_status); - static void __init gpmc_mem_init(void) { int cs; @@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void) } } #endif /* CONFIG_ARCH_OMAP3 */ + +/** + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller + * @cs: Chip select number + * @ecc_size: bytes for which ECC will be generated + */ +void gpmc_ecc_init(int cs, int ecc_size) +{ + unsigned int val = 0x0; + + /* Read from ECC Control Register */ + val = gpmc_read_reg(GPMC_ECC_CONTROL); + + /* Clear all ECC | Enable Reg1 */ + val = ((0x00000001<<8) | 0x00000001); + gpmc_write_reg(GPMC_ECC_CONTROL, val); + + /* Read from ECC Size Config Register */ + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); + /* ECCSIZE1=512 | Select eccResultsize[0-3] */ + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); +} + +/** + * gpmc_calcuate_ecc - Generate non-inverted ECC bytes. + * @cs: Chip select number + * @dat: The pointer to data on which ecc is computed + * @ecc_code: The ecc_code buffer + * + * Using noninverted ECC can be considered ugly since writing a blank + * page ie. padding will clear the ECC bytes. This is no problem as long + * nobody is trying to write data on the seemingly unused page. Reading + * an erased page will produce an ECC mismatch between generated and read + * ECC bytes that has to be dealt with separately. + */ +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) +{ + unsigned int val = 0x0; + + /* Start Reading from HW ECC1_Result = 0x200 */ + val = gpmc_read_reg(GPMC_ECC1_RESULT); + *ecc_code++ = val; /* P128e, ..., P1e */ + *ecc_code++ = val >> 16; /* P128o, ..., P1o */ + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); + + return 0; +} + +/** + * gpmc_enable_hwecc - This function enables the hardware ecc functionality + * @cs: Chip select number + * @mode: Read/Write mode + * @dev_width: device bus width + */ +void gpmc_enable_hwecc(int cs, int mode, int dev_width) +{ + unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG); + + switch (mode) { + case GPMC_ECC_READ: + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width << 7) | (cs << 1) | (0x1); + break; + case GPMC_ECC_READSYN: + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width << 7) | (cs << 1) | (0x1); + break; + case GPMC_ECC_WRITE: + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width << 7) | (cs << 1) | (0x1); + break; + default: + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); + break; + } + + gpmc_write_reg(GPMC_ECC_CONFIG, val); +} diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 145838a..56e1407 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -25,10 +25,22 @@ #define GPMC_CS_NAND_ADDRESS 0x20 #define GPMC_CS_NAND_DATA 0x24 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 +/* Control Commands */ +#define GPMC_GET_SET_STATUS 0x00000001 +#define GPMC_CONFIG_WP 0x00000002 +#define GPMC_CONFIG_RDY_BSY 0x00000003 +#define GPMC_CONFIG_DEV_SIZE 0x00000004 +#define GPMC_CONFIG_DEV_TYPE 0x00000005 +#define GPMC_NAND_COMMAND 0x00000006 +#define GPMC_NAND_ADDRESS 0x00000007 +#define GPMC_NAND_DATA 0x00000008 +#define GPMC_GET_PREF_STATUS 0x00000009 +#define GPMC_GET_SET_IRQ_STATUS 0x0000000a + +/* ECC commands */ +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) @@ -44,10 +56,7 @@ #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2) #define GPMC_CONFIG1_MUXADDDATA (1 << 9) #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) @@ -56,6 +65,12 @@ #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) #define GPMC_CONFIG7_CSVALID (1 << 6) +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) + + /* * Note that all values in this struct are in nanoseconds, while * the register values are in gpmc_fck cycles. @@ -109,9 +124,14 @@ extern int gpmc_cs_reserved(int cs); extern int gpmc_prefetch_enable(int cs, int dma_mode, unsigned int u32_count, int is_write); extern void gpmc_prefetch_reset(void); -extern int gpmc_prefetch_status(void); extern void omap3_gpmc_save_context(void); extern void omap3_gpmc_restore_context(void); extern void gpmc_init(void); +extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval); + +void gpmc_ecc_init(int cs, int ecc_size); +void gpmc_enable_hwecc(int cs, int mode, int dev_width); +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); + #endif diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index f8efd54..6562cd0 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -21,13 +21,11 @@ struct omap_nand_platform_data { int (*dev_ready)(struct omap_nand_platform_data *); int dma_channel; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; int devsize; }; -/* size (4 KiB) for IO mapping */ -#define NAND_IO_SIZE SZ_4K +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) extern int gpmc_nand_init(struct omap_nand_platform_data *d); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 7545568..1858c42 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -23,12 +23,6 @@ #include #include -#define GPMC_IRQ_STATUS 0x18 -#define GPMC_ECC_CONFIG 0x1F4 -#define GPMC_ECC_CONTROL 0x1F8 -#define GPMC_ECC_SIZE_CONFIG 0x1FC -#define GPMC_ECC1_RESULT 0x200 - #define DRIVER_NAME "omap2-nand" #define NAND_WP_OFF 0 @@ -37,6 +31,7 @@ #define GPMC_BUF_FULL 0x00000001 #define GPMC_BUF_EMPTY 0x00000000 +#ifdef CONFIG_MTD_NAND_OMAP_HWECC #define NAND_Ecc_P1e (1 << 0) #define NAND_Ecc_P2e (1 << 1) #define NAND_Ecc_P4e (1 << 2) @@ -103,6 +98,7 @@ #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */ #ifdef CONFIG_MTD_PARTITIONS static const char *part_probes[] = { "cmdlinepart", NULL }; @@ -139,34 +135,11 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; - void __iomem *nand_pref_fifo_add; struct completion comp; int dma_ch; }; /** - * omap_nand_wp - This function enable or disable the Write Protect feature - * @mtd: MTD device structure - * @mode: WP ON/OFF - */ -static void omap_nand_wp(struct mtd_info *mtd, int mode) -{ - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); - - unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG); - - if (mode) - config &= ~(NAND_WP_BIT); /* WP is ON */ - else - config |= (NAND_WP_BIT); /* WP is OFF */ - - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG)); -} - -/** * omap_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure * @cmd: command to device @@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - switch (ctrl) { - case NAND_CTRL_CHANGE | NAND_CTRL_CLE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_COMMAND; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - - case NAND_CTRL_CHANGE | NAND_CTRL_ALE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_ADDRESS; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - - case NAND_CTRL_CHANGE | NAND_NCE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - } - if (cmd != NAND_CMD_NONE) - __raw_writeb(cmd, info->nand.IO_ADDR_W); + if (cmd != NAND_CMD_NONE) { + if (ctrl & NAND_CLE) { + gpmc_hwcontrol(1, info->gpmc_cs, + GPMC_NAND_COMMAND, cmd, NULL); + + } else if (ctrl & NAND_ALE) { + gpmc_hwcontrol(1, info->gpmc_cs, + GPMC_NAND_ADDRESS, cmd, NULL); + + } else /* NAND_NCE */ + gpmc_hwcontrol(1, info->gpmc_cs, + GPMC_NAND_DATA, cmd, NULL); + } } /** @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len) */ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + u32 status; + struct nand_chip *nand = mtd->priv; u_char *p = (u_char *)buf; while (len--) { - iowrite8(*p++, info->nand.IO_ADDR_W); - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + - GPMC_STATUS) & GPMC_BUF_FULL)); + iowrite8(*p++, nand->IO_ADDR_W); + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) + ; } } @@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) */ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) { - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); + u32 status; + struct nand_chip *nand = mtd->priv; u16 *p = (u16 *) buf; /* FIXME try bursts of writesw() or DMA ... */ len >>= 1; while (len--) { - iowrite16(*p++, info->nand.IO_ADDR_W); - - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + - GPMC_STATUS) & GPMC_BUF_FULL)) + iowrite16(*p++, nand->IO_ADDR_W); + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) ; } } @@ -308,9 +270,10 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) omap_read_buf8(mtd, buf, len); } else { do { - pfpw_status = gpmc_prefetch_status(); + gpmc_hwcontrol(0, info->gpmc_cs, + GPMC_GET_PREF_STATUS, 0, &pfpw_status); r_count = ((pfpw_status >> 24) & 0x7F) >> 2; - ioread32_rep(info->nand_pref_fifo_add, p, r_count); + ioread32_rep(info->nand.IO_ADDR_R, p, r_count); p += r_count; len -= r_count << 2; } while (len); @@ -351,12 +314,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd, else omap_write_buf8(mtd, buf, len); } else { - pfpw_status = gpmc_prefetch_status(); + gpmc_hwcontrol(0, 0, GPMC_GET_PREF_STATUS, 0, &pfpw_status); while (pfpw_status & 0x3FFF) { w_count = ((pfpw_status >> 24) & 0x7F) >> 1; for (i = 0; (i < w_count) && len; i++, len -= 2) - iowrite16(*p++, info->nand_pref_fifo_add); - pfpw_status = gpmc_prefetch_status(); + iowrite16(*p++, info->nand.IO_ADDR_W); + gpmc_hwcontrol(0, 0, + GPMC_GET_PREF_STATUS, 0, &pfpw_status); } /* disable and stop the PFPW engine */ @@ -448,7 +412,7 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, /* setup and start DMA using dma_addr */ wait_for_completion(&info->comp); - while (0x3fff & (prefetch_status = gpmc_prefetch_status())) + while (0x3fff & (prefetch_status = gpmc_read_reg(GPMC_PREFETCH_STATUS))) ; /* disable and stop the PFPW engine */ gpmc_prefetch_reset(); @@ -502,7 +466,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd, omap_write_buf_pref(mtd, buf, len); else /* start transfer in DMA mode */ - omap_nand_dma_transfer(mtd, buf, len, 0x1); + omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); } /** @@ -535,22 +499,8 @@ static void omap_hwecc_init(struct mtd_info *mtd) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - struct nand_chip *chip = mtd->priv; - unsigned long val = 0x0; - - /* Read from ECC Control Register */ - val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* Clear all ECC | Enable Reg1 */ - val = ((0x00000001<<8) | 0x00000001); - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - - /* Read from ECC Size Config Register */ - val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); - /* ECCSIZE1=512 | Select eccResultsize[0-3] */ - val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F)); - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); + gpmc_ecc_init(info->gpmc_cs, info->nand.ecc.size); } - /** * gen_true_ecc - This function will generate true ECC value * @ecc_buf: buffer to store ecc code @@ -752,21 +702,8 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - unsigned long val = 0x0; - unsigned long reg; - - /* Start Reading from HW ECC1_Result = 0x200 */ - reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT); - val = __raw_readl(reg); - *ecc_code++ = val; /* P128e, ..., P1e */ - *ecc_code++ = val >> 16; /* P128o, ..., P1o */ - /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ - *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); - reg += 4; - - return 0; + return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code); } - /** * omap_enable_hwecc - This function enables the hardware ecc functionality * @mtd: MTD device structure @@ -778,32 +715,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) mtd); struct nand_chip *chip = mtd->priv; unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; - unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG); - - switch (mode) { - case NAND_ECC_READ: - __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); - break; - case NAND_ECC_READSYN: - __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); - break; - case NAND_ECC_WRITE: - __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); - break; - default: - DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n", - mode); - break; - } - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG); + gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width); } + #endif /** @@ -831,14 +746,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) else timeo += (HZ * 20) / 1000; - this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr + - GPMC_CS_NAND_COMMAND; - this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA; - - __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W); - + gpmc_hwcontrol(1, info->gpmc_cs, + GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF), NULL); while (time_before(jiffies, timeo)) { - status = __raw_readb(this->IO_ADDR_R); + gpmc_hwcontrol(0, info->gpmc_cs, GPMC_NAND_DATA, 0, &status); if (status & NAND_STATUS_READY) break; cond_resched(); @@ -852,22 +763,20 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) */ static int omap_dev_ready(struct mtd_info *mtd) { - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS); + unsigned int val = 0; + gpmc_hwcontrol(0, 0, GPMC_GET_SET_IRQ_STATUS, 0, &val); if ((val & 0x100) == 0x100) { /* Clear IRQ Interrupt */ val |= 0x100; val &= ~(0x0); - __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS); + gpmc_hwcontrol(1, 0, GPMC_GET_SET_IRQ_STATUS, val, NULL); } else { unsigned int cnt = 0; while (cnt++ < 0x1FF) { if ((val & 0x100) == 0x100) return 0; - val = __raw_readl(info->gpmc_baseaddr + - GPMC_IRQ_STATUS); + gpmc_hwcontrol(0, 0, GPMC_GET_SET_IRQ_STATUS, 0, &val); } } @@ -898,8 +807,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->pdev = pdev; info->gpmc_cs = pdata->cs; - info->gpmc_baseaddr = pdata->gpmc_baseaddr; - info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr; info->phys_base = pdata->phys_base; info->mtd.priv = &info->nand; @@ -910,7 +817,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.options |= NAND_SKIP_BBTSCAN; /* NAND write protect off */ - omap_nand_wp(&info->mtd, NAND_WP_OFF); + gpmc_hwcontrol(1, info->gpmc_cs, GPMC_CONFIG_WP, 0, NULL); if (!request_mem_region(info->phys_base, NAND_IO_SIZE, pdev->dev.driver->name)) { @@ -946,7 +853,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) if (use_prefetch) { /* copy the virtual address of nand base for fifo access */ - info->nand_pref_fifo_add = info->nand.IO_ADDR_R; info->nand.read_buf = omap_read_buf_pref; info->nand.write_buf = omap_write_buf_pref; @@ -1036,7 +942,7 @@ static int omap_nand_remove(struct platform_device *pdev) /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); - iounmap(info->nand_pref_fifo_add); + iounmap(info->nand.IO_ADDR_R); kfree(&info->mtd); return 0; } From tony at atomide.com Fri May 14 11:28:55 2010 From: tony at atomide.com (Tony Lindgren) Date: Fri, 14 May 2010 08:28:55 -0700 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <1273850591-19040-2-git-send-email-s-ghorai@ti.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> Message-ID: <20100514152855.GV3428@atomide.com> * Sukumar Ghorai [100514 08:18]: > Necessary function added in GPMC module and used by nand driver. This is for > not to use GPMC address directly from nand driver. Also it was passing GPMC > base address from board files and that is removed. Great, this is starting to look good! I'll take a closer look today, some quick comments below. > --- a/arch/arm/mach-omap2/gpmc.c > +++ b/arch/arm/mach-omap2/gpmc.c > @@ -29,27 +29,27 @@ > #include > > /* GPMC register offsets */ > -#define GPMC_REVISION 0x00 > -#define GPMC_SYSCONFIG 0x10 > -#define GPMC_SYSSTATUS 0x14 > -#define GPMC_IRQSTATUS 0x18 > -#define GPMC_IRQENABLE 0x1c > -#define GPMC_TIMEOUT_CONTROL 0x40 > -#define GPMC_ERR_ADDRESS 0x44 > -#define GPMC_ERR_TYPE 0x48 > -#define GPMC_CONFIG 0x50 > -#define GPMC_STATUS 0x54 > -#define GPMC_PREFETCH_CONFIG1 0x1e0 > -#define GPMC_PREFETCH_CONFIG2 0x1e4 > -#define GPMC_PREFETCH_CONTROL 0x1ec > -#define GPMC_PREFETCH_STATUS 0x1f0 > -#define GPMC_ECC_CONFIG 0x1f4 > -#define GPMC_ECC_CONTROL 0x1f8 > -#define GPMC_ECC_SIZE_CONFIG 0x1fc > - > -#define GPMC_CS0 0x60 > -#define GPMC_CS_SIZE 0x30 > - > +#define GPMC_REVISION 0x00 > +#define GPMC_SYSCONFIG 0x10 > +#define GPMC_SYSSTATUS 0x14 > +#define GPMC_IRQSTATUS 0x18 > +#define GPMC_IRQENABLE 0x1c > +#define GPMC_TIMEOUT_CONTROL 0x40 > +#define GPMC_ERR_ADDRESS 0x44 > +#define GPMC_ERR_TYPE 0x48 > +#define GPMC_CONFIG 0x50 > +#define GPMC_STATUS 0x54 > +#define GPMC_PREFETCH_CONFIG1 0x1e0 > +#define GPMC_PREFETCH_CONFIG2 0x1e4 > +#define GPMC_PREFETCH_CONTROL 0x1ec > +#define GPMC_PREFETCH_STATUS 0x1f0 > +#define GPMC_ECC_CONFIG 0x1f4 > +#define GPMC_ECC_CONTROL 0x1f8 > +#define GPMC_ECC_SIZE_CONFIG 0x1fc > +#define GPMC_ECC1_RESULT 0x200 > + > +#define GPMC_CS0_BASE 0x60 > +#define GPMC_CS_SIZE 0x30 > #define GPMC_MEM_START 0x00000000 > #define GPMC_MEM_END 0x3FFFFFFF > #define BOOT_ROM_SPACE 0x100000 /* 1MB */ These defines should not be modified that much, looks like some spaces sneaked in instead of tabs? Maybe also split this patch into two: First add the new functions, then remove and convert everything to use the new functions. Regards, Tony From vimal.newwork at gmail.com Fri May 14 14:02:33 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Fri, 14 May 2010 23:32:33 +0530 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <1273850591-19040-2-git-send-email-s-ghorai@ti.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> Message-ID: On Fri, May 14, 2010 at 8:53 PM, Sukumar Ghorai wrote: [...] > diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach-omap2/gpmc-onenand.c > index 7bb6922..5d66817 > --- a/arch/arm/mach-omap2/gpmc-onenand.c > +++ b/arch/arm/mach-omap2/gpmc-onenand.c > @@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(GPMC_CONFIG1_WAIT_READ_MON | > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CONFIG1_WAIT_PIN_SEL(0))) | > ? ? ? ? ? ? ? ? ? ? ? ? ?GPMC_CONFIG1_DEVICESIZE_16 | > - ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CONFIG1_DEVICETYPE_NOR | > + ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) | > ? ? ? ? ? ? ? ? ? ? ? ? ?GPMC_CONFIG1_MUXADDDATA); Please do not dp OneNAND changes in NAND patch. > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > index 5bc3ca0..a3fd1ed > --- a/arch/arm/mach-omap2/gpmc.c > +++ b/arch/arm/mach-omap2/gpmc.c > @@ -29,27 +29,27 @@ > ?#include > > ?/* GPMC register offsets */ > -#define GPMC_REVISION ? ? ? ? ?0x00 > -#define GPMC_SYSCONFIG ? ? ? ? 0x10 > -#define GPMC_SYSSTATUS ? ? ? ? 0x14 > -#define GPMC_IRQSTATUS ? ? ? ? 0x18 > -#define GPMC_IRQENABLE ? ? ? ? 0x1c > -#define GPMC_TIMEOUT_CONTROL ? 0x40 > -#define GPMC_ERR_ADDRESS ? ? ? 0x44 > -#define GPMC_ERR_TYPE ? ? ? ? ?0x48 > -#define GPMC_CONFIG ? ? ? ? ? ?0x50 > -#define GPMC_STATUS ? ? ? ? ? ?0x54 > -#define GPMC_PREFETCH_CONFIG1 ?0x1e0 > -#define GPMC_PREFETCH_CONFIG2 ?0x1e4 > -#define GPMC_PREFETCH_CONTROL ?0x1ec > -#define GPMC_PREFETCH_STATUS ? 0x1f0 > -#define GPMC_ECC_CONFIG ? ? ? ? ? ? ? ?0x1f4 > -#define GPMC_ECC_CONTROL ? ? ? 0x1f8 > -#define GPMC_ECC_SIZE_CONFIG ? 0x1fc > - > -#define GPMC_CS0 ? ? ? ? ? ? ? 0x60 > -#define GPMC_CS_SIZE ? ? ? ? ? 0x30 > - > +#define GPMC_REVISION ? ? ? ? ? 0x00 > +#define GPMC_SYSCONFIG ? ? ? ? ?0x10 > +#define GPMC_SYSSTATUS ? ? ? ? ?0x14 > +#define GPMC_IRQSTATUS ? ? ? ? ?0x18 > +#define GPMC_IRQENABLE ? ? ? ? ?0x1c > +#define GPMC_TIMEOUT_CONTROL ? ?0x40 > +#define GPMC_ERR_ADDRESS ? ? ? ?0x44 > +#define GPMC_ERR_TYPE ? ? ? ? ? 0x48 > +#define GPMC_CONFIG ? ? ? ? ? ? 0x50 > +#define GPMC_STATUS ? ? ? ? ? ? 0x54 > +#define GPMC_PREFETCH_CONFIG1 ? 0x1e0 > +#define GPMC_PREFETCH_CONFIG2 ? 0x1e4 > +#define GPMC_PREFETCH_CONTROL ? 0x1ec > +#define GPMC_PREFETCH_STATUS ? ?0x1f0 > +#define GPMC_ECC_CONFIG ? ? ? ? 0x1f4 > +#define GPMC_ECC_CONTROL ? ? ? ?0x1f8 > +#define GPMC_ECC_SIZE_CONFIG ? ?0x1fc > +#define GPMC_ECC1_RESULT ? ? ? ?0x200 > + > +#define GPMC_CS0_BASE ? ? ? ? ?0x60 > +#define GPMC_CS_SIZE ? ? ? ? ? ?0x30 > ?#define GPMC_MEM_START ? ? ? ? 0x00000000 > ?#define GPMC_MEM_END ? ? ? ? ? 0x3FFFFFFF > ?#define BOOT_ROM_SPACE ? ? ? ? 0x100000 ? ? ? ?/* 1MB */ > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx) > ? ? ? ?return __raw_readl(gpmc_base + idx); > ?} > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > +{ > + ? ? ? void __iomem *reg_addr; > + > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? __raw_writeb(val, reg_addr); > +} > + > +static u8 gpmc_cs_read_byte(int cs, int idx) > +{ > + ? ? ? void __iomem *reg_addr; > + > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? return __raw_readb(reg_addr); > +} > + I do not think we need these functions. > ?void gpmc_cs_write_reg(int cs, int idx, u32 val) > ?{ > ? ? ? ?void __iomem *reg_addr; > > - ? ? ? reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > ? ? ? ?__raw_writel(val, reg_addr); > ?} > > @@ -120,7 +136,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > ?{ > ? ? ? ?void __iomem *reg_addr; > > - ? ? ? reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > ? ? ? ?return __raw_readl(reg_addr); > ?} > > @@ -419,6 +435,96 @@ void gpmc_cs_free(int cs) > ?EXPORT_SYMBOL(gpmc_cs_free); > > ?/** > + * gpmc_hwcontrol - hardware specific access (read/ write) to control > + * @write: need 1 for configure; 0 for reading the complete register > + * @cs: chip select number > + * @cmd: Command type > + * @wval: value/information to write > + * @rval: pointer to get the value back > + */ > +int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval) > +{ > + ? ? ? u32 reg = 0; > + ? ? ? u32 regval = 0; > + > + ? ? ? switch (cmd) { > + > + ? ? ? case GPMC_GET_SET_STATUS: > + ? ? ? ? ? ? ? reg = GPMC_STATUS; > + ? ? ? ? ? ? ? if (write) > + ? ? ? ? ? ? ? ? ? ? ? gpmc_write_reg(GPMC_STATUS, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_GET_SET_IRQ_STATUS: > + ? ? ? ? ? ? ? reg = GPMC_IRQSTATUS; > + ? ? ? ? ? ? ? if (write) > + ? ? ? ? ? ? ? ? ? ? ? gpmc_write_reg(GPMC_IRQSTATUS, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_GET_PREF_STATUS: > + ? ? ? ? ? ? ? reg = GPMC_PREFETCH_STATUS; > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_WP: > + ? ? ? ? ? ? ? reg = GPMC_CONFIG; > + ? ? ? ? ? ? ? regval = gpmc_read_reg(GPMC_CONFIG); > + ? ? ? ? ? if (wval) > + ? ? ? ? ? ? ? ? ? ? ? regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? regval |= GPMC_CONFIG_WRITEPROTECT; ?/* WP is OFF */ > + ? ? ? ? ? ? ? gpmc_write_reg(reg, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_RDY_BSY: > + ? ? ? ? ? ? ? #define WR_RD_PIN_MONITORING ? ?0x00600000 > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > + ? ? ? ? ? ? ? regval |= WR_RD_PIN_MONITORING; > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_DEV_SIZE: > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > + ? ? ? ? ? ? ? regval |= GPMC_CONFIG1_DEVICESIZE(wval); > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_DEV_TYPE: > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > + ? ? ? ? ? ? ? regval |= GPMC_CONFIG1_DEVICETYPE(wval); > + ? ? ? ? ? ? ? if (wval == GPMC_DEVICETYPE_NOR) > + ? ? ? ? ? ? ? ? ? ? ? regval |= GPMC_CONFIG1_MUXADDDATA; > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_NAND_COMMAND: > + ? ? ? ? ? ? ? gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_NAND_ADDRESS: > + ? ? ? ? ? ? ? gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_NAND_DATA: > + ? ? ? ? ? ? ? if (write) > + ? ? ? ? ? ? ? ? ? ? ? gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); > + ? ? ? ? ? ? ? break; > + > + ? ? ? default: > + ? ? ? ? ? ? ? dump_stack(); > + ? ? ? ? ? ? ? printk(KERN_ERR "not supported\n"); > + ? ? ? ? ? ? ? return -1; > + ? ? ? } > + > + ? ? ? if (!write && reg) > + ? ? ? ? ? ? ? *rval = gpmc_read_reg(reg); > + > + ? ? ? return 0; > +} > +EXPORT_SYMBOL(gpmc_hwcontrol); > + > +/** > ?* gpmc_prefetch_enable - configures and starts prefetch transfer > ?* @cs: nand cs (chip select) number > ?* @dma_mode: dma mode enable (1) or disable (0) > @@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void) > ?} > ?EXPORT_SYMBOL(gpmc_prefetch_reset); > > -/** > - * gpmc_prefetch_status - reads prefetch status of engine > - */ > -int ?gpmc_prefetch_status(void) > -{ > - ? ? ? return gpmc_read_reg(GPMC_PREFETCH_STATUS); > -} > -EXPORT_SYMBOL(gpmc_prefetch_status); > - > ?static void __init gpmc_mem_init(void) > ?{ > ? ? ? ?int cs; > @@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void) > ? ? ? ?} > ?} > ?#endif /* CONFIG_ARCH_OMAP3 */ > + > +/** > + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller > + * @cs: Chip select number > + * @ecc_size: bytes for which ECC will be generated > + */ > +void gpmc_ecc_init(int cs, int ecc_size) > +{ > + ? ? ? unsigned int val = 0x0; > + > + ? ? ? /* Read from ECC Control Register */ > + ? ? ? val = gpmc_read_reg(GPMC_ECC_CONTROL); > + > + ? ? ? /* Clear all ECC | Enable Reg1 */ > + ? ? ? val = ((0x00000001<<8) | 0x00000001); > + ? ? ? gpmc_write_reg(GPMC_ECC_CONTROL, val); > + > + ? ? ? /* Read from ECC Size Config Register */ > + ? ? ? val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > + ? ? ? /* ECCSIZE1=512 | Select eccResultsize[0-3] */ > + ? ? ? val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > + ? ? ? gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > +} > + > +/** > + * gpmc_calcuate_ecc - Generate non-inverted ECC bytes. > + * @cs: Chip select number > + * @dat: The pointer to data on which ecc is computed > + * @ecc_code: The ecc_code buffer > + * > + * Using noninverted ECC can be considered ugly since writing a blank > + * page ie. padding will clear the ECC bytes. This is no problem as long > + * nobody is trying to write data on the seemingly unused page. Reading > + * an erased page will produce an ECC mismatch between generated and read > + * ECC bytes that has to be dealt with separately. > + */ > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) > +{ > + ? ? ? unsigned int val = 0x0; > + > + ? ? ? /* Start Reading from HW ECC1_Result = 0x200 */ > + ? ? ? val = gpmc_read_reg(GPMC_ECC1_RESULT); > + ? ? ? *ecc_code++ = val; ? ? ? ? ?/* P128e, ..., P1e */ > + ? ? ? *ecc_code++ = val >> 16; ? ?/* P128o, ..., P1o */ > + ? ? ? /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ > + ? ? ? *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); > + > + ? ? ? return 0; > +} > + > +/** > + * gpmc_enable_hwecc - This function enables the hardware ecc functionality > + * @cs: Chip select number > + * @mode: Read/Write mode > + * @dev_width: device bus width > + */ > +void gpmc_enable_hwecc(int cs, int mode, int dev_width) > +{ > + ? ? ? unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG); > + > + ? ? ? switch (mode) { > + ? ? ? case GPMC_ECC_READ: > + ? ? ? ? ? ? ? gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > + ? ? ? ? ? ? ? /* (ECC 16 or 8 bit col) | ( CS ?) ?| ECC Enable */ > + ? ? ? ? ? ? ? val = (dev_width << 7) | (cs << 1) | (0x1); > + ? ? ? ? ? ? ? break; > + ? ? ? case GPMC_ECC_READSYN: > + ? ? ? ? ? ? ? ?gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); > + ? ? ? ? ? ? ? /* (ECC 16 or 8 bit col) | ( CS ?) ?| ECC Enable */ > + ? ? ? ? ? ? ? val = (dev_width << 7) | (cs << 1) | (0x1); > + ? ? ? ? ? ? ? break; > + ? ? ? case GPMC_ECC_WRITE: > + ? ? ? ? ? ? ? gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > + ? ? ? ? ? ? ? /* (ECC 16 or 8 bit col) | ( CS ?) ?| ECC Enable */ > + ? ? ? ? ? ? ? val = (dev_width << 7) | (cs << 1) | (0x1); > + ? ? ? ? ? ? ? break; > + ? ? ? default: > + ? ? ? ? ? ? ? printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); > + ? ? ? ? ? ? ? break; > + ? ? ? } > + > + ? ? ? gpmc_write_reg(GPMC_ECC_CONFIG, val); > +} > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h > index 145838a..56e1407 > --- a/arch/arm/plat-omap/include/plat/gpmc.h > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > @@ -25,10 +25,22 @@ > ?#define GPMC_CS_NAND_ADDRESS ? 0x20 > ?#define GPMC_CS_NAND_DATA ? ? ?0x24 > > -#define GPMC_CONFIG ? ? ? ? ? ?0x50 > -#define GPMC_STATUS ? ? ? ? ? ?0x54 > -#define GPMC_CS0_BASE ? ? ? ? ?0x60 > -#define GPMC_CS_SIZE ? ? ? ? ? 0x30 > +/* Control Commands */ > +#define GPMC_GET_SET_STATUS ? ?0x00000001 > +#define GPMC_CONFIG_WP ? ? ? ? 0x00000002 > +#define GPMC_CONFIG_RDY_BSY ? ?0x00000003 > +#define GPMC_CONFIG_DEV_SIZE ? 0x00000004 > +#define GPMC_CONFIG_DEV_TYPE ? ?0x00000005 > +#define GPMC_NAND_COMMAND ? ? ?0x00000006 > +#define GPMC_NAND_ADDRESS ? ? ?0x00000007 > +#define GPMC_NAND_DATA ? ? ? ? 0x00000008 > +#define GPMC_GET_PREF_STATUS ? 0x00000009 > +#define GPMC_GET_SET_IRQ_STATUS ? ? ? ?0x0000000a > + > +/* ECC commands */ > +#define GPMC_ECC_READ ? ? ? ? ?0 /* Reset Hardware ECC for read */ > +#define GPMC_ECC_WRITE ? ? ? ? 1 /* Reset Hardware ECC for write */ > +#define GPMC_ECC_READSYN ? ? ? 2 /* Reset before syndrom is read back */ > > ?#define GPMC_CONFIG1_WRAPBURST_SUPP ? ? (1 << 31) > ?#define GPMC_CONFIG1_READMULTIPLE_SUPP ?(1 << 30) > @@ -44,10 +56,7 @@ > ?#define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) > ?#define GPMC_CONFIG1_WAIT_PIN_SEL(val) ?((val & 3) << 16) > ?#define GPMC_CONFIG1_DEVICESIZE(val) ? ?((val & 3) << 12) > -#define GPMC_CONFIG1_DEVICESIZE_16 ? ? ?GPMC_CONFIG1_DEVICESIZE(1) > ?#define GPMC_CONFIG1_DEVICETYPE(val) ? ?((val & 3) << 10) > -#define GPMC_CONFIG1_DEVICETYPE_NOR ? ? GPMC_CONFIG1_DEVICETYPE(0) > -#define GPMC_CONFIG1_DEVICETYPE_NAND ? ?GPMC_CONFIG1_DEVICETYPE(2) > ?#define GPMC_CONFIG1_MUXADDDATA ? ? ? ? (1 << 9) > ?#define GPMC_CONFIG1_TIME_PARA_GRAN ? ? (1 << 4) > ?#define GPMC_CONFIG1_FCLK_DIV(val) ? ? ?(val & 3) > @@ -56,6 +65,12 @@ > ?#define GPMC_CONFIG1_FCLK_DIV4 ? ? ? ? ?(GPMC_CONFIG1_FCLK_DIV(3)) > ?#define GPMC_CONFIG7_CSVALID ? ? ? ? ? (1 << 6) > > +#define GPMC_DEVICETYPE_NOR ? ?0 > +#define GPMC_DEVICETYPE_NAND ? 2 > +#define GPMC_CONFIG_WRITEPROTECT ? ? ? 0x00000010 > +#define GPMC_CONFIG1_DEVICESIZE_16 ? ? GPMC_CONFIG1_DEVICESIZE(1) > + > + > ?/* > ?* Note that all values in this struct are in nanoseconds, while > ?* the register values are in gpmc_fck cycles. > @@ -109,9 +124,14 @@ extern int gpmc_cs_reserved(int cs); > ?extern int gpmc_prefetch_enable(int cs, int dma_mode, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned int u32_count, int is_write); > ?extern void gpmc_prefetch_reset(void); > -extern int gpmc_prefetch_status(void); > ?extern void omap3_gpmc_save_context(void); > ?extern void omap3_gpmc_restore_context(void); > ?extern void gpmc_init(void); > +extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval); > + > +void gpmc_ecc_init(int cs, int ecc_size); > +void gpmc_enable_hwecc(int cs, int mode, int dev_width); > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); > + > > ?#endif > diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h > index f8efd54..6562cd0 > --- a/arch/arm/plat-omap/include/plat/nand.h > +++ b/arch/arm/plat-omap/include/plat/nand.h > @@ -21,13 +21,11 @@ struct omap_nand_platform_data { > ? ? ? ?int ? ? ? ? ? ? ? ? ? ? (*dev_ready)(struct omap_nand_platform_data *); > ? ? ? ?int ? ? ? ? ? ? ? ? ? ? dma_channel; > ? ? ? ?unsigned long ? ? ? ? ? phys_base; > - ? ? ? void __iomem ? ? ? ? ? ?*gpmc_cs_baseaddr; > - ? ? ? void __iomem ? ? ? ? ? ?*gpmc_baseaddr; > ? ? ? ?int ? ? ? ? ? ? ? ? ? ? devsize; > ?}; > > -/* size (4 KiB) for IO mapping */ > -#define ? ? ? ?NAND_IO_SIZE ? ?SZ_4K > +/* minimum size for IO mapping */ > +#define ? ? ? ?NAND_IO_SIZE ? ?4 > > ?#if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) > ?extern int gpmc_nand_init(struct omap_nand_platform_data *d); > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > index 7545568..1858c42 > --- a/drivers/mtd/nand/omap2.c > +++ b/drivers/mtd/nand/omap2.c > @@ -23,12 +23,6 @@ > ?#include > ?#include > > -#define GPMC_IRQ_STATUS ? ? ? ? ? ? ? ?0x18 > -#define GPMC_ECC_CONFIG ? ? ? ? ? ? ? ?0x1F4 > -#define GPMC_ECC_CONTROL ? ? ? 0x1F8 > -#define GPMC_ECC_SIZE_CONFIG ? 0x1FC > -#define GPMC_ECC1_RESULT ? ? ? 0x200 > - > ?#define ? ? ? ?DRIVER_NAME ? ? "omap2-nand" > > ?#define ? ? ? ?NAND_WP_OFF ? ? 0 > @@ -37,6 +31,7 @@ > ?#define ? ? ? ?GPMC_BUF_FULL ? 0x00000001 > ?#define ? ? ? ?GPMC_BUF_EMPTY ?0x00000000 > > +#ifdef CONFIG_MTD_NAND_OMAP_HWECC > ?#define NAND_Ecc_P1e ? ? ? ? ? (1 << 0) > ?#define NAND_Ecc_P2e ? ? ? ? ? (1 << 1) > ?#define NAND_Ecc_P4e ? ? ? ? ? (1 << 2) > @@ -103,6 +98,7 @@ > > ?#define P4e_s(a) ? ? ? (TF(a & NAND_Ecc_P4e) ? ? ? ? ? << 0) > ?#define P4o_s(a) ? ? ? (TF(a & NAND_Ecc_P4o) ? ? ? ? ? << 1) > +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */ Why this ifdef macro? > > ?#ifdef CONFIG_MTD_PARTITIONS > ?static const char *part_probes[] = { "cmdlinepart", NULL }; > @@ -139,34 +135,11 @@ struct omap_nand_info { > > ? ? ? ?int ? ? ? ? ? ? ? ? ? ? ? ? ? ? gpmc_cs; > ? ? ? ?unsigned long ? ? ? ? ? ? ? ? ? phys_base; > - ? ? ? void __iomem ? ? ? ? ? ? ? ? ? ?*gpmc_cs_baseaddr; > - ? ? ? void __iomem ? ? ? ? ? ? ? ? ? ?*gpmc_baseaddr; > - ? ? ? void __iomem ? ? ? ? ? ? ? ? ? ?*nand_pref_fifo_add; > ? ? ? ?struct completion ? ? ? ? ? ? ? comp; > ? ? ? ?int ? ? ? ? ? ? ? ? ? ? ? ? ? ? dma_ch; > ?}; > > ?/** > - * omap_nand_wp - This function enable or disable the Write Protect feature > - * @mtd: MTD device structure > - * @mode: WP ON/OFF > - */ > -static void omap_nand_wp(struct mtd_info *mtd, int mode) > -{ > - ? ? ? struct omap_nand_info *info = container_of(mtd, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct omap_nand_info, mtd); > - > - ? ? ? unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG); > - > - ? ? ? if (mode) > - ? ? ? ? ? ? ? config &= ~(NAND_WP_BIT); ? ? ? /* WP is ON */ > - ? ? ? else > - ? ? ? ? ? ? ? config |= (NAND_WP_BIT); ? ? ? ?/* WP is OFF */ > - > - ? ? ? __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG)); > -} > - > -/** > ?* omap_hwcontrol - hardware specific access to control-lines > ?* @mtd: MTD device structure > ?* @cmd: command to device > @@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) > ?{ > ? ? ? ?struct omap_nand_info *info = container_of(mtd, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct omap_nand_info, mtd); > - ? ? ? switch (ctrl) { > - ? ? ? case NAND_CTRL_CHANGE | NAND_CTRL_CLE: > - ? ? ? ? ? ? ? info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CS_NAND_COMMAND; > - ? ? ? ? ? ? ? info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CS_NAND_DATA; > - ? ? ? ? ? ? ? break; > - > - ? ? ? case NAND_CTRL_CHANGE | NAND_CTRL_ALE: > - ? ? ? ? ? ? ? info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CS_NAND_ADDRESS; > - ? ? ? ? ? ? ? info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CS_NAND_DATA; > - ? ? ? ? ? ? ? break; > - > - ? ? ? case NAND_CTRL_CHANGE | NAND_NCE: > - ? ? ? ? ? ? ? info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CS_NAND_DATA; > - ? ? ? ? ? ? ? info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_CS_NAND_DATA; > - ? ? ? ? ? ? ? break; > - ? ? ? } > > - ? ? ? if (cmd != NAND_CMD_NONE) > - ? ? ? ? ? ? ? __raw_writeb(cmd, info->nand.IO_ADDR_W); > + ? ? ? if (cmd != NAND_CMD_NONE) { > + ? ? ? ? ? ? ? if (ctrl & NAND_CLE) { > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(1, info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_NAND_COMMAND, cmd, NULL); > + > + ? ? ? ? ? ? ? } else if (ctrl & NAND_ALE) { > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(1, info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_NAND_ADDRESS, cmd, NULL); > + > + ? ? ? ? ? ? ? } else /* NAND_NCE */ > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(1, info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_NAND_DATA, cmd, NULL); > + ? ? ? } > ?} > > ?/** > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, u_char *buf, int len) > ?*/ > ?static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) > ?{ > - ? ? ? struct omap_nand_info *info = container_of(mtd, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct omap_nand_info, mtd); > + ? ? ? u32 ? ? status; > + ? ? ? struct nand_chip *nand = mtd->priv; > ? ? ? ?u_char *p = (u_char *)buf; > > ? ? ? ?while (len--) { > - ? ? ? ? ? ? ? iowrite8(*p++, info->nand.IO_ADDR_W); > - ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_STATUS) & GPMC_BUF_FULL)); > + ? ? ? ? ? ? ? iowrite8(*p++, nand->IO_ADDR_W); > + ? ? ? ? ? ? ? gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); If I am not mistaking, 2nd argument is 'cs', correct? And then, why are you hard coding this? Different boards will have NAND chip present at different 'cs'. Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this. Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then: > + ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) > + ? ? ? ? ? ? ? ? ? ? ? ; You got in an infinite loop here? > ? ? ? ?} > ?} > > @@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd, u_char *buf, int len) > ?*/ > ?static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) > ?{ > - ? ? ? struct omap_nand_info *info = container_of(mtd, > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct omap_nand_info, mtd); > + ? ? ? u32 ? ? status; > + ? ? ? struct nand_chip *nand = mtd->priv; > ? ? ? ?u16 *p = (u16 *) buf; > > ? ? ? ?/* FIXME try bursts of writesw() or DMA ... */ > ? ? ? ?len >>= 1; > > ? ? ? ?while (len--) { > - ? ? ? ? ? ? ? iowrite16(*p++, info->nand.IO_ADDR_W); > - > - ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_STATUS) & GPMC_BUF_FULL)) > + ? ? ? ? ? ? ? iowrite16(*p++, nand->IO_ADDR_W); > + ? ? ? ? ? ? ? gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); > + ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) same as above. -- Regards, Vimal Singh From tony at atomide.com Fri May 14 19:58:52 2010 From: tony at atomide.com (Tony Lindgren) Date: Fri, 14 May 2010 16:58:52 -0700 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <1273850591-19040-2-git-send-email-s-ghorai@ti.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> Message-ID: <20100514235852.GN3428@atomide.com> Few more comments below. * Sukumar Ghorai [100514 08:18]: > + > +/** > + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC controller > + * @cs: Chip select number > + * @ecc_size: bytes for which ECC will be generated > + */ > +void gpmc_ecc_init(int cs, int ecc_size) > +{ > + unsigned int val = 0x0; > + > + /* Read from ECC Control Register */ > + val = gpmc_read_reg(GPMC_ECC_CONTROL); > + > + /* Clear all ECC | Enable Reg1 */ > + val = ((0x00000001<<8) | 0x00000001); > + gpmc_write_reg(GPMC_ECC_CONTROL, val); > + > + /* Read from ECC Size Config Register */ > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > + /* ECCSIZE1=512 | Select eccResultsize[0-3] */ > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > +} There should be some locking as only one chipselect can use the ECC or prefetch engine at a time. If you have NAND in two chipselects, bad things would happen.. Maybe something like: int gpmc_ecc_request(int cs); void gpmc_ecc_free(int cs); int gpmc_prefetch_request(int cs); void gpmc_prefetch_free(int cs); Other than that, looks like a good clean-up so we can easily add the platform init code for all the board files. Regards, Tony From dave at lambsys.com Fri May 14 23:31:14 2010 From: dave at lambsys.com (David Lambert) Date: Fri, 14 May 2010 22:31:14 -0500 Subject: 2GB file size limit? Message-ID: <4BEE1582.40706@lambsys.com> Is there any way to increase the file size limit on UBIFS beyond 2Gbytes? I have tried enabling the kernel ?Support for large block devices and files? under ?Enable the block layer?, but the 2G limit persists. Regards, Dave. From Larry.Orsak at sanantonio.gov Sat May 15 04:41:17 2010 From: Larry.Orsak at sanantonio.gov (Larry Orsak) Date: Sat, 15 May 2010 03:41:17 -0500 Subject: CONTACT ME PRIVATELY @jack.parkinson11@hotmail.com Message-ID: My name is Mr Jack parkinson and i work with the EURO lottery, i got your email address from your country website. i am soliciting for your opinion to make you a winner in our ongoing online lottery draws,And i can make you a winner and we will share the proceeds equally 50/50. if you are interested contact me via me personal email:jack.parkinson11 at hotmail.com From julia at diku.dk Sat May 15 17:23:31 2010 From: julia at diku.dk (Julia Lawall) Date: Sat, 15 May 2010 23:23:31 +0200 (CEST) Subject: [PATCH 34/37] drivers/mtd: Use kmemdup Message-ID: From: Julia Lawall Use kmemdup when some other buffer is immediately copied into the allocated region. A simplified version of the semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to,size,flag; statement S; @@ - to = \(kmalloc\|kzalloc\)(size,flag); + to = kmemdup(from,size,flag); if (to==NULL || ...) S - memcpy(to, from, size); // Signed-off-by: Julia Lawall --- drivers/mtd/mtdconcat.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff -u -p a/drivers/mtd/mtdconcat.c b/drivers/mtd/mtdconcat.c --- a/drivers/mtd/mtdconcat.c +++ b/drivers/mtd/mtdconcat.c @@ -183,10 +183,9 @@ concat_writev(struct mtd_info *mtd, cons } /* make a copy of vecs */ - vecs_copy = kmalloc(sizeof(struct kvec) * count, GFP_KERNEL); + vecs_copy = kmemdup(vecs, sizeof(struct kvec) * count, GFP_KERNEL); if (!vecs_copy) return -ENOMEM; - memcpy(vecs_copy, vecs, sizeof(struct kvec) * count); entry_low = 0; for (i = 0; i < concat->num_subdev; i++) { From shachar at shemesh.biz Sun May 16 11:40:07 2010 From: shachar at shemesh.biz (Shachar Shemesh) Date: Sun, 16 May 2010 18:40:07 +0300 Subject: Wrong flash type in m25p80 driver Message-ID: <4BF011D7.4010907@shemesh.biz> Hi all, I've found a problem in the m25p80 driver (drives a bunch of SPI flash chips based on similar commands). While the commands that drive those chips are almost exactly the same, some variance between the chips does exist. Almost all of them have 64KB erase blocks, but some also have smaller 4KB erase sectors (terminology differs between chips, but the two sizes, fairly universally, don't). My understanding of the mtd_info struct is that this is precisely what the "writesize" field is for - specifying different maximal and minimal erase sizes. The current m25p80 driver does not specify the two sizes correctly, which leads to total failure when trying to use it to create UBIFS volumes. The second problem I'm having with this driver is that it reports itself as NOR flash. This is obviously not the case, but I'm a bit at a loss as to what is. These are not, exactly, NAND flashes. DATAFLASH is closer to the mark, as both these and the DATAFLASH had SPI interfaces, but setting the type to DATAFLASH triggers nasty behavior by the jffs2 code, which assumes that data flashes have erase blocks of either 536 or 1056 bytes. The result is that it allocates 512KB of erase blocks, causing a 1.5MB of overhead on each volume. For a 4MB flash, that is a large overhead to accept. I'm attaching a patch to the m25p80 driver. I would love to receive comments on the correct flash type to put there for proper operation. Something that is compatible with jffs2 would be appreciated. I've written a fix to the jffs2 code, but I'm not sure of its correctness. Thanks, Shachar -- Shachar Shemesh Lingnu Open Source Consulting Ltd. http://www.lingnu.com -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: erasesize.patch Type: text/x-patch Size: 2299 bytes Desc: not available URL: From vapier.adi at gmail.com Sun May 16 14:40:22 2010 From: vapier.adi at gmail.com (Mike Frysinger) Date: Sun, 16 May 2010 14:40:22 -0400 Subject: Wrong flash type in m25p80 driver In-Reply-To: <4BF011D7.4010907@shemesh.biz> References: <4BF011D7.4010907@shemesh.biz> Message-ID: 2010/5/16 Shachar Shemesh: > The second problem I'm having with this driver is that it reports itself as > NOR flash. the response is: so what ? you havent described how this is problematic in any way. -mike From vapier.adi at gmail.com Sun May 16 15:17:34 2010 From: vapier.adi at gmail.com (Mike Frysinger) Date: Sun, 16 May 2010 15:17:34 -0400 Subject: Wrong flash type in m25p80 driver In-Reply-To: <4BF041A3.70304@shemesh.biz> References: <4BF011D7.4010907@shemesh.biz> <4BF041A3.70304@shemesh.biz> Message-ID: On Sun, May 16, 2010 at 15:04, Shachar Shemesh wrote: > Mike Frysinger wrote: >> 2010/5/16 Shachar Shemesh: >>> The second problem I'm having with this driver is that it reports itself as >>> NOR flash. >> >> the response is: so what ? you havent described how this is >> problematic in any way. > > Then why have flash type at all, if no-one cares? so your answer is "there is no problem with calling it NOR flash" if it looks like a duck, quacks like a duck, and walks like a duck, then why waste time calling it a DataDuck ? for all intents and purposes, all the kernel code/utilities that work with the flashes can treat these SPI flashes as NOR flashes and everything works fine. > Either way, the patch in my previous message is intended for inclusion. it isnt acceptable in the current format. so until you clean it up and submit it properly, nothing is going to happen. this of course ignores the errors in the patch like calling it DataFlash which you yourself clearly have shown is wrong. DataFlash is a special type of flash made by Atmel. it has properties which other SPI flashes do not. -mike From s-ghorai at ti.com Mon May 17 00:22:40 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Mon, 17 May 2010 09:52:40 +0530 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FB75B@dbde02.ent.ti.com> Vimal, > -----Original Message----- > From: Vimal Singh [mailto:vimal.newwork at gmail.com] > Sent: 2010-05-14 23:33 > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; Artem.Bityutskiy at nokia.com; > tony at atomide.com; sakoman at gmail.com; linux-mtd at lists.infradead.org > Subject: Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC > virtual address > > On Fri, May 14, 2010 at 8:53 PM, Sukumar Ghorai wrote: > [...] > > > diff --git a/arch/arm/mach-omap2/gpmc-onenand.c b/arch/arm/mach- > omap2/gpmc-onenand.c > > index 7bb6922..5d66817 > > --- a/arch/arm/mach-omap2/gpmc-onenand.c > > +++ b/arch/arm/mach-omap2/gpmc-onenand.c > > @@ -301,7 +301,7 @@ static int omap2_onenand_set_sync_mode(struct > omap_onenand_platform_data *cfg, > > (GPMC_CONFIG1_WAIT_READ_MON | > > GPMC_CONFIG1_WAIT_PIN_SEL(0))) | > > GPMC_CONFIG1_DEVICESIZE_16 | > > - GPMC_CONFIG1_DEVICETYPE_NOR | > > + GPMC_CONFIG1_DEVICETYPE(GPMC_DEVICETYPE_NOR) | > > GPMC_CONFIG1_MUXADDDATA); > > Please do not dp OneNAND changes in NAND patch. [Ghorai] I agree. > > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > > index 5bc3ca0..a3fd1ed > > --- a/arch/arm/mach-omap2/gpmc.c > > +++ b/arch/arm/mach-omap2/gpmc.c > > @@ -29,27 +29,27 @@ > > #include > > > > /* GPMC register offsets */ > > -#define GPMC_REVISION 0x00 > > -#define GPMC_SYSCONFIG 0x10 > > -#define GPMC_SYSSTATUS 0x14 > > -#define GPMC_IRQSTATUS 0x18 > > -#define GPMC_IRQENABLE 0x1c > > -#define GPMC_TIMEOUT_CONTROL 0x40 > > -#define GPMC_ERR_ADDRESS 0x44 > > -#define GPMC_ERR_TYPE 0x48 > > -#define GPMC_CONFIG 0x50 > > -#define GPMC_STATUS 0x54 > > -#define GPMC_PREFETCH_CONFIG1 0x1e0 > > -#define GPMC_PREFETCH_CONFIG2 0x1e4 > > -#define GPMC_PREFETCH_CONTROL 0x1ec > > -#define GPMC_PREFETCH_STATUS 0x1f0 > > -#define GPMC_ECC_CONFIG 0x1f4 > > -#define GPMC_ECC_CONTROL 0x1f8 > > -#define GPMC_ECC_SIZE_CONFIG 0x1fc > > - > > -#define GPMC_CS0 0x60 > > -#define GPMC_CS_SIZE 0x30 > > - > > +#define GPMC_REVISION 0x00 > > +#define GPMC_SYSCONFIG 0x10 > > +#define GPMC_SYSSTATUS 0x14 > > +#define GPMC_IRQSTATUS 0x18 > > +#define GPMC_IRQENABLE 0x1c > > +#define GPMC_TIMEOUT_CONTROL 0x40 > > +#define GPMC_ERR_ADDRESS 0x44 > > +#define GPMC_ERR_TYPE 0x48 > > +#define GPMC_CONFIG 0x50 > > +#define GPMC_STATUS 0x54 > > +#define GPMC_PREFETCH_CONFIG1 0x1e0 > > +#define GPMC_PREFETCH_CONFIG2 0x1e4 > > +#define GPMC_PREFETCH_CONTROL 0x1ec > > +#define GPMC_PREFETCH_STATUS 0x1f0 > > +#define GPMC_ECC_CONFIG 0x1f4 > > +#define GPMC_ECC_CONTROL 0x1f8 > > +#define GPMC_ECC_SIZE_CONFIG 0x1fc > > +#define GPMC_ECC1_RESULT 0x200 > > + > > +#define GPMC_CS0_BASE 0x60 > > +#define GPMC_CS_SIZE 0x30 > > #define GPMC_MEM_START 0x00000000 > > #define GPMC_MEM_END 0x3FFFFFFF > > #define BOOT_ROM_SPACE 0x100000 /* 1MB */ > > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx) > > return __raw_readl(gpmc_base + idx); > > } > > > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > + __raw_writeb(val, reg_addr); > > +} > > + > > +static u8 gpmc_cs_read_byte(int cs, int idx) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > + return __raw_readb(reg_addr); > > +} > > + > > I do not think we need these functions. [Ghorai] This is used in gpmc_hwcontrol() and to get the nand status from omap2.c. > > > void gpmc_cs_write_reg(int cs, int idx, u32 val) > > { > > void __iomem *reg_addr; > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > __raw_writel(val, reg_addr); > > } > > > > @@ -120,7 +136,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > > { > > void __iomem *reg_addr; > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > return __raw_readl(reg_addr); > > } > > > > @@ -419,6 +435,96 @@ void gpmc_cs_free(int cs) > > EXPORT_SYMBOL(gpmc_cs_free); > > > > /** > > + * gpmc_hwcontrol - hardware specific access (read/ write) to control > > + * @write: need 1 for configure; 0 for reading the complete register > > + * @cs: chip select number > > + * @cmd: Command type > > + * @wval: value/information to write > > + * @rval: pointer to get the value back > > + */ > > +int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int *rval) > > +{ > > + u32 reg = 0; > > + u32 regval = 0; > > + > > + switch (cmd) { > > + > > + case GPMC_GET_SET_STATUS: > > + reg = GPMC_STATUS; > > + if (write) > > + gpmc_write_reg(GPMC_STATUS, regval); > > + break; > > + > > + case GPMC_GET_SET_IRQ_STATUS: > > + reg = GPMC_IRQSTATUS; > > + if (write) > > + gpmc_write_reg(GPMC_IRQSTATUS, regval); > > + break; > > + > > + case GPMC_GET_PREF_STATUS: > > + reg = GPMC_PREFETCH_STATUS; > > + break; > > + > > + case GPMC_CONFIG_WP: > > + reg = GPMC_CONFIG; > > + regval = gpmc_read_reg(GPMC_CONFIG); > > + if (wval) > > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON > */ > > + else > > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is > OFF */ > > + gpmc_write_reg(reg, regval); > > + break; > > + > > + case GPMC_CONFIG_RDY_BSY: > > + #define WR_RD_PIN_MONITORING 0x00600000 > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= WR_RD_PIN_MONITORING; > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_CONFIG_DEV_SIZE: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= GPMC_CONFIG1_DEVICESIZE(wval); > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_CONFIG_DEV_TYPE: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= GPMC_CONFIG1_DEVICETYPE(wval); > > + if (wval == GPMC_DEVICETYPE_NOR) > > + regval |= GPMC_CONFIG1_MUXADDDATA; > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_NAND_COMMAND: > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); > > + break; > > + > > + case GPMC_NAND_ADDRESS: > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); > > + break; > > + > > + case GPMC_NAND_DATA: > > + if (write) > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); > > + else > > + *rval = gpmc_cs_read_byte(cs, > GPMC_CS_NAND_DATA); > > + break; > > + > > + default: > > + dump_stack(); > > + printk(KERN_ERR "not supported\n"); > > + return -1; > > + } > > + > > + if (!write && reg) > > + *rval = gpmc_read_reg(reg); > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(gpmc_hwcontrol); > > + > > +/** > > * gpmc_prefetch_enable - configures and starts prefetch transfer > > * @cs: nand cs (chip select) number > > * @dma_mode: dma mode enable (1) or disable (0) > > @@ -466,15 +572,6 @@ void gpmc_prefetch_reset(void) > > } > > EXPORT_SYMBOL(gpmc_prefetch_reset); > > > > -/** > > - * gpmc_prefetch_status - reads prefetch status of engine > > - */ > > -int gpmc_prefetch_status(void) > > -{ > > - return gpmc_read_reg(GPMC_PREFETCH_STATUS); > > -} > > -EXPORT_SYMBOL(gpmc_prefetch_status); > > - > > static void __init gpmc_mem_init(void) > > { > > int cs; > > @@ -615,3 +712,86 @@ void omap3_gpmc_restore_context(void) > > } > > } > > #endif /* CONFIG_ARCH_OMAP3 */ > > + > > +/** > > + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC > controller > > + * @cs: Chip select number > > + * @ecc_size: bytes for which ECC will be generated > > + */ > > +void gpmc_ecc_init(int cs, int ecc_size) > > +{ > > + unsigned int val = 0x0; > > + > > + /* Read from ECC Control Register */ > > + val = gpmc_read_reg(GPMC_ECC_CONTROL); > > + > > + /* Clear all ECC | Enable Reg1 */ > > + val = ((0x00000001<<8) | 0x00000001); > > + gpmc_write_reg(GPMC_ECC_CONTROL, val); > > + > > + /* Read from ECC Size Config Register */ > > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > > + /* ECCSIZE1=512 | Select eccResultsize[0-3] */ > > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > > +} > > + > > +/** > > + * gpmc_calcuate_ecc - Generate non-inverted ECC bytes. > > + * @cs: Chip select number > > + * @dat: The pointer to data on which ecc is computed > > + * @ecc_code: The ecc_code buffer > > + * > > + * Using noninverted ECC can be considered ugly since writing a blank > > + * page ie. padding will clear the ECC bytes. This is no problem as > long > > + * nobody is trying to write data on the seemingly unused page. Reading > > + * an erased page will produce an ECC mismatch between generated and > read > > + * ECC bytes that has to be dealt with separately. > > + */ > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) > > +{ > > + unsigned int val = 0x0; > > + > > + /* Start Reading from HW ECC1_Result = 0x200 */ > > + val = gpmc_read_reg(GPMC_ECC1_RESULT); > > + *ecc_code++ = val; /* P128e, ..., P1e */ > > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */ > > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ > > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); > > + > > + return 0; > > +} > > + > > +/** > > + * gpmc_enable_hwecc - This function enables the hardware ecc > functionality > > + * @cs: Chip select number > > + * @mode: Read/Write mode > > + * @dev_width: device bus width > > + */ > > +void gpmc_enable_hwecc(int cs, int mode, int dev_width) > > +{ > > + unsigned int val = gpmc_read_reg(GPMC_ECC_CONFIG); > > + > > + switch (mode) { > > + case GPMC_ECC_READ: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ > > + val = (dev_width << 7) | (cs << 1) | (0x1); > > + break; > > + case GPMC_ECC_READSYN: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ > > + val = (dev_width << 7) | (cs << 1) | (0x1); > > + break; > > + case GPMC_ECC_WRITE: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ > > + val = (dev_width << 7) | (cs << 1) | (0x1); > > + break; > > + default: > > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", > mode); > > + break; > > + } > > + > > + gpmc_write_reg(GPMC_ECC_CONFIG, val); > > +} > > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat- > omap/include/plat/gpmc.h > > index 145838a..56e1407 > > --- a/arch/arm/plat-omap/include/plat/gpmc.h > > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > > @@ -25,10 +25,22 @@ > > #define GPMC_CS_NAND_ADDRESS 0x20 > > #define GPMC_CS_NAND_DATA 0x24 > > > > -#define GPMC_CONFIG 0x50 > > -#define GPMC_STATUS 0x54 > > -#define GPMC_CS0_BASE 0x60 > > -#define GPMC_CS_SIZE 0x30 > > +/* Control Commands */ > > +#define GPMC_GET_SET_STATUS 0x00000001 > > +#define GPMC_CONFIG_WP 0x00000002 > > +#define GPMC_CONFIG_RDY_BSY 0x00000003 > > +#define GPMC_CONFIG_DEV_SIZE 0x00000004 > > +#define GPMC_CONFIG_DEV_TYPE 0x00000005 > > +#define GPMC_NAND_COMMAND 0x00000006 > > +#define GPMC_NAND_ADDRESS 0x00000007 > > +#define GPMC_NAND_DATA 0x00000008 > > +#define GPMC_GET_PREF_STATUS 0x00000009 > > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000a > > + > > +/* ECC commands */ > > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ > > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ > > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back > */ > > > > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) > > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) > > @@ -44,10 +56,7 @@ > > #define GPMC_CONFIG1_WAIT_MON_IIME(val) ((val & 3) << 18) > > #define GPMC_CONFIG1_WAIT_PIN_SEL(val) ((val & 3) << 16) > > #define GPMC_CONFIG1_DEVICESIZE(val) ((val & 3) << 12) > > -#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) > > #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) > > -#define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) > > -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2) > > #define GPMC_CONFIG1_MUXADDDATA (1 << 9) > > #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) > > #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) > > @@ -56,6 +65,12 @@ > > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) > > #define GPMC_CONFIG7_CSVALID (1 << 6) > > > > +#define GPMC_DEVICETYPE_NOR 0 > > +#define GPMC_DEVICETYPE_NAND 2 > > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 > > +#define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) > > + > > + > > /* > > * Note that all values in this struct are in nanoseconds, while > > * the register values are in gpmc_fck cycles. > > @@ -109,9 +124,14 @@ extern int gpmc_cs_reserved(int cs); > > extern int gpmc_prefetch_enable(int cs, int dma_mode, > > unsigned int u32_count, int > is_write); > > extern void gpmc_prefetch_reset(void); > > -extern int gpmc_prefetch_status(void); > > extern void omap3_gpmc_save_context(void); > > extern void omap3_gpmc_restore_context(void); > > extern void gpmc_init(void); > > +extern int gpmc_hwcontrol(int write, int cs, int cmd, int wval, int > *rval); > > + > > +void gpmc_ecc_init(int cs, int ecc_size); > > +void gpmc_enable_hwecc(int cs, int mode, int dev_width); > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); > > + > > > > #endif > > diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat- > omap/include/plat/nand.h > > index f8efd54..6562cd0 > > --- a/arch/arm/plat-omap/include/plat/nand.h > > +++ b/arch/arm/plat-omap/include/plat/nand.h > > @@ -21,13 +21,11 @@ struct omap_nand_platform_data { > > int (*dev_ready)(struct > omap_nand_platform_data *); > > int dma_channel; > > unsigned long phys_base; > > - void __iomem *gpmc_cs_baseaddr; > > - void __iomem *gpmc_baseaddr; > > int devsize; > > }; > > > > -/* size (4 KiB) for IO mapping */ > > -#define NAND_IO_SIZE SZ_4K > > +/* minimum size for IO mapping */ > > +#define NAND_IO_SIZE 4 > > > > #if defined(CONFIG_MTD_NAND_OMAP2) || > defined(CONFIG_MTD_NAND_OMAP2_MODULE) > > extern int gpmc_nand_init(struct omap_nand_platform_data *d); > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > > index 7545568..1858c42 > > --- a/drivers/mtd/nand/omap2.c > > +++ b/drivers/mtd/nand/omap2.c > > @@ -23,12 +23,6 @@ > > #include > > #include > > > > -#define GPMC_IRQ_STATUS 0x18 > > -#define GPMC_ECC_CONFIG 0x1F4 > > -#define GPMC_ECC_CONTROL 0x1F8 > > -#define GPMC_ECC_SIZE_CONFIG 0x1FC > > -#define GPMC_ECC1_RESULT 0x200 > > - > > #define DRIVER_NAME "omap2-nand" > > > > #define NAND_WP_OFF 0 > > @@ -37,6 +31,7 @@ > > #define GPMC_BUF_FULL 0x00000001 > > #define GPMC_BUF_EMPTY 0x00000000 > > > > +#ifdef CONFIG_MTD_NAND_OMAP_HWECC > > #define NAND_Ecc_P1e (1 << 0) > > #define NAND_Ecc_P2e (1 << 1) > > #define NAND_Ecc_P4e (1 << 2) > > @@ -103,6 +98,7 @@ > > > > #define P4e_s(a) (TF(a & NAND_Ecc_P4e) << 0) > > #define P4o_s(a) (TF(a & NAND_Ecc_P4o) << 1) > > +#endif /* CONFIG_MTD_NAND_OMAP_HWECC */ > > Why this ifdef macro? > > > > > #ifdef CONFIG_MTD_PARTITIONS > > static const char *part_probes[] = { "cmdlinepart", NULL }; > > @@ -139,34 +135,11 @@ struct omap_nand_info { > > > > int gpmc_cs; > > unsigned long phys_base; > > - void __iomem *gpmc_cs_baseaddr; > > - void __iomem *gpmc_baseaddr; > > - void __iomem *nand_pref_fifo_add; > > struct completion comp; > > int dma_ch; > > }; > > > > /** > > - * omap_nand_wp - This function enable or disable the Write Protect > feature > > - * @mtd: MTD device structure > > - * @mode: WP ON/OFF > > - */ > > -static void omap_nand_wp(struct mtd_info *mtd, int mode) > > -{ > > - struct omap_nand_info *info = container_of(mtd, > > - struct omap_nand_info, > mtd); > > - > > - unsigned long config = __raw_readl(info->gpmc_baseaddr + > GPMC_CONFIG); > > - > > - if (mode) > > - config &= ~(NAND_WP_BIT); /* WP is ON */ > > - else > > - config |= (NAND_WP_BIT); /* WP is OFF */ > > - > > - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG)); > > -} > > - > > -/** > > * omap_hwcontrol - hardware specific access to control-lines > > * @mtd: MTD device structure > > * @cmd: command to device > > @@ -181,31 +154,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, > int cmd, unsigned int ctrl) > > { > > struct omap_nand_info *info = container_of(mtd, > > struct omap_nand_info, mtd); > > - switch (ctrl) { > > - case NAND_CTRL_CHANGE | NAND_CTRL_CLE: > > - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + > > - GPMC_CS_NAND_COMMAND; > > - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + > > - GPMC_CS_NAND_DATA; > > - break; > > - > > - case NAND_CTRL_CHANGE | NAND_CTRL_ALE: > > - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + > > - GPMC_CS_NAND_ADDRESS; > > - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + > > - GPMC_CS_NAND_DATA; > > - break; > > - > > - case NAND_CTRL_CHANGE | NAND_NCE: > > - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + > > - GPMC_CS_NAND_DATA; > > - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + > > - GPMC_CS_NAND_DATA; > > - break; > > - } > > > > - if (cmd != NAND_CMD_NONE) > > - __raw_writeb(cmd, info->nand.IO_ADDR_W); > > + if (cmd != NAND_CMD_NONE) { > > + if (ctrl & NAND_CLE) { > > + gpmc_hwcontrol(1, info->gpmc_cs, > > + GPMC_NAND_COMMAND, cmd, NULL); > > + > > + } else if (ctrl & NAND_ALE) { > > + gpmc_hwcontrol(1, info->gpmc_cs, > > + GPMC_NAND_ADDRESS, cmd, NULL); > > + > > + } else /* NAND_NCE */ > > + gpmc_hwcontrol(1, info->gpmc_cs, > > + GPMC_NAND_DATA, cmd, NULL); > > + } > > } > > > > /** > > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, > u_char *buf, int len) > > */ > > static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, > int len) > > { > > - struct omap_nand_info *info = container_of(mtd, > > - struct omap_nand_info, > mtd); > > + u32 status; > > + struct nand_chip *nand = mtd->priv; > > u_char *p = (u_char *)buf; > > > > while (len--) { > > - iowrite8(*p++, info->nand.IO_ADDR_W); > > - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + > > - GPMC_STATUS) & > GPMC_BUF_FULL)); > > + iowrite8(*p++, nand->IO_ADDR_W); > > + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); > If I am not mistaking, 2nd argument is 'cs', correct? And then, why > are you hard coding this? > Different boards will have NAND chip present at different 'cs'. > Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this. [Ghorai] I agree. > > Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then: > > > + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) > > + ; > > You got in an infinite loop here? [Ghorai] if you see carefully this is same as existing code. Let me check if any better solution. > > > } > > } > > > > @@ -261,18 +224,17 @@ static void omap_read_buf16(struct mtd_info *mtd, > u_char *buf, int len) > > */ > > static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, > int len) > > { > > - struct omap_nand_info *info = container_of(mtd, > > - struct omap_nand_info, > mtd); > > + u32 status; > > + struct nand_chip *nand = mtd->priv; > > u16 *p = (u16 *) buf; > > > > /* FIXME try bursts of writesw() or DMA ... */ > > len >>= 1; > > > > while (len--) { > > - iowrite16(*p++, info->nand.IO_ADDR_W); > > - > > - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + > > - GPMC_STATUS) & > GPMC_BUF_FULL)) > > + iowrite16(*p++, nand->IO_ADDR_W); > > + gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); > > + while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) > > same as above. [Ghorai] if you see carefully this is same as existing code. Let me check if any better solution. > > > -- > Regards, > Vimal Singh From vapier.adi at gmail.com Mon May 17 00:54:29 2010 From: vapier.adi at gmail.com (Mike Frysinger) Date: Mon, 17 May 2010 00:54:29 -0400 Subject: Wrong flash type in m25p80 driver In-Reply-To: <4BF04DBE.5020309@shemesh.biz> References: <4BF011D7.4010907@shemesh.biz> <4BF041A3.70304@shemesh.biz> <4BF04DBE.5020309@shemesh.biz> Message-ID: On Sun, May 16, 2010 at 15:55, Shachar Shemesh wrote: > Mike Frysinger wrote: >> so your answer is "there is no problem with calling it NOR flash" >> >> if it looks like a duck, quacks like a duck, and walks like a duck, >> then why waste time calling it a DataDuck ? for all intents and >> purposes, all the kernel code/utilities that work with the flashes can >> treat these SPI flashes as NOR flashes and everything works fine. > > Actually, that is not the case. Not even remotely. > > NOR flashes (and the m25p80 driver broadcasts it this way) have the ability > to change individual bytes (and, some flashes, individual bits). The SPI > flashes need to erase an entire block. NOR flashes are accessible via the > data bus, these require complicated SPI transactions. They neither quack nor > look anywhere near the same. you havent shown how the current behavior results in non-working flashes. you probably can claim that things dont work as optimally as possible according to the hardware, but as you noted, people work on what interests/annoys them rather than what other people report. > You might want to claim that they are NAND flashes, but, again, those are > somewhat different. Dataflashes are the closest these come to, as far as I > can tell. it doesnt make sense to lump SPI and NAND together because NAND allows for bad blocks. both NOR and SPI are guaranteed to be good throughout or the device is dead. so for all practical uses thus far, SPI and NOR operate the same way. >> it isnt acceptable in the current format. so until you clean it up >> and submit it properly, nothing is going to happen. > > Care to elaborate? Have never submitted patches to Linux before. I don't > mind RTFM, but please point me to the right manual. all Linux documentation is in the folder aptly named "Documentation", and from there it's a short hop to "SubmittingPatches". >> this of course ignores the errors in the patch like calling it >> DataFlash which you yourself clearly have shown is wrong. DataFlash >> is a special type of flash made by Atmel. it has properties which >> other SPI flashes do not. > > What would have really been necessary was a property saying "Serial flash". > I'm afraid I don't fully understand all of the consequence of adding such a > property, however. For one thing, this type is exported to user space. If > that's the only way to get this patch in, I'll do it, of course. I was > attempting to defer to your experience on the matter. since it is an exported ABI as you noted, the details need to be thought & hashed out before committing things as typically you cant go back. so why not start with a list of the differences that matter to the MTD layers where the NOR flashes differ from SPI flashes. emphasis here is on "where it matters to the MTD layers". if the MTD layers operate no differently whatsoever when encountering NOR and SPI flashes, then it doesnt really make sense to declare a new type for it. > I am not so sure about the "properties which other SPI flashes do not". Not, > at least, according to my research (which does not beat experience, but does > beat obscure abstract statements). iirc, dataflashes allow programming on individual bytes just like NOR flashes. most serial flashes (like the ST micro that started the SPI flash driver in the first place) have to be programmed on a page basis. dataflashes also have more flexible erase structures (4kb, 32kb, or 64kb) while ST micro can only be erased at 64kb sectors. my point is just that calling all SPI flashes "dataflashes" is inherently wrong since only Atmel makes dataflashes. it's also a bit funny since you started off the thread with the complaint that calling SPI flashes NOR flashes was wrong because SPI flashes arent NOR flashes. if you're going to declare a new category for SPI flashes, then it should be something that applies to all the current SPI flashes (just look in the m25p80.c driver to see all the ones supported). > Again, I'm trying to recruit the collective knowledge of this list in order > to do the right thing, not get into a fight. i'm just a schlub here. i'm not a MTD maintainer and wont be approving any patches. but this list suffers from responses, so i figured i'd throw something out i have a passing knowledge of. > I don't mind doing the work, > but I need help filling in the knowledge. I was told that newbies are > welcome, so long as they show a willingness not to dump their desires on > others, say by submitting actual patches..... that is indeed the way. but you cant really say "this patch is intended for inclusion" when (1) it is incorrectly formatted and (2) it has clearly unacceptable known bugs before the patch was even reviewed. -mike From haojian.zhuang at gmail.com Mon May 17 01:05:41 2010 From: haojian.zhuang at gmail.com (Haojian Zhuang) Date: Mon, 17 May 2010 13:05:41 +0800 Subject: [PATCH 17/20] pxa3xx_nand: add cmdline part parser support In-Reply-To: <4BED2FD0.5010308@pengutronix.de> References: <1273804364.9999.881.camel@macbook.infradead.org> <1273824971.9999.1582.camel@macbook.infradead.org> <20100514084149.GJ30801@buzzloop.caiaq.de> <4BED2FD0.5010308@pengutronix.de> Message-ID: On Fri, May 14, 2010 at 7:11 PM, Marc Kleine-Budde wrote: > Haojian Zhuang wrote: >> On Fri, May 14, 2010 at 4:41 PM, Daniel Mack wrote: >>> On Fri, May 14, 2010 at 09:16:11AM +0100, David Woodhouse wrote: >>>> On Fri, 2010-05-14 at 14:08 +0800, Haojian Zhuang wrote: >>>>> New patches are rebased for mtd-2.6 master branch. There're contained >>>>> in another mail loop. >>>> Hm, please test these by sending to yourself first, saving the patches >>>> and checking that they apply. >>>> >>>> [dwmw2 at macbook mtd-2.6]$ git describe HEAD >>>> v2.6.34-rc7-142-gf6b173c >>>> >>>> [dwmw2 at macbook mtd-2.6]$ for a in `seq -w 1 20` ; do echo Patch $a ; patch -p1 < pxa$a.patch ; done >>>> Patch 01 >>>> patching file arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >>>> patching file drivers/mtd/nand/Kconfig >>>> patching file drivers/mtd/nand/pxa3xx_nand.c >>>> patch: **** malformed patch at line 203: transfering to/from NAND HW"); >>> Jep, they're line-wrapped, just like the version before. >>> >>> Haojian, you can avoid this to happen by using 'git send-email'. >>> >>> Thanks, >>> Daniel >>> >> >> Now I attach these patches directly. Only 0011 patch is changed to >> using dev_dbg for debug print. > > I NACK patches 1 and 17. See my reply to these individual patches. > > Cheers, Marc > > -- Now these patches are updated. Please review them. Best Regards Haojian -------------- next part -------------- A non-text attachment was scrubbed... Name: pxa3xx_nand_update.tgz Type: application/x-gzip Size: 43415 bytes Desc: not available URL: From s-ghorai at ti.com Mon May 17 01:48:58 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Mon, 17 May 2010 11:18:58 +0530 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <20100514235852.GN3428@atomide.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> <20100514235852.GN3428@atomide.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FB825@dbde02.ent.ti.com> Tony, > -----Original Message----- > From: Tony Lindgren [mailto:tony at atomide.com] > Sent: 2010-05-15 05:29 > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; > sakoman at gmail.com; mike at compulab.co.il; Artem.Bityutskiy at nokia.com > Subject: Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC > virtual address > > Few more comments below. > > * Sukumar Ghorai [100514 08:18]: > > + > > +/** > > + * gmpc_ecc_init - Initialize the HW ECC for NAND flash in GPMC > controller > > + * @cs: Chip select number > > + * @ecc_size: bytes for which ECC will be generated > > + */ > > +void gpmc_ecc_init(int cs, int ecc_size) > > +{ > > + unsigned int val = 0x0; > > + > > + /* Read from ECC Control Register */ > > + val = gpmc_read_reg(GPMC_ECC_CONTROL); > > + > > + /* Clear all ECC | Enable Reg1 */ > > + val = ((0x00000001<<8) | 0x00000001); > > + gpmc_write_reg(GPMC_ECC_CONTROL, val); > > + > > + /* Read from ECC Size Config Register */ > > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > > + /* ECCSIZE1=512 | Select eccResultsize[0-3] */ > > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > > +} > > There should be some locking as only one chipselect can use > the ECC or prefetch engine at a time. If you have NAND in > two chipselects, bad things would happen.. > > Maybe something like: > > int gpmc_ecc_request(int cs); > void gpmc_ecc_free(int cs); > int gpmc_prefetch_request(int cs); > void gpmc_prefetch_free(int cs); > > Other than that, looks like a good clean-up so we can easily > add the platform init code for all the board files. [Ghorai] agreed.. and - 1). Adding one flag/variable for prefetch enable/reset request 2). Adding another flag/variable for ecc int/reset request Regards, Ghorai > > Regards, > > Tony From glecerf at gmail.com Mon May 17 05:39:42 2010 From: glecerf at gmail.com (Guillaume LECERF) Date: Mon, 17 May 2010 11:39:42 +0200 Subject: [PATCH] mtd: gen_probe: use AMD standard command-set with Winbond flash chips Message-ID: <20100517093942.12147.98889.stgit@dev.siriade.com> Tested with W19L320SBT9C [1]. [1] http://www.datasheetarchive.com/pdf-datasheets/Datasheets-40/DSA-795343.pdf Signed-off-by: Obinou Signed-off-by: Guillaume LECERF --- drivers/mtd/chips/gen_probe.c | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 75a8f9d..3b9a284 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -249,6 +249,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) #ifdef CONFIG_MTD_CFI_AMDSTD case P_ID_AMD_STD: case P_ID_SST_OLD: + case P_ID_WINBOND: return cfi_cmdset_0002(map, primary); #endif #ifdef CONFIG_MTD_CFI_STAA From florian at openwrt.org Mon May 17 05:51:45 2010 From: florian at openwrt.org (Florian Fainelli) Date: Mon, 17 May 2010 11:51:45 +0200 Subject: [PATCH] mtd: gen_probe: use AMD standard command-set with Winbond flash chips In-Reply-To: <20100517093942.12147.98889.stgit@dev.siriade.com> References: <20100517093942.12147.98889.stgit@dev.siriade.com> Message-ID: <201005171151.45960.florian@openwrt.org> Hi Guillaume, On Monday 17 May 2010 11:39:42 Guillaume LECERF wrote: > Tested with W19L320SBT9C [1]. > > [1] > http://www.datasheetarchive.com/pdf-datasheets/Datasheets-40/DSA-795343.pd > f > That's correct, thanks! > Signed-off-by: Obinou > Signed-off-by: Guillaume LECERF Acked-by: Florian Fainelli > --- > drivers/mtd/chips/gen_probe.c | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c > index 75a8f9d..3b9a284 100644 > --- a/drivers/mtd/chips/gen_probe.c > +++ b/drivers/mtd/chips/gen_probe.c > @@ -249,6 +249,7 @@ static struct mtd_info *check_cmd_set(struct map_info > *map, int primary) #ifdef CONFIG_MTD_CFI_AMDSTD > case P_ID_AMD_STD: > case P_ID_SST_OLD: > + case P_ID_WINBOND: > return cfi_cmdset_0002(map, primary); > #endif > #ifdef CONFIG_MTD_CFI_STAA > > > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ From dwmw2 at infradead.org Mon May 17 05:52:47 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Mon, 17 May 2010 10:52:47 +0100 Subject: [PATCH] mtd: gen_probe: use AMD standard command-set with Winbond flash chips In-Reply-To: <20100517093942.12147.98889.stgit@dev.siriade.com> References: <20100517093942.12147.98889.stgit@dev.siriade.com> Message-ID: <1274089967.6930.6909.camel@macbook.infradead.org> On Mon, 2010-05-17 at 11:39 +0200, Guillaume LECERF wrote: > Tested with W19L320SBT9C [1]. > > [1] http://www.datasheetarchive.com/pdf-datasheets/Datasheets-40/DSA-795343.pdf > > Signed-off-by: Obinou > Signed-off-by: Guillaume LECERF > --- > drivers/mtd/chips/gen_probe.c | 1 + > 1 files changed, 1 insertions(+), 0 deletions(-) > > diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c > index 75a8f9d..3b9a284 100644 > --- a/drivers/mtd/chips/gen_probe.c > +++ b/drivers/mtd/chips/gen_probe.c > @@ -249,6 +249,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) > #ifdef CONFIG_MTD_CFI_AMDSTD > case P_ID_AMD_STD: > case P_ID_SST_OLD: > + case P_ID_WINBOND: > return cfi_cmdset_0002(map, primary); > #endif > #ifdef CONFIG_MTD_CFI_STAA Looks like this won't automatically load the cfi_cmdset_0002 module on demand, from cfi_cmdset_unknown(). See how the cfi_cmdset_0001 module does it with aliases for 0003 and 0200. Your recent addition of P_ID_SST_OLD suffers the same problem. You want something like this... please test (with CONFIG_MTD_CFI_AMDSTD=m): diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 87e86e9..d81079e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -489,7 +489,11 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) return cfi_amdstd_setup(mtd); } +struct mtd_info *cfi_cmdset_0006(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002"))); +struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002"))); EXPORT_SYMBOL_GPL(cfi_cmdset_0002); +EXPORT_SYMBOL_GPL(cfi_cmdset_0006); +EXPORT_SYMBOL_GPL(cfi_cmdset_0701); static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) { @@ -2040,3 +2044,5 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Crossnet Co. et al."); MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips"); +MODULE_ALIAS("cfi_cmdset_0006"); +MODULE_ALIAS("cfi_cmdset_0701"); -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From doront at mellanox.co.il Mon May 17 05:54:16 2010 From: doront at mellanox.co.il (Doron Tsur) Date: Mon, 17 May 2010 12:54:16 +0300 Subject: '0's during write to NAND mtd stress , on a PPC 460EX system Message-ID: <1EEC75D0B27041449A1EEA2927D1B14536437915EE@MTLMAIL.mtl.com> Kernel version: 2.6.27 NAND HW:IC memory nand flash SLC SMT 16GBIT 2K Page size 48TSOP1 Filesystem 1K-blocks Used Available Use% Mounted on /dev/mtdblock6 256000 179332 76668 71% / /dev/mtdblock8 102400 3096 99304 4% /config /dev/mtdblock9 409600 9872 399728 3% /var CPU: PPC 460EX Scenario: 1. Initialize mtd partition to 0's [using dd] . 2. Perform copying to mtd partition by tar extract to a mounted mtd device. 3. Extracted files are verified using md5 sum. When running this script in a loop, after ~ 1day I get Nulls bytes on 1 file, thus failing md5 verification. I tried activating "CONFIG_JFFS2_FS_WBUF_VERIFY=y" kernel flag; It seems to reduce probability, but not solve the issue. Can you review logs below and provide a lead? Since I extract files to 2 partitions, I can compare valid to non-valid file. "cmp -l" values are in octal base: 508929 124 0 508930 347 0 508931 140 0 508932 46 0 508933 174 0 508935 72 0 ... 511991 53 0 511992 5 0 511993 200 0 511994 1 0 511996 64 0 511997 177 0 511998 343 0 511999 373 0 512000 170 0 Full log of write failure below. == Calling writeimage to image system Write verify error (ECC corrected) at 05a83800. Wrote: 00000000: 7b f3 2a de 95 15 c5 b2 0d ef 7e a1 7c d7 d8 a7 00000010: c8 48 3e 2e 74 c4 75 dd 8c d3 03 1f 72 3e 2d bb 00000020: d2 ec 3d 41 09 cc d5 28 1f 3f af 7c dc 8b fd 47 00000030: fe 1f 1f 39 7e e4 43 e3 5c 00 b3 95 68 3f f8 09 00000040: db ec 03 ec 1f 51 b6 81 79 2e b3 21 9e 5a e4 f5 00000050: d6 86 78 1e c1 bb b7 39 c7 2a 96 46 60 a2 b1 0d 00000060: f0 fb 12 6d bd 34 0d 3e 64 8a f8 e0 63 3e 84 bb 00000070: 81 05 ee 2b c5 09 37 f0 67 8c 3d c0 d8 0f 8c bd 00000080: cc 11 eb 38 b8 70 6d 97 69 4d 3f 6a 5a d9 7a 13 00000090: 18 c7 ad f3 f8 3f 5f 2f 6a 17 f9 80 8d c7 9e 45 000000a0: 2e 82 ec b3 c0 0b 35 08 9c ca 81 93 07 38 79 81 000000b0: 93 0f 38 f9 95 16 04 18 a3 f4 b8 e3 62 7e d9 3f 000000c0: 5b e0 33 2a 80 bb 81 18 b6 db dd b3 52 13 0e 03 000000d0: 0b c1 a5 c7 b6 89 73 79 9d e4 08 af 3d 60 64 df 000000e0: f9 90 6d de ab 3d da fa cb b7 3e db 1c 44 76 fe 000000f0: 8f 39 28 2b ca c1 41 c4 b5 ed ee 1c ec bb 51 94 00000100: 03 e6 20 e7 a0 d9 c8 4e cf 7d ba 1c bc fc 26 72 00000110: 30 5a c4 83 26 a5 0b 6d cc 01 d6 02 c6 9c eb b4 00000120: 3f 49 b5 fd e7 68 0f b4 22 0e 4e 24 c0 87 46 f0 00000130: a2 b9 bf 95 6a fa 27 49 ef 9f a1 06 e8 46 04 ba 00000140: 11 03 6f f6 43 0f 42 e0 92 db b2 c0 97 9f 40 43 00000150: 2e 83 23 37 c1 99 db f5 b8 33 3e 4e 42 0f 8e 45 00000160: 53 5a bb 91 fb d7 2d fb fc 02 de fd b3 c2 32 81 00000170: ab 1c 6f b1 be b7 36 d6 ac 1f 54 9a 8e 4d 1e 23 00000180: 97 f9 48 7f 9a ee 4b bd eb b8 ac 63 0f 76 d8 75 00000190: da 20 df e5 5d af bd 62 ea a3 da 6d 23 bb 50 1d 000001a0: 3e 8d 3a 85 5e 81 97 66 f8 c7 42 83 3a 76 97 e2 000001b0: d9 4f ed f6 99 0c 45 87 34 b2 bf 06 3e 31 af 44 000001c0: cf 72 ab d0 07 0c 3a 67 71 1f a2 37 33 72 7f 3d 000001d0: 20 f4 7a 48 eb e9 fa 3d ce 6e 21 17 72 7c 48 1f 000001e0: a5 6e 3d 53 52 16 d7 fe 36 57 9f c9 e7 a5 af 1f 000001f0: 6d 91 cf db c3 b8 37 f5 dd 95 b8 ef 79 8f 5c 1f 00000200: d5 33 da 32 ef c7 9e df ca 75 4b ef a8 f5 cf b2 00000210: 4f e2 1c d5 1b 19 d9 7f cc f0 d8 c8 2e 4e 02 c7 00000220: 36 e8 5d 48 dc ab c8 71 0a f9 4f 21 ff 29 e4 1a 00000230: f7 6c 03 34 30 02 0d 8c a1 b6 e2 a8 ad fd a8 ad 00000240: 04 6a ab 11 b5 d5 84 da 6a 2e d2 c0 16 ae 2f b6 00000250: c3 b5 bf 21 9e 76 c4 43 f0 6d bb 9a af ed 98 e0 00000260: 7e 53 bb ac fa 0e ff bd dc b3 b8 93 ca 81 b5 07 00000270: f7 92 17 77 ac 0f 77 93 bf 1e ef 3a 26 a8 04 18 00000280: bf c0 bd 46 b8 47 e8 7b 9b e8 45 a0 6b a2 a7 42 00000290: 5d ab fe 57 dc 5d f6 cf 17 d6 7a 91 08 ee 0e e9 000002a0: 53 6e 08 7d 4a 03 df 29 38 cf 89 a6 68 1a cf 40 000002b0: 24 85 fe 65 07 f9 45 cf 34 9e df 8f 71 40 8d f9 000002c0: 7d 50 8d f7 60 1c 52 e3 10 c6 35 6a 2c fb 70 e9 000002d0: 87 d7 9e cb 0a 3f 84 0f 63 eb 3e e0 5c 27 3c 24 000002e0: 38 14 74 92 58 8f 7e a7 eb f0 4b b2 97 83 af b8 000002f0: eb 27 55 6f d0 24 f6 a2 7f 31 72 37 4f 86 5f a4 00000300: 12 eb 30 73 50 0b 45 87 69 10 ff 35 8c 25 2f d6 00000310: b9 f4 3c 72 9f 88 6b 1f 9c 91 71 ae 5e 66 ac 75 00000320: b6 03 6d 33 f2 cb 4f a1 76 50 23 74 51 d8 06 57 00000330: d9 b6 b4 fb 6f d5 93 e4 b8 c7 6c 40 8e 96 d2 df 00000340: 15 7d 40 ef 1d bd 07 62 31 f2 63 27 55 ef 71 99 00000350: 71 c0 1a 07 fe 94 22 a6 8b 78 ba 70 97 b5 77 a5 00000360: cf cb de 1c 7d b8 fd e5 d7 cd 3a d4 7b 5d 80 28 00000370: 4e 5f f9 13 eb 8c b8 43 86 56 bd 1b fc 7f 0e fe 00000380: 37 c6 b5 f7 df 46 1f b2 bc 61 2e 86 b9 2f 60 ee 00000390: aa 8c 6d e5 ad 8d 36 e2 b4 ab 8a cf 06 27 2f dc 000003a0: 3d 57 3b ac e6 7a ee 9e 7b 74 46 cd b5 d3 d6 31 000003b0: ef a7 d6 2f d4 ca 7f d5 2f d4 d4 9a 7e c1 47 6b 000003c0: 58 e9 d7 54 41 bf 6e 4d 4a 6c b4 04 ea f9 61 d9 000003d0: 07 ff fd 9b d6 31 68 96 1c 1f 10 fa 25 c7 51 eb 000003e0: 79 e8 d7 09 d6 af e9 47 84 7e e5 a0 5f c7 a1 5f 000003f0: 07 a1 5f d0 22 fe 3e 80 7e 3d 67 64 e7 8f 84 cf 00000400: 40 bf a0 83 c0 a7 39 fc 23 c1 bd 46 a5 5f 09 89 00000410: 9b 36 84 e7 26 bc 9f 56 bc 1a ed 9a c7 7e c9 ab 00000420: c3 d0 1c f0 4a 3b 15 d7 e6 a3 42 5b 84 0f 8b 47 00000430: e4 73 e9 13 a1 51 3e 68 14 ef 91 eb 59 a3 be 2f 00000440: 35 6a 7e 8b 5a 5f a7 d6 df 58 d3 28 e8 a2 8d 6f 00000450: 07 68 ec 5e a1 91 d9 0f 1e f8 ac 34 8a f9 6f cf 00000460: 67 85 bd 38 3d 71 5b f4 b2 c3 34 c4 76 f9 9d bd 00000470: 93 bf df de 57 df 75 d4 ed bc 04 dd 16 df 74 d3 00000480: 2f 4a dd a6 8d 39 81 6e 6b bd 71 6d ee 61 a5 29 00000490: 8b 47 5b c4 f7 26 a5 af 90 ef 68 8b d0 a9 45 f4 000004a0: db 05 9d 7a 2d 59 2f eb 90 75 aa eb fa 2b f2 db 000004b0: 0f 35 e2 4c dd f9 cd 04 9d fa 0d 9f f9 1f 01 04 000004c0: cc 57 33 60 ee 06 08 30 00 1d a3 05 c8 ff ff ff 000004d0: 19 85 e0 02 00 00 03 79 d7 aa 3d ec 00 00 05 44 000004e0: 00 00 00 b9 00 00 81 ed 00 00 00 00 00 08 14 00 000004f0: 49 af ee a6 49 af ee a6 49 af ee a6 00 08 10 00 00000500: 00 00 03 35 00 00 04 00 06 00 00 00 bc df 41 48 00000510: b1 8c c2 0f 78 5e 4c 53 5d 68 53 67 18 7e 4e 12 00000520: d7 16 b3 91 8b 08 c5 64 25 c5 6c 18 56 8c c3 0e 00000530: 4e 49 61 e7 b8 5e 04 8e 0c 85 0a ee 6a 2d ce ce 00000540: 9b 81 82 c2 a7 fd 92 ef 3b 4d fc 19 ec a2 49 3a 00000550: 46 69 6b 93 fd 84 c1 e6 18 b8 c1 46 59 a9 38 61 00000560: d0 1b a1 c3 9f 15 6c 62 d0 29 51 f0 67 7a d3 ed 00000570: 9c bd df 39 b9 f0 ea 7d 78 cf f3 be ef f3 3e ef 00000580: 77 c4 c8 1a cb e2 ed 47 96 eb 66 c5 37 6d 26 ee 00000590: 6d 32 e1 e5 06 ae 52 6e d0 9e c4 70 a6 01 1c 1f 000005a0: 83 34 a7 b4 38 c5 84 31 05 43 c6 10 4f 4b c0 5c 000005b0: 76 3f 22 9c e8 e0 43 84 93 1d bc 8f f0 ce 0e 56 000005c0: fc 81 0e 1e b4 33 e8 ce 5f b9 c4 ec 14 a2 22 b9 000005d0: ca 72 a9 60 5d 1c 59 67 e2 6c 8b bd 2f 43 fd e9 000005e0: 82 d7 f7 50 7a 91 e2 05 24 a5 8d 6e d1 da 64 f9 000005f0: 89 39 96 bf 7a 89 89 73 2d 66 b9 2f 9e 74 78 bb 00000600: d3 9f 63 0b f1 46 f3 1b f4 8d 78 96 73 eb a4 5e 00000610: 40 17 2f f6 1d e3 45 6d 86 17 af ed 57 79 5e fc 00000620: 32 6a 39 7f 95 78 f0 da 01 de 13 ac 1b 36 7a 87 00000630: 12 80 0e 80 f7 d4 7e 18 4a 41 db 0b f7 1f f1 e1 00000640: 1a f5 ff ef 84 9c 43 c4 9b b7 63 95 7a 5e bc ab 00000650: 34 2b bd 96 b3 fe 81 9a 2d de 5d 65 c6 b2 3b 4d 00000660: 3e 9d 17 87 d7 99 ae 74 9e 51 da 9e 99 5c c4 4e 00000670: 99 53 a8 7a da df 58 f5 b4 fb ba 9f bf e3 eb 76 00000680: 98 f2 d6 72 9d 1f e5 12 22 fa 24 0c 5d a2 47 79 00000690: 60 b9 b5 5c 87 33 6a c7 60 10 27 91 a9 21 2c be 000006a0: 6a d3 ec 8d 1e aa eb b5 fb 11 97 5b 11 39 98 ea 000006b0: 72 46 81 61 f2 90 d9 16 40 b9 90 bd 15 dd b2 8d 000006c0: b0 ea 3f 9e c2 2b 25 13 e1 69 0d 91 92 86 e8 74 000006d0: 13 bd 25 aa a5 fd 7e c9 df 5b 62 fa 18 42 34 77 000006e0: 42 af 62 44 6f 68 b3 59 ed ce cf 99 86 eb 5a ee 000006f0: bf 27 f0 5a 6d 6c a6 df 5d e1 dd 81 fa de 45 6c 00000700: a9 5c 86 2e fe 08 d4 a9 d7 88 ec 73 1f e7 24 de 00000710: ac 68 48 70 16 63 72 02 11 b1 f2 34 5a b6 11 29 00000720: 5f 46 6f b9 89 78 a5 89 e1 72 0d d1 4a 3f 92 15 00000730: 13 3b 2b e3 18 a8 d8 d8 5d a9 61 b0 64 23 cc 37 00000740: f6 30 fe c5 0e c6 7f 7a 8b f1 17 19 da ed c6 6f 00000750: e9 82 01 73 21 f0 bb 14 88 c8 45 d0 bd 6e 7d a2 00000760: bc 30 16 82 71 95 23 ce 6c ba 10 26 0e fe b4 9c 00000770: fb 77 39 57 3e 6b df 5b 4e fb 80 28 90 77 ce 83 00000780: 1c cf c5 58 07 1f e7 93 a4 cd af 1b d7 0f a3 6b 00000790: 6a 59 86 f8 a9 be 63 62 48 9b 51 77 cd 7f fd 1d 000007a0: d3 ab 81 4f ad cd e6 6c 7a 81 de c1 e9 18 a3 b7 000007b0: f4 6d 7a ce 7b 7b d5 5d 41 8a 65 cc 8b d9 15 98 000007c0: f3 5a 32 df 5a 62 22 74 85 a9 7f c5 72 5a 67 bc 000007d0: 3b 5d d0 f6 93 d6 88 7f 9f 9b b4 03 e5 e6 b5 91 000007e0: 7c 9d 7a fb fe 7e 4c fe 16 f5 46 60 3e ab 35 0f 000007f0: 66 aa ae eb eb fb 3b e7 c7 87 af 66 81 a3 a4 93 Read back: 00000000: 7b f3 2a de 95 15 c5 b2 0d ef 7e a1 7c d7 d8 a7 00000010: c8 48 3e 2e 74 c4 75 dd 8c d3 03 1f 72 3e 2d bb 00000020: d2 ec 3d 41 09 cc d5 28 1f 3f af 7c dc 8b fd 47 00000030: fe 1f 1f 39 7e e4 43 e3 5c 00 b3 95 68 3f f8 09 00000040: db ec 03 ec 1f 51 b6 81 79 2e b3 21 9e 5a e4 f5 00000050: d6 86 78 1e c1 bb b7 39 c7 2a 96 46 60 a2 b1 0d 00000060: f0 fb 12 6d bd 34 0d 3e 64 8a f8 e0 63 3e 84 bb 00000070: 81 05 ee 2b c5 09 37 f0 67 8c 3d c0 d8 0f 8c bd 00000080: cc 11 eb 38 b8 70 6d 97 69 4d 3f 6a 5a d9 7a 13 00000090: 18 c7 ad f3 f8 3f 5f 2f 6a 17 f9 80 8d c7 9e 45 000000a0: 2e 82 ec b3 c0 0b 35 08 9c ca 81 93 07 38 79 81 000000b0: 93 0f 38 f9 95 16 04 18 a3 f4 b8 e3 62 7e d9 3f 000000c0: 5b e0 33 2a 80 bb 81 18 b6 db dd b3 52 13 0e 03 000000d0: 0b c1 a5 c7 b6 89 73 79 9d e4 08 af 3d 60 64 df 000000e0: f9 90 6d de ab 3d da fa cb b7 3e db 1c 44 76 fe 000000f0: 8f 39 28 2b ca c1 41 c4 b5 ed ee 1c ec bb 51 94 00000100: 03 e6 20 e7 a0 d9 c8 4e cf 7d ba 1c bc fc 26 72 00000110: 30 5a c4 83 26 a5 0b 6d cc 01 d6 02 c6 9c eb b4 00000120: 3f 49 b5 fd e7 68 0f b4 22 0e 4e 24 c0 87 46 f0 00000130: a2 b9 bf 95 6a fa 27 49 ef 9f a1 06 e8 46 04 ba 00000140: 11 03 6f f6 43 0f 42 e0 92 db b2 c0 97 9f 40 43 00000150: 2e 83 23 37 c1 99 db f5 b8 33 3e 4e 42 0f 8e 45 00000160: 53 5a bb 91 fb d7 2d fb fc 02 de fd b3 c2 32 81 00000170: ab 1c 6f b1 be b7 36 d6 ac 1f 54 9a 8e 4d 1e 23 00000180: 97 f9 48 7f 9a ee 4b bd eb b8 ac 63 0f 76 d8 75 00000190: da 20 df e5 5d af bd 62 ea a3 da 6d 23 bb 50 1d 000001a0: 3e 8d 3a 85 5e 81 97 66 f8 c7 42 83 3a 76 97 e2 000001b0: d9 4f ed f6 99 0c 45 87 34 b2 bf 06 3e 31 af 44 000001c0: cf 72 ab d0 07 0c 3a 67 71 1f a2 37 33 72 7f 3d 000001d0: 20 f4 7a 48 eb e9 fa 3d ce 6e 21 17 72 7c 48 1f 000001e0: a5 6e 3d 53 52 16 d7 fe 36 57 9f c9 e7 a5 af 1f 000001f0: 6d 91 cf db c3 b8 37 f5 dd 95 b8 ef 79 8f 5c 1f 00000200: d5 33 da 32 ef c7 9e df ca 75 4b ef a8 f5 cf b2 00000210: 4f e2 1c d5 1b 19 d9 7f cc f0 d8 c8 2e 4e 02 c7 00000220: 36 e8 5d 48 dc ab c8 71 0a f9 4f 21 ff 29 e4 1a 00000230: f7 6c 03 34 30 02 0d 8c a1 b6 e2 a8 ad fd a8 ad 00000240: 04 6a ab 11 b5 d5 84 da 6a 2e d2 c0 16 ae 2f b6 00000250: c3 b5 bf 21 9e 76 c4 43 f0 6d bb 9a af ed 98 e0 00000260: 7e 53 bb ac fa 0e ff bd dc b3 b8 93 ca 81 b5 07 00000270: f7 92 17 77 ac 0f 77 93 bf 1e ef 3a 26 a8 04 18 00000280: bf c0 bd 46 b8 47 e8 7b 9b e8 45 a0 6b a2 a7 42 00000290: 5d ab fe 57 dc 5d f6 cf 17 d6 7a 91 08 ee 0e e9 000002a0: 53 6e 08 7d 4a 03 df 29 38 cf 89 a6 68 1a cf 40 000002b0: 24 85 fe 65 07 f9 45 cf 34 9e df 8f 71 40 8d f9 000002c0: 7d 50 8d f7 60 1c 52 e3 10 c6 35 6a 2c fb 70 e9 000002d0: 87 d7 9e cb 0a 3f 84 0f 63 eb 3e e0 5c 27 3c 24 000002e0: 38 14 74 92 58 8f 7e a7 eb f0 4b b2 97 83 af b8 000002f0: eb 27 55 6f d0 24 f6 a2 7f 31 72 37 4f 86 5f a4 00000300: 12 eb 30 73 50 0b 45 87 69 10 ff 35 8c 25 2f d6 00000310: b9 f4 3c 72 9f 88 6b 1f 9c 91 71 ae 5e 66 ac 75 00000320: b6 03 6d 33 f2 cb 4f a1 76 50 23 74 51 d8 06 57 00000330: d9 b6 b4 fb 6f d5 93 e4 b8 c7 6c 40 8e 96 d2 df 00000340: 15 7d 40 ef 1d bd 07 62 31 f2 63 27 55 ef 71 99 00000350: 71 c0 1a 07 fe 94 22 a6 8b 78 ba 70 97 b5 77 a5 00000360: cf cb de 1c 7d b8 fd e5 d7 cd 3a d4 7b 5d 80 28 00000370: 4e 5f f9 13 eb 8c b8 43 86 56 bd 1b fc 7f 0e fe 00000380: 37 c6 b5 f7 df 46 1f b2 bc 61 2e 86 b9 2f 60 ee 00000390: aa 8c 6d e5 ad 8d 36 e2 b4 ab 8a cf 06 27 2f dc 000003a0: 3d 57 3b ac e6 7a ee 9e 7b 74 46 cd b5 d3 d6 31 000003b0: ef a7 d6 2f d4 ca 7f d5 2f d4 d4 9a 7e c1 47 6b 000003c0: 58 e9 d7 54 41 bf 6e 4d 4a 6c b4 04 ea f9 61 d9 000003d0: 07 ff fd 9b d6 31 68 96 1c 1f 10 fa 25 c7 51 eb 000003e0: 79 e8 d7 09 d6 af e9 47 84 7e e5 a0 5f c7 a1 5f 000003f0: 07 a1 5f d0 22 fe 3e 80 7e 3d 67 64 e7 8f 84 cf 00000400: 40 bf a0 83 c0 a7 39 fc 23 c1 bd 46 a5 5f 09 89 00000410: 9b 36 84 e7 26 bc 9f 56 bc 1a ed 9a c7 7e c9 ab 00000420: c3 d0 1c f0 4a 3b 15 d7 e6 a3 42 5b 84 0f 8b 47 00000430: e4 73 e9 13 a1 51 3e 68 14 ef 91 eb 59 a3 be 2f 00000440: 35 6a 7e 8b 5a 5f a7 d6 df 58 d3 28 e8 a2 8d 6f 00000450: 07 68 ec 5e a1 91 d9 0f 1e f8 ac 34 8a f9 6f cf 00000460: 67 85 bd 38 3d 71 5b f4 b2 c3 34 c4 76 f9 9d bd 00000470: 93 bf df de 57 df 75 d4 ed bc 04 dd 16 df 74 d3 00000480: 2f 4a dd a6 8d 39 81 6e 6b bd 71 6d ee 61 a5 29 00000490: 8b 47 5b c4 f7 26 a5 af 90 ef 68 8b d0 a9 45 f4 000004a0: db 05 9d 7a 2d 59 2f eb 90 75 aa eb fa 2b f2 db 000004b0: 0f 35 e2 4c dd f9 cd 04 9d fa 0d 9f f9 1f 01 04 000004c0: cc 57 33 60 ee 06 08 30 00 1d a3 05 c8 ff ff ff 000004d0: 19 85 e0 02 00 00 03 79 d7 aa 3d ec 00 00 05 44 000004e0: 00 00 00 b9 00 00 81 ed 00 00 00 00 00 08 14 00 000004f0: 49 af ee a6 49 af ee a6 49 af ee a6 00 08 10 00 00000500: 00 00 03 35 00 00 04 00 06 00 00 00 bc df 41 48 00000510: b1 8c c2 0f 78 5e 4c 53 5d 68 53 67 18 7e 4e 12 00000520: d7 16 b3 91 8b 08 c5 64 25 c5 6c 18 56 8c c3 0e 00000530: 4e 49 61 e7 b8 5e 04 8e 0c 85 0a ee 6a 2d ce ce 00000540: 9b 81 82 c2 a7 fd 92 ef 3b 4d fc 19 ec a2 49 3a 00000550: 46 69 6b 93 fd 84 c1 e6 18 b8 c1 46 59 a9 38 61 00000560: d0 1b a1 c3 9f 15 6c 62 d0 29 51 f0 67 7a d3 ed 00000570: 9c bd df 39 b9 f0 ea 7d 78 cf f3 be ef f3 3e ef 00000580: 77 c4 c8 1a cb e2 ed 47 96 eb 66 c5 37 6d 26 ee 00000590: 6d 32 e1 e5 06 ae 52 6e d0 9e c4 70 a6 01 1c 1f 000005a0: 83 34 a7 b4 38 c5 84 31 05 43 c6 10 4f 4b c0 5c 000005b0: 76 3f 22 9c e8 e0 43 84 93 1d bc 8f f0 ce 0e 56 000005c0: fc 81 0e 1e b4 33 e8 ce 5f b9 c4 ec 14 a2 22 b9 000005d0: ca 72 a9 60 5d 1c 59 67 e2 6c 8b bd 2f 43 fd e9 000005e0: 82 d7 f7 50 7a 91 e2 05 24 a5 8d 6e d1 da 64 f9 000005f0: 89 39 96 bf 7a 89 89 73 2d 66 b9 2f 9e 74 78 bb 00000600: d3 9f 63 0b f1 46 f3 1b f4 8d 78 96 73 eb a4 5e 00000610: 40 17 2f f6 1d e3 45 6d 86 17 af ed 57 79 5e fc 00000620: 32 6a 39 7f 95 78 f0 da 01 de 13 ac 1b 36 7a 87 00000630: 12 80 0e 80 f7 d4 7e 18 4a 41 db 0b f7 1f f1 e1 00000640: 1a f5 ff ef 84 9c 43 c4 9b b7 63 95 7a 5e bc ab 00000650: 34 2b bd 96 b3 fe 81 9a 2d de 5d 65 c6 b2 3b 4d 00000660: 3e 9d 17 87 d7 99 ae 74 9e 51 da 9e 99 5c c4 4e 00000670: 99 53 a8 7a da df 58 f5 b4 fb ba 9f bf e3 eb 76 00000680: 98 f2 d6 72 9d 1f e5 12 22 fa 24 0c 5d a2 47 79 00000690: 60 b9 b5 5c 87 33 6a c7 60 10 27 91 a9 21 2c be 000006a0: 6a d3 ec 8d 1e aa eb b5 fb 11 97 5b 11 39 98 ea 000006b0: 72 46 81 61 f2 90 d9 16 40 b9 90 bd 15 dd b2 8d 000006c0: b0 ea 3f 9e c2 2b 25 13 e1 69 0d 91 92 86 e8 74 000006d0: 13 bd 25 aa a5 fd 7e c9 df 5b 62 fa 18 42 34 77 000006e0: 42 af 62 44 6f 68 b3 59 ed ce cf 99 86 eb 5a ee 000006f0: bf 27 f0 5a 6d 6c a6 df 5d e1 dd 81 fa de 45 6c 00000700: a9 5c 86 2e fe 08 d4 a9 d7 88 ec 73 1f e7 24 de 00000710: ac 68 48 70 16 63 72 02 11 b1 f2 34 5a b6 11 21 00000720: 5f 46 6f b9 89 78 a5 89 e1 72 0d d1 4a 3f 92 15 00000730: 13 3b 2b e3 18 a8 d8 d8 5d a9 61 b0 64 23 cc 37 00000740: f6 30 fe c5 0e c6 7f 7a 8b f1 17 19 da ed c6 6f 00000750: e9 82 01 73 21 f0 bb 14 88 c8 45 d0 bd 6e 7d a2 00000760: bc 30 16 82 71 95 23 ce 6c ba 10 26 0e fe b4 9c 00000770: fb 77 39 57 3e 6b df 5b 4e fb 80 28 90 77 ce 83 00000780: 1c cf c5 58 07 1f e7 93 a4 cd af 1b d7 0f a3 6b 00000790: 6a 59 86 f8 a9 be 63 62 48 9b 51 77 cd 7f fd 1d 000007a0: d3 ab 81 4f ad cd e6 6c 7a 81 de c1 e9 18 a3 b7 000007b0: f4 6d 7a ce 7b 7b d5 5d 41 8a 65 cc 8b d9 15 98 000007c0: f3 5a 32 df 5a 62 22 74 85 a9 7f c5 72 5a 67 bc 000007d0: 3b 5d d0 f6 93 d6 88 7f 9f 9b b4 03 e5 e6 b5 91 000007e0: 7c 9d 7a fb fe 7e 4c fe 16 f5 46 60 3e ab 35 0f 000007f0: 66 a2 ae eb eb fb 3b e7 c7 87 af 66 81 a3 a4 93 Recovery of wbuf succeeded to 05a60000 Write of 889 bytes at 0x05a83cd0 failed. returned -5, retlen 0 Not marking the space at 0x05a83cd0 as dirty because the flash driver returned retlen zero Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 == System successfully imaged Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 -- Writing Host ID: f44b68e95cf2 == Calling imgverify to verify manufactured system Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 FAILED-HASH: ./lib/libcrypto.so.0.9.8b FAILED: 1 of 8656 files (0 missing) did not verify. *** Image location 1 verification failed. *** Could not verify manufactured system From doront at mellanox.co.il Mon May 17 05:54:16 2010 From: doront at mellanox.co.il (Doron Tsur) Date: Mon, 17 May 2010 12:54:16 +0300 Subject: '0's during write to NAND mtd stress , on a PPC 460EX system Message-ID: <1EEC75D0B27041449A1EEA2927D1B14536437915EE@MTLMAIL.mtl.com> Kernel version: 2.6.27 NAND HW:IC memory nand flash SLC SMT 16GBIT 2K Page size 48TSOP1 Filesystem 1K-blocks Used Available Use% Mounted on /dev/mtdblock6 256000 179332 76668 71% / /dev/mtdblock8 102400 3096 99304 4% /config /dev/mtdblock9 409600 9872 399728 3% /var CPU: PPC 460EX Scenario: 1. Initialize mtd partition to 0's [using dd] . 2. Perform copying to mtd partition by tar extract to a mounted mtd device. 3. Extracted files are verified using md5 sum. When running this script in a loop, after ~ 1day I get Nulls bytes on 1 file, thus failing md5 verification. I tried activating "CONFIG_JFFS2_FS_WBUF_VERIFY=y" kernel flag; It seems to reduce probability, but not solve the issue. Can you review logs below and provide a lead? Since I extract files to 2 partitions, I can compare valid to non-valid file. "cmp -l" values are in octal base: 508929 124 0 508930 347 0 508931 140 0 508932 46 0 508933 174 0 508935 72 0 ... 511991 53 0 511992 5 0 511993 200 0 511994 1 0 511996 64 0 511997 177 0 511998 343 0 511999 373 0 512000 170 0 Full log of write failure below. == Calling writeimage to image system Write verify error (ECC corrected) at 05a83800. Wrote: 00000000: 7b f3 2a de 95 15 c5 b2 0d ef 7e a1 7c d7 d8 a7 00000010: c8 48 3e 2e 74 c4 75 dd 8c d3 03 1f 72 3e 2d bb 00000020: d2 ec 3d 41 09 cc d5 28 1f 3f af 7c dc 8b fd 47 00000030: fe 1f 1f 39 7e e4 43 e3 5c 00 b3 95 68 3f f8 09 00000040: db ec 03 ec 1f 51 b6 81 79 2e b3 21 9e 5a e4 f5 00000050: d6 86 78 1e c1 bb b7 39 c7 2a 96 46 60 a2 b1 0d 00000060: f0 fb 12 6d bd 34 0d 3e 64 8a f8 e0 63 3e 84 bb 00000070: 81 05 ee 2b c5 09 37 f0 67 8c 3d c0 d8 0f 8c bd 00000080: cc 11 eb 38 b8 70 6d 97 69 4d 3f 6a 5a d9 7a 13 00000090: 18 c7 ad f3 f8 3f 5f 2f 6a 17 f9 80 8d c7 9e 45 000000a0: 2e 82 ec b3 c0 0b 35 08 9c ca 81 93 07 38 79 81 000000b0: 93 0f 38 f9 95 16 04 18 a3 f4 b8 e3 62 7e d9 3f 000000c0: 5b e0 33 2a 80 bb 81 18 b6 db dd b3 52 13 0e 03 000000d0: 0b c1 a5 c7 b6 89 73 79 9d e4 08 af 3d 60 64 df 000000e0: f9 90 6d de ab 3d da fa cb b7 3e db 1c 44 76 fe 000000f0: 8f 39 28 2b ca c1 41 c4 b5 ed ee 1c ec bb 51 94 00000100: 03 e6 20 e7 a0 d9 c8 4e cf 7d ba 1c bc fc 26 72 00000110: 30 5a c4 83 26 a5 0b 6d cc 01 d6 02 c6 9c eb b4 00000120: 3f 49 b5 fd e7 68 0f b4 22 0e 4e 24 c0 87 46 f0 00000130: a2 b9 bf 95 6a fa 27 49 ef 9f a1 06 e8 46 04 ba 00000140: 11 03 6f f6 43 0f 42 e0 92 db b2 c0 97 9f 40 43 00000150: 2e 83 23 37 c1 99 db f5 b8 33 3e 4e 42 0f 8e 45 00000160: 53 5a bb 91 fb d7 2d fb fc 02 de fd b3 c2 32 81 00000170: ab 1c 6f b1 be b7 36 d6 ac 1f 54 9a 8e 4d 1e 23 00000180: 97 f9 48 7f 9a ee 4b bd eb b8 ac 63 0f 76 d8 75 00000190: da 20 df e5 5d af bd 62 ea a3 da 6d 23 bb 50 1d 000001a0: 3e 8d 3a 85 5e 81 97 66 f8 c7 42 83 3a 76 97 e2 000001b0: d9 4f ed f6 99 0c 45 87 34 b2 bf 06 3e 31 af 44 000001c0: cf 72 ab d0 07 0c 3a 67 71 1f a2 37 33 72 7f 3d 000001d0: 20 f4 7a 48 eb e9 fa 3d ce 6e 21 17 72 7c 48 1f 000001e0: a5 6e 3d 53 52 16 d7 fe 36 57 9f c9 e7 a5 af 1f 000001f0: 6d 91 cf db c3 b8 37 f5 dd 95 b8 ef 79 8f 5c 1f 00000200: d5 33 da 32 ef c7 9e df ca 75 4b ef a8 f5 cf b2 00000210: 4f e2 1c d5 1b 19 d9 7f cc f0 d8 c8 2e 4e 02 c7 00000220: 36 e8 5d 48 dc ab c8 71 0a f9 4f 21 ff 29 e4 1a 00000230: f7 6c 03 34 30 02 0d 8c a1 b6 e2 a8 ad fd a8 ad 00000240: 04 6a ab 11 b5 d5 84 da 6a 2e d2 c0 16 ae 2f b6 00000250: c3 b5 bf 21 9e 76 c4 43 f0 6d bb 9a af ed 98 e0 00000260: 7e 53 bb ac fa 0e ff bd dc b3 b8 93 ca 81 b5 07 00000270: f7 92 17 77 ac 0f 77 93 bf 1e ef 3a 26 a8 04 18 00000280: bf c0 bd 46 b8 47 e8 7b 9b e8 45 a0 6b a2 a7 42 00000290: 5d ab fe 57 dc 5d f6 cf 17 d6 7a 91 08 ee 0e e9 000002a0: 53 6e 08 7d 4a 03 df 29 38 cf 89 a6 68 1a cf 40 000002b0: 24 85 fe 65 07 f9 45 cf 34 9e df 8f 71 40 8d f9 000002c0: 7d 50 8d f7 60 1c 52 e3 10 c6 35 6a 2c fb 70 e9 000002d0: 87 d7 9e cb 0a 3f 84 0f 63 eb 3e e0 5c 27 3c 24 000002e0: 38 14 74 92 58 8f 7e a7 eb f0 4b b2 97 83 af b8 000002f0: eb 27 55 6f d0 24 f6 a2 7f 31 72 37 4f 86 5f a4 00000300: 12 eb 30 73 50 0b 45 87 69 10 ff 35 8c 25 2f d6 00000310: b9 f4 3c 72 9f 88 6b 1f 9c 91 71 ae 5e 66 ac 75 00000320: b6 03 6d 33 f2 cb 4f a1 76 50 23 74 51 d8 06 57 00000330: d9 b6 b4 fb 6f d5 93 e4 b8 c7 6c 40 8e 96 d2 df 00000340: 15 7d 40 ef 1d bd 07 62 31 f2 63 27 55 ef 71 99 00000350: 71 c0 1a 07 fe 94 22 a6 8b 78 ba 70 97 b5 77 a5 00000360: cf cb de 1c 7d b8 fd e5 d7 cd 3a d4 7b 5d 80 28 00000370: 4e 5f f9 13 eb 8c b8 43 86 56 bd 1b fc 7f 0e fe 00000380: 37 c6 b5 f7 df 46 1f b2 bc 61 2e 86 b9 2f 60 ee 00000390: aa 8c 6d e5 ad 8d 36 e2 b4 ab 8a cf 06 27 2f dc 000003a0: 3d 57 3b ac e6 7a ee 9e 7b 74 46 cd b5 d3 d6 31 000003b0: ef a7 d6 2f d4 ca 7f d5 2f d4 d4 9a 7e c1 47 6b 000003c0: 58 e9 d7 54 41 bf 6e 4d 4a 6c b4 04 ea f9 61 d9 000003d0: 07 ff fd 9b d6 31 68 96 1c 1f 10 fa 25 c7 51 eb 000003e0: 79 e8 d7 09 d6 af e9 47 84 7e e5 a0 5f c7 a1 5f 000003f0: 07 a1 5f d0 22 fe 3e 80 7e 3d 67 64 e7 8f 84 cf 00000400: 40 bf a0 83 c0 a7 39 fc 23 c1 bd 46 a5 5f 09 89 00000410: 9b 36 84 e7 26 bc 9f 56 bc 1a ed 9a c7 7e c9 ab 00000420: c3 d0 1c f0 4a 3b 15 d7 e6 a3 42 5b 84 0f 8b 47 00000430: e4 73 e9 13 a1 51 3e 68 14 ef 91 eb 59 a3 be 2f 00000440: 35 6a 7e 8b 5a 5f a7 d6 df 58 d3 28 e8 a2 8d 6f 00000450: 07 68 ec 5e a1 91 d9 0f 1e f8 ac 34 8a f9 6f cf 00000460: 67 85 bd 38 3d 71 5b f4 b2 c3 34 c4 76 f9 9d bd 00000470: 93 bf df de 57 df 75 d4 ed bc 04 dd 16 df 74 d3 00000480: 2f 4a dd a6 8d 39 81 6e 6b bd 71 6d ee 61 a5 29 00000490: 8b 47 5b c4 f7 26 a5 af 90 ef 68 8b d0 a9 45 f4 000004a0: db 05 9d 7a 2d 59 2f eb 90 75 aa eb fa 2b f2 db 000004b0: 0f 35 e2 4c dd f9 cd 04 9d fa 0d 9f f9 1f 01 04 000004c0: cc 57 33 60 ee 06 08 30 00 1d a3 05 c8 ff ff ff 000004d0: 19 85 e0 02 00 00 03 79 d7 aa 3d ec 00 00 05 44 000004e0: 00 00 00 b9 00 00 81 ed 00 00 00 00 00 08 14 00 000004f0: 49 af ee a6 49 af ee a6 49 af ee a6 00 08 10 00 00000500: 00 00 03 35 00 00 04 00 06 00 00 00 bc df 41 48 00000510: b1 8c c2 0f 78 5e 4c 53 5d 68 53 67 18 7e 4e 12 00000520: d7 16 b3 91 8b 08 c5 64 25 c5 6c 18 56 8c c3 0e 00000530: 4e 49 61 e7 b8 5e 04 8e 0c 85 0a ee 6a 2d ce ce 00000540: 9b 81 82 c2 a7 fd 92 ef 3b 4d fc 19 ec a2 49 3a 00000550: 46 69 6b 93 fd 84 c1 e6 18 b8 c1 46 59 a9 38 61 00000560: d0 1b a1 c3 9f 15 6c 62 d0 29 51 f0 67 7a d3 ed 00000570: 9c bd df 39 b9 f0 ea 7d 78 cf f3 be ef f3 3e ef 00000580: 77 c4 c8 1a cb e2 ed 47 96 eb 66 c5 37 6d 26 ee 00000590: 6d 32 e1 e5 06 ae 52 6e d0 9e c4 70 a6 01 1c 1f 000005a0: 83 34 a7 b4 38 c5 84 31 05 43 c6 10 4f 4b c0 5c 000005b0: 76 3f 22 9c e8 e0 43 84 93 1d bc 8f f0 ce 0e 56 000005c0: fc 81 0e 1e b4 33 e8 ce 5f b9 c4 ec 14 a2 22 b9 000005d0: ca 72 a9 60 5d 1c 59 67 e2 6c 8b bd 2f 43 fd e9 000005e0: 82 d7 f7 50 7a 91 e2 05 24 a5 8d 6e d1 da 64 f9 000005f0: 89 39 96 bf 7a 89 89 73 2d 66 b9 2f 9e 74 78 bb 00000600: d3 9f 63 0b f1 46 f3 1b f4 8d 78 96 73 eb a4 5e 00000610: 40 17 2f f6 1d e3 45 6d 86 17 af ed 57 79 5e fc 00000620: 32 6a 39 7f 95 78 f0 da 01 de 13 ac 1b 36 7a 87 00000630: 12 80 0e 80 f7 d4 7e 18 4a 41 db 0b f7 1f f1 e1 00000640: 1a f5 ff ef 84 9c 43 c4 9b b7 63 95 7a 5e bc ab 00000650: 34 2b bd 96 b3 fe 81 9a 2d de 5d 65 c6 b2 3b 4d 00000660: 3e 9d 17 87 d7 99 ae 74 9e 51 da 9e 99 5c c4 4e 00000670: 99 53 a8 7a da df 58 f5 b4 fb ba 9f bf e3 eb 76 00000680: 98 f2 d6 72 9d 1f e5 12 22 fa 24 0c 5d a2 47 79 00000690: 60 b9 b5 5c 87 33 6a c7 60 10 27 91 a9 21 2c be 000006a0: 6a d3 ec 8d 1e aa eb b5 fb 11 97 5b 11 39 98 ea 000006b0: 72 46 81 61 f2 90 d9 16 40 b9 90 bd 15 dd b2 8d 000006c0: b0 ea 3f 9e c2 2b 25 13 e1 69 0d 91 92 86 e8 74 000006d0: 13 bd 25 aa a5 fd 7e c9 df 5b 62 fa 18 42 34 77 000006e0: 42 af 62 44 6f 68 b3 59 ed ce cf 99 86 eb 5a ee 000006f0: bf 27 f0 5a 6d 6c a6 df 5d e1 dd 81 fa de 45 6c 00000700: a9 5c 86 2e fe 08 d4 a9 d7 88 ec 73 1f e7 24 de 00000710: ac 68 48 70 16 63 72 02 11 b1 f2 34 5a b6 11 29 00000720: 5f 46 6f b9 89 78 a5 89 e1 72 0d d1 4a 3f 92 15 00000730: 13 3b 2b e3 18 a8 d8 d8 5d a9 61 b0 64 23 cc 37 00000740: f6 30 fe c5 0e c6 7f 7a 8b f1 17 19 da ed c6 6f 00000750: e9 82 01 73 21 f0 bb 14 88 c8 45 d0 bd 6e 7d a2 00000760: bc 30 16 82 71 95 23 ce 6c ba 10 26 0e fe b4 9c 00000770: fb 77 39 57 3e 6b df 5b 4e fb 80 28 90 77 ce 83 00000780: 1c cf c5 58 07 1f e7 93 a4 cd af 1b d7 0f a3 6b 00000790: 6a 59 86 f8 a9 be 63 62 48 9b 51 77 cd 7f fd 1d 000007a0: d3 ab 81 4f ad cd e6 6c 7a 81 de c1 e9 18 a3 b7 000007b0: f4 6d 7a ce 7b 7b d5 5d 41 8a 65 cc 8b d9 15 98 000007c0: f3 5a 32 df 5a 62 22 74 85 a9 7f c5 72 5a 67 bc 000007d0: 3b 5d d0 f6 93 d6 88 7f 9f 9b b4 03 e5 e6 b5 91 000007e0: 7c 9d 7a fb fe 7e 4c fe 16 f5 46 60 3e ab 35 0f 000007f0: 66 aa ae eb eb fb 3b e7 c7 87 af 66 81 a3 a4 93 Read back: 00000000: 7b f3 2a de 95 15 c5 b2 0d ef 7e a1 7c d7 d8 a7 00000010: c8 48 3e 2e 74 c4 75 dd 8c d3 03 1f 72 3e 2d bb 00000020: d2 ec 3d 41 09 cc d5 28 1f 3f af 7c dc 8b fd 47 00000030: fe 1f 1f 39 7e e4 43 e3 5c 00 b3 95 68 3f f8 09 00000040: db ec 03 ec 1f 51 b6 81 79 2e b3 21 9e 5a e4 f5 00000050: d6 86 78 1e c1 bb b7 39 c7 2a 96 46 60 a2 b1 0d 00000060: f0 fb 12 6d bd 34 0d 3e 64 8a f8 e0 63 3e 84 bb 00000070: 81 05 ee 2b c5 09 37 f0 67 8c 3d c0 d8 0f 8c bd 00000080: cc 11 eb 38 b8 70 6d 97 69 4d 3f 6a 5a d9 7a 13 00000090: 18 c7 ad f3 f8 3f 5f 2f 6a 17 f9 80 8d c7 9e 45 000000a0: 2e 82 ec b3 c0 0b 35 08 9c ca 81 93 07 38 79 81 000000b0: 93 0f 38 f9 95 16 04 18 a3 f4 b8 e3 62 7e d9 3f 000000c0: 5b e0 33 2a 80 bb 81 18 b6 db dd b3 52 13 0e 03 000000d0: 0b c1 a5 c7 b6 89 73 79 9d e4 08 af 3d 60 64 df 000000e0: f9 90 6d de ab 3d da fa cb b7 3e db 1c 44 76 fe 000000f0: 8f 39 28 2b ca c1 41 c4 b5 ed ee 1c ec bb 51 94 00000100: 03 e6 20 e7 a0 d9 c8 4e cf 7d ba 1c bc fc 26 72 00000110: 30 5a c4 83 26 a5 0b 6d cc 01 d6 02 c6 9c eb b4 00000120: 3f 49 b5 fd e7 68 0f b4 22 0e 4e 24 c0 87 46 f0 00000130: a2 b9 bf 95 6a fa 27 49 ef 9f a1 06 e8 46 04 ba 00000140: 11 03 6f f6 43 0f 42 e0 92 db b2 c0 97 9f 40 43 00000150: 2e 83 23 37 c1 99 db f5 b8 33 3e 4e 42 0f 8e 45 00000160: 53 5a bb 91 fb d7 2d fb fc 02 de fd b3 c2 32 81 00000170: ab 1c 6f b1 be b7 36 d6 ac 1f 54 9a 8e 4d 1e 23 00000180: 97 f9 48 7f 9a ee 4b bd eb b8 ac 63 0f 76 d8 75 00000190: da 20 df e5 5d af bd 62 ea a3 da 6d 23 bb 50 1d 000001a0: 3e 8d 3a 85 5e 81 97 66 f8 c7 42 83 3a 76 97 e2 000001b0: d9 4f ed f6 99 0c 45 87 34 b2 bf 06 3e 31 af 44 000001c0: cf 72 ab d0 07 0c 3a 67 71 1f a2 37 33 72 7f 3d 000001d0: 20 f4 7a 48 eb e9 fa 3d ce 6e 21 17 72 7c 48 1f 000001e0: a5 6e 3d 53 52 16 d7 fe 36 57 9f c9 e7 a5 af 1f 000001f0: 6d 91 cf db c3 b8 37 f5 dd 95 b8 ef 79 8f 5c 1f 00000200: d5 33 da 32 ef c7 9e df ca 75 4b ef a8 f5 cf b2 00000210: 4f e2 1c d5 1b 19 d9 7f cc f0 d8 c8 2e 4e 02 c7 00000220: 36 e8 5d 48 dc ab c8 71 0a f9 4f 21 ff 29 e4 1a 00000230: f7 6c 03 34 30 02 0d 8c a1 b6 e2 a8 ad fd a8 ad 00000240: 04 6a ab 11 b5 d5 84 da 6a 2e d2 c0 16 ae 2f b6 00000250: c3 b5 bf 21 9e 76 c4 43 f0 6d bb 9a af ed 98 e0 00000260: 7e 53 bb ac fa 0e ff bd dc b3 b8 93 ca 81 b5 07 00000270: f7 92 17 77 ac 0f 77 93 bf 1e ef 3a 26 a8 04 18 00000280: bf c0 bd 46 b8 47 e8 7b 9b e8 45 a0 6b a2 a7 42 00000290: 5d ab fe 57 dc 5d f6 cf 17 d6 7a 91 08 ee 0e e9 000002a0: 53 6e 08 7d 4a 03 df 29 38 cf 89 a6 68 1a cf 40 000002b0: 24 85 fe 65 07 f9 45 cf 34 9e df 8f 71 40 8d f9 000002c0: 7d 50 8d f7 60 1c 52 e3 10 c6 35 6a 2c fb 70 e9 000002d0: 87 d7 9e cb 0a 3f 84 0f 63 eb 3e e0 5c 27 3c 24 000002e0: 38 14 74 92 58 8f 7e a7 eb f0 4b b2 97 83 af b8 000002f0: eb 27 55 6f d0 24 f6 a2 7f 31 72 37 4f 86 5f a4 00000300: 12 eb 30 73 50 0b 45 87 69 10 ff 35 8c 25 2f d6 00000310: b9 f4 3c 72 9f 88 6b 1f 9c 91 71 ae 5e 66 ac 75 00000320: b6 03 6d 33 f2 cb 4f a1 76 50 23 74 51 d8 06 57 00000330: d9 b6 b4 fb 6f d5 93 e4 b8 c7 6c 40 8e 96 d2 df 00000340: 15 7d 40 ef 1d bd 07 62 31 f2 63 27 55 ef 71 99 00000350: 71 c0 1a 07 fe 94 22 a6 8b 78 ba 70 97 b5 77 a5 00000360: cf cb de 1c 7d b8 fd e5 d7 cd 3a d4 7b 5d 80 28 00000370: 4e 5f f9 13 eb 8c b8 43 86 56 bd 1b fc 7f 0e fe 00000380: 37 c6 b5 f7 df 46 1f b2 bc 61 2e 86 b9 2f 60 ee 00000390: aa 8c 6d e5 ad 8d 36 e2 b4 ab 8a cf 06 27 2f dc 000003a0: 3d 57 3b ac e6 7a ee 9e 7b 74 46 cd b5 d3 d6 31 000003b0: ef a7 d6 2f d4 ca 7f d5 2f d4 d4 9a 7e c1 47 6b 000003c0: 58 e9 d7 54 41 bf 6e 4d 4a 6c b4 04 ea f9 61 d9 000003d0: 07 ff fd 9b d6 31 68 96 1c 1f 10 fa 25 c7 51 eb 000003e0: 79 e8 d7 09 d6 af e9 47 84 7e e5 a0 5f c7 a1 5f 000003f0: 07 a1 5f d0 22 fe 3e 80 7e 3d 67 64 e7 8f 84 cf 00000400: 40 bf a0 83 c0 a7 39 fc 23 c1 bd 46 a5 5f 09 89 00000410: 9b 36 84 e7 26 bc 9f 56 bc 1a ed 9a c7 7e c9 ab 00000420: c3 d0 1c f0 4a 3b 15 d7 e6 a3 42 5b 84 0f 8b 47 00000430: e4 73 e9 13 a1 51 3e 68 14 ef 91 eb 59 a3 be 2f 00000440: 35 6a 7e 8b 5a 5f a7 d6 df 58 d3 28 e8 a2 8d 6f 00000450: 07 68 ec 5e a1 91 d9 0f 1e f8 ac 34 8a f9 6f cf 00000460: 67 85 bd 38 3d 71 5b f4 b2 c3 34 c4 76 f9 9d bd 00000470: 93 bf df de 57 df 75 d4 ed bc 04 dd 16 df 74 d3 00000480: 2f 4a dd a6 8d 39 81 6e 6b bd 71 6d ee 61 a5 29 00000490: 8b 47 5b c4 f7 26 a5 af 90 ef 68 8b d0 a9 45 f4 000004a0: db 05 9d 7a 2d 59 2f eb 90 75 aa eb fa 2b f2 db 000004b0: 0f 35 e2 4c dd f9 cd 04 9d fa 0d 9f f9 1f 01 04 000004c0: cc 57 33 60 ee 06 08 30 00 1d a3 05 c8 ff ff ff 000004d0: 19 85 e0 02 00 00 03 79 d7 aa 3d ec 00 00 05 44 000004e0: 00 00 00 b9 00 00 81 ed 00 00 00 00 00 08 14 00 000004f0: 49 af ee a6 49 af ee a6 49 af ee a6 00 08 10 00 00000500: 00 00 03 35 00 00 04 00 06 00 00 00 bc df 41 48 00000510: b1 8c c2 0f 78 5e 4c 53 5d 68 53 67 18 7e 4e 12 00000520: d7 16 b3 91 8b 08 c5 64 25 c5 6c 18 56 8c c3 0e 00000530: 4e 49 61 e7 b8 5e 04 8e 0c 85 0a ee 6a 2d ce ce 00000540: 9b 81 82 c2 a7 fd 92 ef 3b 4d fc 19 ec a2 49 3a 00000550: 46 69 6b 93 fd 84 c1 e6 18 b8 c1 46 59 a9 38 61 00000560: d0 1b a1 c3 9f 15 6c 62 d0 29 51 f0 67 7a d3 ed 00000570: 9c bd df 39 b9 f0 ea 7d 78 cf f3 be ef f3 3e ef 00000580: 77 c4 c8 1a cb e2 ed 47 96 eb 66 c5 37 6d 26 ee 00000590: 6d 32 e1 e5 06 ae 52 6e d0 9e c4 70 a6 01 1c 1f 000005a0: 83 34 a7 b4 38 c5 84 31 05 43 c6 10 4f 4b c0 5c 000005b0: 76 3f 22 9c e8 e0 43 84 93 1d bc 8f f0 ce 0e 56 000005c0: fc 81 0e 1e b4 33 e8 ce 5f b9 c4 ec 14 a2 22 b9 000005d0: ca 72 a9 60 5d 1c 59 67 e2 6c 8b bd 2f 43 fd e9 000005e0: 82 d7 f7 50 7a 91 e2 05 24 a5 8d 6e d1 da 64 f9 000005f0: 89 39 96 bf 7a 89 89 73 2d 66 b9 2f 9e 74 78 bb 00000600: d3 9f 63 0b f1 46 f3 1b f4 8d 78 96 73 eb a4 5e 00000610: 40 17 2f f6 1d e3 45 6d 86 17 af ed 57 79 5e fc 00000620: 32 6a 39 7f 95 78 f0 da 01 de 13 ac 1b 36 7a 87 00000630: 12 80 0e 80 f7 d4 7e 18 4a 41 db 0b f7 1f f1 e1 00000640: 1a f5 ff ef 84 9c 43 c4 9b b7 63 95 7a 5e bc ab 00000650: 34 2b bd 96 b3 fe 81 9a 2d de 5d 65 c6 b2 3b 4d 00000660: 3e 9d 17 87 d7 99 ae 74 9e 51 da 9e 99 5c c4 4e 00000670: 99 53 a8 7a da df 58 f5 b4 fb ba 9f bf e3 eb 76 00000680: 98 f2 d6 72 9d 1f e5 12 22 fa 24 0c 5d a2 47 79 00000690: 60 b9 b5 5c 87 33 6a c7 60 10 27 91 a9 21 2c be 000006a0: 6a d3 ec 8d 1e aa eb b5 fb 11 97 5b 11 39 98 ea 000006b0: 72 46 81 61 f2 90 d9 16 40 b9 90 bd 15 dd b2 8d 000006c0: b0 ea 3f 9e c2 2b 25 13 e1 69 0d 91 92 86 e8 74 000006d0: 13 bd 25 aa a5 fd 7e c9 df 5b 62 fa 18 42 34 77 000006e0: 42 af 62 44 6f 68 b3 59 ed ce cf 99 86 eb 5a ee 000006f0: bf 27 f0 5a 6d 6c a6 df 5d e1 dd 81 fa de 45 6c 00000700: a9 5c 86 2e fe 08 d4 a9 d7 88 ec 73 1f e7 24 de 00000710: ac 68 48 70 16 63 72 02 11 b1 f2 34 5a b6 11 21 00000720: 5f 46 6f b9 89 78 a5 89 e1 72 0d d1 4a 3f 92 15 00000730: 13 3b 2b e3 18 a8 d8 d8 5d a9 61 b0 64 23 cc 37 00000740: f6 30 fe c5 0e c6 7f 7a 8b f1 17 19 da ed c6 6f 00000750: e9 82 01 73 21 f0 bb 14 88 c8 45 d0 bd 6e 7d a2 00000760: bc 30 16 82 71 95 23 ce 6c ba 10 26 0e fe b4 9c 00000770: fb 77 39 57 3e 6b df 5b 4e fb 80 28 90 77 ce 83 00000780: 1c cf c5 58 07 1f e7 93 a4 cd af 1b d7 0f a3 6b 00000790: 6a 59 86 f8 a9 be 63 62 48 9b 51 77 cd 7f fd 1d 000007a0: d3 ab 81 4f ad cd e6 6c 7a 81 de c1 e9 18 a3 b7 000007b0: f4 6d 7a ce 7b 7b d5 5d 41 8a 65 cc 8b d9 15 98 000007c0: f3 5a 32 df 5a 62 22 74 85 a9 7f c5 72 5a 67 bc 000007d0: 3b 5d d0 f6 93 d6 88 7f 9f 9b b4 03 e5 e6 b5 91 000007e0: 7c 9d 7a fb fe 7e 4c fe 16 f5 46 60 3e ab 35 0f 000007f0: 66 a2 ae eb eb fb 3b e7 c7 87 af 66 81 a3 a4 93 Recovery of wbuf succeeded to 05a60000 Write of 889 bytes at 0x05a83cd0 failed. returned -5, retlen 0 Not marking the space at 0x05a83cd0 as dirty because the flash driver returned retlen zero Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 == System successfully imaged Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 -- Writing Host ID: f44b68e95cf2 == Calling imgverify to verify manufactured system Empty flash at 0x05a8404c ends at 0x05a84f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84f1c: 0xffff instead Empty flash at 0x05a84f20 ends at 0x05a84ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a84ff0: 0xfff7 instead Empty flash at 0x05a84ff4 ends at 0x05a85f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85f1c: 0xffff instead Empty flash at 0x05a85f20 ends at 0x05a85ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a85ff0: 0xfff7 instead Empty flash at 0x05a85ff4 ends at 0x05a86f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86f1c: 0xffff instead Empty flash at 0x05a86f20 ends at 0x05a86ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a86ff0: 0xfff7 instead Empty flash at 0x05a86ff4 ends at 0x05a87f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87f1c: 0xffff instead Empty flash at 0x05a87f20 ends at 0x05a87ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a87ff0: 0xfff7 instead Empty flash at 0x05a87ff4 ends at 0x05a88f1c jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88f1c: 0xffff instead Empty flash at 0x05a88f20 ends at 0x05a88ff0 jffs2_scan_eraseblock(): Magic bitmask 0x1985 not found at 0x05a88ff0: 0xfff7 instead Further such events for this erase block will not be printed Empty flash at 0x05a88ff4 ends at 0x05a89f1c Empty flash at 0x05a89f20 ends at 0x05a89ff0 Empty flash at 0x05a89ff4 ends at 0x05a8af1c Empty flash at 0x05a8af20 ends at 0x05a8aff0 Empty flash at 0x05a8aff4 ends at 0x05a8bf1c Empty flash at 0x05a8bf20 ends at 0x05a8bff0 Empty flash at 0x05a8bff4 ends at 0x05a8cf1c Empty flash at 0x05a8cf20 ends at 0x05a8cff0 Empty flash at 0x05a8cff4 ends at 0x05a8df1c Empty flash at 0x05a8df20 ends at 0x05a8dff0 Empty flash at 0x05a8dff4 ends at 0x05a8ef1c Empty flash at 0x05a8ef20 ends at 0x05a8eff0 Empty flash at 0x05a8eff4 ends at 0x05a8ff1c Empty flash at 0x05a8ff20 ends at 0x05a8fff0 Empty flash at 0x05a8fff4 ends at 0x05a90f1c Empty flash at 0x05a90f20 ends at 0x05a90ff0 Empty flash at 0x05a90ff4 ends at 0x05a91f1c Empty flash at 0x05a91f20 ends at 0x05a91ff0 Empty flash at 0x05a91ff4 ends at 0x05a92f1c Empty flash at 0x05a92f20 ends at 0x05a92ff0 Empty flash at 0x05a92ff4 ends at 0x05a93f1c Empty flash at 0x05a93f20 ends at 0x05a93ff0 Empty flash at 0x05a93ff4 ends at 0x05a94f1c Empty flash at 0x05a94f20 ends at 0x05a94ff0 Empty flash at 0x05a94ff4 ends at 0x05a95f1c Empty flash at 0x05a95f20 ends at 0x05a95ff0 Empty flash at 0x05a95ff4 ends at 0x05a96f1c Empty flash at 0x05a96f20 ends at 0x05a96ff0 Empty flash at 0x05a96ff4 ends at 0x05a97f1c Empty flash at 0x05a97f20 ends at 0x05a97ff0 Empty flash at 0x05a97ff4 ends at 0x05a98f1c Empty flash at 0x05a98f20 ends at 0x05a98ff0 Empty flash at 0x05a98ff4 ends at 0x05a99f1c Empty flash at 0x05a99f20 ends at 0x05a99ff0 Empty flash at 0x05a99ff4 ends at 0x05a9af1c Empty flash at 0x05a9af20 ends at 0x05a9aff0 Empty flash at 0x05a9aff4 ends at 0x05a9bf1c Empty flash at 0x05a9bf20 ends at 0x05a9bff0 Empty flash at 0x05a9bff4 ends at 0x05a9cf1c Empty flash at 0x05a9cf20 ends at 0x05a9cff0 Empty flash at 0x05a9cff4 ends at 0x05a9df1c Empty flash at 0x05a9df20 ends at 0x05a9dff0 Empty flash at 0x05a9dff4 ends at 0x05a9ef1c Empty flash at 0x05a9ef20 ends at 0x05a9eff0 Empty flash at 0x05a9eff4 ends at 0x05a9ff1c Empty flash at 0x05a9ff20 ends at 0x05a9fff0 FAILED-HASH: ./lib/libcrypto.so.0.9.8b FAILED: 1 of 8656 files (0 missing) did not verify. *** Image location 1 verification failed. *** Could not verify manufactured system From kirill at shutemov.name Mon May 17 09:19:34 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Mon, 17 May 2010 16:19:34 +0300 Subject: [PATCH v4] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1273799074.9999.653.camel@macbook.infradead.org> References: <1273074054-11849-1-git-send-email-kirill@shutemov.name> <1273799074.9999.653.camel@macbook.infradead.org> Message-ID: On Fri, May 14, 2010 at 4:04 AM, David Woodhouse wrote: > On Wed, 2010-05-05 at 18:40 +0300, Kirill A. Shutemov wrote: >> We cannot modify file->f_mapping->backing_dev_info, because it will corrupt >> backing device of device node inode, since file->f_mapping is equal to >> inode->i_mapping (see __dentry_open() in fs/open.c). >> >> Let's introduce separate inode for MTD device with appropriate backing >> device. > > I hate the fact that we have to do this -- is it really the only option? > > Is it _just_ for the backing_device_info? Can't that be done > differently? Yes, it's ugly, but I don't see options. >> @@ -85,11 +88,27 @@ static int mtd_open(struct inode *inode, struct file *file) >> ? ? ? ? ? ? ? goto out; >> ? ? ? } >> >> - ? ? if (mtd->backing_dev_info) >> - ? ? ? ? ? ? file->f_mapping->backing_dev_info = mtd->backing_dev_info; >> + ? ? if (!mtd->inode) { >> + ? ? ? ? ? ? mtd->inode = new_inode(mtd_inode_mnt->mnt_sb); > > I believe that would be a race condition, if it wasn't for the BKL. Ok, I'll fix it. > And what happens when you close the chardevice and call iput() on the > inode so it's destroyed, and then you re-open the device? You never set > mtd->inode = NULL, so won't it now try to igrab a stale pointer? inode destroys only on del_mtd_device() so it's safe to re-open chardevice. > You won't have seen this in your testing unless you made it prune the > icache between the close and open calls. > > -- > David Woodhouse ? ? ? ? ? ? ? ? ? ? ? ? ? ?Open Source Technology Centre > David.Woodhouse at intel.com ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Intel Corporation > > From kirill at shutemov.name Mon May 17 09:55:47 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Mon, 17 May 2010 16:55:47 +0300 Subject: [PATCH v5] mtd: Do not corrupt backing device of device node inode Message-ID: We cannot modify file->f_mapping->backing_dev_info, because it will corrupt backing device of device node inode, since file->f_mapping is equal to inode->i_mapping (see __dentry_open() in fs/open.c). Let's introduce separate inode for MTD device with appropriate backing device. Signed-off-by: Kirill A. Shutemov Acked-by: Jan Kara --- Changelog: v4 -> v5: - Fix race pointed by David Woodhouse. v3 -> v4: - Use igrab() instead of __iget inside the inode_lock; - Add stable@ to CC list. v2 -> v3: - Rebase to mtd-2.6.git. v1 -> v2: - Fix error handling based on comments by Jan Kara. --- drivers/mtd/mtdchar.c | 80 ++++++++++++++++++++++++++++++++++++++++++----- drivers/mtd/mtdcore.c | 3 ++ include/linux/mtd/mtd.h | 3 ++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index c355491..eb672ec 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include +#define MTD_INODE_FS_MAGIC 0x11307854 +static struct vfsmount *mtd_inode_mnt __read_mostly; /* * Data structure to hold the pointer to the mtd device as well @@ -85,11 +88,33 @@ static int mtd_open(struct inode *inode, struct file *file) goto out; } - if (mtd->backing_dev_info) - file->f_mapping->backing_dev_info = mtd->backing_dev_info; + if (!mtd->inode) { + struct inode *mtd_inode; + mtd_inode = new_inode(mtd_inode_mnt->mnt_sb); + if (!mtd_inode) { + put_mtd_device(mtd); + ret = -ENOMEM; + goto out; + } + mtd_inode->i_mode = S_IFCHR; + mtd_inode->i_rdev = inode->i_rdev; + if (mtd->backing_dev_info) { + mtd_inode->i_data.backing_dev_info = + mtd->backing_dev_info; + } + + if (unlikely(cmpxchg(&mtd->inode, NULL, mtd_inode))) { + /* Somebody has already initialized mtd->inode */ + iput(mtd_inode); + } + } + + igrab(mtd->inode); + file->f_mapping = mtd->inode->i_mapping; /* You can't open it RW if it's not a writeable device */ if ((file->f_mode & FMODE_WRITE) && !(mtd->flags & MTD_WRITEABLE)) { + iput(mtd->inode); put_mtd_device(mtd); ret = -EACCES; goto out; @@ -97,6 +122,7 @@ static int mtd_open(struct inode *inode, struct file *file) mfi = kzalloc(sizeof(*mfi), GFP_KERNEL); if (!mfi) { + iput(mtd->inode); put_mtd_device(mtd); ret = -ENOMEM; goto out; @@ -122,6 +148,8 @@ static int mtd_close(struct inode *inode, struct file *file) if ((file->f_mode & FMODE_WRITE) && mtd->sync) mtd->sync(mtd); + iput(mtd->inode); + put_mtd_device(mtd); file->private_data = NULL; kfree(mfi); @@ -951,22 +979,58 @@ static const struct file_operations mtd_fops = { #endif }; +static int mtd_inodefs_get_sb(struct file_system_type *fs_type, int flags, + const char *dev_name, void *data, + struct vfsmount *mnt) +{ + return get_sb_pseudo(fs_type, "mtd_inode:", NULL, MTD_INODE_FS_MAGIC, + mnt); +} + +static struct file_system_type mtd_inodefs_type = { + .name = "mtd_inodefs", + .get_sb = mtd_inodefs_get_sb, + .kill_sb = kill_anon_super, +}; + static int __init init_mtdchar(void) { - int status; + int ret; - status = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, + ret = __register_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd", &mtd_fops); - if (status < 0) { - printk(KERN_NOTICE "Can't allocate major number %d for Memory Technology Devices.\n", - MTD_CHAR_MAJOR); + if (ret < 0) { + pr_notice("Can't allocate major number %d for " + "Memory Technology Devices.\n", MTD_CHAR_MAJOR); + return ret; + } + + ret = register_filesystem(&mtd_inodefs_type); + if (ret) { + pr_notice("Can't register mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_chdev; } - return status; + mtd_inode_mnt = kern_mount(&mtd_inodefs_type); + if (IS_ERR(mtd_inode_mnt)) { + ret = PTR_ERR(mtd_inode_mnt); + pr_notice("Error mounting mtd_inodefs filesystem: %d\n", ret); + goto err_unregister_filesystem; + } + + return ret; + +err_unregister_filesystem: + unregister_filesystem(&mtd_inodefs_type); +err_unregister_chdev: + unregister_chrdev(MTD_CHAR_MAJOR, "mtd"); + return ret; } static void __exit cleanup_mtdchar(void) { + mntput(mtd_inode_mnt); + unregister_filesystem(&mtd_inodefs_type); __unregister_chrdev(MTD_CHAR_MAJOR, 0, 1 << MINORBITS, "mtd"); } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index 3ae06c8..54aab32 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -399,6 +399,9 @@ int del_mtd_device (struct mtd_info *mtd) mtd->index, mtd->name, mtd->usecount); ret = -EBUSY; } else { + if (mtd->inode) + iput(mtd->inode); + device_unregister(&mtd->dev); idr_remove(&mtd_idr, mtd->index); diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 5326435..d66409a 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -174,6 +175,8 @@ struct mtd_info { */ struct backing_dev_info *backing_dev_info; + /* inode for mtd device */ + struct inode *inode; int (*read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf); int (*write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf); -- 1.7.0.4 From dwmw2 at infradead.org Mon May 17 10:10:41 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Mon, 17 May 2010 15:10:41 +0100 Subject: [PATCH v5] mtd: Do not corrupt backing device of device node inode In-Reply-To: References: Message-ID: <1274105441.6930.6920.camel@macbook.infradead.org> On Mon, 2010-05-17 at 16:55 +0300, Kirill A. Shutemov wrote: > + if (!mtd->inode) { > + struct inode *mtd_inode; > + mtd_inode = new_inode(mtd_inode_mnt->mnt_sb); > + if (!mtd_inode) { > + put_mtd_device(mtd); > + ret = -ENOMEM; > + goto out; > + } > + mtd_inode->i_mode = S_IFCHR; > + mtd_inode->i_rdev = inode->i_rdev; > + if (mtd->backing_dev_info) { > + mtd_inode->i_data.backing_dev_info = > + mtd->backing_dev_info; > + } > + > + if (unlikely(cmpxchg(&mtd->inode, NULL, mtd_inode))) { > + /* Somebody has already initialized mtd->inode > */ > + iput(mtd_inode); > + } > + } > + > + igrab(mtd->inode); Now you're just reimplementing iget(). Can we just use iget_locked() to get the appropriate inode (using the mtd device number as the inode number)? Then we don't need to bother storing it in mtd->inode at all, and we can iput() the last refcount on it when the chardevice is closed -- we don't need it to stick around until the MTD device is destroyed. -- dwmw2 From vimal.newwork at gmail.com Mon May 17 10:26:48 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Mon, 17 May 2010 19:56:48 +0530 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FB75B@dbde02.ent.ti.com> References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FB75B@dbde02.ent.ti.com> Message-ID: On Mon, May 17, 2010 at 9:52 AM, Ghorai, Sukumar wrote: [...] >> > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx) >> > ? ? ? ?return __raw_readl(gpmc_base + idx); >> > ?} >> > >> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) >> > +{ >> > + ? ? ? void __iomem *reg_addr; >> > + >> > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + >> idx; >> > + ? ? ? __raw_writeb(val, reg_addr); >> > +} >> > + >> > +static u8 gpmc_cs_read_byte(int cs, int idx) >> > +{ >> > + ? ? ? void __iomem *reg_addr; >> > + >> > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + >> idx; >> > + ? ? ? return __raw_readb(reg_addr); >> > +} >> > + >> >> I do not think we need these functions. > [Ghorai] This is used in gpmc_hwcontrol() and to get the nand status from omap2.c. Yes, I can see that. But I think you should read complete register (32-bits) and the manipulate them accordingly. > [...] >> > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info *mtd, >> u_char *buf, int len) >> > ?*/ >> > ?static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, >> int len) >> > ?{ >> > - ? ? ? struct omap_nand_info *info = container_of(mtd, >> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct omap_nand_info, >> mtd); >> > + ? ? ? u32 ? ? status; >> > + ? ? ? struct nand_chip *nand = mtd->priv; >> > ? ? ? ?u_char *p = (u_char *)buf; >> > >> > ? ? ? ?while (len--) { >> > - ? ? ? ? ? ? ? iowrite8(*p++, info->nand.IO_ADDR_W); >> > - ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + >> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_STATUS) & >> GPMC_BUF_FULL)); >> > + ? ? ? ? ? ? ? iowrite8(*p++, nand->IO_ADDR_W); >> > + ? ? ? ? ? ? ? gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, &status); >> If I am not mistaking, 2nd argument is 'cs', correct? And then, why >> are you hard coding this? >> Different boards will have NAND chip present at different 'cs'. >> Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for this. > [Ghorai] I agree. >> >> Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then: >> >> > + ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) >> > + ? ? ? ? ? ? ? ? ? ? ? ; >> >> You got in an infinite loop here? > [Ghorai] if you see carefully this is same as existing code. Let me check if any better solution. No. Look carefully. In previous code 'gpmc status' was being read in each loop, while in your code you read it once and then you never look for updated value. That's why your code is going into infinite loop -- Regards, Vimal Singh From s-ghorai at ti.com Mon May 17 10:34:14 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Mon, 17 May 2010 20:04:14 +0530 Subject: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC virtual address In-Reply-To: References: <1273850591-19040-1-git-send-email-s-ghorai@ti.com> <1273850591-19040-2-git-send-email-s-ghorai@ti.com> <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FB75B@dbde02.ent.ti.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D8FBB71@dbde02.ent.ti.com> > -----Original Message----- > From: Vimal Singh [mailto:vimal.newwork at gmail.com] > Sent: 2010-05-17 19:57 > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; Artem.Bityutskiy at nokia.com; > tony at atomide.com; sakoman at gmail.com; linux-mtd at lists.infradead.org > Subject: Re: [PATCH v2 1/2] omap3 nand: cleanup for not to use GPMC > virtual address > > On Mon, May 17, 2010 at 9:52 AM, Ghorai, Sukumar wrote: > [...] > >> > @@ -108,11 +108,27 @@ static u32 gpmc_read_reg(int idx) > >> > ? ? ? ?return __raw_readl(gpmc_base + idx); > >> > ?} > >> > > >> > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > >> > +{ > >> > + ? ? ? void __iomem *reg_addr; > >> > + > >> > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > >> idx; > >> > + ? ? ? __raw_writeb(val, reg_addr); > >> > +} > >> > + > >> > +static u8 gpmc_cs_read_byte(int cs, int idx) > >> > +{ > >> > + ? ? ? void __iomem *reg_addr; > >> > + > >> > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > >> idx; > >> > + ? ? ? return __raw_readb(reg_addr); > >> > +} > >> > + > >> > >> I do not think we need these functions. > > [Ghorai] This is used in gpmc_hwcontrol() and to get the nand status > from omap2.c. > > Yes, I can see that. But I think you should read complete register > (32-bits) and the manipulate them accordingly. > > > > [...] > >> > @@ -229,14 +191,15 @@ static void omap_read_buf8(struct mtd_info > *mtd, > >> u_char *buf, int len) > >> > ?*/ > >> > ?static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, > >> int len) > >> > ?{ > >> > - ? ? ? struct omap_nand_info *info = container_of(mtd, > >> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct > omap_nand_info, > >> mtd); > >> > + ? ? ? u32 ? ? status; > >> > + ? ? ? struct nand_chip *nand = mtd->priv; > >> > ? ? ? ?u_char *p = (u_char *)buf; > >> > > >> > ? ? ? ?while (len--) { > >> > - ? ? ? ? ? ? ? iowrite8(*p++, info->nand.IO_ADDR_W); > >> > - ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + > >> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_STATUS) & > >> GPMC_BUF_FULL)); > >> > + ? ? ? ? ? ? ? iowrite8(*p++, nand->IO_ADDR_W); > >> > + ? ? ? ? ? ? ? gpmc_hwcontrol(0, 0, GPMC_GET_SET_STATUS, 0, > &status); > >> If I am not mistaking, 2nd argument is 'cs', correct? And then, why > >> are you hard coding this? > >> Different boards will have NAND chip present at different 'cs'. > >> Please have a look at uses of 'gpmc_hwcontrol' elsewhere as well for > this. > > [Ghorai] I agree. > >> > >> Again, say, you got '(status & GPMC_BUF_FULL) != GPMC_BUF_EMPTY', then: > >> > >> > + ? ? ? ? ? ? ? while (GPMC_BUF_EMPTY == (status & GPMC_BUF_FULL)) > >> > + ? ? ? ? ? ? ? ? ? ? ? ; > >> > >> You got in an infinite loop here? > > [Ghorai] if you see carefully this is same as existing code. Let me > check if any better solution. > > No. Look carefully. In previous code 'gpmc status' was being read in > each loop, while in your code you read it once and then you never look > for updated value. > That's why your code is going into infinite loop [Ghorai] ok. thanks > > > -- > Regards, > Vimal Singh From joakim.tjernlund at transmode.se Mon May 17 11:35:23 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Mon, 17 May 2010 17:35:23 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> Message-ID: > > > > > David Woodhouse wrote on 2010/05/14 12:35:04: > > > > > > On Fri, 2010-05-14 at 12:10 +0200, Joakim Tjernlund wrote: > > > > The only callers of jffs2_erase_pending_blocks() now call it with a > > > > > 'count' argument of 1. So perhaps it's now misnamed and the 's' and the > > > > > extra argument should be dropped? > > > > > > > > I didn't want to change to much and who knows, maybe someone wants > > > > to erase more than one block in the future. Removing the > > > > count could be an add on patch once this patch has proven itself. > > > > > > Yeah, that makes some sense. > > > > > > > > I don't much like the calculation you've added to the end of that > > > > > function either, which really ought to be under locks (even though right > > > > > now I suspect it doesn't hurt). Why recalculate that at all, though -- > > > > > > > > Why does a simple list test need locks? > > > > > > Because it's not just about the test itself. It's also about the memory > > > barriers. Some other CPU could have changed the list (under locks) but > > > unless you have the memory barrier which is implicit in the spinlock, > > > you might see old data. > > > > old data doesn't matter here I think. > > > > > > > > > > why not keep a 'ret' variable which defaults to 0 but is set to 1 just > > > > > before the 'goto done' which is the only way out of the function where > > > > > the return value should be non-zero anyway? > > > > > > > > That would not be the same, would it? One wants to know if the lists > > > > are empty AFTER erasing count blocks. > > > > > > Hm, does one? There's precisely one place we use this return value, in > > > the GC thread. Can you explain the logic of what you were doing there? > > > > Sure, return 1 if there are more blocks left in the list after > > erasing count. That way the caller knows if there are any block left > > to erase. > > > > > It looks like you really wanted it to return a flag saying whether it > > > actually _did_ anything or not. And if it did, that's your work for this > > > GC wakeup and you don't call jffs2_garbage_collect_pass(). Why are you > > > returning a value which tells whether there's more work to do? > > > > hmm, I guess the simpler method like you suggested would work too. > > Details are a bit fuzzy now. > > > > > > > > > I guess I could move the list empty > > > > check before goto done, but that would not really change anything. > > > > > > Ah, yes. Instead of setting ret=1 at the 'goto done', you'd actually do > > > the test somewhere there too, before dropping the locks. Assuming that > > > this really is the return value you need to return, rather than a simple > > > 'work_done' flag. > > How about this then? I have changed jffs2_erase_pending_blocks() to use > the simpler work_done flag: Ping? From randy.dunlap at oracle.com Mon May 17 12:16:32 2010 From: randy.dunlap at oracle.com (Randy Dunlap) Date: Mon, 17 May 2010 09:16:32 -0700 Subject: [PATCH -next] pcmciamtd: fix printk format warnings In-Reply-To: <20100517163521.649526d0.sfr@canb.auug.org.au> References: <20100517163521.649526d0.sfr@canb.auug.org.au> Message-ID: <20100517091632.59c2696c.randy.dunlap@oracle.com> From: Randy Dunlap Fix printk format warnings in pcmciamtd debug code: drivers/mtd/maps/pcmciamtd.c:163: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' drivers/mtd/maps/pcmciamtd.c:212: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' drivers/mtd/maps/pcmciamtd.c:274: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' drivers/mtd/maps/pcmciamtd.c:312: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' Signed-off-by: Randy Dunlap --- drivers/mtd/maps/pcmciamtd.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) --- linux-next-20100517.orig/drivers/mtd/maps/pcmciamtd.c +++ linux-next-20100517/drivers/mtd/maps/pcmciamtd.c @@ -160,7 +160,7 @@ static void pcmcia_copy_from_remap(struc struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; unsigned long win_size = dev->win_size; - DEBUG(3, "to = %p from = %lu len = %u", to, from, len); + DEBUG(3, "to = %p from = %lu len = %zd", to, from, len); while(len) { int toread = win_size - (from & (win_size-1)); caddr_t addr; @@ -209,7 +209,7 @@ static void pcmcia_copy_to_remap(struct struct pcmciamtd_dev *dev = (struct pcmciamtd_dev *)map->map_priv_1; unsigned long win_size = dev->win_size; - DEBUG(3, "to = %lu from = %p len = %u", to, from, len); + DEBUG(3, "to = %lu from = %p len = %zd", to, from, len); while(len) { int towrite = win_size - (to & (win_size-1)); caddr_t addr; @@ -271,7 +271,7 @@ static void pcmcia_copy_from(struct map_ if(DEV_REMOVED(map)) return; - DEBUG(3, "to = %p from = %lu len = %u", to, from, len); + DEBUG(3, "to = %p from = %lu len = %zd", to, from, len); memcpy_fromio(to, win_base + from, len); } @@ -309,7 +309,7 @@ static void pcmcia_copy_to(struct map_in if(DEV_REMOVED(map)) return; - DEBUG(3, "to = %lu from = %p len = %u", to, from, len); + DEBUG(3, "to = %lu from = %p len = %zd", to, from, len); memcpy_toio(win_base + to, from, len); } From c-d.hailfinger.devel.2006 at gmx.net Mon May 17 12:50:45 2010 From: c-d.hailfinger.devel.2006 at gmx.net (Carl-Daniel Hailfinger) Date: Mon, 17 May 2010 18:50:45 +0200 Subject: Wrong flash type in m25p80 driver In-Reply-To: References: <4BF011D7.4010907@shemesh.biz> <4BF041A3.70304@shemesh.biz> <4BF04DBE.5020309@shemesh.biz> Message-ID: <4BF173E5.2030304@gmx.net> On 17.05.2010 06:54, Mike Frysinger wrote: > On Sun, May 16, 2010 at 15:55, Shachar Shemesh wrote: > >> Mike Frysinger wrote: >> >>> so your answer is "there is no problem with calling it NOR flash" >>> >>> if it looks like a duck, quacks like a duck, and walks like a duck, >>> then why waste time calling it a DataDuck ? for all intents and >>> purposes, all the kernel code/utilities that work with the flashes can >>> treat these SPI flashes as NOR flashes and everything works fine. >>> >> Actually, that is not the case. Not even remotely. >> >> NOR flashes (and the m25p80 driver broadcasts it this way) have the ability >> to change individual bytes (and, some flashes, individual bits). The SPI >> flashes need to erase an entire block. NOR flashes are accessible via the >> data bus, these require complicated SPI transactions. They neither quack nor >> look anywhere near the same. >> > > you havent shown how the current behavior results in non-working > flashes. you probably can claim that things dont work as optimally as > possible according to the hardware, but as you noted, people work on > what interests/annoys them rather than what other people report. > ST M25P80 can change individual bytes. >> You might want to claim that they are NAND flashes, but, again, those are >> somewhat different. Dataflashes are the closest these come to, as far as I >> can tell. >> > > it doesnt make sense to lump SPI and NAND together because NAND allows > for bad blocks. both NOR and SPI are guaranteed to be good throughout > or the device is dead. so for all practical uses thus far, SPI and > NOR operate the same way. > Yes. >> I am not so sure about the "properties which other SPI flashes do not". Not, >> at least, according to my research (which does not beat experience, but does >> beat obscure abstract statements). >> > > iirc, dataflashes allow programming on individual bytes just like NOR > flashes. most serial flashes (like the ST micro that started the SPI > flash driver in the first place) have to be programmed on a page > basis. dataflashes also have more flexible erase structures (4kb, > 32kb, or 64kb) while ST micro can only be erased at 64kb sectors. > The ST M25P80 has a minimum write size of 1 bit (datasheet is a bit unclear, could also be 1 byte) and a maximum write size of 256 bytes. > my point is just that calling all SPI flashes "dataflashes" is > inherently wrong since only Atmel makes dataflashes. it's also a bit > funny since you started off the thread with the complaint that calling > SPI flashes NOR flashes was wrong because SPI flashes arent NOR > flashes. if you're going to declare a new category for SPI flashes, > then it should be something that applies to all the current SPI > flashes (just look in the m25p80.c driver to see all the ones > supported). > DataFlash is special because some of the chips have a user configurable page size: 512 or 528 Bytes per page. There's always the option of looking at how flashrom handles those chips. flashrom an OS-independent userspace tool specialized on chips which are used for BIOS/firmware, but it handles some other flash chips as well. Regards, Carl-Daniel -- http://www.hailfinger.org/ From anders.grafstrom at netinsight.net Mon May 17 13:26:53 2010 From: anders.grafstrom at netinsight.net (=?UTF-8?B?QW5kZXJzIEdyYWZzdHLDtm0=?=) Date: Mon, 17 May 2010 19:26:53 +0200 Subject: [PATCH] mtd: cfi_cmdset_0001: Fix max timeout for locking operations In-Reply-To: <1273792018.9999.268.camel@macbook.infradead.org> References: <4B8834FB.2070004@netinsight.net> <1273792018.9999.268.camel@macbook.infradead.org> Message-ID: <4BF17C5D.1020501@netinsight.net> On 2010-05-14 01:06, David Woodhouse wrote: > On Fri, 2010-02-26 at 21:54 +0100, Anders Grafstr?m wrote: >> The max timeout is currently too short for some flash chips. >> This patch increases it to 10 seconds. The typical timeout >> remains unchanged (the tick period, 1000000/HZ). >> >> Specification change #11 in '5 Volt Intel StrataFlash Memory Specification Update' >> (297848-15) specifies an increase of Clear Block Lock-Bit Time Max to 7 sec. >> This is contradicted by the table in Specification Change #8 which says .70 sec >> but a 10 sec timeout doesn't hurt so play it safe. >> >> Signed-off-by: Anders Grafstr?m >> --- >> drivers/mtd/chips/cfi_cmdset_0001.c | 2 +- >> 1 files changed, 1 insertions(+), 1 deletions(-) >> >> diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c >> index 9253043..83e4ae2 100644 >> --- a/drivers/mtd/chips/cfi_cmdset_0001.c >> +++ b/drivers/mtd/chips/cfi_cmdset_0001.c >> @@ -2077,7 +2077,7 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip >> */ >> udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; >> >> - ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100); >> + ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * HZ * 10); > > I don't see how this makes any sense. What is the _unit_ of the argument > you're changing? Is it ?s, is it ticks? You aren't just changing the > value here; you're actually changing the units. The dimensional analysis > doesn't make sense. > > AFAICT this really is supposed to be ?s, so multiplying by HZ has to be > wrong. Hm, I make it: udelay: 1000000 / HZ = (?s/s) / (ticks/s) = ?s/ticks udelay_max (before): udelay * 100 = (?s/ticks) * ticks = ?s udelay_max (after): udelay * HZ * 10 = (?s/ticks) * (ticks/s) * s = ?s Here's a re-spin, with less HZ involvement: From anders.grafstrom at netinsight.net Mon May 17 09:23:08 2010 From: anders.grafstrom at netinsight.net (Anders Grafström) Date: Mon, 17 May 2010 15:23:08 +0200 Subject: [PATCH] mtd: cfi_cmdset_0001: Fix timeout for locking operations Message-ID: The lock/unlock timeout is currently way too short for some flash chips. This patch increases it to 10 seconds. The typical delay remains unchanged. Specification change #11 in '5 Volt Intel StrataFlash Memory Specification Update' (297848-15) specifies an increase of Clear Block Lock-Bit Time Max to 7 sec. This is contradicted by the table in Specification Change #8 which says .70 sec but a 10 sec timeout doesn't hurt so play it safe. Signed-off-by: Anders Grafstr??m --- drivers/mtd/chips/cfi_cmdset_0001.c | 14 +++++++++----- 1 files changed, 9 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 62f3ea9..3a22f47 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -2045,7 +2045,8 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip { struct cfi_private *cfi = map->fldrv_priv; struct cfi_pri_intelext *extp = cfi->cmdset_priv; - int udelay; + unsigned int udelay = 0; + unsigned int udelay_max = 0; int ret; adr += chip->start; @@ -2071,12 +2072,15 @@ static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip BUG(); /* - * If Instant Individual Block Locking supported then no need - * to delay. + * If Instant Individual Block Locking is unsupported then use + * the tick period as the typical delay and 10 seconds for the timeout. */ - udelay = (!extp || !(extp->FeatureSupport & (1 << 5))) ? 1000000/HZ : 0; + if (!extp || !(extp->FeatureSupport & (1 << 5))) { + udelay = 1000000 / HZ; + udelay_max = 10000000; + } - ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay * 100); + ret = WAIT_TIMEOUT(map, chip, adr, udelay, udelay_max); if (ret) { map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; -- 1.7.1 From dwmw2 at infradead.org Mon May 17 14:55:28 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Mon, 17 May 2010 19:55:28 +0100 (BST) Subject: [PATCH -next] pcmciamtd: fix printk format warnings In-Reply-To: <20100517091632.59c2696c.randy.dunlap@oracle.com> References: <20100517163521.649526d0.sfr@canb.auug.org.au> <20100517091632.59c2696c.randy.dunlap@oracle.com> Message-ID: On Mon, 17 May 2010, Randy Dunlap wrote: > From: Randy Dunlap > > Fix printk format warnings in pcmciamtd debug code: > > drivers/mtd/maps/pcmciamtd.c:163: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' > drivers/mtd/maps/pcmciamtd.c:212: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' > drivers/mtd/maps/pcmciamtd.c:274: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' > drivers/mtd/maps/pcmciamtd.c:312: warning: format '%u' expects type 'unsigned int', but argument 5 has type 'ssize_t' I pushed something identical to that earlier today, but thanks. -- dwmw2 From r.schwebel at pengutronix.de Mon May 17 16:15:41 2010 From: r.schwebel at pengutronix.de (Robert Schwebel) Date: Mon, 17 May 2010 22:15:41 +0200 Subject: mxc-nand duplicate case value in -next In-Reply-To: <20100429080954.GI6204@pengutronix.de> References: <20100423073625.GY7882@pengutronix.de> <20100427075310.GM18567@pengutronix.de> <20100429080954.GI6204@pengutronix.de> Message-ID: <20100517201541.GE6055@pengutronix.de> Hi, On Thu, Apr 29, 2010 at 10:09:54AM +0200, Robert Schwebel wrote: > On Tue, Apr 27, 2010 at 09:53:10AM +0200, Robert Schwebel wrote: > > On Fri, Apr 23, 2010 at 09:36:25AM +0200, Sascha Hauer wrote: > > > Currently we have a duplicate case value in the mxc-nand driver in > > > -next. This is because of to different patches adding reset command > > > support to the driver, one from Eric (coming via the mtd master tree) > > > and one from Ivo (coming from the mxc master tree). As I see it we > > > should take Ivos patch as it adds i.MX21 support along the way, so > > > David, can you please drop Erics patch? > > > > linux-next does still crash with > > > > drivers/mtd/nand/mxc_nand.c: In function 'mxc_nand_command': > > drivers/mtd/nand/mxc_nand.c:689: error: duplicate case value > > drivers/mtd/nand/mxc_nand.c:606: error: previously used here > > drivers/mtd/nand/mxc_nand.c: In function 'mxcnd_resume': > > drivers/mtd/nand/mxc_nand.c:921: warning: unused variable 'host' > > make[3]: *** [drivers/mtd/nand/mxc_nand.o] Error 1 > > > > David, would dropping Eric's patch (like suggested by Sascha) be an > > acceptable solution? > > ping I just tested with next-20100517 and the duplicate case is still there. David, can we do something to resolve this? Sascha has suggested a solution above. Thanks, rsc -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | From jack at suse.cz Mon May 17 17:56:30 2010 From: jack at suse.cz (Jan Kara) Date: Mon, 17 May 2010 23:56:30 +0200 Subject: [PATCH v4] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1273799074.9999.653.camel@macbook.infradead.org> References: <1273074054-11849-1-git-send-email-kirill@shutemov.name> <1273799074.9999.653.camel@macbook.infradead.org> Message-ID: <20100517215630.GF3364@quack.suse.cz> On Fri 14-05-10 02:04:34, David Woodhouse wrote: > On Wed, 2010-05-05 at 18:40 +0300, Kirill A. Shutemov wrote: > > We cannot modify file->f_mapping->backing_dev_info, because it will corrupt > > backing device of device node inode, since file->f_mapping is equal to > > inode->i_mapping (see __dentry_open() in fs/open.c). > > > > Let's introduce separate inode for MTD device with appropriate backing > > device. > > I hate the fact that we have to do this -- is it really the only option? > > Is it _just_ for the backing_device_info? Can't that be done > differently? Well, if I understand the problem MTD tries to solve, what you really need is that file->f_mapping->backing_dev_info points to your structure so that you can specify the capability of backing device to support mmap and whatever else. What I'm not sure about is, why you cannot have this backing_dev_info directly in the original device inode but since this is the problem you are originally trying to solve, I guess you have some good reason for that. So with this requirement, you have to at least setup complete struct address_space to which f_mapping can point. This address_space has to be linked (via mapping->host) to some inode. So you could point i_mapping to your address_space structure if that would work for you. But this only has a reasonable chance to work if you would somehow tie the lifetime of your address_space with the lifetime of your device inode (code in block_dev.c does something like this because all inodes which represent the same block block device share one address_space). Moreover you would have to do all the address_space initialization inode_init_always does (or probably split out the mapping initialization from inode_init_always and call it from MTD code). So I'm not sure it's really better. When you decide you don't want to take care about proper setup of address_space and refcounting and whatever, you have to create a full inode. But this inode has to live in some filesystem -> what Kirill did is unavoidable in this case... Honza -- Jan Kara SUSE Labs, CR From stanley.miao at windriver.com Mon May 17 22:17:14 2010 From: stanley.miao at windriver.com (stanley.miao) Date: Tue, 18 May 2010 10:17:14 +0800 Subject: who is the maintainer of mtd-utils ? Message-ID: <4BF1F8AA.20809@windriver.com> who is the maintainer of mtd-utils ? Thanks. Stanley. From vapier.adi at gmail.com Tue May 18 00:52:12 2010 From: vapier.adi at gmail.com (Mike Frysinger) Date: Tue, 18 May 2010 00:52:12 -0400 Subject: who is the maintainer of mtd-utils ? In-Reply-To: <4BF1F8AA.20809@windriver.com> References: <4BF1F8AA.20809@windriver.com> Message-ID: On Mon, May 17, 2010 at 22:17, stanley.miao wrote: > who is the maintainer of mtd-utils ? just post patches to this list -mike From shachar at shemesh.biz Tue May 18 02:37:34 2010 From: shachar at shemesh.biz (Shachar Shemesh) Date: Tue, 18 May 2010 09:37:34 +0300 Subject: Wrong flash type in m25p80 driver In-Reply-To: <4BF173E5.2030304@gmx.net> References: <4BF011D7.4010907@shemesh.biz> <4BF041A3.70304@shemesh.biz> <4BF04DBE.5020309@shemesh.biz> <4BF173E5.2030304@gmx.net> Message-ID: <4BF235AE.3030903@shemesh.biz> I should point out that I have sent a retraction to the patch, but my messages got held up for moderation with "suspicious header" and no further explanation. I'm taking a wild guess as to the reason, in the hope that this message does get through. If it does, holding messages with "list does not support HTML or mixed format mail" will be a more useful error report. Carl-Daniel Hailfinger wrote: > > > > The ST M25P80 has a minimum write size of 1 bit (datasheet is a bit > unclear, could also be 1 byte) and a maximum write size of 256 bytes. > > I have not studies the M25P80 data sheet, but did the M25P32 and the MX25L6405D chips, and I believe all SPI flahses handled by the m25p80 driver behave the same in that regard (which is why they were clamped together to begin with). The minimal "program" length is 1 byte, but since a program can only change a 1 bit into 0, effectively, setting a word to "11...101...11", where the zero is at the bit you want to set, will program 1 bit. > > There's always the option of looking at how flashrom > handles those chips. flashrom an > OS-independent userspace tool specialized on chips which are used for > BIOS/firmware, but it handles some other flash chips as well. > It lists them as "SPI", and the chip support page claims, at least for most of them, that it does not know how to erase them (http://www.flashrom.org/Supported_hardware). Shachar -- Shachar Shemesh Lingnu Open Source Consulting Ltd. http://www.lingnu.com From eballetbo at gmail.com Tue May 18 05:53:59 2010 From: eballetbo at gmail.com (Enric Balletbo i Serra) Date: Tue, 18 May 2010 11:53:59 +0200 Subject: [PATCH] mtd-utils: Support 4096+64 page sizes. Message-ID: <1274176439-22351-1-git-send-email-eballetbo@gmail.com> From: Enric Balletbo i Serra Add support for oobsize 64 and writesize 4096 in nanddump & nandwrite. Signed-off-by: Enric Balletbo i Serra --- nanddump.c | 1 + nandwrite.c | 1 + 2 files changed, 2 insertions(+), 0 deletions(-) diff --git a/nanddump.c b/nanddump.c index ae0e425..e44ab36 100644 --- a/nanddump.c +++ b/nanddump.c @@ -212,6 +212,7 @@ int main(int argc, char * const argv[]) if (!(meminfo.oobsize == 224 && meminfo.writesize == 4096) && !(meminfo.oobsize == 218 && meminfo.writesize == 4096) && !(meminfo.oobsize == 128 && meminfo.writesize == 4096) && + !(meminfo.oobsize == 64 && meminfo.writesize == 4096) && !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && !(meminfo.oobsize == 32 && meminfo.writesize == 1024) && !(meminfo.oobsize == 16 && meminfo.writesize == 512) && diff --git a/nandwrite.c b/nandwrite.c index b77edd6..bd45879 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -294,6 +294,7 @@ int main(int argc, char * const argv[]) if (!(meminfo.oobsize == 16 && meminfo.writesize == 512) && !(meminfo.oobsize == 8 && meminfo.writesize == 256) && !(meminfo.oobsize == 64 && meminfo.writesize == 2048) && + !(meminfo.oobsize == 64 && meminfo.writesize == 4096) && !(meminfo.oobsize == 128 && meminfo.writesize == 4096)) { fprintf(stderr, "Unknown flash (not normal NAND)\n"); close(fd); -- 1.7.0.4 From s-ghorai at ti.com Tue May 18 07:16:26 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Tue, 18 May 2010 16:46:26 +0530 Subject: [PATCH v3 0/3] omap3 nand: cleanup exiting platform related code In-Reply-To: References: Message-ID: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> The following set of patches applies on top of for-next branch. http://git.kernel.org/?p=linux/kernel/git/tmlind/linux-omap-2.6.git Patches verified on: omap3430-SDP, omap3630-sdp, zoom3 and beagle board And these are the patches required to address the following input - 1. The NAND driver needs to stop tinkering with the GPMC registers The omap General Purpose Memory Controller (GPMC) registers are omap specific, and not driver specific. Tinkering with these registers can cause issues with the other devices on the GPMC. 2. Passing hardcoded GPMC_CS0_BASE needs to go from the board files Passing hardcoded GPMC virtual addressess is sure way to mess up things. This should all become unnecessary once the NAND drivers stops messing with the GPMC registers directly. v2: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28467.html Few functionality was missing like - There should be some locking as only one chipselect can use the ECC or prefetch engine at a time. If you have NAND in two chipselects, bad things would happen. v1: http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28164.html Additionally, it was needed to implement more functions for the platform init code to use. Sukumar Ghorai (3): omap3 gpmc: functionality enhancement omap3 nand: cleanup virtual address usages omap3 nand: fix issue in board file to detect nand arch/arm/mach-omap2/board-cm-t35.c | 20 +--- arch/arm/mach-omap2/board-devkit8000.c | 25 +--- arch/arm/mach-omap2/board-omap3beagle.c | 24 +--- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +--- arch/arm/mach-omap2/board-overo.c | 24 +--- arch/arm/mach-omap2/gpmc-nand.c | 39 ++---- arch/arm/mach-omap2/gpmc.c | 9 - arch/arm/plat-omap/include/plat/gpmc.h | 7 +- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 242 +++++++++------------------- 10 files changed, 93 insertions(+), 328 deletions(-) From s-ghorai at ti.com Tue May 18 07:16:27 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Tue, 18 May 2010 16:46:27 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> Message-ID: <1274181389-7488-2-git-send-email-s-ghorai@ti.com> few functions added in gpmc module and to be used by other drivers like NAND. E.g.: - ioctl function - ecc functions Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++- arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++- drivers/mtd/nand/omap2.c | 4 +- 3 files changed, 274 insertions(+), 11 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index 5bc3ca0..7e6d821 --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -46,8 +46,9 @@ #define GPMC_ECC_CONFIG 0x1f4 #define GPMC_ECC_CONTROL 0x1f8 #define GPMC_ECC_SIZE_CONFIG 0x1fc +#define GPMC_ECC1_RESULT 0x200 -#define GPMC_CS0 0x60 +#define GPMC_CS0_BASE 0x60 #define GPMC_CS_SIZE 0x30 #define GPMC_MEM_START 0x00000000 @@ -92,7 +93,9 @@ struct omap3_gpmc_regs { static struct resource gpmc_mem_root; static struct resource gpmc_cs_mem[GPMC_CS_NUM]; static DEFINE_SPINLOCK(gpmc_mem_lock); -static unsigned gpmc_cs_map; +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ static void __iomem *gpmc_base; @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx) return __raw_readl(gpmc_base + idx); } +static void gpmc_cs_write_byte(int cs, int idx, u8 val) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; + __raw_writeb(val, reg_addr); +} + +static u8 gpmc_cs_read_byte(int cs, int idx) +{ + void __iomem *reg_addr; + + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; + return __raw_readb(reg_addr); +} + void gpmc_cs_write_reg(int cs, int idx, u32 val) { void __iomem *reg_addr; - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; __raw_writel(val, reg_addr); } @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) { void __iomem *reg_addr; - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; return __raw_readl(reg_addr); } @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs) EXPORT_SYMBOL(gpmc_cs_free); /** + * gpmc_hwcontrol - hardware specific access (read/ write) control + * @cs: chip select number + * @cmd: command type + * @write: 1 for write; 0 for read + * @wval: value to write + * @rval: read pointer + */ +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval) +{ + u32 regval = 0; + + if (!write && !rval) + return -EINVAL; + + switch (cmd) { + case GPMC_STATUS_BUFFER: + regval = gpmc_read_reg(GPMC_STATUS); + /* 1 : buffer is available to write */ + *rval = regval & GPMC_STATUS_BUFF_EMPTY; + break; + + case GPMC_GET_SET_IRQ_STATUS: + if (write) + gpmc_write_reg(GPMC_IRQSTATUS, wval); + else + *rval = gpmc_read_reg(GPMC_IRQSTATUS); + break; + + case GPMC_PREFETCH_FIFO_CNT: + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); + break; + + case GPMC_PREFETCH_COUNT: + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); + *rval = GPMC_PREFETCH_STATUS_COUNT(regval); + break; + + case GPMC_CONFIG_WP: + regval = gpmc_read_reg(GPMC_CONFIG); + if (wval) + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ + else + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */ + gpmc_write_reg(GPMC_CONFIG, regval); + break; + + case GPMC_CONFIG_RDY_BSY: + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + regval |= WR_RD_PIN_MONITORING; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); + break; + + case GPMC_CONFIG_DEV_SIZE: + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + regval |= GPMC_CONFIG1_DEVICESIZE(wval); + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); + break; + + case GPMC_CONFIG_DEV_TYPE: + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); + regval |= GPMC_CONFIG1_DEVICETYPE(wval); + if (wval == GPMC_DEVICETYPE_NOR) + regval |= GPMC_CONFIG1_MUXADDDATA; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); + break; + + case GPMC_NAND_COMMAND: + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); + break; + + case GPMC_NAND_ADDRESS: + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); + break; + + case GPMC_NAND_DATA: + if (write) + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); + else + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); + break; + + default: + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n"); + return -EINVAL; + } + + return 0; +} +EXPORT_SYMBOL(gpmc_hwcontrol); + +/** * gpmc_prefetch_enable - configures and starts prefetch transfer - * @cs: nand cs (chip select) number + * @cs: cs (chip select) number * @dma_mode: dma mode enable (1) or disable (0) * @u32_count: number of bytes to be transferred * @is_write: prefetch read(0) or write post(1) mode @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode, { uint32_t prefetch_config1; + if (gpmc_pref_used == -EINVAL) + gpmc_pref_used = cs; + else + return -EBUSY; + if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { /* Set the amount of bytes to be prefetched */ gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); /** * gpmc_prefetch_reset - disables and stops the prefetch engine */ -void gpmc_prefetch_reset(void) +int gpmc_prefetch_reset(int cs) { + if (gpmc_pref_used == cs) + gpmc_pref_used = -EINVAL; + else + return -EINVAL; + /* Stop the PFPW engine */ gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); /* Reset/disable the PFPW engine */ gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); + + return 0; } EXPORT_SYMBOL(gpmc_prefetch_reset); @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void) } } #endif /* CONFIG_ARCH_OMAP3 */ + +/** + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller + * @cs: chip select number + * @ecc_size: number of bytes for ecc generation + */ + +int gpmc_ecc_init(int cs, int ecc_size) +{ + unsigned int val = 0x0; + + /* check if ecc engine already by another cs */ + if (gpmc_ecc_used == -EINVAL) + gpmc_ecc_used = cs; + else + return -EBUSY; + + /* read ecc control register */ + val = gpmc_read_reg(GPMC_ECC_CONTROL); + + /* clear ecc and enable bits */ + val = ((0x00000001<<8) | 0x00000001); + gpmc_write_reg(GPMC_ECC_CONTROL, val); + + /* Read from ECC Size Config Register */ + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); + + /* program ecc and result sizes */ + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); + + return 0; +} + +/** + * gpmc_calculate_ecc - generate non-inverted ecc bytes + * @cs: chip select number + * @dat: data pointer over which ecc is computed + * @ecc_code: ecc code buffer + * + * Using non-inverted ECC is considered ugly since writing a blank + * page (padding) will clear the ECC bytes. This is not a problem as long + * no one is trying to write data on the seemingly unused page. Reading + * an erased page will produce an ECC mismatch between generated and read + * ECC bytes that has to be dealt with separately. + */ +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) +{ + unsigned int val = 0x0; + + if (gpmc_ecc_used != cs) + return -EINVAL; + + /* read ecc result */ + val = gpmc_read_reg(GPMC_ECC1_RESULT); + *ecc_code++ = val; /* P128e, ..., P1e */ + *ecc_code++ = val >> 16; /* P128o, ..., P1o */ + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); + + return 0; +} + +/** + * gpmc_enable_hwecc - enable hardware ecc functionality + * @cs: chip select number + * @mode: read/write mode + * @dev_width: device bus width(1 for x16, 0 for x8) + */ +int gpmc_enable_hwecc(int cs, int mode, int dev_width) +{ + unsigned int val; + + if (gpmc_ecc_used != cs) + return -EINVAL; + + switch (mode) { + case GPMC_ECC_READ: + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); + break; + case GPMC_ECC_READSYN: + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); + break; + case GPMC_ECC_WRITE: + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); + break; + default: + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); + break; + } + + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ + val = (dev_width << 7) | (cs << 1) | (0x1); + gpmc_write_reg(GPMC_ECC_CONFIG, val); + return 0; +} + +/** + * gmpc_ecc_reset - release the HW ECC in GPMC controller + * @cs: Chip select number + */ +int gpmc_ecc_reset(int cs) +{ + if (gpmc_ecc_used == cs) + gpmc_ecc_used = -EINVAL; + else + return -EINVAL; + + return 0; +} + diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 145838a..67a3442 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -27,8 +27,24 @@ #define GPMC_CONFIG 0x50 #define GPMC_STATUS 0x54 -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 + +/* Control Commands */ +#define GPMC_CONFIG_WP 0x00000001 +#define GPMC_CONFIG_RDY_BSY 0x00000002 +#define GPMC_CONFIG_DEV_SIZE 0x00000003 +#define GPMC_CONFIG_DEV_TYPE 0x00000004 +#define GPMC_NAND_COMMAND 0x00000005 +#define GPMC_NAND_ADDRESS 0x00000006 +#define GPMC_NAND_DATA 0x00000007 +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */ +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */ +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/ +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B + +/* ECC commands */ +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) @@ -56,6 +72,14 @@ #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) #define GPMC_CONFIG7_CSVALID (1 << 6) +#define GPMC_DEVICETYPE_NOR 0 +#define GPMC_DEVICETYPE_NAND 2 +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 +#define GPMC_STATUS_BUFF_EMPTY 0x00000001 +#define WR_RD_PIN_MONITORING 0x00600000 +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24) +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) + /* * Note that all values in this struct are in nanoseconds, while * the register values are in gpmc_fck cycles. @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved); extern int gpmc_cs_reserved(int cs); extern int gpmc_prefetch_enable(int cs, int dma_mode, unsigned int u32_count, int is_write); -extern void gpmc_prefetch_reset(void); +extern int gpmc_prefetch_reset(int cs); extern int gpmc_prefetch_status(void); extern void omap3_gpmc_save_context(void); extern void omap3_gpmc_restore_context(void); extern void gpmc_init(void); +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval); +int gpmc_ecc_init(int cs, int ecc_size); +int gpmc_enable_hwecc(int cs, int mode, int dev_width); +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); +int gpmc_ecc_reset(int cs); #endif diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 7545568..206406b --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) } while (len); /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(); + gpmc_prefetch_reset(info->gpmc_cs); } } @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, } /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(); + gpmc_prefetch_reset(info->gpmc_cs); } } From s-ghorai at ti.com Tue May 18 07:16:28 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Tue, 18 May 2010 16:46:28 +0530 Subject: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages In-Reply-To: <1274181389-7488-2-git-send-email-s-ghorai@ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> Message-ID: <1274181389-7488-3-git-send-email-s-ghorai@ti.com> This patch removes direct reference of gpmc address from generic nand platform code. Nand platform code now uses wrapper functions which are implemented in gpmc module. Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/gpmc-nand.c | 39 ++---- arch/arm/mach-omap2/gpmc.c | 9 -- arch/arm/plat-omap/include/plat/gpmc.h | 7 +- arch/arm/plat-omap/include/plat/nand.h | 6 +- drivers/mtd/nand/omap2.c | 242 ++++++++++---------------------- 5 files changed, 88 insertions(+), 215 deletions(-) diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c index e57fb29..80f5d94 --- a/arch/arm/mach-omap2/gpmc-nand.c +++ b/arch/arm/mach-omap2/gpmc-nand.c @@ -19,8 +19,6 @@ #include #include -#define WR_RD_PIN_MONITORING 0x00600000 - static struct omap_nand_platform_data *gpmc_nand_data; static struct resource gpmc_nand_resource = { @@ -71,10 +69,10 @@ static int omap2_nand_gpmc_retime(void) t.wr_cycle = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle); /* Configure GPMC */ - gpmc_cs_write_reg(gpmc_nand_data->cs, GPMC_CS_CONFIG1, - GPMC_CONFIG1_DEVICESIZE(gpmc_nand_data->devsize) | - GPMC_CONFIG1_DEVICETYPE_NAND); - + gpmc_hwcontrol(gpmc_nand_data->cs, + GPMC_CONFIG_DEV_SIZE, 1, gpmc_nand_data->devsize, NULL); + gpmc_hwcontrol(gpmc_nand_data->cs, + GPMC_CONFIG_DEV_TYPE, 1, GPMC_DEVICETYPE_NAND, NULL); err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t); if (err) return err; @@ -82,27 +80,13 @@ static int omap2_nand_gpmc_retime(void) return 0; } -static int gpmc_nand_setup(void) -{ - struct device *dev = &gpmc_nand_device.dev; - - /* Set timings in GPMC */ - if (omap2_nand_gpmc_retime() < 0) { - dev_err(dev, "Unable to set gpmc timings\n"); - return -EINVAL; - } - - return 0; -} - int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data) { - unsigned int val; int err = 0; struct device *dev = &gpmc_nand_device.dev; gpmc_nand_data = _nand_data; - gpmc_nand_data->nand_setup = gpmc_nand_setup; + gpmc_nand_data->nand_setup = omap2_nand_gpmc_retime; gpmc_nand_device.dev.platform_data = gpmc_nand_data; err = gpmc_cs_request(gpmc_nand_data->cs, NAND_IO_SIZE, @@ -112,19 +96,17 @@ int __init gpmc_nand_init(struct omap_nand_platform_data *_nand_data) return err; } - err = gpmc_nand_setup(); + /* Set timings in GPMC */ + err = omap2_nand_gpmc_retime(); if (err < 0) { - dev_err(dev, "NAND platform setup failed: %d\n", err); + dev_err(dev, "Unable to set gpmc timings: %d\n", err); return err; } /* Enable RD PIN Monitoring Reg */ if (gpmc_nand_data->dev_ready) { - val = gpmc_cs_read_reg(gpmc_nand_data->cs, - GPMC_CS_CONFIG1); - val |= WR_RD_PIN_MONITORING; - gpmc_cs_write_reg(gpmc_nand_data->cs, - GPMC_CS_CONFIG1, val); + gpmc_hwcontrol(gpmc_nand_data->cs, + GPMC_CONFIG_RDY_BSY, 1, 1, NULL); } err = platform_device_register(&gpmc_nand_device); @@ -140,3 +122,4 @@ out_free_cs: return err; } + diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c index f414aeb..cbe0efb --- a/arch/arm/mach-omap2/gpmc.c +++ b/arch/arm/mach-omap2/gpmc.c @@ -589,15 +589,6 @@ int gpmc_prefetch_reset(int cs) } EXPORT_SYMBOL(gpmc_prefetch_reset); -/** - * gpmc_prefetch_status - reads prefetch status of engine - */ -int gpmc_prefetch_status(void) -{ - return gpmc_read_reg(GPMC_PREFETCH_STATUS); -} -EXPORT_SYMBOL(gpmc_prefetch_status); - static void __init gpmc_mem_init(void) { int cs; diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 67a3442..2386ff6 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -25,9 +25,6 @@ #define GPMC_CS_NAND_ADDRESS 0x20 #define GPMC_CS_NAND_DATA 0x24 -#define GPMC_CONFIG 0x50 -#define GPMC_STATUS 0x54 - /* Control Commands */ #define GPMC_CONFIG_WP 0x00000001 #define GPMC_CONFIG_RDY_BSY 0x00000002 @@ -63,7 +60,6 @@ #define GPMC_CONFIG1_DEVICESIZE_16 GPMC_CONFIG1_DEVICESIZE(1) #define GPMC_CONFIG1_DEVICETYPE(val) ((val & 3) << 10) #define GPMC_CONFIG1_DEVICETYPE_NOR GPMC_CONFIG1_DEVICETYPE(0) -#define GPMC_CONFIG1_DEVICETYPE_NAND GPMC_CONFIG1_DEVICETYPE(2) #define GPMC_CONFIG1_MUXADDDATA (1 << 9) #define GPMC_CONFIG1_TIME_PARA_GRAN (1 << 4) #define GPMC_CONFIG1_FCLK_DIV(val) (val & 3) @@ -77,7 +73,7 @@ #define GPMC_CONFIG_WRITEPROTECT 0x00000010 #define GPMC_STATUS_BUFF_EMPTY 0x00000001 #define WR_RD_PIN_MONITORING 0x00600000 -#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24) +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val >> 24) & 0x7F) #define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) /* @@ -133,7 +129,6 @@ extern int gpmc_cs_reserved(int cs); extern int gpmc_prefetch_enable(int cs, int dma_mode, unsigned int u32_count, int is_write); extern int gpmc_prefetch_reset(int cs); -extern int gpmc_prefetch_status(void); extern void omap3_gpmc_save_context(void); extern void omap3_gpmc_restore_context(void); extern void gpmc_init(void); diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h index f8efd54..6562cd0 --- a/arch/arm/plat-omap/include/plat/nand.h +++ b/arch/arm/plat-omap/include/plat/nand.h @@ -21,13 +21,11 @@ struct omap_nand_platform_data { int (*dev_ready)(struct omap_nand_platform_data *); int dma_channel; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; int devsize; }; -/* size (4 KiB) for IO mapping */ -#define NAND_IO_SIZE SZ_4K +/* minimum size for IO mapping */ +#define NAND_IO_SIZE 4 #if defined(CONFIG_MTD_NAND_OMAP2) || defined(CONFIG_MTD_NAND_OMAP2_MODULE) extern int gpmc_nand_init(struct omap_nand_platform_data *d); diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c index 206406b..e2302a7 --- a/drivers/mtd/nand/omap2.c +++ b/drivers/mtd/nand/omap2.c @@ -23,20 +23,8 @@ #include #include -#define GPMC_IRQ_STATUS 0x18 -#define GPMC_ECC_CONFIG 0x1F4 -#define GPMC_ECC_CONTROL 0x1F8 -#define GPMC_ECC_SIZE_CONFIG 0x1FC -#define GPMC_ECC1_RESULT 0x200 - #define DRIVER_NAME "omap2-nand" -#define NAND_WP_OFF 0 -#define NAND_WP_BIT 0x00000010 - -#define GPMC_BUF_FULL 0x00000001 -#define GPMC_BUF_EMPTY 0x00000000 - #define NAND_Ecc_P1e (1 << 0) #define NAND_Ecc_P2e (1 << 1) #define NAND_Ecc_P4e (1 << 2) @@ -139,34 +127,11 @@ struct omap_nand_info { int gpmc_cs; unsigned long phys_base; - void __iomem *gpmc_cs_baseaddr; - void __iomem *gpmc_baseaddr; - void __iomem *nand_pref_fifo_add; struct completion comp; int dma_ch; }; /** - * omap_nand_wp - This function enable or disable the Write Protect feature - * @mtd: MTD device structure - * @mode: WP ON/OFF - */ -static void omap_nand_wp(struct mtd_info *mtd, int mode) -{ - struct omap_nand_info *info = container_of(mtd, - struct omap_nand_info, mtd); - - unsigned long config = __raw_readl(info->gpmc_baseaddr + GPMC_CONFIG); - - if (mode) - config &= ~(NAND_WP_BIT); /* WP is ON */ - else - config |= (NAND_WP_BIT); /* WP is OFF */ - - __raw_writel(config, (info->gpmc_baseaddr + GPMC_CONFIG)); -} - -/** * omap_hwcontrol - hardware specific access to control-lines * @mtd: MTD device structure * @cmd: command to device @@ -181,31 +146,20 @@ static void omap_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - switch (ctrl) { - case NAND_CTRL_CHANGE | NAND_CTRL_CLE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_COMMAND; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - - case NAND_CTRL_CHANGE | NAND_CTRL_ALE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_ADDRESS; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - - case NAND_CTRL_CHANGE | NAND_NCE: - info->nand.IO_ADDR_W = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - info->nand.IO_ADDR_R = info->gpmc_cs_baseaddr + - GPMC_CS_NAND_DATA; - break; - } - if (cmd != NAND_CMD_NONE) - __raw_writeb(cmd, info->nand.IO_ADDR_W); + if (cmd != NAND_CMD_NONE) { + if (ctrl & NAND_CLE) + gpmc_hwcontrol(info->gpmc_cs, + GPMC_NAND_COMMAND, 1, cmd, NULL); + + else if (ctrl & NAND_ALE) + gpmc_hwcontrol(info->gpmc_cs, + GPMC_NAND_ADDRESS, 1, cmd, NULL); + + else /* NAND_NCE */ + gpmc_hwcontrol(info->gpmc_cs, + GPMC_NAND_DATA, 1, cmd, NULL); + } } /** @@ -232,11 +186,15 @@ static void omap_write_buf8(struct mtd_info *mtd, const u_char *buf, int len) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); u_char *p = (u_char *)buf; + u32 status = 0; while (len--) { iowrite8(*p++, info->nand.IO_ADDR_W); - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + - GPMC_STATUS) & GPMC_BUF_FULL)); + /* wait until buffer is available for write */ + do { + gpmc_hwcontrol(info->gpmc_cs, + GPMC_STATUS_BUFFER, 0, 0, &status); + } while (!status); } } @@ -264,16 +222,17 @@ static void omap_write_buf16(struct mtd_info *mtd, const u_char * buf, int len) struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); u16 *p = (u16 *) buf; - + u32 status = 0; /* FIXME try bursts of writesw() or DMA ... */ len >>= 1; while (len--) { iowrite16(*p++, info->nand.IO_ADDR_W); - - while (GPMC_BUF_EMPTY == (readl(info->gpmc_baseaddr + - GPMC_STATUS) & GPMC_BUF_FULL)) - ; + /* wait until buffer is available for write */ + do { + gpmc_hwcontrol(info->gpmc_cs, + GPMC_STATUS_BUFFER, 0, 0, &status); + } while (!status); } } @@ -287,16 +246,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - uint32_t pfpw_status = 0, r_count = 0; + u32 r_count = 0; int ret = 0; - u32 *p = (u32 *)buf; + u32 *p; /* take care of subpage reads */ for (; len % 4 != 0; ) { *buf++ = __raw_readb(info->nand.IO_ADDR_R); len--; } - p = (u32 *) buf; /* configure and start prefetch transfer */ ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0); @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) else omap_read_buf8(mtd, buf, len); } else { + p = (u32 *) buf; do { - pfpw_status = gpmc_prefetch_status(); - r_count = ((pfpw_status >> 24) & 0x7F) >> 2; - ioread32_rep(info->nand_pref_fifo_add, p, r_count); + gpmc_hwcontrol(info->gpmc_cs, + GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count); + r_count = r_count >> 2; + ioread32_rep(info->nand.IO_ADDR_R, p, r_count); p += r_count; - len -= r_count << 2; + len -= (r_count << 2); } while (len); - - /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(info->gpmc_cs); } + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); } /** @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - uint32_t pfpw_status = 0, w_count = 0; + uint32_t pref_count = 0, w_count = 0; int i = 0, ret = 0; - u16 *p = (u16 *) buf; + u16 *p; /* take care of subpage writes */ if (len % 2 != 0) { - writeb(*buf, info->nand.IO_ADDR_R); + writeb(*buf, info->nand.IO_ADDR_W); p = (u16 *)(buf + 1); len--; } @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info *mtd, else omap_write_buf8(mtd, buf, len); } else { - pfpw_status = gpmc_prefetch_status(); - while (pfpw_status & 0x3FFF) { - w_count = ((pfpw_status >> 24) & 0x7F) >> 1; + p = (u16 *) buf; + while (len) { + gpmc_hwcontrol(info->gpmc_cs, + GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count); + w_count = w_count >> 1; for (i = 0; (i < w_count) && len; i++, len -= 2) - iowrite16(*p++, info->nand_pref_fifo_add); - pfpw_status = gpmc_prefetch_status(); + iowrite16(*p++, info->nand.IO_ADDR_W); } - - /* disable and stop the PFPW engine */ - gpmc_prefetch_reset(info->gpmc_cs); + /* wait for data to flushed-out before reset the prefetch */ + do { + gpmc_hwcontrol(info->gpmc_cs, + GPMC_PREFETCH_COUNT, 0, 0, &pref_count); + } while (pref_count); } + /* disable and stop the PFPW engine */ + gpmc_prefetch_reset(info->gpmc_cs); } #ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, /* setup and start DMA using dma_addr */ wait_for_completion(&info->comp); - while (0x3fff & (prefetch_status = gpmc_prefetch_status())) - ; + do { + gpmc_hwcontrol(info->gpmc_cs, + GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status); + } while (prefetch_status); /* disable and stop the PFPW engine */ gpmc_prefetch_reset(); @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd, omap_write_buf_pref(mtd, buf, len); else /* start transfer in DMA mode */ - omap_nand_dma_transfer(mtd, buf, len, 0x1); + omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); } /** @@ -528,30 +494,6 @@ static int omap_verify_buf(struct mtd_info *mtd, const u_char * buf, int len) #ifdef CONFIG_MTD_NAND_OMAP_HWECC /** - * omap_hwecc_init - Initialize the HW ECC for NAND flash in GPMC controller - * @mtd: MTD device structure - */ -static void omap_hwecc_init(struct mtd_info *mtd) -{ - struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, - mtd); - struct nand_chip *chip = mtd->priv; - unsigned long val = 0x0; - - /* Read from ECC Control Register */ - val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* Clear all ECC | Enable Reg1 */ - val = ((0x00000001<<8) | 0x00000001); - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - - /* Read from ECC Size Config Register */ - val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); - /* ECCSIZE1=512 | Select eccResultsize[0-3] */ - val = ((((chip->ecc.size >> 1) - 1) << 22) | (0x0000000F)); - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_SIZE_CONFIG); -} - -/** * gen_true_ecc - This function will generate true ECC value * @ecc_buf: buffer to store ecc code * @@ -752,19 +694,7 @@ static int omap_calculate_ecc(struct mtd_info *mtd, const u_char *dat, { struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - unsigned long val = 0x0; - unsigned long reg; - - /* Start Reading from HW ECC1_Result = 0x200 */ - reg = (unsigned long)(info->gpmc_baseaddr + GPMC_ECC1_RESULT); - val = __raw_readl(reg); - *ecc_code++ = val; /* P128e, ..., P1e */ - *ecc_code++ = val >> 16; /* P128o, ..., P1o */ - /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ - *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); - reg += 4; - - return 0; + return gpmc_calculate_ecc(info->gpmc_cs, dat, ecc_code); } /** @@ -778,32 +708,10 @@ static void omap_enable_hwecc(struct mtd_info *mtd, int mode) mtd); struct nand_chip *chip = mtd->priv; unsigned int dev_width = (chip->options & NAND_BUSWIDTH_16) ? 1 : 0; - unsigned long val = __raw_readl(info->gpmc_baseaddr + GPMC_ECC_CONFIG); - - switch (mode) { - case NAND_ECC_READ: - __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); - break; - case NAND_ECC_READSYN: - __raw_writel(0x100, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); - break; - case NAND_ECC_WRITE: - __raw_writel(0x101, info->gpmc_baseaddr + GPMC_ECC_CONTROL); - /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ - val = (dev_width << 7) | (info->gpmc_cs << 1) | (0x1); - break; - default: - DEBUG(MTD_DEBUG_LEVEL0, "Error: Unrecognized Mode[%d]!\n", - mode); - break; - } - __raw_writel(val, info->gpmc_baseaddr + GPMC_ECC_CONFIG); + gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width); } + #endif /** @@ -831,14 +739,10 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) else timeo += (HZ * 20) / 1000; - this->IO_ADDR_W = (void *) info->gpmc_cs_baseaddr + - GPMC_CS_NAND_COMMAND; - this->IO_ADDR_R = (void *) info->gpmc_cs_baseaddr + GPMC_CS_NAND_DATA; - - __raw_writeb(NAND_CMD_STATUS & 0xFF, this->IO_ADDR_W); - + gpmc_hwcontrol(info->gpmc_cs, + GPMC_NAND_COMMAND, 1, (NAND_CMD_STATUS & 0xFF), NULL); while (time_before(jiffies, timeo)) { - status = __raw_readb(this->IO_ADDR_R); + gpmc_hwcontrol(info->gpmc_cs, GPMC_NAND_DATA, 0, 0, &status); if (status & NAND_STATUS_READY) break; cond_resched(); @@ -852,22 +756,24 @@ static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip) */ static int omap_dev_ready(struct mtd_info *mtd) { + unsigned int val = 0; struct omap_nand_info *info = container_of(mtd, struct omap_nand_info, mtd); - unsigned int val = __raw_readl(info->gpmc_baseaddr + GPMC_IRQ_STATUS); + gpmc_hwcontrol(info->gpmc_cs, GPMC_GET_SET_IRQ_STATUS, 0, 0, &val); if ((val & 0x100) == 0x100) { /* Clear IRQ Interrupt */ val |= 0x100; val &= ~(0x0); - __raw_writel(val, info->gpmc_baseaddr + GPMC_IRQ_STATUS); + gpmc_hwcontrol(info->gpmc_cs, + GPMC_GET_SET_IRQ_STATUS, 1, val, NULL); } else { unsigned int cnt = 0; while (cnt++ < 0x1FF) { if ((val & 0x100) == 0x100) return 0; - val = __raw_readl(info->gpmc_baseaddr + - GPMC_IRQ_STATUS); + gpmc_hwcontrol(info->gpmc_cs, + GPMC_GET_SET_IRQ_STATUS, 0, 0, &val); } } @@ -898,8 +804,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->pdev = pdev; info->gpmc_cs = pdata->cs; - info->gpmc_baseaddr = pdata->gpmc_baseaddr; - info->gpmc_cs_baseaddr = pdata->gpmc_cs_baseaddr; info->phys_base = pdata->phys_base; info->mtd.priv = &info->nand; @@ -910,7 +814,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.options |= NAND_SKIP_BBTSCAN; /* NAND write protect off */ - omap_nand_wp(&info->mtd, NAND_WP_OFF); + gpmc_hwcontrol(info->gpmc_cs, GPMC_CONFIG_WP, 1, 0, NULL); if (!request_mem_region(info->phys_base, NAND_IO_SIZE, pdev->dev.driver->name)) { @@ -946,7 +850,6 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) if (use_prefetch) { /* copy the virtual address of nand base for fifo access */ - info->nand_pref_fifo_add = info->nand.IO_ADDR_R; info->nand.read_buf = omap_read_buf_pref; info->nand.write_buf = omap_write_buf_pref; @@ -987,7 +890,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev) info->nand.ecc.mode = NAND_ECC_HW; /* init HW ECC */ - omap_hwecc_init(&info->mtd); + gpmc_ecc_init(info->gpmc_cs, info->nand.ecc.size); #else info->nand.ecc.mode = NAND_ECC_SOFT; #endif @@ -1034,9 +937,12 @@ static int omap_nand_remove(struct platform_device *pdev) if (use_dma) omap_free_dma(info->dma_ch); + /* reset/ releae the ecc module */ + gpmc_ecc_reset(info->gpmc_cs); + /* Release NAND device, its internal structures and partitions */ nand_release(&info->mtd); - iounmap(info->nand_pref_fifo_add); + iounmap(info->nand.IO_ADDR_R); kfree(&info->mtd); return 0; } From s-ghorai at ti.com Tue May 18 07:16:29 2010 From: s-ghorai at ti.com (Sukumar Ghorai) Date: Tue, 18 May 2010 16:46:29 +0530 Subject: [PATCH v3 3/3] omap3 nand: fix issue in board file to detect nand In-Reply-To: <1274181389-7488-3-git-send-email-s-ghorai@ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274181389-7488-3-git-send-email-s-ghorai@ti.com> Message-ID: <1274181389-7488-4-git-send-email-s-ghorai@ti.com> Board file modified for not to provide gpmc phys_base address to nand driver. The gpmc_nand_init funciton is now used to detect the nand and required to adopt _prob function as in nand/omap2.c Signed-off-by: Sukumar Ghorai --- arch/arm/mach-omap2/board-cm-t35.c | 20 +------------------- arch/arm/mach-omap2/board-devkit8000.c | 25 +------------------------ arch/arm/mach-omap2/board-omap3beagle.c | 24 +----------------------- arch/arm/mach-omap2/board-omap3touchbook.c | 25 +------------------------ arch/arm/mach-omap2/board-overo.c | 24 +----------------------- 5 files changed, 5 insertions(+), 113 deletions(-) diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c index f4e8063..8a41268 --- a/arch/arm/mach-omap2/board-cm-t35.c +++ b/arch/arm/mach-omap2/board-cm-t35.c @@ -61,8 +61,6 @@ #define SB_T35_SMSC911X_GPIO 65 #define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS0_BASE_ADDR (OMAP34XX_GPMC_VIRT + GPMC_CS0_BASE) #if defined(CONFIG_SMSC911X) || defined(CONFIG_SMSC911X_MODULE) #include @@ -223,28 +221,12 @@ static struct omap_nand_platform_data cm_t35_nand_data = { .nr_parts = ARRAY_SIZE(cm_t35_nand_partitions), .dma_channel = -1, /* disable DMA in OMAP NAND driver */ .cs = 0, - .gpmc_cs_baseaddr = (void __iomem *)GPMC_CS0_BASE_ADDR, - .gpmc_baseaddr = (void __iomem *)OMAP34XX_GPMC_VIRT, }; -static struct resource cm_t35_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device cm_t35_nand_device = { - .name = "omap2-nand", - .id = -1, - .num_resources = 1, - .resource = &cm_t35_nand_resource, - .dev = { - .platform_data = &cm_t35_nand_data, - }, -}; - static void __init cm_t35_init_nand(void) { - if (platform_device_register(&cm_t35_nand_device) < 0) + if (gpmc_nand_init(&cm_t35_nand_data) < 0) pr_err("CM-T35: Unable to register NAND device\n"); } #else diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c index 6d910df..b172414 --- a/arch/arm/mach-omap2/board-devkit8000.c +++ b/arch/arm/mach-omap2/board-devkit8000.c @@ -58,9 +58,6 @@ #include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K #define OMAP_DM9000_GPIO_IRQ 25 @@ -104,20 +101,6 @@ static struct omap_nand_platform_data devkit8000_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource devkit8000_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device devkit8000_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &devkit8000_nand_data, - }, - .num_resources = 1, - .resource = &devkit8000_nand_resource, -}; - static struct omap2_hsmmc_info mmc[] = { { .mmc = 1, @@ -581,8 +564,6 @@ static void __init devkit8000_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -604,13 +585,9 @@ static void __init devkit8000_flash_init(void) if (nandcs < GPMC_CS_NUM) { devkit8000_nand_data.cs = nandcs; - devkit8000_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - devkit8000_nand_data.gpmc_baseaddr = (void *) - (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&devkit8000_nand_device) < 0) + if (gpmc_nand_init(&devkit8000_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c index 5df89f6..9ec3ef8 100644 --- a/arch/arm/mach-omap2/board-omap3beagle.c +++ b/arch/arm/mach-omap2/board-omap3beagle.c @@ -47,9 +47,6 @@ #include "mux.h" #include "hsmmc.h" -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K static struct mtd_partition omap3beagle_nand_partitions[] = { @@ -92,20 +89,6 @@ static struct omap_nand_platform_data omap3beagle_nand_data = { .dev_ready = NULL, }; -static struct resource omap3beagle_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device omap3beagle_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &omap3beagle_nand_data, - }, - .num_resources = 1, - .resource = &omap3beagle_nand_resource, -}; - #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -377,8 +360,6 @@ static void __init omap3beagle_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -400,12 +381,9 @@ static void __init omap3beagle_flash_init(void) if (nandcs < GPMC_CS_NUM) { omap3beagle_nand_data.cs = nandcs; - omap3beagle_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - omap3beagle_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&omap3beagle_nand_device) < 0) + if (gpmc_nand_init(&omap3beagle_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c index c59050d..29dd266 --- a/arch/arm/mach-omap2/board-omap3touchbook.c +++ b/arch/arm/mach-omap2/board-omap3touchbook.c @@ -54,9 +54,6 @@ #include -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 - #define NAND_BLOCK_SIZE SZ_128K #define OMAP3_AC_GPIO 136 @@ -106,20 +103,6 @@ static struct omap_nand_platform_data omap3touchbook_nand_data = { .dev_ready = NULL, }; -static struct resource omap3touchbook_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device omap3touchbook_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &omap3touchbook_nand_data, - }, - .num_resources = 1, - .resource = &omap3touchbook_nand_resource, -}; - #include "sdram-micron-mt46h32m32lf-6.h" static struct omap2_hsmmc_info mmc[] = { @@ -459,8 +442,6 @@ static void __init omap3touchbook_flash_init(void) u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -482,13 +463,9 @@ static void __init omap3touchbook_flash_init(void) if (nandcs < GPMC_CS_NUM) { omap3touchbook_nand_data.cs = nandcs; - omap3touchbook_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - omap3touchbook_nand_data.gpmc_baseaddr = - (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&omap3touchbook_nand_device) < 0) + if (gpmc_nand_init(&omap3touchbook_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c index 24b32d7..df0fb0d --- a/arch/arm/mach-omap2/board-overo.c +++ b/arch/arm/mach-omap2/board-overo.c @@ -58,8 +58,6 @@ #define OVERO_GPIO_USBH_NRESET 183 #define NAND_BLOCK_SIZE SZ_128K -#define GPMC_CS0_BASE 0x60 -#define GPMC_CS_SIZE 0x30 #define OVERO_SMSC911X_CS 5 #define OVERO_SMSC911X_GPIO 176 @@ -231,28 +229,11 @@ static struct omap_nand_platform_data overo_nand_data = { .dma_channel = -1, /* disable DMA in OMAP NAND driver */ }; -static struct resource overo_nand_resource = { - .flags = IORESOURCE_MEM, -}; - -static struct platform_device overo_nand_device = { - .name = "omap2-nand", - .id = -1, - .dev = { - .platform_data = &overo_nand_data, - }, - .num_resources = 1, - .resource = &overo_nand_resource, -}; - - static void __init overo_flash_init(void) { u8 cs = 0; u8 nandcs = GPMC_CS_NUM + 1; - u32 gpmc_base_add = OMAP34XX_GPMC_VIRT; - /* find out the chip-select on which NAND exists */ while (cs < GPMC_CS_NUM) { u32 ret = 0; @@ -274,12 +255,9 @@ static void __init overo_flash_init(void) if (nandcs < GPMC_CS_NUM) { overo_nand_data.cs = nandcs; - overo_nand_data.gpmc_cs_baseaddr = (void *) - (gpmc_base_add + GPMC_CS0_BASE + nandcs * GPMC_CS_SIZE); - overo_nand_data.gpmc_baseaddr = (void *) (gpmc_base_add); printk(KERN_INFO "Registering NAND on CS%d\n", nandcs); - if (platform_device_register(&overo_nand_device) < 0) + if (gpmc_nand_init(&overo_nand_data) < 0) printk(KERN_ERR "Unable to register NAND device\n"); } } From dwmw2 at infradead.org Tue May 18 07:27:03 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 18 May 2010 12:27:03 +0100 Subject: [PATCH v5] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1274105441.6930.6920.camel@macbook.infradead.org> References: <1274105441.6930.6920.camel@macbook.infradead.org> Message-ID: <1274182023.6930.7023.camel@macbook.infradead.org> On Mon, 2010-05-17 at 15:10 +0100, David Woodhouse wrote: > Now you're just reimplementing iget(). > > Can we just use iget_locked() to get the appropriate inode (using the > mtd device number as the inode number)? Then we don't need to bother > storing it in mtd->inode at all, and we can iput() the last refcount on > it when the chardevice is closed -- we don't need it to stick around > until the MTD device is destroyed. ... and we don't _want_ it to stick around until the MTD device is destroyed, either. We may actually unload the mtdchar module and its inodes will be destroyed when we unregister the fs type; we don't want stale pointers to them hanging around to be reused if/when we reload the mtdchar module later. I've committed a version which keeps it entirely within the mtdchar code: http://git.infradead.org/mtd-2.6.git/commitdiff/cd874237 Thanks. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From c-d.hailfinger.devel.2006 at gmx.net Tue May 18 08:12:15 2010 From: c-d.hailfinger.devel.2006 at gmx.net (Carl-Daniel Hailfinger) Date: Tue, 18 May 2010 14:12:15 +0200 Subject: Wrong flash type in m25p80 driver In-Reply-To: <4BF235AE.3030903@shemesh.biz> References: <4BF011D7.4010907@shemesh.biz> <4BF041A3.70304@shemesh.biz> <4BF04DBE.5020309@shemesh.biz> <4BF173E5.2030304@gmx.net> <4BF235AE.3030903@shemesh.biz> Message-ID: <4BF2841F.8000405@gmx.net> On 18.05.2010 08:37, Shachar Shemesh wrote: > Carl-Daniel Hailfinger wrote: >> The ST M25P80 has a minimum write size of 1 bit (datasheet is a bit >> unclear, could also be 1 byte) and a maximum write size of 256 bytes. >> > I have not studies the M25P80 data sheet, but did the M25P32 and the > MX25L6405D chips, and I believe all SPI flahses handled by the m25p80 > driver behave the same in that regard (which is why they were clamped > together to begin with). > > The minimal "program" length is 1 byte, but since a program can only > change a 1 bit into 0, effectively, setting a word to "11...101...11", > where the zero is at the bit you want to set, will program 1 bit. Yes. The situation is a bit complicated. Some flash chips will not accept further writes to a location that has been written once even if those further writes would only change more bits to 0. Such chips have true 1 byte granularity. Other chips (and AFAIK the whole ST M25 series) can do at least two writes per byte location as long as the second write does not set any 0 bit to 1. >> There's always the option of looking at how flashrom >> handles those chips. flashrom an >> OS-independent userspace tool specialized on chips which are used for >> BIOS/firmware, but it handles some other flash chips as well. >> > It lists them as "SPI", and the chip support page claims, at least for > most of them, that it does not know how to erase them > (http://www.flashrom.org/Supported_hardware). Thanks for pointing out that this page is misleading. The status "?" means that it is untested and should work. Only a read "No" means unsupported. I'll change the wiki to be more readable. Regards, Carl-Daniel -- http://www.hailfinger.org/ From stanley.miao at windriver.com Tue May 18 08:23:08 2010 From: stanley.miao at windriver.com (Stanley.Miao) Date: Tue, 18 May 2010 20:23:08 +0800 Subject: Fix the bug that nandwrite can't write the yaffs2 image correctly Message-ID: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> Many people encountered this problerm, creating a image by mkyaffs2image, then write it into a nand falsh with nandwrite, then mounted failed. This is because mkyaffs2image didn't know the oob layout of a NAND flash, so it put the yaffs2 tags at the offset 0 of oob area, nandwrite didn't put it at right position when writing oobdata. Stanley. From stanley.miao at windriver.com Tue May 18 08:23:10 2010 From: stanley.miao at windriver.com (Stanley.Miao) Date: Tue, 18 May 2010 20:23:10 +0800 Subject: [PATCH 2/2] check if the start address is page-aligned. In-Reply-To: <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> Message-ID: <1274185390-3066-3-git-send-email-stanley.miao@windriver.com> Only page-aligned address is permitted in NAND subsystem. Signed-off-by: Stanley.Miao --- nandwrite.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-) diff --git a/nandwrite.c b/nandwrite.c index 1e30ad1..fbb1153 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -306,6 +306,14 @@ int main(int argc, char * const argv[]) close(fd); exit (EXIT_FAILURE); } + + if (mtdoffset & (meminfo.writesize - 1)) { + fprintf(stderr, "The start address is not page-aligned !\n" + "The pagesize of this NAND Flash is 0x%x.\n", + meminfo.writesize); + close(fd); + exit(EXIT_FAILURE); + } if (autoplace) { /* Read the current oob info */ -- 1.5.4.3 From stanley.miao at windriver.com Tue May 18 08:23:09 2010 From: stanley.miao at windriver.com (Stanley.Miao) Date: Tue, 18 May 2010 20:23:09 +0800 Subject: [PATCH 1/2] Fix the bug of writing a yaffs2 image to NAND In-Reply-To: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> Message-ID: <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> The tool mkyaffs2image doesn't know the oob layout of a NAND flash, so it puts the yaffs2 tags at the offset 0 of oob area, as a result, the image generated by mkyaffs2image is different with the image dumped by nanddump. Now adding a parameter "-r" for nandwrite to differentiate these images. Write a image generated by mkyaffs2image: $> nandwrite -a -o /dev/mtd3 yaffs2.bin Write a image dumped by nanddump: $> nandwrite -a -r /dev/mtd3 image.bin Signed-off-by: Stanley.Miao --- nandwrite.c | 20 ++++++++++++++++---- 1 files changed, 16 insertions(+), 4 deletions(-) diff --git a/nandwrite.c b/nandwrite.c index b77edd6..1e30ad1 100644 --- a/nandwrite.c +++ b/nandwrite.c @@ -80,6 +80,7 @@ static void display_help (void) " -m, --markbad Mark blocks bad if write fails\n" " -n, --noecc Write without ecc\n" " -o, --oob Image contains oob data\n" +" -r, --raw Image contains the raw oob data dumped by nanddump\n" " -s addr, --start=addr Set start address (default is 0)\n" " -p, --pad Pad to page size\n" " -b, --blockalign=1|2|4 Set multiple of eraseblocks to align to\n" @@ -110,6 +111,7 @@ static const char *mtd_device, *img; static int mtdoffset = 0; static bool quiet = false; static bool writeoob = false; +static bool rawoob = false; static bool autoplace = false; static bool markbad = false; static bool forcejffs2 = false; @@ -125,7 +127,7 @@ static void process_options (int argc, char * const argv[]) for (;;) { int option_index = 0; - static const char *short_options = "ab:fjmnopqs:y"; + static const char *short_options = "ab:fjmnopqrs:y"; static const struct option long_options[] = { {"help", no_argument, 0, 0}, {"version", no_argument, 0, 0}, @@ -138,6 +140,7 @@ static void process_options (int argc, char * const argv[]) {"oob", no_argument, 0, 'o'}, {"pad", no_argument, 0, 'p'}, {"quiet", no_argument, 0, 'q'}, + {"raw", no_argument, 0, 'r'}, {"start", required_argument, 0, 's'}, {"yaffs", no_argument, 0, 'y'}, {0, 0, 0, 0}, @@ -187,6 +190,10 @@ static void process_options (int argc, char * const argv[]) case 'p': pad = true; break; + case 'r': + rawoob = true; + writeoob = true; + break; case 's': mtdoffset = strtol (optarg, NULL, 0); break; @@ -583,6 +590,7 @@ int main(int argc, char * const argv[]) oob.ptr = oobreadbuf; } else { int i, start, len; + int tags_pos = 0; /* * We use autoplacement and have the oobinfo with the autoplacement * information from the kernel available @@ -595,9 +603,13 @@ int main(int argc, char * const argv[]) /* Set the reserved bytes to 0xff */ start = old_oobinfo.oobfree[i][0]; len = old_oobinfo.oobfree[i][1]; - memcpy(oobbuf + start, - oobreadbuf + start, - len); + if (rawoob) + memcpy(oobbuf + start, + oobreadbuf + start, len); + else + memcpy(oobbuf + start, + oobreadbuf + tags_pos, len); + tags_pos += len; } } else { /* Set at least the ecc byte positions to 0xff */ -- 1.5.4.3 From kirill at shutemov.name Tue May 18 08:18:25 2010 From: kirill at shutemov.name (Kirill A. Shutemov) Date: Tue, 18 May 2010 15:18:25 +0300 Subject: [PATCH v5] mtd: Do not corrupt backing device of device node inode In-Reply-To: <1274182023.6930.7023.camel@macbook.infradead.org> References: <1274105441.6930.6920.camel@macbook.infradead.org> <1274182023.6930.7023.camel@macbook.infradead.org> Message-ID: On Tue, May 18, 2010 at 2:27 PM, David Woodhouse wrote: > On Mon, 2010-05-17 at 15:10 +0100, David Woodhouse wrote: >> Now you're just reimplementing iget(). >> >> Can we just use iget_locked() to get the appropriate inode (using the >> mtd device number as the inode number)? Then we don't need to bother >> storing it in mtd->inode at all, and we can iput() the last refcount on >> it when the chardevice is closed -- we don't need it to stick around >> until the MTD device is destroyed. > > ... and we don't _want_ it to stick around until the MTD device is > destroyed, either. We may actually unload the mtdchar module and its > inodes will be destroyed when we unregister the fs type; we don't want > stale pointers to them hanging around to be reused if/when we reload the > mtdchar module later. > > I've committed a version which keeps it entirely within the mtdchar > code: http://git.infradead.org/mtd-2.6.git/commitdiff/cd874237 Looks ok. Thank you. What about stable@? > > Thanks. > > -- > David Woodhouse ? ? ? ? ? ? ? ? ? ? ? ? ? ?Open Source Technology Centre > David.Woodhouse at intel.com ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?Intel Corporation > > From dwmw2 at infradead.org Tue May 18 08:45:06 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 18 May 2010 13:45:06 +0100 Subject: [PATCH v5] mtd: Do not corrupt backing device of device node inode In-Reply-To: References: <1274105441.6930.6920.camel@macbook.infradead.org> <1274182023.6930.7023.camel@macbook.infradead.org> Message-ID: <1274186706.6930.7213.camel@macbook.infradead.org> On Tue, 2010-05-18 at 15:18 +0300, Kirill A. Shutemov wrote: > > http://git.infradead.org/mtd-2.6.git/commitdiff/cd874237 > > Looks ok. Thank you. > > What about stable@? Ah, yes. For future reference, we should have included an explicit 'Cc: stable at kernel.org' in the commit itself, rather than just in the email thread. As it is, we'll probably need to wait for it to hit Linus' tree and then submit a backport to -stable. It'll need a slight massage to apply to older kernels anyway. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From dwmw2 at infradead.org Tue May 18 11:46:27 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 18 May 2010 16:46:27 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> Message-ID: <1274197587.6930.7407.camel@macbook.infradead.org> On Fri, 2010-05-14 at 14:12 +0200, Joakim Tjernlund wrote: > @@ -167,8 +170,6 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo > list_move_tail(&jeb->list, &c->erase_complete_list); > spin_unlock(&c->erase_completion_lock); > mutex_unlock(&c->erase_free_sem); > - /* Ensure that kupdated calls us again to mark them clean */ > - jffs2_erase_pending_trigger(c); > } > > static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset) Why remove this? If you have asynchronous erases, with the erase callback (and hence this jffs2_erase_succeeded function) getting called asynchronously, then we _do_ want to trigger the GC thread to run, to that it can write the cleanmarker to the block and refile it on the empty_list. -- dwmw2 From brijesh.s.singh at gmail.com Tue May 18 13:40:49 2010 From: brijesh.s.singh at gmail.com (Brijesh Singh) Date: Tue, 18 May 2010 23:10:49 +0530 Subject: [PATCH] UBI: fix delete compatible internal volume scan Message-ID: This patch resolves a possible bug. Scan is adding delete compatible blocks to both corr list and used list. It should return after adding the block to corr list. Signed-off-by: Brijesh Singh --- drivers/mtd/ubi/scan.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c index 6b7c0c4..fde15f1 100644 --- a/drivers/mtd/ubi/scan.c +++ b/drivers/mtd/ubi/scan.c @@ -845,7 +845,7 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si, err = add_to_list(si, pnum, ec, &si->corr); if (err) return err; - break; + return 0; case UBI_COMPAT_RO: ubi_msg("read-only compatible internal volume %d:%d" -- From joakim.tjernlund at transmode.se Tue May 18 14:19:13 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Tue, 18 May 2010 20:19:13 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1274197587.6930.7407.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274197587.6930.7407.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/18 17:46:27: > > On Fri, 2010-05-14 at 14:12 +0200, Joakim Tjernlund wrote: > > @@ -167,8 +170,6 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info > *c, struct jffs2_eraseblo > > list_move_tail(&jeb->list, &c->erase_complete_list); > > spin_unlock(&c->erase_completion_lock); > > mutex_unlock(&c->erase_free_sem); > > - /* Ensure that kupdated calls us again to mark them clean */ > > - jffs2_erase_pending_trigger(c); > > } > > > > static void jffs2_erase_failed(struct jffs2_sb_info *c, struct > jffs2_eraseblock *jeb, uint32_t bad_offset) > > Why remove this? If you have asynchronous erases, with the erase > callback (and hence this jffs2_erase_succeeded function) getting called > asynchronously, then we _do_ want to trigger the GC thread to run, to > that it can write the cleanmarker to the block and refile it on the > empty_list. hmm, I haven't given async erases much thought(is anyone using that?) but yes it looks premature to remove this. Could you add that back or do you want me to submit another patch? From dwmw2 at infradead.org Tue May 18 14:37:24 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 18 May 2010 19:37:24 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> Message-ID: <1274207844.6930.7754.camel@macbook.infradead.org> On Fri, 2010-05-14 at 14:12 +0200, Joakim Tjernlund wrote: > +/* erase.c */ > +static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) > +{ > + jffs2_garbage_collect_trigger(c); > +} Hrm, and now everything which calls jffs2_erase_pending_trigger() needs _not_ to be holding c->erase_completion_lock, or it'll deadlock... Eraseblock at 0x001c0000 completely dirtied. Removing from (dirty?) list... ...and adding to erase_pending_list ============================================= [ INFO: possible recursive locking detected ] 2.6.34-rc7 #2 --------------------------------------------- dbench/4263 is trying to acquire lock: (&(&c->erase_completion_lock)->rlock){+.+...}, at: [] jffs2_garbage_collect_trigger+0x19/0x4e [jffs2] but task is already holding lock: (&(&c->erase_completion_lock)->rlock){+.+...}, at: [] jffs2_mark_node_obsolete+0xcb/0x737 [jffs2] other info that might help us debug this: 5 locks held by dbench/4263: #0: (&sb->s_type->i_mutex_key#12){+.+.+.}, at: [] generic_file_aio_write+0x47/0xa8 #1: (&c->alloc_sem){+.+.+.}, at: [] jffs2_reserve_space+0x71/0x39e [jffs2] #2: (&f->sem){+.+.+.}, at: [] jffs2_write_inode_range+0xb0/0x2f3 [jffs2] #3: (&c->erase_free_sem){+.+...}, at: [] jffs2_mark_node_obsolete+0xb4/0x737 [jffs2] #4: (&(&c->erase_completion_lock)->rlock){+.+...}, at: [] jffs2_mark_node_obsolete+0xcb/0x737 [jffs2] stack backtrace: Pid: 4263, comm: dbench Not tainted 2.6.34-rc7 #2 Call Trace: [] __lock_acquire+0x1633/0x16cd [] ? trace_hardirqs_off+0xd/0xf [] ? mutex_lock_nested+0x2c7/0x31a [] ? trace_hardirqs_on_caller+0x10c/0x130 [] lock_acquire+0x57/0x6d [] ? jffs2_garbage_collect_trigger+0x19/0x4e [jffs2] [] _raw_spin_lock+0x3b/0x4a [] ? jffs2_garbage_collect_trigger+0x19/0x4e [jffs2] [] jffs2_garbage_collect_trigger+0x19/0x4e [jffs2] [] jffs2_mark_node_obsolete+0x3a7/0x737 [jffs2] [] ? printk+0x3c/0x3e [] jffs2_obsolete_node_frag+0x2a/0x48 [jffs2] [] jffs2_add_full_dnode_to_inode+0x2f3/0x3cc [jffs2] [] jffs2_write_inode_range+0x203/0x2f3 [jffs2] [] jffs2_write_end+0x176/0x25b [jffs2] [] generic_file_buffered_write+0x188/0x282 -- dwmw2 From dwmw2 at infradead.org Tue May 18 14:59:12 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 18 May 2010 19:59:12 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1274207844.6930.7754.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> Message-ID: <1274209152.6930.7802.camel@macbook.infradead.org> On Tue, 2010-05-18 at 19:37 +0100, David Woodhouse wrote: > > Hrm, and now everything which calls jffs2_erase_pending_trigger() > needs > _not_ to be holding c->erase_completion_lock, or it'll deadlock... Playing with this incremental patch now... I also moved the erasing into jffs2_garbage_collect_pass() itself rather than having both callers of jffs2_garbage_collect_pass() do it for themselves, under different circumstances. I think the one in jffs2_reserve_space() was buggy anyway. diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 6cc014c..8c9ffdc 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -21,12 +21,11 @@ static int jffs2_garbage_collect_thread(void *); -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) { - spin_lock(&c->erase_completion_lock); + BUG_ON(spin_trylock(&c->erase_completion_lock)); if (c->gc_task && jffs2_thread_should_wake(c)) send_sig(SIGHUP, c->gc_task, 1); - spin_unlock(&c->erase_completion_lock); } /* This must only ever be called when no GC thread is currently running */ @@ -146,9 +145,8 @@ static int jffs2_garbage_collect_thread(void *_c) disallow_signal(SIGHUP); D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); - if (jffs2_erase_pending_blocks(c, 1)) - /* Nothing more to do ATM */; - else if (jffs2_garbage_collect_pass(c) == -ENOSPC) { + + if (jffs2_garbage_collect_pass(c) == -ENOSPC) { printk(KERN_NOTICE "No space for garbage collection. Aborting GC thread\n"); goto die; } diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index 2a6cc6c..e8638f8 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -168,8 +168,11 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo mutex_lock(&c->erase_free_sem); spin_lock(&c->erase_completion_lock); list_move_tail(&jeb->list, &c->erase_complete_list); + /* Wake the GC thread to mark them clean */ + jffs2_erase_pending_trigger(c); spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->erase_free_sem); + wake_up(&c->erase_wait); } static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset) @@ -488,9 +491,9 @@ filebad: refile: /* Stick it back on the list from whence it came and come back later */ - jffs2_erase_pending_trigger(c); mutex_lock(&c->erase_free_sem); spin_lock(&c->erase_completion_lock); + jffs2_erase_pending_trigger(c); list_move(&jeb->list, &c->erase_complete_list); spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->erase_free_sem); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 3b6f2fa..1ea4a84 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -214,6 +214,19 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) return ret; } + /* If there are any blocks which need erasing, erase them now */ + if (!list_empty(&c->erase_complete_list) || + !list_empty(&c->erase_pending_list)) { + spin_unlock(&c->erase_completion_lock); + D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); + if (jffs2_erase_pending_blocks(c, 1)) { + mutex_unlock(&c->alloc_sem); + return 0; + } + D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); + spin_lock(&c->erase_completion_lock); + } + /* First, work out which block we're garbage-collecting */ jeb = c->gcblock; @@ -222,7 +235,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) if (!jeb) { /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */ - if (!list_empty(&c->erase_pending_list)) { + if (c->nr_erasing_blocks) { spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->alloc_sem); return -EAGAIN; diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 4779301..8ec436a 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -115,9 +115,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, spin_unlock(&c->erase_completion_lock); ret = jffs2_garbage_collect_pass(c); - - if (ret == -EAGAIN) - jffs2_erase_pending_blocks(c, 1); + if (ret == -EAGAIN) { + spin_lock(&c->erase_completion_lock); + if (c->nr_erasing_blocks && + list_empty(&c->erase_pending_list) && + list_empty(&c->erase_complete_list)) { + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&c->erase_wait, &wait); + D1(printk(KERN_DEBUG "%s waiting for erase to complete\n", __func__)); + spin_unlock(&c->erase_completion_lock); + + schedule(); + } else + spin_unlock(&c->erase_completion_lock); + } else if (ret) return ret; @@ -469,7 +481,9 @@ struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, void jffs2_complete_reservation(struct jffs2_sb_info *c) { D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); - jffs2_garbage_collect_trigger(c); + spin_lock(&c->erase_completion_lock); + jffs2_erase_pending_trigger(c); + spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->alloc_sem); } diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index 5d26362..64ac455 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -148,13 +148,7 @@ static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c) /* background.c */ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); - -/* erase.c */ -static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) -{ - jffs2_garbage_collect_trigger(c); -} +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); /* dir.c */ extern const struct file_operations jffs2_dir_operations; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 696686c..1312552 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -260,7 +260,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ret = -EIO; goto out; } + spin_lock(&c->erase_completion_lock); jffs2_erase_pending_trigger(c); + spin_unlock(&c->erase_completion_lock); } ret = 0; out: -- dwmw2 From joakim.tjernlund at transmode.se Tue May 18 18:44:19 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Wed, 19 May 2010 00:44:19 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1274209152.6930.7802.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/18 20:59:12: > > On Tue, 2010-05-18 at 19:37 +0100, David Woodhouse wrote: > > > > Hrm, and now everything which calls jffs2_erase_pending_trigger() > > needs > > _not_ to be holding c->erase_completion_lock, or it'll deadlock... > > Playing with this incremental patch now... oops, this got a lot more complicated. I will have closer look tmw. BTW, I had a much simpler patch to start with but it was reject because it tested for signals in erase_pending_blocks(). Look for jffs2: Move erasing from write_super to GC. and jffs2: Make jffs2_erase_pending_trigger() initiate GC. if you want to look. > > I also moved the erasing into jffs2_garbage_collect_pass() itself rather > than having both callers of jffs2_garbage_collect_pass() do it for > themselves, under different circumstances. I think the one in > jffs2_reserve_space() was buggy anyway. > > diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c > index 6cc014c..8c9ffdc 100644 > --- a/fs/jffs2/background.c > +++ b/fs/jffs2/background.c > @@ -21,12 +21,11 @@ > > static int jffs2_garbage_collect_thread(void *); > > -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) > +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) > { > - spin_lock(&c->erase_completion_lock); > + BUG_ON(spin_trylock(&c->erase_completion_lock)); > if (c->gc_task && jffs2_thread_should_wake(c)) > send_sig(SIGHUP, c->gc_task, 1); > - spin_unlock(&c->erase_completion_lock); > } > > /* This must only ever be called when no GC thread is currently running */ > @@ -146,9 +145,8 @@ static int jffs2_garbage_collect_thread(void *_c) > disallow_signal(SIGHUP); > > D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); > - if (jffs2_erase_pending_blocks(c, 1)) > - /* Nothing more to do ATM */; > - else if (jffs2_garbage_collect_pass(c) == -ENOSPC) { > + > + if (jffs2_garbage_collect_pass(c) == -ENOSPC) { > printk(KERN_NOTICE "No space for garbage collection. Aborting GC thread\n"); > goto die; > } > diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c > index 2a6cc6c..e8638f8 100644 > --- a/fs/jffs2/erase.c > +++ b/fs/jffs2/erase.c > @@ -168,8 +168,11 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info > *c, struct jffs2_eraseblo > mutex_lock(&c->erase_free_sem); > spin_lock(&c->erase_completion_lock); > list_move_tail(&jeb->list, &c->erase_complete_list); > + /* Wake the GC thread to mark them clean */ > + jffs2_erase_pending_trigger(c); > spin_unlock(&c->erase_completion_lock); > mutex_unlock(&c->erase_free_sem); > + wake_up(&c->erase_wait); > } > > static void jffs2_erase_failed(struct jffs2_sb_info *c, struct > jffs2_eraseblock *jeb, uint32_t bad_offset) > @@ -488,9 +491,9 @@ filebad: > > refile: > /* Stick it back on the list from whence it came and come back later */ > - jffs2_erase_pending_trigger(c); > mutex_lock(&c->erase_free_sem); > spin_lock(&c->erase_completion_lock); > + jffs2_erase_pending_trigger(c); > list_move(&jeb->list, &c->erase_complete_list); > spin_unlock(&c->erase_completion_lock); > mutex_unlock(&c->erase_free_sem); > diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c > index 3b6f2fa..1ea4a84 100644 > --- a/fs/jffs2/gc.c > +++ b/fs/jffs2/gc.c > @@ -214,6 +214,19 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) > return ret; > } > > + /* If there are any blocks which need erasing, erase them now */ > + if (!list_empty(&c->erase_complete_list) || > + !list_empty(&c->erase_pending_list)) { > + spin_unlock(&c->erase_completion_lock); > + D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); > + if (jffs2_erase_pending_blocks(c, 1)) { > + mutex_unlock(&c->alloc_sem); > + return 0; > + } > + D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); > + spin_lock(&c->erase_completion_lock); > + } > + > /* First, work out which block we're garbage-collecting */ > jeb = c->gcblock; > > @@ -222,7 +235,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) > > if (!jeb) { > /* Couldn't find a free block. But maybe we can just erase one and make > 'progress'? */ > - if (!list_empty(&c->erase_pending_list)) { > + if (c->nr_erasing_blocks) { > spin_unlock(&c->erase_completion_lock); > mutex_unlock(&c->alloc_sem); > return -EAGAIN; > diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c > index 4779301..8ec436a 100644 > --- a/fs/jffs2/nodemgmt.c > +++ b/fs/jffs2/nodemgmt.c > @@ -115,9 +115,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, > spin_unlock(&c->erase_completion_lock); > > ret = jffs2_garbage_collect_pass(c); > - > - if (ret == -EAGAIN) > - jffs2_erase_pending_blocks(c, 1); > + if (ret == -EAGAIN) { > + spin_lock(&c->erase_completion_lock); > + if (c->nr_erasing_blocks && > + list_empty(&c->erase_pending_list) && > + list_empty(&c->erase_complete_list)) { > + DECLARE_WAITQUEUE(wait, current); > + set_current_state(TASK_UNINTERRUPTIBLE); > + add_wait_queue(&c->erase_wait, &wait); > + D1(printk(KERN_DEBUG "%s waiting for erase to complete\n", __func__)); > + spin_unlock(&c->erase_completion_lock); > + > + schedule(); > + } else > + spin_unlock(&c->erase_completion_lock); > + } > else if (ret) > return ret; > > @@ -469,7 +481,9 @@ struct jffs2_raw_node_ref *jffs2_add_physical_node_ref > (struct jffs2_sb_info *c, > void jffs2_complete_reservation(struct jffs2_sb_info *c) > { > D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); > - jffs2_garbage_collect_trigger(c); > + spin_lock(&c->erase_completion_lock); > + jffs2_erase_pending_trigger(c); > + spin_unlock(&c->erase_completion_lock); > mutex_unlock(&c->alloc_sem); > } > > diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h > index 5d26362..64ac455 100644 > --- a/fs/jffs2/os-linux.h > +++ b/fs/jffs2/os-linux.h > @@ -148,13 +148,7 @@ static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c) > /* background.c */ > int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); > void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); > -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); > - > -/* erase.c */ > -static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) > -{ > - jffs2_garbage_collect_trigger(c); > -} > +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); > > /* dir.c */ > extern const struct file_operations jffs2_dir_operations; > diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c > index 696686c..1312552 100644 > --- a/fs/jffs2/scan.c > +++ b/fs/jffs2/scan.c > @@ -260,7 +260,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) > ret = -EIO; > goto out; > } > + spin_lock(&c->erase_completion_lock); > jffs2_erase_pending_trigger(c); > + spin_unlock(&c->erase_completion_lock); > } > ret = 0; > out: > > > -- > dwmw2 > > > From dwmw2 at infradead.org Tue May 18 18:58:25 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 18 May 2010 23:58:25 +0100 Subject: JFFS2 on NAND and when is file on media? In-Reply-To: References: Message-ID: <1274223505.6930.8287.camel@macbook.infradead.org> On Mon, 2010-02-15 at 13:34 +0100, Joakim Tjernlund wrote: > Ping? Pretty please :) > > Joakim Tjernlund/Transmode wrote on 2010/02/09 18:54:39: > > I have been using JFFS2 for many years on NOR flash but never on NAND. > > I wonder if NAND has the same guaranties as NOR as to when one > > can expect file contents to be safely on media so one can pull the power > > without loss of data? > > Is the the whole file safe once close(2) returns? If not, what do > > I have to do flush all outstanding data to media? > > > > Jocke POSIX answers this. You need to fsync() before you close, if you want to be sure the data have all hit the medium. You _ought_ to be doing that on NOR flash too. Although JFFS2 _today_ might not do any write-behind, there's no guarantee that it won't do so tomorrow. Or that you won't switch to ubifs/logfs/etc. There's no excuse for writing buggy applications just because you _happen_ to know that the file system doesn't _currently_ take certain liberties that it's permitted to take. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From rpjday at crashcourse.ca Tue May 18 19:40:57 2010 From: rpjday at crashcourse.ca (Robert P. J. Day) Date: Tue, 18 May 2010 19:40:57 -0400 (EDT) Subject: how to pre-screen patch submissions from a newbie janitor? Message-ID: not that long ago, i suggested cleaning up the MTD Kconfig/Makefile structure since there was some definite redundancy in the inclusion of source files and subdirectories. now, i could whip up those patches myself and submit them, but i have a local friend who's itching to get start doing some simple kernel work and submitting some patches, and he's more than smart enough to do what i described above. however, since he's new to patch creation and submission, i offered to "vet" his patches first. i realize that my vetting carries no weight on the MTD list, but given that i've submitted lots and lots of patches elsewhere, i can still at least sanity check what he comes up with before it hits the list. is there a canonical signage for that nowadays? is it "Reviewed-By" or something like that? so that by the time it gets to the MTD list, he would have done the "Signed-Off-By" and i'd sign off as a reviewer. is that the way it works? or is there an alternative? thanks. rday -- ======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA Linux Consulting, Training and Kernel Pedantry. Web page: http://crashcourse.ca Twitter: http://twitter.com/rpjday ======================================================================== From dwmw2 at infradead.org Tue May 18 19:42:02 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Wed, 19 May 2010 00:42:02 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> Message-ID: <1274226122.6930.8416.camel@macbook.infradead.org> On Wed, 2010-05-19 at 00:44 +0200, Joakim Tjernlund wrote: > > oops, this got a lot more complicated. I will have closer look tmw. It's not so bad -- the whole thing looks like this (I'll follow it up with a global s/jffs2_erase_pending_trigger/jffs2_gc_thread_trigger/). It could perhaps be broken into smaller simple patches along the lines of: - Add 'work_done' return value from jffs2_erase_pending_blocks() - Call jffs2_erase_pending_blocks() from jffs2_g_c_pass() - Fix the conditions under which jffs2_g_c_pass() will return -EINVAL, fix the way that jffs2_reserve_space() will respond to that, and fix jffs2_erase_succeeded() to actually wake up the erase_wait queue. - Remove locking from jffs2_garbage_collect_trigger() and require that callers have c->erase_completion_lock already held. - Change most callers of jffs2_erase_pending_trigger() to call jffs2_garbage_collect_trigger() instead. To comply with the locking rules, this may involve moving the call up or down a few lines, or sometimes adding a new lock/unlock pair around it. - Remove jffs2_erase_pending_blocks() call from jffs2_write_super(). - Rename jffs2_erase_pending_trigger() and its only remaining caller in wbuf.c to jffs2_dirty_trigger(). diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c index 3ff50da..39c65ad 100644 --- a/fs/jffs2/background.c +++ b/fs/jffs2/background.c @@ -21,12 +21,11 @@ static int jffs2_garbage_collect_thread(void *); -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) { - spin_lock(&c->erase_completion_lock); + BUG_ON(spin_trylock(&c->erase_completion_lock)); if (c->gc_task && jffs2_thread_should_wake(c)) send_sig(SIGHUP, c->gc_task, 1); - spin_unlock(&c->erase_completion_lock); } /* This must only ever be called when no GC thread is currently running */ diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index b47679b..e8638f8 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c @@ -103,9 +103,10 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, jffs2_erase_failed(c, jeb, bad_offset); } -void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) +int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) { struct jffs2_eraseblock *jeb; + int work_done = 0; mutex_lock(&c->erase_free_sem); @@ -123,6 +124,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) if (!--count) { D1(printk(KERN_DEBUG "Count reached. jffs2_erase_pending_blocks leaving\n")); + work_done = 1; goto done; } @@ -157,6 +159,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) mutex_unlock(&c->erase_free_sem); done: D1(printk(KERN_DEBUG "jffs2_erase_pending_blocks completed\n")); + return work_done; } static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) @@ -165,10 +168,11 @@ static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblo mutex_lock(&c->erase_free_sem); spin_lock(&c->erase_completion_lock); list_move_tail(&jeb->list, &c->erase_complete_list); + /* Wake the GC thread to mark them clean */ + jffs2_erase_pending_trigger(c); spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->erase_free_sem); - /* Ensure that kupdated calls us again to mark them clean */ - jffs2_erase_pending_trigger(c); + wake_up(&c->erase_wait); } static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset) @@ -487,9 +491,9 @@ filebad: refile: /* Stick it back on the list from whence it came and come back later */ - jffs2_erase_pending_trigger(c); mutex_lock(&c->erase_free_sem); spin_lock(&c->erase_completion_lock); + jffs2_erase_pending_trigger(c); list_move(&jeb->list, &c->erase_complete_list); spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->erase_free_sem); diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index 3b6f2fa..1ea4a84 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c @@ -214,6 +214,19 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) return ret; } + /* If there are any blocks which need erasing, erase them now */ + if (!list_empty(&c->erase_complete_list) || + !list_empty(&c->erase_pending_list)) { + spin_unlock(&c->erase_completion_lock); + D1(printk(KERN_DEBUG "jffs2_garbage_collect_pass() erasing pending blocks\n")); + if (jffs2_erase_pending_blocks(c, 1)) { + mutex_unlock(&c->alloc_sem); + return 0; + } + D1(printk(KERN_DEBUG "No progress from erasing blocks; doing GC anyway\n")); + spin_lock(&c->erase_completion_lock); + } + /* First, work out which block we're garbage-collecting */ jeb = c->gcblock; @@ -222,7 +235,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) if (!jeb) { /* Couldn't find a free block. But maybe we can just erase one and make 'progress'? */ - if (!list_empty(&c->erase_pending_list)) { + if (c->nr_erasing_blocks) { spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->alloc_sem); return -EAGAIN; diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 36d7a84..a881a42 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h @@ -464,7 +464,7 @@ int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb int jffs2_do_mount_fs(struct jffs2_sb_info *c); /* erase.c */ -void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); +int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); #ifdef CONFIG_JFFS2_FS_WRITEBUFFER diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 191359d..8ec436a 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c @@ -115,9 +115,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, spin_unlock(&c->erase_completion_lock); ret = jffs2_garbage_collect_pass(c); - - if (ret == -EAGAIN) - jffs2_erase_pending_blocks(c, 1); + if (ret == -EAGAIN) { + spin_lock(&c->erase_completion_lock); + if (c->nr_erasing_blocks && + list_empty(&c->erase_pending_list) && + list_empty(&c->erase_complete_list)) { + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&c->erase_wait, &wait); + D1(printk(KERN_DEBUG "%s waiting for erase to complete\n", __func__)); + spin_unlock(&c->erase_completion_lock); + + schedule(); + } else + spin_unlock(&c->erase_completion_lock); + } else if (ret) return ret; @@ -469,7 +481,9 @@ struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, void jffs2_complete_reservation(struct jffs2_sb_info *c) { D1(printk(KERN_DEBUG "jffs2_complete_reservation()\n")); - jffs2_garbage_collect_trigger(c); + spin_lock(&c->erase_completion_lock); + jffs2_erase_pending_trigger(c); + spin_unlock(&c->erase_completion_lock); mutex_unlock(&c->alloc_sem); } @@ -732,6 +746,10 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c) int nr_very_dirty = 0; struct jffs2_eraseblock *jeb; + if (!list_empty(&c->erase_complete_list) || + !list_empty(&c->erase_pending_list)) + return 1; + if (c->unchecked_size) { D1(printk(KERN_DEBUG "jffs2_thread_should_wake(): unchecked_size %d, checked_ino #%d\n", c->unchecked_size, c->checked_ino)); diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index a7f03b7..64ac455 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h @@ -140,8 +140,7 @@ void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); #endif /* WRITEBUFFER */ -/* erase.c */ -static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) +static inline void jffs2_dirty_trigger(struct jffs2_sb_info *c) { OFNI_BS_2SFFJ(c)->s_dirt = 1; } @@ -149,7 +148,7 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) /* background.c */ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c); void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c); -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c); +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c); /* dir.c */ extern const struct file_operations jffs2_dir_operations; diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index 696686c..1312552 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c @@ -260,7 +260,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) ret = -EIO; goto out; } + spin_lock(&c->erase_completion_lock); jffs2_erase_pending_trigger(c); + spin_unlock(&c->erase_completion_lock); } ret = 0; out: diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index 9a80e8e..511e2d6 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c @@ -63,8 +63,6 @@ static void jffs2_write_super(struct super_block *sb) if (!(sb->s_flags & MS_RDONLY)) { D1(printk(KERN_DEBUG "jffs2_write_super()\n")); - jffs2_garbage_collect_trigger(c); - jffs2_erase_pending_blocks(c, 0); jffs2_flush_wbuf_gc(c, 0); } diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 5ef7bac..f319efc 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c @@ -84,7 +84,7 @@ static void jffs2_wbuf_dirties_inode(struct jffs2_sb_info *c, uint32_t ino) struct jffs2_inodirty *new; /* Mark the superblock dirty so that kupdated will flush... */ - jffs2_erase_pending_trigger(c); + jffs2_dirty_trigger(c); if (jffs2_wbuf_pending_for_ino(c, ino)) return; -- dwmw2 From w.sang at pengutronix.de Tue May 18 20:01:37 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Wed, 19 May 2010 02:01:37 +0200 Subject: how to pre-screen patch submissions from a newbie janitor? In-Reply-To: References: Message-ID: <20100519000137.GA18592@pengutronix.de> > however, since he's new to patch creation and submission, i offered > to "vet" his patches first. i realize that my vetting carries no > weight on the MTD list, but given that i've submitted lots and lots of > patches elsewhere, i can still at least sanity check what he comes up > with before it hits the list. > > is there a canonical signage for that nowadays? is it "Reviewed-By" > or something like that? so that by the time it gets to the MTD list, > he would have done the "Signed-Off-By" and i'd sign off as a reviewer. > is that the way it works? or is there an alternative? thanks. Yes, that sounds like a good case for Reviewed-by. It will surely help these patches knowing there is somebody with experience who already had a look at (and in that case probably build-tested) them. Looking forward to the series, Wolfram -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: Digital signature URL: From linux at dominikbrodowski.net Wed May 19 02:42:43 2010 From: linux at dominikbrodowski.net (Dominik Brodowski) Date: Wed, 19 May 2010 08:42:43 +0200 Subject: [PATCH 07/29] pcmcia: dev_node removal (write-only drivers) In-Reply-To: <20100519064149.GA5755@comet.dominikbrodowski.net> References: <20100519064149.GA5755@comet.dominikbrodowski.net> Message-ID: <1274251385-6196-7-git-send-email-linux@dominikbrodowski.net> dev_node_t was only used to transport some minor/major numbers from the PCMCIA device drivers to deprecated userspace helpers. However, only a few drivers made use of it, and the userspace helpers are deprecated anyways. Therefore, get rid of dev_node_t . As a first step, remove any usage of dev_node_t from drivers which only wrote to this typedef/struct, but did not make use of it. CC: linux-bluetooth at vger.kernel.org CC: Harald Welte CC: linux-mtd at lists.infradead.org CC: linux-wireless at vger.kernel.org CC: netdev at vger.kernel.org CC: linux-serial at vger.kernel.org CC: alsa-devel at alsa-project.org Signed-off-by: Dominik Brodowski --- drivers/bluetooth/bluecard_cs.c | 4 --- drivers/bluetooth/bt3c_cs.c | 4 --- drivers/bluetooth/btuart_cs.c | 4 --- drivers/bluetooth/dtl1_cs.c | 4 --- drivers/char/pcmcia/cm4040_cs.c | 5 --- drivers/mtd/maps/pcmciamtd.c | 3 -- drivers/net/wireless/atmel_cs.c | 42 ------------------------------- drivers/net/wireless/hostap/hostap_cs.c | 9 +----- drivers/parport/parport_cs.c | 5 --- drivers/scsi/pcmcia/aha152x_stub.c | 3 -- drivers/scsi/pcmcia/fdomain_stub.c | 3 -- drivers/scsi/pcmcia/nsp_cs.c | 3 -- drivers/scsi/pcmcia/nsp_cs.h | 1 - drivers/scsi/pcmcia/qlogic_stub.c | 3 -- drivers/scsi/pcmcia/sym53c500_cs.c | 3 -- drivers/serial/serial_cs.c | 9 ------ drivers/telephony/ixj_pcmcia.c | 3 -- sound/pcmcia/pdaudiocf/pdaudiocf.c | 1 - sound/pcmcia/pdaudiocf/pdaudiocf.h | 1 - sound/pcmcia/vx/vxpocket.c | 2 - sound/pcmcia/vx/vxpocket.h | 1 - 21 files changed, 2 insertions(+), 111 deletions(-) diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index a34653d..6f907eb 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -65,7 +65,6 @@ MODULE_LICENSE("GPL"); typedef struct bluecard_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct hci_dev *hdev; @@ -916,9 +915,6 @@ static int bluecard_config(struct pcmcia_device *link) if (bluecard_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev->name); - link->dev_node = &info->node; - return 0; failed: diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 1ad9694..21e05fd 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -72,7 +72,6 @@ MODULE_FIRMWARE("BT3CPCC.bin"); typedef struct bt3c_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct hci_dev *hdev; @@ -751,9 +750,6 @@ found_port: if (bt3c_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev->name); - link->dev_node = &info->node; - return 0; failed: diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 1073d66..4ed7288 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -67,7 +67,6 @@ MODULE_LICENSE("GPL"); typedef struct btuart_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct hci_dev *hdev; @@ -680,9 +679,6 @@ found_port: if (btuart_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev->name); - link->dev_node = &info->node; - return 0; failed: diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 3d72afd..ef044d5 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -67,7 +67,6 @@ MODULE_LICENSE("GPL"); typedef struct dtl1_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct hci_dev *hdev; @@ -629,9 +628,6 @@ static int dtl1_config(struct pcmcia_device *link) if (dtl1_open(info) != 0) goto failed; - strcpy(info->node.dev_name, info->hdev->name); - link->dev_node = &info->node; - return 0; failed: diff --git a/drivers/char/pcmcia/cm4040_cs.c b/drivers/char/pcmcia/cm4040_cs.c index a6a70e4..c0775c8 100644 --- a/drivers/char/pcmcia/cm4040_cs.c +++ b/drivers/char/pcmcia/cm4040_cs.c @@ -72,7 +72,6 @@ static struct class *cmx_class; struct reader_dev { struct pcmcia_device *p_dev; - dev_node_t node; wait_queue_head_t devq; wait_queue_head_t poll_wait; wait_queue_head_t read_wait; @@ -568,10 +567,6 @@ static int reader_config(struct pcmcia_device *link, int devno) } dev = link->priv; - sprintf(dev->node.dev_name, DEVICE_NAME "%d", devno); - dev->node.major = major; - dev->node.minor = devno; - dev->node.next = &dev->node; DEBUGP(2, dev, "device " DEVICE_NAME "%d at 0x%.4x-0x%.4x\n", devno, link->io.BasePort1, link->io.BasePort1+link->io.NumPorts1); diff --git a/drivers/mtd/maps/pcmciamtd.c b/drivers/mtd/maps/pcmciamtd.c index 689d6a7..87b2b8f 100644 --- a/drivers/mtd/maps/pcmciamtd.c +++ b/drivers/mtd/maps/pcmciamtd.c @@ -52,7 +52,6 @@ static const int debug = 0; struct pcmciamtd_dev { struct pcmcia_device *p_dev; - dev_node_t node; /* device node */ caddr_t win_base; /* ioremapped address of PCMCIA window */ unsigned int win_size; /* size of window */ unsigned int offset; /* offset into card the window currently points at */ @@ -647,9 +646,7 @@ static int pcmciamtd_config(struct pcmcia_device *link) pcmciamtd_release(link); return -ENODEV; } - snprintf(dev->node.dev_name, sizeof(dev->node.dev_name), "mtd%d", mtd->index); info("mtd%d: %s", mtd->index, mtd->name); - link->dev_node = &dev->node; return 0; failed: diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c index 759cdc4..c2746fc 100644 --- a/drivers/net/wireless/atmel_cs.c +++ b/drivers/net/wireless/atmel_cs.c @@ -85,41 +85,7 @@ static void atmel_release(struct pcmcia_device *link); static void atmel_detach(struct pcmcia_device *p_dev); -/* - You'll also need to prototype all the functions that will actually - be used to talk to your device. See 'pcmem_cs' for a good example - of a fully self-sufficient driver; the other drivers rely more or - less on other parts of the kernel. -*/ - -/* - A linked list of "instances" of the atmelnet device. Each actual - PCMCIA card corresponds to one device instance, and is described - by one struct pcmcia_device structure (defined in ds.h). - - You may not want to use a linked list for this -- for example, the - memory card driver uses an array of struct pcmcia_device pointers, where minor - device numbers are used to derive the corresponding array index. -*/ - -/* - A driver needs to provide a dev_node_t structure for each device - on a card. In some cases, there is only one device per card (for - example, ethernet cards, modems). In other cases, there may be - many actual or logical devices (SCSI adapters, memory cards with - multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a struct pcmcia_device - structure. We allocate them in the card's private data structure, - because they generally shouldn't be allocated dynamically. - - In this case, we also provide a flag to indicate if a device is - "stopped" due to a power management event, or card ejection. The - device IO routines can use a flag like this to throttle IO to a - card that is not ready to accept it. -*/ - typedef struct local_info_t { - dev_node_t node; struct net_device *eth_dev; } local_info_t; @@ -297,14 +263,6 @@ static int atmel_config(struct pcmcia_device *link) goto failed; - /* - At this point, the dev_node_t structure(s) need to be - initialized and arranged in a linked list at link->dev_node. - */ - strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); - dev->node.major = dev->node.minor = 0; - link->dev_node = &dev->node; - return 0; failed: diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c index 5e2efbb..db72461 100644 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ b/drivers/net/wireless/hostap/hostap_cs.c @@ -39,7 +39,6 @@ MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); /* struct local_info::hw_priv */ struct hostap_cs_priv { - dev_node_t node; struct pcmcia_device *link; int sandisk_connectplus; }; @@ -625,8 +624,6 @@ static int prism2_config(struct pcmcia_device *link) local = iface->local; local->hw_priv = hw_priv; hw_priv->link = link; - strcpy(hw_priv->node.dev_name, dev->name); - link->dev_node = &hw_priv->node; ret = pcmcia_request_irq(link, prism2_interrupt); if (ret) @@ -665,11 +662,9 @@ static int prism2_config(struct pcmcia_device *link) sandisk_enable_wireless(dev); ret = prism2_hw_config(dev, 1); - if (!ret) { + if (!ret) ret = hostap_hw_ready(dev); - if (ret == 0 && local->ddev) - strcpy(hw_priv->node.dev_name, local->ddev->name); - } + return ret; failed: diff --git a/drivers/parport/parport_cs.c b/drivers/parport/parport_cs.c index 80c9052..fd8cfe9 100644 --- a/drivers/parport/parport_cs.c +++ b/drivers/parport/parport_cs.c @@ -75,7 +75,6 @@ INT_MODULE_PARM(epp_mode, 1); typedef struct parport_info_t { struct pcmcia_device *p_dev; int ndev; - dev_node_t node; struct parport *port; } parport_info_t; @@ -193,11 +192,7 @@ static int parport_config(struct pcmcia_device *link) if (epp_mode) p->modes |= PARPORT_MODE_TRISTATE | PARPORT_MODE_EPP; info->ndev = 1; - info->node.major = LP_MAJOR; - info->node.minor = p->number; info->port = p; - strcpy(info->node.dev_name, p->name); - link->dev_node = &info->node; return 0; diff --git a/drivers/scsi/pcmcia/aha152x_stub.c b/drivers/scsi/pcmcia/aha152x_stub.c index c1de4ba..9d70aef 100644 --- a/drivers/scsi/pcmcia/aha152x_stub.c +++ b/drivers/scsi/pcmcia/aha152x_stub.c @@ -80,7 +80,6 @@ MODULE_LICENSE("Dual MPL/GPL"); typedef struct scsi_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct Scsi_Host *host; } scsi_info_t; @@ -185,8 +184,6 @@ static int aha152x_config_cs(struct pcmcia_device *link) goto failed; } - sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev_node = &info->node; info->host = host; return 0; diff --git a/drivers/scsi/pcmcia/fdomain_stub.c b/drivers/scsi/pcmcia/fdomain_stub.c index 8cb6d71..21b1411 100644 --- a/drivers/scsi/pcmcia/fdomain_stub.c +++ b/drivers/scsi/pcmcia/fdomain_stub.c @@ -63,7 +63,6 @@ MODULE_LICENSE("Dual MPL/GPL"); typedef struct scsi_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct Scsi_Host *host; } scsi_info_t; @@ -155,8 +154,6 @@ static int fdomain_config(struct pcmcia_device *link) goto failed; scsi_scan_host(host); - sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev_node = &info->node; info->host = host; return 0; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 24c78ed..0f0e112 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -1754,8 +1754,6 @@ static int nsp_cs_config(struct pcmcia_device *link) scsi_scan_host(host); - snprintf(info->node.dev_name, sizeof(info->node.dev_name), "scsi%d", host->host_no); - link->dev_node = &info->node; info->host = host; /* Finally, report what we've done */ @@ -1813,7 +1811,6 @@ static void nsp_cs_release(struct pcmcia_device *link) if (info->host != NULL) { scsi_remove_host(info->host); } - link->dev_node = NULL; if (link->win) { if (data != NULL) { diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 8c61a4f..d68c9f2 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -224,7 +224,6 @@ typedef struct scsi_info_t { struct pcmcia_device *p_dev; struct Scsi_Host *host; - dev_node_t node; int stop; } scsi_info_t; diff --git a/drivers/scsi/pcmcia/qlogic_stub.c b/drivers/scsi/pcmcia/qlogic_stub.c index c3a4428..f0fc6ba 100644 --- a/drivers/scsi/pcmcia/qlogic_stub.c +++ b/drivers/scsi/pcmcia/qlogic_stub.c @@ -82,7 +82,6 @@ static struct scsi_host_template qlogicfas_driver_template = { typedef struct scsi_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct Scsi_Host *host; unsigned short manf_id; } scsi_info_t; @@ -235,8 +234,6 @@ static int qlogic_config(struct pcmcia_device * link) goto failed; } - sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev_node = &info->node; info->host = host; return 0; diff --git a/drivers/scsi/pcmcia/sym53c500_cs.c b/drivers/scsi/pcmcia/sym53c500_cs.c index 6eacf4c..a511641 100644 --- a/drivers/scsi/pcmcia/sym53c500_cs.c +++ b/drivers/scsi/pcmcia/sym53c500_cs.c @@ -191,7 +191,6 @@ struct scsi_info_t { struct pcmcia_device *p_dev; - dev_node_t node; struct Scsi_Host *host; unsigned short manf_id; }; @@ -792,8 +791,6 @@ SYM53C500_config(struct pcmcia_device *link) */ data->fast_pio = USE_FAST_PIO; - sprintf(info->node.dev_name, "scsi%d", host->host_no); - link->dev_node = &info->node; info->host = host; if (scsi_add_host(host, NULL)) diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 6459252..dadd686 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -89,7 +89,6 @@ struct serial_info { int manfid; int prodid; int c950ctrl; - dev_node_t node[4]; int line[4]; const struct serial_quirk *quirk; }; @@ -289,8 +288,6 @@ static void serial_remove(struct pcmcia_device *link) for (i = 0; i < info->ndev; i++) serial8250_unregister_port(info->line[i]); - info->p_dev->dev_node = NULL; - if (!info->slave) pcmcia_disable_device(link); } @@ -410,11 +407,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info * info, } info->line[info->ndev] = line; - sprintf(info->node[info->ndev].dev_name, "ttyS%d", line); - info->node[info->ndev].major = TTY_MAJOR; - info->node[info->ndev].minor = 0x40 + line; - if (info->ndev > 0) - info->node[info->ndev - 1].next = &info->node[info->ndev]; info->ndev++; return 0; @@ -711,7 +703,6 @@ static int serial_config(struct pcmcia_device * link) if (info->quirk->post(link)) goto failed; - link->dev_node = &info->node[0]; return 0; failed: diff --git a/drivers/telephony/ixj_pcmcia.c b/drivers/telephony/ixj_pcmcia.c index d442fd3..99cb224 100644 --- a/drivers/telephony/ixj_pcmcia.c +++ b/drivers/telephony/ixj_pcmcia.c @@ -22,7 +22,6 @@ typedef struct ixj_info_t { int ndev; - dev_node_t node; struct ixj *port; } ixj_info_t; @@ -155,8 +154,6 @@ static int ixj_config(struct pcmcia_device * link) j = ixj_pcmcia_probe(link->io.BasePort1, link->io.BasePort1 + 0x10); info->ndev = 1; - info->node.major = PHONE_MAJOR; - link->dev_node = &info->node; ixj_get_serial(link, j); return 0; diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c index 60fddf3..df110df 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.c +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c @@ -234,7 +234,6 @@ static int pdacf_config(struct pcmcia_device *link) if (snd_pdacf_assign_resources(pdacf, link->io.BasePort1, link->irq) < 0) goto failed; - link->dev_node = &pdacf->node; return 0; failed: diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.h b/sound/pcmcia/pdaudiocf/pdaudiocf.h index b060183..a0a7ec6 100644 --- a/sound/pcmcia/pdaudiocf/pdaudiocf.h +++ b/sound/pcmcia/pdaudiocf/pdaudiocf.h @@ -117,7 +117,6 @@ struct snd_pdacf { /* pcmcia stuff */ struct pcmcia_device *p_dev; - dev_node_t node; }; static inline void pdacf_reg_write(struct snd_pdacf *chip, unsigned char reg, unsigned short val) diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c index 5eced7a..624b47a 100644 --- a/sound/pcmcia/vx/vxpocket.c +++ b/sound/pcmcia/vx/vxpocket.c @@ -211,7 +211,6 @@ static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq static int vxpocket_config(struct pcmcia_device *link) { struct vx_core *chip = link->priv; - struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; int ret; snd_printdd(KERN_DEBUG "vxpocket_config called\n"); @@ -245,7 +244,6 @@ static int vxpocket_config(struct pcmcia_device *link) if (snd_vxpocket_assign_resources(chip, link->io.BasePort1, link->irq) < 0) goto failed; - link->dev_node = &vxp->node; return 0; failed: diff --git a/sound/pcmcia/vx/vxpocket.h b/sound/pcmcia/vx/vxpocket.h index 27ea002..ea4df16 100644 --- a/sound/pcmcia/vx/vxpocket.h +++ b/sound/pcmcia/vx/vxpocket.h @@ -43,7 +43,6 @@ struct snd_vxpocket { /* pcmcia stuff */ struct pcmcia_device *p_dev; - dev_node_t node; }; extern struct snd_vx_ops snd_vxpocket_ops; -- 1.6.3.3 From muehlfelder at enertex.de Wed May 19 03:45:13 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Wed, 19 May 2010 09:45:13 +0200 Subject: Some questions on bit-flips and JFFS2 In-Reply-To: References: <201005031505.18604.muehlfelder@enertex.de> <201005121321.07822.muehlfelder@enertex.de> Message-ID: <201005190945.13505.muehlfelder@enertex.de> Am Wednesday 12 May 2010 14:22:19 schrieb Ricard Wanderlof: > > - Or write some tool, that can distinguish between real bad blocks and > > the Sam-ba 2.5 created bad blocks, unmark the false bad blocks. But > > perhaps this is not possible at all. > > It depends on how exactly Sam-ba 2.5 overwrites the existing bad block > markers. As you can see here the Sam-Ba 2.5 tool writes some ECC code to the first 4 bytes of each erase block's OOB while in the first byte the bad block information usually is stored. Therefore it is impossible to restore factory set bad blocks. IMHO this is a mature bug in Atmel's Sam-Ba tool, but it is fixed in newer versions. I'm quite sure this behaviour is the source of my problem. Probably factory set bad blocks have been overwritten by Sam-Ba and I guess in these blocks occur the bit flips: nand dump 0x100000 Page 00100000 dump: ... OOB: b1 20 46 df ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff U-Boot> nand dump 0x100800 Page 00100800 dump: ... OOB: 71 31 86 ce ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff U-Boot> nand dump 101800 Page 00101800 dump: ... OOB: 16 4b 16 4b ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff U-Boot> nand dump 102000 Page 00102000 dump: ... OOB: 06 47 f1 b8 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff U-Boot> nand dump 102800 Page 00102800 dump: ... OOB: 24 5c d3 a3 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff U-Boot> nand dump 103000 Page 00103000 dump: ... OOB: c3 37 c3 37 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff U-Boot> nand dump 103800 Page 00103800 dump: ... OOB: 81 0c 81 0c ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff From muehlfelder at enertex.de Wed May 19 05:09:44 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Wed, 19 May 2010 11:09:44 +0200 Subject: What jffs2 compression is used and how to disable it? Message-ID: <201005191109.44983.muehlfelder@enertex.de> Hi, how can I find out what jffs2 compression mode is used on a mounted filesystem? And if compression is used, how would I disable it? Or how would I disable compression on a jffs2 image? Greetings Thorsten From joakim.tjernlund at transmode.se Wed May 19 05:47:39 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Wed, 19 May 2010 11:47:39 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1274226122.6930.8416.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> <1274226122.6930.8416.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/19 01:42:02: > > On Wed, 2010-05-19 at 00:44 +0200, Joakim Tjernlund wrote: > > > > oops, this got a lot more complicated. I will have closer look tmw. > > It's not so bad -- the whole thing looks like this (I'll follow it up > with a global s/jffs2_erase_pending_trigger/jffs2_gc_thread_trigger/). > > It could perhaps be broken into smaller simple patches along the lines > of: > - Add 'work_done' return value from jffs2_erase_pending_blocks() > - Call jffs2_erase_pending_blocks() from jffs2_g_c_pass() > - Fix the conditions under which jffs2_g_c_pass() will return -EINVAL, > fix the way that jffs2_reserve_space() will respond to that, and fix > jffs2_erase_succeeded() to actually wake up the erase_wait queue. > - Remove locking from jffs2_garbage_collect_trigger() and require that > callers have c->erase_completion_lock already held. > - Change most callers of jffs2_erase_pending_trigger() to call > jffs2_garbage_collect_trigger() instead. To comply with the locking > rules, this may involve moving the call up or down a few lines, or > sometimes adding a new lock/unlock pair around it. > - Remove jffs2_erase_pending_blocks() call from jffs2_write_super(). > - Rename jffs2_erase_pending_trigger() and its only remaining caller > in wbuf.c to jffs2_dirty_trigger(). I have tried this on my 2.6.33 tree and it seems to work OK. I am currenltly copying lots of files and deleting them in a loop, so far so good :) Needed to "tweak": > > > diff --git a/fs/jffs2/background.c b/fs/jffs2/background.c > index 3ff50da..39c65ad 100644 > --- a/fs/jffs2/background.c > +++ b/fs/jffs2/background.c > @@ -21,12 +21,11 @@ > > static int jffs2_garbage_collect_thread(void *); > > -void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) > +void jffs2_erase_pending_trigger(struct jffs2_sb_info *c) > { > - spin_lock(&c->erase_completion_lock); > + BUG_ON(spin_trylock(&c->erase_completion_lock)); This looks like a typo and I had to change that to: BUG_ON(spin_is_locked(&c->erase_completion_lock)); > if (c->gc_task && jffs2_thread_should_wake(c)) > send_sig(SIGHUP, c->gc_task, 1); > - spin_unlock(&c->erase_completion_lock); > } > > /* This must only ever be called when no GC thread is currently running */ > diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c > index b47679b..e8638f8 100644 > --- a/fs/jffs2/erase.c > +++ b/fs/jffs2/erase.c > @@ -103,9 +103,10 @@ static void jffs2_erase_block(struct jffs2_sb_info *c, > jffs2_erase_failed(c, jeb, bad_offset); > } > > -void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) > +int jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) > { > struct jffs2_eraseblock *jeb; > + int work_done = 0; > > mutex_lock(&c->erase_free_sem); > > @@ -123,6 +124,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) > > if (!--count) { > D1(printk(KERN_DEBUG "Count reached. jffs2_erase_pending_blocks > leaving\n")); > + work_done = 1; work_done = 1; should move outside the if, otherwise it might get set if count is big. From dwmw2 at infradead.org Wed May 19 06:05:31 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Wed, 19 May 2010 11:05:31 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> <1274226122.6930.8416.camel@macbook.infradead.org> Message-ID: <1274263531.6930.9695.camel@macbook.infradead.org> On Wed, 2010-05-19 at 11:47 +0200, Joakim Tjernlund wrote: > > This looks like a typo and I had to change that to: > BUG_ON(spin_is_locked(&c->erase_completion_lock)); Hm, no -- we want it to BUG() if the spinlock is _NOT_ locked. You're building on UP, without preemption or spinlock debugging. In that case, spinlocks are a no-op. So spin_trylock() _always_ succeeds, and spin_is_locked() always returns 0. It should be lockdep_assert_held(), I think. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From pazdnikov at prosoft.ural.ru Wed May 19 06:36:21 2010 From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov) Date: Wed, 19 May 2010 16:36:21 +0600 Subject: ubifs became broken on contigous power-fails In-Reply-To: <201005131408.01573.pazdnikov@prosoft.ural.ru> References: <201005121330.07802.pazdnikov@prosoft.ural.ru> <201005131408.01573.pazdnikov@prosoft.ural.ru> Message-ID: <201005191636.21845.pazdnikov@prosoft.ural.ru> ? ????????? ?? ??????? 13 ??? 2010 14:08:01 ????? Alexander Pazdnikov ???????: > We've separated EC and VID headers to different pages, setuped 4 devices on > test run. We've setuped 5 devices with EC and VID headers in one page (data offset = 2048) and 5 devices with EC and VID headers in separate pages (data offset = 4096). On all devices the filesystem can became broken. But a strange thing we've admited. If FS became broken then mounting it by hand at boot time in RO mode and then remounting in RW mode repairs the filesystem and an assertion and the following error disappears: UBIFS error (pid 462): ubifs_rcvry_gc_commit: could not find a dirty LEB UBIFS error (pid 495): ubifs_leb_unmap: unmap LEB -1 failed, error -22 Any advices, please. -- Best regards, Sasha From joakim.tjernlund at transmode.se Wed May 19 06:36:08 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Wed, 19 May 2010 12:36:08 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1274263531.6930.9695.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> <1274226122.6930.8416.camel@macbook.infradead.org> <1274263531.6930.9695.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/19 12:05:31: > > On Wed, 2010-05-19 at 11:47 +0200, Joakim Tjernlund wrote: > > > > This looks like a typo and I had to change that to: > > BUG_ON(spin_is_locked(&c->erase_completion_lock)); > > Hm, no -- we want it to BUG() if the spinlock is _NOT_ locked. > > You're building on UP, without preemption or spinlock debugging. In that > case, spinlocks are a no-op. So spin_trylock() _always_ succeeds, and > spin_is_locked() always returns 0. > > It should be lockdep_assert_held(), I think. Ah, now I remember. There was an discussion about this on LKML a while ago. But would not assert_spin_locked() be better? On the other hand lockdep_assert_held() will work too. Depends on what you want? Jocke From al at alarsen.net Wed May 19 07:05:00 2010 From: al at alarsen.net (Anders Larsen) Date: Wed, 19 May 2010 13:05:00 +0200 Subject: [PATCH] Fix Oops with Atmel SPI In-Reply-To: <20100421152410.0fea5e12.akpm@linux-foundation.org> (from akpm@linux-foundation.org on Thu Apr 22 00:24:10 2010) References: <1271231840l.5270l.0l@i-dmzi_al.realan.de> <20100421152410.0fea5e12.akpm@linux-foundation.org> Message-ID: <1274267100l.1747l.1l@i-dmzi_al.realan.de> On 2010-04-22 00:24:10, Andrew Morton wrote: > Finally.. Wouldn't it be better to just fix the atmel SPI driver so > that it doesn't barf when handed vmalloc'ed memory? Who do we ridicule > about that? You mean something like this instead? diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index c4e0442..a9ad5e8 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -352,16 +352,30 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS; if (xfer->tx_buf) { - xfer->tx_dma = dma_map_single(dev, - (void *) xfer->tx_buf, xfer->len, - DMA_TO_DEVICE); + if (is_vmalloc_addr(xfer->tx_buf)) + xfer->tx_dma = dma_map_page(dev, + vmalloc_to_page(xfer->tx_buf), + (unsigned long)xfer->tx_buf & (PAGE_SIZE-1), + xfer->len, + DMA_TO_DEVICE); + else + xfer->tx_dma = dma_map_single(dev, + (void *) xfer->tx_buf, xfer->len, + DMA_TO_DEVICE); if (dma_mapping_error(dev, xfer->tx_dma)) return -ENOMEM; } if (xfer->rx_buf) { - xfer->rx_dma = dma_map_single(dev, - xfer->rx_buf, xfer->len, - DMA_FROM_DEVICE); + if (is_vmalloc_addr(xfer->rx_buf)) + xfer->rx_dma = dma_map_page(dev, + vmalloc_to_page(xfer->rx_buf), + (unsigned long)xfer->rx_buf & (PAGE_SIZE-1), + xfer->len, + DMA_FROM_DEVICE); + else + xfer->rx_dma = dma_map_single(dev, + xfer->rx_buf, xfer->len, + DMA_FROM_DEVICE); if (dma_mapping_error(dev, xfer->rx_dma)) { if (xfer->tx_buf) dma_unmap_single(dev, From rpjday at crashcourse.ca Wed May 19 07:40:16 2010 From: rpjday at crashcourse.ca (Robert P. J. Day) Date: Wed, 19 May 2010 07:40:16 -0400 (EDT) Subject: how to pre-screen patch submissions from a newbie janitor? In-Reply-To: <20100519000137.GA18592@pengutronix.de> References: <20100519000137.GA18592@pengutronix.de> Message-ID: On Wed, 19 May 2010, Wolfram Sang wrote: > > however, since he's new to patch creation and submission, i > > offered to "vet" his patches first. i realize that my vetting > > carries no weight on the MTD list, but given that i've submitted > > lots and lots of patches elsewhere, i can still at least sanity > > check what he comes up with before it hits the list. > > > > is there a canonical signage for that nowadays? is it > > "Reviewed-By" or something like that? so that by the time it gets > > to the MTD list, he would have done the "Signed-Off-By" and i'd > > sign off as a reviewer. is that the way it works? or is there an > > alternative? thanks. > > Yes, that sounds like a good case for Reviewed-by. It will surely > help these patches knowing there is somebody with experience who > already had a look at (and in that case probably build-tested) them. > > Looking forward to the series, what i'm going to have this trainee(?) do is just simplify the config/Kconfig/Makefile combos, which i openly admit is not earth-shaking in its complexity. for example. in a number of places elsewhere in the kernel tree, i've submitted patches to change things like this in the config menus: OneNAND Device Support ---> LPDDR flash memory drivers ---> UBI - Unsorted block images ---> note how, to select either LPDDR or UBI, you need to *go* to those submenus, where you find a top-level selector. it's simpler to just put that selector right on that menu item, as it's done for "OneNAND" just above it. no wasting time. and another simplification is to cut down the conditional inclusion in the makefiles. for instance, here's tests/Makefile: obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o ... etc etc ... there's little point having every single line in the Makefile test CONFIG_MTD_TESTS when that can all be done with a single test one level up that checks whether or not to process the tests/ directory at all. in short, nothing spectacular, just tidying up. rday -- ======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA Linux Consulting, Training and Kernel Pedantry. Web page: http://crashcourse.ca Twitter: http://twitter.com/rpjday ======================================================================== From raghu.msrpsr at gmail.com Wed May 19 10:13:46 2010 From: raghu.msrpsr at gmail.com (Raghu MSRPSR) Date: Wed, 19 May 2010 07:13:46 -0700 Subject: Running jffs2 filesystem on mtd nand flash driver Message-ID: Hi, Could some one /review post a exact sequence of steps to get jffs2 up and running on a NAND MTD driver for kernel 2.6.27+ 1. load nand (mtd) driver 2. flash_eraseall -q /dev/mtdx 3. mount -t jffs2 /dev/mtdblockx /flash is this correct sequence? Any info shared is appreciated. Thanks, Raghu From vimal.newwork at gmail.com Wed May 19 10:46:43 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Wed, 19 May 2010 20:16:43 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: <1274181389-7488-2-git-send-email-s-ghorai@ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> Message-ID: On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > few functions added in gpmc module and to be used by other drivers like NAND. > E.g.: - ioctl function > ? ? ?- ecc functions > > Signed-off-by: Sukumar Ghorai > --- > ?arch/arm/mach-omap2/gpmc.c ? ? ? ? ? ? | ?246 +++++++++++++++++++++++++++++++- > ?arch/arm/plat-omap/include/plat/gpmc.h | ? 35 ++++- > ?drivers/mtd/nand/omap2.c ? ? ? ? ? ? ? | ? ?4 +- > ?3 files changed, 274 insertions(+), 11 deletions(-) > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > index 5bc3ca0..7e6d821 > --- a/arch/arm/mach-omap2/gpmc.c > +++ b/arch/arm/mach-omap2/gpmc.c > @@ -46,8 +46,9 @@ > ?#define GPMC_ECC_CONFIG ? ? ? ? ? ? ? ?0x1f4 > ?#define GPMC_ECC_CONTROL ? ? ? 0x1f8 > ?#define GPMC_ECC_SIZE_CONFIG ? 0x1fc > +#define GPMC_ECC1_RESULT ? ? ? ?0x200 > > -#define GPMC_CS0 ? ? ? ? ? ? ? 0x60 > +#define GPMC_CS0_BASE ? ? ? ? ?0x60 > ?#define GPMC_CS_SIZE ? ? ? ? ? 0x30 > > ?#define GPMC_MEM_START ? ? ? ? 0x00000000 > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs { > ?static struct resource gpmc_mem_root; > ?static struct resource gpmc_cs_mem[GPMC_CS_NUM]; > ?static DEFINE_SPINLOCK(gpmc_mem_lock); > -static unsigned ? ? ? ? ? ? ? ?gpmc_cs_map; > +static unsigned ? ? ? ?int gpmc_cs_map; ? ? ? ?/* flag for cs which are initialized */ > +static int gpmc_pref_used = -EINVAL; ? /* cs using prefetch engine */ > +static int gpmc_ecc_used = -EINVAL; ? ?/* cs using ecc engine */ > > ?static void __iomem *gpmc_base; > > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx) > ? ? ? ?return __raw_readl(gpmc_base + idx); > ?} > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > +{ > + ? ? ? void __iomem *reg_addr; > + > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? __raw_writeb(val, reg_addr); > +} > + > +static u8 gpmc_cs_read_byte(int cs, int idx) > +{ > + ? ? ? void __iomem *reg_addr; > + > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? return __raw_readb(reg_addr); > +} > + > ?void gpmc_cs_write_reg(int cs, int idx, u32 val) > ?{ > ? ? ? ?void __iomem *reg_addr; > > - ? ? ? reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > ? ? ? ?__raw_writel(val, reg_addr); > ?} > > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > ?{ > ? ? ? ?void __iomem *reg_addr; > > - ? ? ? reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > + ? ? ? reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > ? ? ? ?return __raw_readl(reg_addr); > ?} > > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs) > ?EXPORT_SYMBOL(gpmc_cs_free); > > ?/** > + * gpmc_hwcontrol - hardware specific access (read/ write) control > + * @cs: chip select number > + * @cmd: command type > + * @write: 1 for write; 0 for read > + * @wval: value to write > + * @rval: read pointer > + */ > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval) > +{ > + ? ? ? u32 regval = 0; > + > + ? ? ? if (!write && !rval) > + ? ? ? ? ? ? ? return -EINVAL; > + > + ? ? ? switch (cmd) { > + ? ? ? case GPMC_STATUS_BUFFER: > + ? ? ? ? ? ? ? regval = gpmc_read_reg(GPMC_STATUS); > + ? ? ? ? ? ? ? /* 1 : buffer is available to write */ > + ? ? ? ? ? ? ? *rval = regval & GPMC_STATUS_BUFF_EMPTY; > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_GET_SET_IRQ_STATUS: > + ? ? ? ? ? ? ? if (write) > + ? ? ? ? ? ? ? ? ? ? ? gpmc_write_reg(GPMC_IRQSTATUS, wval); > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? *rval = gpmc_read_reg(GPMC_IRQSTATUS); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_PREFETCH_FIFO_CNT: > + ? ? ? ? ? ? ? regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > + ? ? ? ? ? ? ? *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_PREFETCH_COUNT: > + ? ? ? ? ? ? ? regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > + ? ? ? ? ? ? ? *rval = GPMC_PREFETCH_STATUS_COUNT(regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_WP: > + ? ? ? ? ? ? ? regval = gpmc_read_reg(GPMC_CONFIG); > + ? ? ? ? ? ? ? if (wval) > + ? ? ? ? ? ? ? ? ? ? ? regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? regval |= GPMC_CONFIG_WRITEPROTECT; ?/* WP is OFF */ > + ? ? ? ? ? ? ? gpmc_write_reg(GPMC_CONFIG, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_RDY_BSY: > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > + ? ? ? ? ? ? ? regval |= WR_RD_PIN_MONITORING; > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > + ? ? ? ? ? ? ? break; IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). > + > + ? ? ? case GPMC_CONFIG_DEV_SIZE: > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > + ? ? ? ? ? ? ? regval |= GPMC_CONFIG1_DEVICESIZE(wval); > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_CONFIG_DEV_TYPE: > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > + ? ? ? ? ? ? ? regval |= GPMC_CONFIG1_DEVICETYPE(wval); > + ? ? ? ? ? ? ? if (wval == GPMC_DEVICETYPE_NOR) > + ? ? ? ? ? ? ? ? ? ? ? regval |= GPMC_CONFIG1_MUXADDDATA; > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_NAND_COMMAND: > + ? ? ? ? ? ? ? gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_NAND_ADDRESS: > + ? ? ? ? ? ? ? gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); > + ? ? ? ? ? ? ? break; > + > + ? ? ? case GPMC_NAND_DATA: > + ? ? ? ? ? ? ? if (write) > + ? ? ? ? ? ? ? ? ? ? ? gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); > + ? ? ? ? ? ? ? else > + ? ? ? ? ? ? ? ? ? ? ? *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); > + ? ? ? ? ? ? ? break; > + > + ? ? ? default: > + ? ? ? ? ? ? ? printk(KERN_ERR "gpmc_hwcontrol: Not supported\n"); > + ? ? ? ? ? ? ? return -EINVAL; > + ? ? ? } > + > + ? ? ? return 0; > +} > +EXPORT_SYMBOL(gpmc_hwcontrol); > + > +/** > ?* gpmc_prefetch_enable - configures and starts prefetch transfer > - * @cs: nand cs (chip select) number > + * @cs: cs (chip select) number > ?* @dma_mode: dma mode enable (1) or disable (0) > ?* @u32_count: number of bytes to be transferred > ?* @is_write: prefetch read(0) or write post(1) mode > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode, > ?{ > ? ? ? ?uint32_t prefetch_config1; > > + ? ? ? if (gpmc_pref_used == -EINVAL) > + ? ? ? ? ? ? ? gpmc_pref_used = cs; > + ? ? ? else > + ? ? ? ? ? ? ? return -EBUSY; This is not required. Prefetch engine has just one instance > + > ? ? ? ?if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { and any prefetch request will be done only if above check passes. Which actually checks if 'prefetch' is busy or not. You can see in NAND driver (omap2.c) code, it understands that. > ? ? ? ? ? ? ? ?/* Set the amount of bytes to be prefetched */ > ? ? ? ? ? ? ? ?gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > ?/** > ?* gpmc_prefetch_reset - disables and stops the prefetch engine > ?*/ > -void gpmc_prefetch_reset(void) > +int gpmc_prefetch_reset(int cs) > ?{ > + ? ? ? if (gpmc_pref_used == cs) > + ? ? ? ? ? ? ? gpmc_pref_used = -EINVAL; > + ? ? ? else > + ? ? ? ? ? ? ? return -EINVAL; > + This is also not required. As, this function will be called only if prefetch was used. > ? ? ? ?/* Stop the PFPW engine */ > ? ? ? ?gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); > > ? ? ? ?/* Reset/disable the PFPW engine */ > ? ? ? ?gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); > + > + ? ? ? return 0; > ?} > ?EXPORT_SYMBOL(gpmc_prefetch_reset); > > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void) > ? ? ? ?} > ?} > ?#endif /* CONFIG_ARCH_OMAP3 */ > + > +/** > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller > + * @cs: chip select number > + * @ecc_size: number of bytes for ecc generation > + */ > + > +int gpmc_ecc_init(int cs, int ecc_size) > +{ > + ? ? ? unsigned int val = 0x0; > + > + ? ? ? /* check if ecc engine already by another cs */ > + ? ? ? if (gpmc_ecc_used == -EINVAL) > + ? ? ? ? ? ? ? gpmc_ecc_used = cs; > + ? ? ? else > + ? ? ? ? ? ? ? return -EBUSY; Here few things need be to consider: 1. 'init' is supposed to done once for every instance of driver during probe 2. But ECC engine, too, have only one instance at a time, So 3. As long as all NAND chip are supposed to use same ECC machenism, we can go for only one time 'init' for all drivers, perhaps in gpmc_nand.c. 4. But in case, different instances of driver (or NAND chip) requires different ECC machenism (for ex. Hamming or BCH, or even with different capabilities of error correction), this will no longer vailid. Then rather we should have something like 'gpmc_ecc_config' call to configer ECC engine for everytime a driver needs it (something like as it is done for prefetch engine). > + > + ? ? ? /* read ecc control register */ > + ? ? ? val = gpmc_read_reg(GPMC_ECC_CONTROL); > + > + ? ? ? /* clear ecc and enable bits */ > + ? ? ? val = ((0x00000001<<8) | 0x00000001); > + ? ? ? gpmc_write_reg(GPMC_ECC_CONTROL, val); > + > + ? ? ? /* Read from ECC Size Config Register */ > + ? ? ? val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > + > + ? ? ? /* program ecc and result sizes */ > + ? ? ? val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > + ? ? ? gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > + > + ? ? ? return 0; > +} > + > +/** > + * gpmc_calculate_ecc - generate non-inverted ecc bytes > + * @cs: chip select number > + * @dat: data pointer over which ecc is computed > + * @ecc_code: ecc code buffer > + * > + * Using non-inverted ECC is considered ugly since writing a blank > + * page (padding) will clear the ECC bytes. This is not a problem as long > + * no one is trying to write data on the seemingly unused page. Reading > + * an erased page will produce an ECC mismatch between generated and read > + * ECC bytes that has to be dealt with separately. > + */ > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) > +{ > + ? ? ? unsigned int val = 0x0; > + > + ? ? ? if (gpmc_ecc_used != cs) > + ? ? ? ? ? ? ? return -EINVAL; > + > + ? ? ? /* read ecc result */ > + ? ? ? val = gpmc_read_reg(GPMC_ECC1_RESULT); > + ? ? ? *ecc_code++ = val; ? ? ? ? ?/* P128e, ..., P1e */ > + ? ? ? *ecc_code++ = val >> 16; ? ?/* P128o, ..., P1o */ > + ? ? ? /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ > + ? ? ? *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); > + > + ? ? ? return 0; > +} > + > +/** > + * gpmc_enable_hwecc - enable hardware ecc functionality > + * @cs: chip select number > + * @mode: read/write mode > + * @dev_width: device bus width(1 for x16, 0 for x8) > + */ > +int gpmc_enable_hwecc(int cs, int mode, int dev_width) > +{ > + ? ? ? unsigned int val; > + > + ? ? ? if (gpmc_ecc_used != cs) > + ? ? ? ? ? ? ? return -EINVAL; > + > + ? ? ? switch (mode) { > + ? ? ? case GPMC_ECC_READ: > + ? ? ? ? ? ? ? gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > + ? ? ? ? ? ? ? break; > + ? ? ? case GPMC_ECC_READSYN: > + ? ? ? ? ? ? ? ?gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); > + ? ? ? ? ? ? ? break; > + ? ? ? case GPMC_ECC_WRITE: > + ? ? ? ? ? ? ? gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > + ? ? ? ? ? ? ? break; > + ? ? ? default: > + ? ? ? ? ? ? ? printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); > + ? ? ? ? ? ? ? break; > + ? ? ? } > + > + ? ? ? /* (ECC 16 or 8 bit col) | ( CS ?) ?| ECC Enable */ > + ? ? ? val = (dev_width << 7) | (cs << 1) | (0x1); > + ? ? ? gpmc_write_reg(GPMC_ECC_CONFIG, val); > + ? ? ? return 0; > +} > + > +/** > + * gmpc_ecc_reset - release the HW ECC in GPMC controller > + * @cs: Chip select number > + */ > +int gpmc_ecc_reset(int cs) > +{ > + ? ? ? if (gpmc_ecc_used == cs) > + ? ? ? ? ? ? ? gpmc_ecc_used = -EINVAL; > + ? ? ? else > + ? ? ? ? ? ? ? return -EINVAL; > + > + ? ? ? return 0; > +} > + > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h > index 145838a..67a3442 > --- a/arch/arm/plat-omap/include/plat/gpmc.h > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > @@ -27,8 +27,24 @@ > > ?#define GPMC_CONFIG ? ? ? ? ? ?0x50 > ?#define GPMC_STATUS ? ? ? ? ? ?0x54 > -#define GPMC_CS0_BASE ? ? ? ? ?0x60 > -#define GPMC_CS_SIZE ? ? ? ? ? 0x30 > + > +/* Control Commands */ > +#define GPMC_CONFIG_WP ? ? ? ? 0x00000001 > +#define GPMC_CONFIG_RDY_BSY ? ?0x00000002 > +#define GPMC_CONFIG_DEV_SIZE ? 0x00000003 > +#define GPMC_CONFIG_DEV_TYPE ? 0x00000004 > +#define GPMC_NAND_COMMAND ? ? ?0x00000005 > +#define GPMC_NAND_ADDRESS ? ? ?0x00000006 > +#define GPMC_NAND_DATA ? ? ? ? 0x00000007 > +#define GPMC_STATUS_BUFFER ? ? 0x00000008 /* 1: buffer is available to write */ > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */ > +#define GPMC_PREFETCH_COUNT ? ?0x0000000A /* remaining bytes to be read/write*/ > +#define GPMC_GET_SET_IRQ_STATUS ? ? ? ?0x0000000B > + > +/* ECC commands */ > +#define GPMC_ECC_READ ? ? ? ? ?0 /* Reset Hardware ECC for read */ > +#define GPMC_ECC_WRITE ? ? ? ? 1 /* Reset Hardware ECC for write */ > +#define GPMC_ECC_READSYN ? ? ? 2 /* Reset before syndrom is read back */ > > ?#define GPMC_CONFIG1_WRAPBURST_SUPP ? ? (1 << 31) > ?#define GPMC_CONFIG1_READMULTIPLE_SUPP ?(1 << 30) > @@ -56,6 +72,14 @@ > ?#define GPMC_CONFIG1_FCLK_DIV4 ? ? ? ? ?(GPMC_CONFIG1_FCLK_DIV(3)) > ?#define GPMC_CONFIG7_CSVALID ? ? ? ? ? (1 << 6) > > +#define GPMC_DEVICETYPE_NOR ? ? ? ? ? ?0 > +#define GPMC_DEVICETYPE_NAND ? ? ? ? ? 2 > +#define GPMC_CONFIG_WRITEPROTECT ? ? ? 0x00000010 > +#define GPMC_STATUS_BUFF_EMPTY ? ? ? ? 0x00000001 > +#define WR_RD_PIN_MONITORING ? ? ? ? ? 0x00600000 > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ? ? ((val & 0x7f000000) >> 24) > +#define GPMC_PREFETCH_STATUS_COUNT(val) ? ? ? ?(val & 0x00003fff) > + > ?/* > ?* Note that all values in this struct are in nanoseconds, while > ?* the register values are in gpmc_fck cycles. > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved); > ?extern int gpmc_cs_reserved(int cs); > ?extern int gpmc_prefetch_enable(int cs, int dma_mode, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?unsigned int u32_count, int is_write); > -extern void gpmc_prefetch_reset(void); > +extern int gpmc_prefetch_reset(int cs); > ?extern int gpmc_prefetch_status(void); > ?extern void omap3_gpmc_save_context(void); > ?extern void omap3_gpmc_restore_context(void); > ?extern void gpmc_init(void); > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval); > > +int gpmc_ecc_init(int cs, int ecc_size); > +int gpmc_enable_hwecc(int cs, int mode, int dev_width); > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); > +int gpmc_ecc_reset(int cs); > ?#endif > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > index 7545568..206406b > --- a/drivers/mtd/nand/omap2.c > +++ b/drivers/mtd/nand/omap2.c > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) > ? ? ? ? ? ? ? ?} while (len); > > ? ? ? ? ? ? ? ?/* disable and stop the PFPW engine */ > - ? ? ? ? ? ? ? gpmc_prefetch_reset(); > + ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); Not required. see above comments. > ? ? ? ?} > ?} > > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, > ? ? ? ? ? ? ? ?} > > ? ? ? ? ? ? ? ?/* disable and stop the PFPW engine */ > - ? ? ? ? ? ? ? gpmc_prefetch_reset(); > + ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); Not required. see above comments. > ? ? ? ?} > ?} > > -- > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > the body of a message to majordomo at vger.kernel.org > More majordomo info at ?http://vger.kernel.org/majordomo-info.html > -- Regards, Vimal Singh From peterb at logicpd.com Wed May 19 11:14:11 2010 From: peterb at logicpd.com (Peter Barada) Date: Wed, 19 May 2010 11:14:11 -0400 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> Message-ID: <1274282051.6286.11.camel@thunk> On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote: > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > > few functions added in gpmc module and to be used by other drivers like NAND. > > E.g.: - ioctl function > > - ecc functions > > > > Signed-off-by: Sukumar Ghorai > > --- > > arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++- > > arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++- > > drivers/mtd/nand/omap2.c | 4 +- > > 3 files changed, 274 insertions(+), 11 deletions(-) > > > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > > index 5bc3ca0..7e6d821 > > --- a/arch/arm/mach-omap2/gpmc.c > > +++ b/arch/arm/mach-omap2/gpmc.c > > @@ -46,8 +46,9 @@ > > #define GPMC_ECC_CONFIG 0x1f4 > > #define GPMC_ECC_CONTROL 0x1f8 > > #define GPMC_ECC_SIZE_CONFIG 0x1fc > > +#define GPMC_ECC1_RESULT 0x200 > > > > -#define GPMC_CS0 0x60 > > +#define GPMC_CS0_BASE 0x60 > > #define GPMC_CS_SIZE 0x30 > > > > #define GPMC_MEM_START 0x00000000 > > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs { > > static struct resource gpmc_mem_root; > > static struct resource gpmc_cs_mem[GPMC_CS_NUM]; > > static DEFINE_SPINLOCK(gpmc_mem_lock); > > -static unsigned gpmc_cs_map; > > +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ > > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ > > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ > > > > static void __iomem *gpmc_base; > > > > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx) > > return __raw_readl(gpmc_base + idx); > > } > > > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > + __raw_writeb(val, reg_addr); > > +} > > + > > +static u8 gpmc_cs_read_byte(int cs, int idx) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > + return __raw_readb(reg_addr); > > +} > > + > > void gpmc_cs_write_reg(int cs, int idx, u32 val) > > { > > void __iomem *reg_addr; > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > __raw_writel(val, reg_addr); > > } > > > > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > > { > > void __iomem *reg_addr; > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > return __raw_readl(reg_addr); > > } > > > > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs) > > EXPORT_SYMBOL(gpmc_cs_free); > > > > /** > > + * gpmc_hwcontrol - hardware specific access (read/ write) control > > + * @cs: chip select number > > + * @cmd: command type > > + * @write: 1 for write; 0 for read > > + * @wval: value to write > > + * @rval: read pointer > > + */ > > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval) > > +{ > > + u32 regval = 0; > > + > > + if (!write && !rval) > > + return -EINVAL; > > + > > + switch (cmd) { > > + case GPMC_STATUS_BUFFER: > > + regval = gpmc_read_reg(GPMC_STATUS); > > + /* 1 : buffer is available to write */ > > + *rval = regval & GPMC_STATUS_BUFF_EMPTY; > > + break; > > + > > + case GPMC_GET_SET_IRQ_STATUS: > > + if (write) > > + gpmc_write_reg(GPMC_IRQSTATUS, wval); > > + else > > + *rval = gpmc_read_reg(GPMC_IRQSTATUS); > > + break; > > + > > + case GPMC_PREFETCH_FIFO_CNT: > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); > > + break; > > + > > + case GPMC_PREFETCH_COUNT: > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval); > > + break; > > + > > + case GPMC_CONFIG_WP: > > + regval = gpmc_read_reg(GPMC_CONFIG); > > + if (wval) > > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ > > + else > > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */ > > + gpmc_write_reg(GPMC_CONFIG, regval); > > + break; > > + > > + case GPMC_CONFIG_RDY_BSY: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= WR_RD_PIN_MONITORING; > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). On the Logic LV SOM/Torpedo, indeed the R/B# pin from the NAND flash in the Micron mt29c2g4maklajg-6it POP part is connected to the WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND accesses. > > + > > + case GPMC_CONFIG_DEV_SIZE: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= GPMC_CONFIG1_DEVICESIZE(wval); > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_CONFIG_DEV_TYPE: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= GPMC_CONFIG1_DEVICETYPE(wval); > > + if (wval == GPMC_DEVICETYPE_NOR) > > + regval |= GPMC_CONFIG1_MUXADDDATA; > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_NAND_COMMAND: > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); > > + break; > > + > > + case GPMC_NAND_ADDRESS: > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); > > + break; > > + > > + case GPMC_NAND_DATA: > > + if (write) > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); > > + else > > + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); > > + break; > > + > > + default: > > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(gpmc_hwcontrol); > > + > > +/** > > * gpmc_prefetch_enable - configures and starts prefetch transfer > > - * @cs: nand cs (chip select) number > > + * @cs: cs (chip select) number > > * @dma_mode: dma mode enable (1) or disable (0) > > * @u32_count: number of bytes to be transferred > > * @is_write: prefetch read(0) or write post(1) mode > > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode, > > { > > uint32_t prefetch_config1; > > > > + if (gpmc_pref_used == -EINVAL) > > + gpmc_pref_used = cs; > > + else > > + return -EBUSY; > > This is not required. Prefetch engine has just one instance > > > + > > if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { > > and any prefetch request will be done only if above check passes. > Which actually checks if 'prefetch' is busy or not. > You can see in NAND driver (omap2.c) code, it understands that. > > > /* Set the amount of bytes to be prefetched */ > > gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > > /** > > * gpmc_prefetch_reset - disables and stops the prefetch engine > > */ > > -void gpmc_prefetch_reset(void) > > +int gpmc_prefetch_reset(int cs) > > { > > + if (gpmc_pref_used == cs) > > + gpmc_pref_used = -EINVAL; > > + else > > + return -EINVAL; > > + > > This is also not required. As, this function will be called only if > prefetch was used. > > > /* Stop the PFPW engine */ > > gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); > > > > /* Reset/disable the PFPW engine */ > > gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); > > + > > + return 0; > > } > > EXPORT_SYMBOL(gpmc_prefetch_reset); > > > > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void) > > } > > } > > #endif /* CONFIG_ARCH_OMAP3 */ > > + > > +/** > > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller > > + * @cs: chip select number > > + * @ecc_size: number of bytes for ecc generation > > + */ > > + > > +int gpmc_ecc_init(int cs, int ecc_size) > > +{ > > + unsigned int val = 0x0; > > + > > + /* check if ecc engine already by another cs */ > > + if (gpmc_ecc_used == -EINVAL) > > + gpmc_ecc_used = cs; > > + else > > + return -EBUSY; > Here few things need be to consider: > 1. 'init' is supposed to done once for every instance of driver during probe > 2. But ECC engine, too, have only one instance at a time, So > 3. As long as all NAND chip are supposed to use same ECC machenism, we > can go for only one time 'init' for all drivers, perhaps in > gpmc_nand.c. > 4. But in case, different instances of driver (or NAND chip) requires > different ECC machenism (for ex. Hamming or BCH, or even with > different capabilities of error correction), > this will no longer vailid. Then rather we should have something like > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > needs it (something like as it is done for prefetch engine). > > > + > > + /* read ecc control register */ > > + val = gpmc_read_reg(GPMC_ECC_CONTROL); > > + > > + /* clear ecc and enable bits */ > > + val = ((0x00000001<<8) | 0x00000001); > > + gpmc_write_reg(GPMC_ECC_CONTROL, val); > > + > > + /* Read from ECC Size Config Register */ > > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > > + > > + /* program ecc and result sizes */ > > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > > + > > + return 0; > > +} > > + > > +/** > > + * gpmc_calculate_ecc - generate non-inverted ecc bytes > > + * @cs: chip select number > > + * @dat: data pointer over which ecc is computed > > + * @ecc_code: ecc code buffer > > + * > > + * Using non-inverted ECC is considered ugly since writing a blank > > + * page (padding) will clear the ECC bytes. This is not a problem as long > > + * no one is trying to write data on the seemingly unused page. Reading > > + * an erased page will produce an ECC mismatch between generated and read > > + * ECC bytes that has to be dealt with separately. > > + */ > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) > > +{ > > + unsigned int val = 0x0; > > + > > + if (gpmc_ecc_used != cs) > > + return -EINVAL; > > + > > + /* read ecc result */ > > + val = gpmc_read_reg(GPMC_ECC1_RESULT); > > + *ecc_code++ = val; /* P128e, ..., P1e */ > > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */ > > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ > > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); > > + > > + return 0; > > +} > > + > > +/** > > + * gpmc_enable_hwecc - enable hardware ecc functionality > > + * @cs: chip select number > > + * @mode: read/write mode > > + * @dev_width: device bus width(1 for x16, 0 for x8) > > + */ > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width) > > +{ > > + unsigned int val; > > + > > + if (gpmc_ecc_used != cs) > > + return -EINVAL; > > + > > + switch (mode) { > > + case GPMC_ECC_READ: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > + break; > > + case GPMC_ECC_READSYN: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); > > + break; > > + case GPMC_ECC_WRITE: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > + break; > > + default: > > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); > > + break; > > + } > > + > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ > > + val = (dev_width << 7) | (cs << 1) | (0x1); > > + gpmc_write_reg(GPMC_ECC_CONFIG, val); > > + return 0; > > +} > > + > > +/** > > + * gmpc_ecc_reset - release the HW ECC in GPMC controller > > + * @cs: Chip select number > > + */ > > +int gpmc_ecc_reset(int cs) > > +{ > > + if (gpmc_ecc_used == cs) > > + gpmc_ecc_used = -EINVAL; > > + else > > + return -EINVAL; > > + > > + return 0; > > +} > > + > > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h > > index 145838a..67a3442 > > --- a/arch/arm/plat-omap/include/plat/gpmc.h > > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > > @@ -27,8 +27,24 @@ > > > > #define GPMC_CONFIG 0x50 > > #define GPMC_STATUS 0x54 > > -#define GPMC_CS0_BASE 0x60 > > -#define GPMC_CS_SIZE 0x30 > > + > > +/* Control Commands */ > > +#define GPMC_CONFIG_WP 0x00000001 > > +#define GPMC_CONFIG_RDY_BSY 0x00000002 > > +#define GPMC_CONFIG_DEV_SIZE 0x00000003 > > +#define GPMC_CONFIG_DEV_TYPE 0x00000004 > > +#define GPMC_NAND_COMMAND 0x00000005 > > +#define GPMC_NAND_ADDRESS 0x00000006 > > +#define GPMC_NAND_DATA 0x00000007 > > +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */ > > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */ > > +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/ > > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B > > + > > +/* ECC commands */ > > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ > > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ > > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ > > > > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) > > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) > > @@ -56,6 +72,14 @@ > > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) > > #define GPMC_CONFIG7_CSVALID (1 << 6) > > > > +#define GPMC_DEVICETYPE_NOR 0 > > +#define GPMC_DEVICETYPE_NAND 2 > > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 > > +#define GPMC_STATUS_BUFF_EMPTY 0x00000001 > > +#define WR_RD_PIN_MONITORING 0x00600000 > > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24) > > +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) > > + > > /* > > * Note that all values in this struct are in nanoseconds, while > > * the register values are in gpmc_fck cycles. > > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved); > > extern int gpmc_cs_reserved(int cs); > > extern int gpmc_prefetch_enable(int cs, int dma_mode, > > unsigned int u32_count, int is_write); > > -extern void gpmc_prefetch_reset(void); > > +extern int gpmc_prefetch_reset(int cs); > > extern int gpmc_prefetch_status(void); > > extern void omap3_gpmc_save_context(void); > > extern void omap3_gpmc_restore_context(void); > > extern void gpmc_init(void); > > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval); > > > > +int gpmc_ecc_init(int cs, int ecc_size); > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width); > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); > > +int gpmc_ecc_reset(int cs); > > #endif > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > > index 7545568..206406b > > --- a/drivers/mtd/nand/omap2.c > > +++ b/drivers/mtd/nand/omap2.c > > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) > > } while (len); > > > > /* disable and stop the PFPW engine */ > > - gpmc_prefetch_reset(); > > + gpmc_prefetch_reset(info->gpmc_cs); > Not required. see above comments. > > > } > > } > > > > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, > > } > > > > /* disable and stop the PFPW engine */ > > - gpmc_prefetch_reset(); > > + gpmc_prefetch_reset(info->gpmc_cs); > Not required. see above comments. > > } > > } > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > > the body of a message to majordomo at vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > > From vimal.newwork at gmail.com Wed May 19 11:30:04 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Wed, 19 May 2010 21:00:04 +0530 Subject: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages In-Reply-To: <1274181389-7488-3-git-send-email-s-ghorai@ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274181389-7488-3-git-send-email-s-ghorai@ti.com> Message-ID: On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > This patch removes direct reference of gpmc address from generic nand platform code. > Nand platform code now uses wrapper functions which are implemented in gpmc module. > > Signed-off-by: Sukumar Ghorai [...] > > @@ -287,16 +246,15 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) > ?{ > ? ? ? ?struct omap_nand_info *info = container_of(mtd, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct omap_nand_info, mtd); > - ? ? ? uint32_t pfpw_status = 0, r_count = 0; > + ? ? ? u32 r_count = 0; > ? ? ? ?int ret = 0; > - ? ? ? u32 *p = (u32 *)buf; > + ? ? ? u32 *p; > > ? ? ? ?/* take care of subpage reads */ > ? ? ? ?for (; len % 4 != 0; ) { > ? ? ? ? ? ? ? ?*buf++ = __raw_readb(info->nand.IO_ADDR_R); > ? ? ? ? ? ? ? ?len--; > ? ? ? ?} > - ? ? ? p = (u32 *) buf; Above code had an issue, which was fixed by this commit: http://git.infradead.org/mtd-2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d I would suggest you to prepare your patch on MTD tree. > > ? ? ? ?/* configure and start prefetch transfer */ > ? ? ? ?ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0); > @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) > ? ? ? ? ? ? ? ?else > ? ? ? ? ? ? ? ? ? ? ? ?omap_read_buf8(mtd, buf, len); > ? ? ? ?} else { > + ? ? ? ? ? ? ? p = (u32 *) buf; > ? ? ? ? ? ? ? ?do { > - ? ? ? ? ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); > - ? ? ? ? ? ? ? ? ? ? ? r_count = ((pfpw_status >> 24) & 0x7F) >> 2; > - ? ? ? ? ? ? ? ? ? ? ? ioread32_rep(info->nand_pref_fifo_add, p, r_count); > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count); > + ? ? ? ? ? ? ? ? ? ? ? r_count = r_count >> 2; > + ? ? ? ? ? ? ? ? ? ? ? ioread32_rep(info->nand.IO_ADDR_R, p, r_count); > ? ? ? ? ? ? ? ? ? ? ? ?p += r_count; > - ? ? ? ? ? ? ? ? ? ? ? len -= r_count << 2; > + ? ? ? ? ? ? ? ? ? ? ? len -= (r_count << 2); Braces are not required here. > ? ? ? ? ? ? ? ?} while (len); > - After call to 'gpmc_prefetch_enable', next line are: if (ret) { /* PFPW engine is busy, use cpu copy method */ if (info->nand.options & NAND_BUSWIDTH_16) ... ... > - ? ? ? ? ? ? ? /* disable and stop the PFPW engine */ > - ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); > ? ? ? ?} So, if above 'if' fails, driver will not get prefetch engine (it was already busy). Then it doesn't makes sense to call for __reset__. > + ? ? ? /* disable and stop the PFPW engine */ > + ? ? ? gpmc_prefetch_reset(info->gpmc_cs); (Also see my comments on your other patch.) > ?} > > ?/** > @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info *mtd, > ?{ > ? ? ? ?struct omap_nand_info *info = container_of(mtd, > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct omap_nand_info, mtd); > - ? ? ? uint32_t pfpw_status = 0, w_count = 0; > + ? ? ? uint32_t pref_count = 0, w_count = 0; > ? ? ? ?int i = 0, ret = 0; > - ? ? ? u16 *p = (u16 *) buf; > + ? ? ? u16 *p; > > ? ? ? ?/* take care of subpage writes */ > ? ? ? ?if (len % 2 != 0) { > - ? ? ? ? ? ? ? writeb(*buf, info->nand.IO_ADDR_R); > + ? ? ? ? ? ? ? writeb(*buf, info->nand.IO_ADDR_W); > ? ? ? ? ? ? ? ?p = (u16 *)(buf + 1); > ? ? ? ? ? ? ? ?len--; > ? ? ? ?} > @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info *mtd, > ? ? ? ? ? ? ? ?else > ? ? ? ? ? ? ? ? ? ? ? ?omap_write_buf8(mtd, buf, len); > ? ? ? ?} else { > - ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); > - ? ? ? ? ? ? ? while (pfpw_status & 0x3FFF) { > - ? ? ? ? ? ? ? ? ? ? ? w_count = ((pfpw_status >> 24) & 0x7F) >> 1; > + ? ? ? ? ? ? ? p = (u16 *) buf; > + ? ? ? ? ? ? ? while (len) { > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_FIFO_CNT, 0, 0, &w_count); > + ? ? ? ? ? ? ? ? ? ? ? w_count = w_count >> 1; > ? ? ? ? ? ? ? ? ? ? ? ?for (i = 0; (i < w_count) && len; i++, len -= 2) > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iowrite16(*p++, info->nand_pref_fifo_add); > - ? ? ? ? ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iowrite16(*p++, info->nand.IO_ADDR_W); > ? ? ? ? ? ? ? ?} > - > - ? ? ? ? ? ? ? /* disable and stop the PFPW engine */ > - ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); > + ? ? ? ? ? ? ? /* wait for data to flushed-out before reset the prefetch */ > + ? ? ? ? ? ? ? do { > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_COUNT, 0, 0, &pref_count); > + ? ? ? ? ? ? ? } while (pref_count); > ? ? ? ?} > + ? ? ? /* disable and stop the PFPW engine */ > + ? ? ? gpmc_prefetch_reset(info->gpmc_cs); Same as above. > ?} > > ?#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA > @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr, > ? ? ? ?/* setup and start DMA using dma_addr */ > ? ? ? ?wait_for_completion(&info->comp); > > - ? ? ? while (0x3fff & (prefetch_status = gpmc_prefetch_status())) > - ? ? ? ? ? ? ? ; > + ? ? ? do { > + ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_COUNT, 0, 0, &prefetch_status); > + ? ? ? } while (prefetch_status); > ? ? ? ?/* disable and stop the PFPW engine */ > ? ? ? ?gpmc_prefetch_reset(); > > @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info *mtd, > ? ? ? ? ? ? ? ?omap_write_buf_pref(mtd, buf, len); > ? ? ? ?else > ? ? ? ? ? ? ? ?/* start transfer in DMA mode */ > - ? ? ? ? ? ? ? omap_nand_dma_transfer(mtd, buf, len, 0x1); > + ? ? ? ? ? ? ? omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); This is already fixed. See commit: http://git.infradead.org/mtd-2.6.git/commitdiff/bdaefc41627b6f2815ef7aa476dfa4ebb3ad499f Rest, patches looks good. It is a good clean-up all together. -- Regards, Vimal Singh From peter.barada at gmail.com Wed May 19 11:48:14 2010 From: peter.barada at gmail.com (Peter Barada) Date: Wed, 19 May 2010 11:48:14 -0400 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> Message-ID: <1274284094.6286.17.camel@thunk> On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote: > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > > few functions added in gpmc module and to be used by other drivers like NAND. > > E.g.: - ioctl function > > - ecc functions > > > > Signed-off-by: Sukumar Ghorai > > --- > > arch/arm/mach-omap2/gpmc.c | 246 +++++++++++++++++++++++++++++++- > > arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++- > > drivers/mtd/nand/omap2.c | 4 +- > > 3 files changed, 274 insertions(+), 11 deletions(-) > > > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > > index 5bc3ca0..7e6d821 > > --- a/arch/arm/mach-omap2/gpmc.c > > +++ b/arch/arm/mach-omap2/gpmc.c > > @@ -46,8 +46,9 @@ > > #define GPMC_ECC_CONFIG 0x1f4 > > #define GPMC_ECC_CONTROL 0x1f8 > > #define GPMC_ECC_SIZE_CONFIG 0x1fc > > +#define GPMC_ECC1_RESULT 0x200 > > > > -#define GPMC_CS0 0x60 > > +#define GPMC_CS0_BASE 0x60 > > #define GPMC_CS_SIZE 0x30 > > > > #define GPMC_MEM_START 0x00000000 > > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs { > > static struct resource gpmc_mem_root; > > static struct resource gpmc_cs_mem[GPMC_CS_NUM]; > > static DEFINE_SPINLOCK(gpmc_mem_lock); > > -static unsigned gpmc_cs_map; > > +static unsigned int gpmc_cs_map; /* flag for cs which are initialized */ > > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ > > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ > > > > static void __iomem *gpmc_base; > > > > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx) > > return __raw_readl(gpmc_base + idx); > > } > > > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > + __raw_writeb(val, reg_addr); > > +} > > + > > +static u8 gpmc_cs_read_byte(int cs, int idx) > > +{ > > + void __iomem *reg_addr; > > + > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > + return __raw_readb(reg_addr); > > +} > > + > > void gpmc_cs_write_reg(int cs, int idx, u32 val) > > { > > void __iomem *reg_addr; > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > __raw_writel(val, reg_addr); > > } > > > > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > > { > > void __iomem *reg_addr; > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + idx; > > return __raw_readl(reg_addr); > > } > > > > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs) > > EXPORT_SYMBOL(gpmc_cs_free); > > > > /** > > + * gpmc_hwcontrol - hardware specific access (read/ write) control > > + * @cs: chip select number > > + * @cmd: command type > > + * @write: 1 for write; 0 for read > > + * @wval: value to write > > + * @rval: read pointer > > + */ > > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval) > > +{ > > + u32 regval = 0; > > + > > + if (!write && !rval) > > + return -EINVAL; > > + > > + switch (cmd) { > > + case GPMC_STATUS_BUFFER: > > + regval = gpmc_read_reg(GPMC_STATUS); > > + /* 1 : buffer is available to write */ > > + *rval = regval & GPMC_STATUS_BUFF_EMPTY; > > + break; > > + > > + case GPMC_GET_SET_IRQ_STATUS: > > + if (write) > > + gpmc_write_reg(GPMC_IRQSTATUS, wval); > > + else > > + *rval = gpmc_read_reg(GPMC_IRQSTATUS); > > + break; > > + > > + case GPMC_PREFETCH_FIFO_CNT: > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); > > + break; > > + > > + case GPMC_PREFETCH_COUNT: > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval); > > + break; > > + > > + case GPMC_CONFIG_WP: > > + regval = gpmc_read_reg(GPMC_CONFIG); > > + if (wval) > > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is ON */ > > + else > > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is OFF */ > > + gpmc_write_reg(GPMC_CONFIG, regval); > > + break; > > + > > + case GPMC_CONFIG_RDY_BSY: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= WR_RD_PIN_MONITORING; > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND accesses > > + > > + case GPMC_CONFIG_DEV_SIZE: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= GPMC_CONFIG1_DEVICESIZE(wval); > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_CONFIG_DEV_TYPE: > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > + regval |= GPMC_CONFIG1_DEVICETYPE(wval); > > + if (wval == GPMC_DEVICETYPE_NOR) > > + regval |= GPMC_CONFIG1_MUXADDDATA; > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > + break; > > + > > + case GPMC_NAND_COMMAND: > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); > > + break; > > + > > + case GPMC_NAND_ADDRESS: > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); > > + break; > > + > > + case GPMC_NAND_DATA: > > + if (write) > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, wval); > > + else > > + *rval = gpmc_cs_read_byte(cs, GPMC_CS_NAND_DATA); > > + break; > > + > > + default: > > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n"); > > + return -EINVAL; > > + } > > + > > + return 0; > > +} > > +EXPORT_SYMBOL(gpmc_hwcontrol); > > + > > +/** > > * gpmc_prefetch_enable - configures and starts prefetch transfer > > - * @cs: nand cs (chip select) number > > + * @cs: cs (chip select) number > > * @dma_mode: dma mode enable (1) or disable (0) > > * @u32_count: number of bytes to be transferred > > * @is_write: prefetch read(0) or write post(1) mode > > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode, > > { > > uint32_t prefetch_config1; > > > > + if (gpmc_pref_used == -EINVAL) > > + gpmc_pref_used = cs; > > + else > > + return -EBUSY; > > This is not required. Prefetch engine has just one instance > > > + > > if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { > > and any prefetch request will be done only if above check passes. > Which actually checks if 'prefetch' is busy or not. > You can see in NAND driver (omap2.c) code, it understands that. > > > /* Set the amount of bytes to be prefetched */ > > gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > > /** > > * gpmc_prefetch_reset - disables and stops the prefetch engine > > */ > > -void gpmc_prefetch_reset(void) > > +int gpmc_prefetch_reset(int cs) > > { > > + if (gpmc_pref_used == cs) > > + gpmc_pref_used = -EINVAL; > > + else > > + return -EINVAL; > > + > > This is also not required. As, this function will be called only if > prefetch was used. > > > /* Stop the PFPW engine */ > > gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); > > > > /* Reset/disable the PFPW engine */ > > gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); > > + > > + return 0; > > } > > EXPORT_SYMBOL(gpmc_prefetch_reset); > > > > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void) > > } > > } > > #endif /* CONFIG_ARCH_OMAP3 */ > > + > > +/** > > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller > > + * @cs: chip select number > > + * @ecc_size: number of bytes for ecc generation > > + */ > > + > > +int gpmc_ecc_init(int cs, int ecc_size) > > +{ > > + unsigned int val = 0x0; > > + > > + /* check if ecc engine already by another cs */ > > + if (gpmc_ecc_used == -EINVAL) > > + gpmc_ecc_used = cs; > > + else > > + return -EBUSY; > Here few things need be to consider: > 1. 'init' is supposed to done once for every instance of driver during probe > 2. But ECC engine, too, have only one instance at a time, So > 3. As long as all NAND chip are supposed to use same ECC machenism, we > can go for only one time 'init' for all drivers, perhaps in > gpmc_nand.c. > 4. But in case, different instances of driver (or NAND chip) requires > different ECC machenism (for ex. Hamming or BCH, or even with > different capabilities of error correction), > this will no longer vailid. Then rather we should have something like > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > needs it (something like as it is done for prefetch engine). > > > + > > + /* read ecc control register */ > > + val = gpmc_read_reg(GPMC_ECC_CONTROL); > > + > > + /* clear ecc and enable bits */ > > + val = ((0x00000001<<8) | 0x00000001); > > + gpmc_write_reg(GPMC_ECC_CONTROL, val); > > + > > + /* Read from ECC Size Config Register */ > > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > > + > > + /* program ecc and result sizes */ > > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > > + > > + return 0; > > +} > > + > > +/** > > + * gpmc_calculate_ecc - generate non-inverted ecc bytes > > + * @cs: chip select number > > + * @dat: data pointer over which ecc is computed > > + * @ecc_code: ecc code buffer > > + * > > + * Using non-inverted ECC is considered ugly since writing a blank > > + * page (padding) will clear the ECC bytes. This is not a problem as long > > + * no one is trying to write data on the seemingly unused page. Reading > > + * an erased page will produce an ECC mismatch between generated and read > > + * ECC bytes that has to be dealt with separately. > > + */ > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) > > +{ > > + unsigned int val = 0x0; > > + > > + if (gpmc_ecc_used != cs) > > + return -EINVAL; > > + > > + /* read ecc result */ > > + val = gpmc_read_reg(GPMC_ECC1_RESULT); > > + *ecc_code++ = val; /* P128e, ..., P1e */ > > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */ > > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e */ > > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); > > + > > + return 0; > > +} > > + > > +/** > > + * gpmc_enable_hwecc - enable hardware ecc functionality > > + * @cs: chip select number > > + * @mode: read/write mode > > + * @dev_width: device bus width(1 for x16, 0 for x8) > > + */ > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width) > > +{ > > + unsigned int val; > > + > > + if (gpmc_ecc_used != cs) > > + return -EINVAL; > > + > > + switch (mode) { > > + case GPMC_ECC_READ: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > + break; > > + case GPMC_ECC_READSYN: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); > > + break; > > + case GPMC_ECC_WRITE: > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > + break; > > + default: > > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", mode); > > + break; > > + } > > + > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ > > + val = (dev_width << 7) | (cs << 1) | (0x1); > > + gpmc_write_reg(GPMC_ECC_CONFIG, val); > > + return 0; > > +} > > + > > +/** > > + * gmpc_ecc_reset - release the HW ECC in GPMC controller > > + * @cs: Chip select number > > + */ > > +int gpmc_ecc_reset(int cs) > > +{ > > + if (gpmc_ecc_used == cs) > > + gpmc_ecc_used = -EINVAL; > > + else > > + return -EINVAL; > > + > > + return 0; > > +} > > + > > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h > > index 145838a..67a3442 > > --- a/arch/arm/plat-omap/include/plat/gpmc.h > > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > > @@ -27,8 +27,24 @@ > > > > #define GPMC_CONFIG 0x50 > > #define GPMC_STATUS 0x54 > > -#define GPMC_CS0_BASE 0x60 > > -#define GPMC_CS_SIZE 0x30 > > + > > +/* Control Commands */ > > +#define GPMC_CONFIG_WP 0x00000001 > > +#define GPMC_CONFIG_RDY_BSY 0x00000002 > > +#define GPMC_CONFIG_DEV_SIZE 0x00000003 > > +#define GPMC_CONFIG_DEV_TYPE 0x00000004 > > +#define GPMC_NAND_COMMAND 0x00000005 > > +#define GPMC_NAND_ADDRESS 0x00000006 > > +#define GPMC_NAND_DATA 0x00000007 > > +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available to write */ > > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO for r/w */ > > +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be read/write*/ > > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B > > + > > +/* ECC commands */ > > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ > > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ > > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back */ > > > > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) > > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) > > @@ -56,6 +72,14 @@ > > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) > > #define GPMC_CONFIG7_CSVALID (1 << 6) > > > > +#define GPMC_DEVICETYPE_NOR 0 > > +#define GPMC_DEVICETYPE_NAND 2 > > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 > > +#define GPMC_STATUS_BUFF_EMPTY 0x00000001 > > +#define WR_RD_PIN_MONITORING 0x00600000 > > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> 24) > > +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) > > + > > /* > > * Note that all values in this struct are in nanoseconds, while > > * the register values are in gpmc_fck cycles. > > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int reserved); > > extern int gpmc_cs_reserved(int cs); > > extern int gpmc_prefetch_enable(int cs, int dma_mode, > > unsigned int u32_count, int is_write); > > -extern void gpmc_prefetch_reset(void); > > +extern int gpmc_prefetch_reset(int cs); > > extern int gpmc_prefetch_status(void); > > extern void omap3_gpmc_save_context(void); > > extern void omap3_gpmc_restore_context(void); > > extern void gpmc_init(void); > > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval); > > > > +int gpmc_ecc_init(int cs, int ecc_size); > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width); > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); > > +int gpmc_ecc_reset(int cs); > > #endif > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > > index 7545568..206406b > > --- a/drivers/mtd/nand/omap2.c > > +++ b/drivers/mtd/nand/omap2.c > > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len) > > } while (len); > > > > /* disable and stop the PFPW engine */ > > - gpmc_prefetch_reset(); > > + gpmc_prefetch_reset(info->gpmc_cs); > Not required. see above comments. > > > } > > } > > > > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd, > > } > > > > /* disable and stop the PFPW engine */ > > - gpmc_prefetch_reset(); > > + gpmc_prefetch_reset(info->gpmc_cs); > Not required. see above comments. > > } > > } > > > > -- > > To unsubscribe from this list: send the line "unsubscribe linux-omap" in > > the body of a message to majordomo at vger.kernel.org > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > > From dwmw2 at infradead.org Wed May 19 12:49:08 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Wed, 19 May 2010 17:49:08 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> <1274226122.6930.8416.camel@macbook.infradead.org> Message-ID: <1274287748.6930.10308.camel@macbook.infradead.org> On Wed, 2010-05-19 at 11:47 +0200, Joakim Tjernlund wrote: > > > It could perhaps be broken into smaller simple patches along the lines > > of: > > - Add 'work_done' return value from jffs2_erase_pending_blocks() > > - Call jffs2_erase_pending_blocks() from jffs2_g_c_pass() > > - Fix the conditions under which jffs2_g_c_pass() will return -EINVAL, > > fix the way that jffs2_reserve_space() will respond to that, and fix > > jffs2_erase_succeeded() to actually wake up the erase_wait queue. > > - Remove locking from jffs2_garbage_collect_trigger() and require that > > callers have c->erase_completion_lock already held. > > - Change most callers of jffs2_erase_pending_trigger() to call > > jffs2_garbage_collect_trigger() instead. To comply with the locking > > rules, this may involve moving the call up or down a few lines, or > > sometimes adding a new lock/unlock pair around it. > > - Remove jffs2_erase_pending_blocks() call from jffs2_write_super(). > > - Rename jffs2_erase_pending_trigger() and its only remaining caller > > in wbuf.c to jffs2_dirty_trigger(). > > I have tried this on my 2.6.33 tree and it seems to work OK. > I am currenltly copying lots of files and deleting them in a loop, > so far so good :) Needed to "tweak": OK, this is now pushed, in some semblance of the above form. I think I got the attribution right on the bits which you wrote. Thanks again. -- dwmw2 From s-ghorai at ti.com Wed May 19 13:24:19 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Wed, 19 May 2010 22:54:19 +0530 Subject: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages In-Reply-To: References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274181389-7488-3-git-send-email-s-ghorai@ti.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D43@dbde02.ent.ti.com> Vimal, > -----Original Message----- > From: Vimal Singh [mailto:vimal.newwork at gmail.com] > Sent: 2010-05-19 21:00 > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; > tony at atomide.com; sakoman at gmail.com; mike at compulab.co.il; > Artem.Bityutskiy at nokia.com > Subject: Re: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages > > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > > This patch removes direct reference of gpmc address from generic nand > platform code. > > Nand platform code now uses wrapper functions which are implemented in > gpmc module. > > > > Signed-off-by: Sukumar Ghorai > [...] > > > > > @@ -287,16 +246,15 @@ static void omap_read_buf_pref(struct mtd_info > *mtd, u_char *buf, int len) > > ?{ > > ? ? ? ?struct omap_nand_info *info = container_of(mtd, > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct omap_nand_info, > mtd); > > - ? ? ? uint32_t pfpw_status = 0, r_count = 0; > > + ? ? ? u32 r_count = 0; > > ? ? ? ?int ret = 0; > > - ? ? ? u32 *p = (u32 *)buf; > > + ? ? ? u32 *p; > > > > ? ? ? ?/* take care of subpage reads */ > > ? ? ? ?for (; len % 4 != 0; ) { > > ? ? ? ? ? ? ? ?*buf++ = __raw_readb(info->nand.IO_ADDR_R); > > ? ? ? ? ? ? ? ?len--; > > ? ? ? ?} > > - ? ? ? p = (u32 *) buf; > > Above code had an issue, which was fixed by this commit: > http://git.infradead.org/mtd- > 2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d > > I would suggest you to prepare your patch on MTD tree. [Ghorai] Patches started posting on lo. And lets continue the same. > > > > > ? ? ? ?/* configure and start prefetch transfer */ > > ? ? ? ?ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0); > > @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info > *mtd, u_char *buf, int len) > > ? ? ? ? ? ? ? ?else > > ? ? ? ? ? ? ? ? ? ? ? ?omap_read_buf8(mtd, buf, len); > > ? ? ? ?} else { > > + ? ? ? ? ? ? ? p = (u32 *) buf; > > ? ? ? ? ? ? ? ?do { > > - ? ? ? ? ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); > > - ? ? ? ? ? ? ? ? ? ? ? r_count = ((pfpw_status >> 24) & 0x7F) >> 2; > > - ? ? ? ? ? ? ? ? ? ? ? ioread32_rep(info->nand_pref_fifo_add, p, > r_count); > > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count); > > + ? ? ? ? ? ? ? ? ? ? ? r_count = r_count >> 2; > > + ? ? ? ? ? ? ? ? ? ? ? ioread32_rep(info->nand.IO_ADDR_R, p, r_count); > > ? ? ? ? ? ? ? ? ? ? ? ?p += r_count; > > - ? ? ? ? ? ? ? ? ? ? ? len -= r_count << 2; > > + ? ? ? ? ? ? ? ? ? ? ? len -= (r_count << 2); > > Braces are not required here. [Ghorai] thanks > > > ? ? ? ? ? ? ? ?} while (len); > > - > > After call to 'gpmc_prefetch_enable', next line are: > if (ret) { > /* PFPW engine is busy, use cpu copy method */ > if (info->nand.options & NAND_BUSWIDTH_16) > ... > ... > > - ? ? ? ? ? ? ? /* disable and stop the PFPW engine */ > > - ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); > > ? ? ? ?} > > So, if above 'if' fails, driver will not get prefetch engine (it was > already busy). Then it doesn't makes sense to call for __reset__. [Ghorai] I will take this clean up as 4th patch. As its not matching with patch description. > > > + ? ? ? /* disable and stop the PFPW engine */ > > + ? ? ? gpmc_prefetch_reset(info->gpmc_cs); > > (Also see my comments on your other patch.) [Ghorai] Agree and I will take this kind of cleanup as 4th patch > > > ?} > > > > ?/** > > @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info > *mtd, > > ?{ > > ? ? ? ?struct omap_nand_info *info = container_of(mtd, > > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct omap_nand_info, > mtd); > > - ? ? ? uint32_t pfpw_status = 0, w_count = 0; > > + ? ? ? uint32_t pref_count = 0, w_count = 0; > > ? ? ? ?int i = 0, ret = 0; > > - ? ? ? u16 *p = (u16 *) buf; > > + ? ? ? u16 *p; > > > > ? ? ? ?/* take care of subpage writes */ > > ? ? ? ?if (len % 2 != 0) { > > - ? ? ? ? ? ? ? writeb(*buf, info->nand.IO_ADDR_R); > > + ? ? ? ? ? ? ? writeb(*buf, info->nand.IO_ADDR_W); > > ? ? ? ? ? ? ? ?p = (u16 *)(buf + 1); > > ? ? ? ? ? ? ? ?len--; > > ? ? ? ?} > > @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info > *mtd, > > ? ? ? ? ? ? ? ?else > > ? ? ? ? ? ? ? ? ? ? ? ?omap_write_buf8(mtd, buf, len); > > ? ? ? ?} else { > > - ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); > > - ? ? ? ? ? ? ? while (pfpw_status & 0x3FFF) { > > - ? ? ? ? ? ? ? ? ? ? ? w_count = ((pfpw_status >> 24) & 0x7F) >> 1; > > + ? ? ? ? ? ? ? p = (u16 *) buf; > > + ? ? ? ? ? ? ? while (len) { > > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_FIFO_CNT, 0, 0, > &w_count); > > + ? ? ? ? ? ? ? ? ? ? ? w_count = w_count >> 1; > > ? ? ? ? ? ? ? ? ? ? ? ?for (i = 0; (i < w_count) && len; i++, len -= 2) > > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iowrite16(*p++, info- > >nand_pref_fifo_add); > > - ? ? ? ? ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iowrite16(*p++, info->nand.IO_ADDR_W); > > ? ? ? ? ? ? ? ?} > > - > > - ? ? ? ? ? ? ? /* disable and stop the PFPW engine */ > > - ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); > > + ? ? ? ? ? ? ? /* wait for data to flushed-out before reset the > prefetch */ > > + ? ? ? ? ? ? ? do { > > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_COUNT, 0, 0, &pref_count); > > + ? ? ? ? ? ? ? } while (pref_count); > > ? ? ? ?} > > + ? ? ? /* disable and stop the PFPW engine */ > > + ? ? ? gpmc_prefetch_reset(info->gpmc_cs); > > Same as above. [Ghorai] Agree and I will take this kind of cleanup as 4th patch, as its not matching with patch description. > > > > ?} > > > > ?#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA > > @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct > mtd_info *mtd, void *addr, > > ? ? ? ?/* setup and start DMA using dma_addr */ > > ? ? ? ?wait_for_completion(&info->comp); > > > > - ? ? ? while (0x3fff & (prefetch_status = gpmc_prefetch_status())) > > - ? ? ? ? ? ? ? ; > > + ? ? ? do { > > + ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, > > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_COUNT, 0, 0, > &prefetch_status); > > + ? ? ? } while (prefetch_status); > > ? ? ? ?/* disable and stop the PFPW engine */ > > ? ? ? ?gpmc_prefetch_reset(); > > > > @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info > *mtd, > > ? ? ? ? ? ? ? ?omap_write_buf_pref(mtd, buf, len); > > ? ? ? ?else > > ? ? ? ? ? ? ? ?/* start transfer in DMA mode */ > > - ? ? ? ? ? ? ? omap_nand_dma_transfer(mtd, buf, len, 0x1); > > + ? ? ? ? ? ? ? omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); > > This is already fixed. See commit: > http://git.infradead.org/mtd- > 2.6.git/commitdiff/bdaefc41627b6f2815ef7aa476dfa4ebb3ad499f [Ghorai] thanks I will omit this from this patch > > > Rest, patches looks good. It is a good clean-up all together. [Ghorai] Is it possible for you to check once again if you have any additional comments! This is to identify the issue if any at early stage. > > -- > Regards, > Vimal Singh From s-ghorai at ti.com Wed May 19 14:04:22 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Wed, 19 May 2010 23:34:22 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: <1274284094.6286.17.camel@thunk> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274284094.6286.17.camel@thunk> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> Vimal, > -----Original Message----- > From: Peter Barada [mailto:peter.barada at gmail.com] > Sent: 2010-05-19 21:18 > To: Vimal Singh > Cc: Ghorai, Sukumar; linux-omap at vger.kernel.org; linux- > mtd at lists.infradead.org; tony at atomide.com; sakoman at gmail.com; > mike at compulab.co.il; Artem.Bityutskiy at nokia.com > Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement > > On Wed, 2010-05-19 at 20:16 +0530, Vimal Singh wrote: > > On Tue, May 18, 2010 at 4:46 PM, Sukumar Ghorai wrote: > > > few functions added in gpmc module and to be used by other drivers > like NAND. > > > E.g.: - ioctl function > > > - ecc functions > > > > > > Signed-off-by: Sukumar Ghorai > > > --- > > > arch/arm/mach-omap2/gpmc.c | 246 > +++++++++++++++++++++++++++++++- > > > arch/arm/plat-omap/include/plat/gpmc.h | 35 ++++- > > > drivers/mtd/nand/omap2.c | 4 +- > > > 3 files changed, 274 insertions(+), 11 deletions(-) > > > > > > diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c > > > index 5bc3ca0..7e6d821 > > > --- a/arch/arm/mach-omap2/gpmc.c > > > +++ b/arch/arm/mach-omap2/gpmc.c > > > @@ -46,8 +46,9 @@ > > > #define GPMC_ECC_CONFIG 0x1f4 > > > #define GPMC_ECC_CONTROL 0x1f8 > > > #define GPMC_ECC_SIZE_CONFIG 0x1fc > > > +#define GPMC_ECC1_RESULT 0x200 > > > > > > -#define GPMC_CS0 0x60 > > > +#define GPMC_CS0_BASE 0x60 > > > #define GPMC_CS_SIZE 0x30 > > > > > > #define GPMC_MEM_START 0x00000000 > > > @@ -92,7 +93,9 @@ struct omap3_gpmc_regs { > > > static struct resource gpmc_mem_root; > > > static struct resource gpmc_cs_mem[GPMC_CS_NUM]; > > > static DEFINE_SPINLOCK(gpmc_mem_lock); > > > -static unsigned gpmc_cs_map; > > > +static unsigned int gpmc_cs_map; /* flag for cs which > are initialized */ > > > +static int gpmc_pref_used = -EINVAL; /* cs using prefetch engine */ > > > +static int gpmc_ecc_used = -EINVAL; /* cs using ecc engine */ > > > > > > static void __iomem *gpmc_base; > > > > > > @@ -108,11 +111,27 @@ static u32 gpmc_read_reg(int idx) > > > return __raw_readl(gpmc_base + idx); > > > } > > > > > > +static void gpmc_cs_write_byte(int cs, int idx, u8 val) > > > +{ > > > + void __iomem *reg_addr; > > > + > > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > > + __raw_writeb(val, reg_addr); > > > +} > > > + > > > +static u8 gpmc_cs_read_byte(int cs, int idx) > > > +{ > > > + void __iomem *reg_addr; > > > + > > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > > + return __raw_readb(reg_addr); > > > +} > > > + > > > void gpmc_cs_write_reg(int cs, int idx, u32 val) > > > { > > > void __iomem *reg_addr; > > > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > > __raw_writel(val, reg_addr); > > > } > > > > > > @@ -120,7 +139,7 @@ u32 gpmc_cs_read_reg(int cs, int idx) > > > { > > > void __iomem *reg_addr; > > > > > > - reg_addr = gpmc_base + GPMC_CS0 + (cs * GPMC_CS_SIZE) + idx; > > > + reg_addr = gpmc_base + GPMC_CS0_BASE + (cs * GPMC_CS_SIZE) + > idx; > > > return __raw_readl(reg_addr); > > > } > > > > > > @@ -419,8 +438,100 @@ void gpmc_cs_free(int cs) > > > EXPORT_SYMBOL(gpmc_cs_free); > > > > > > /** > > > + * gpmc_hwcontrol - hardware specific access (read/ write) control > > > + * @cs: chip select number > > > + * @cmd: command type > > > + * @write: 1 for write; 0 for read > > > + * @wval: value to write > > > + * @rval: read pointer > > > + */ > > > +int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int *rval) > > > +{ > > > + u32 regval = 0; > > > + > > > + if (!write && !rval) > > > + return -EINVAL; > > > + > > > + switch (cmd) { > > > + case GPMC_STATUS_BUFFER: > > > + regval = gpmc_read_reg(GPMC_STATUS); > > > + /* 1 : buffer is available to write */ > > > + *rval = regval & GPMC_STATUS_BUFF_EMPTY; > > > + break; > > > + > > > + case GPMC_GET_SET_IRQ_STATUS: > > > + if (write) > > > + gpmc_write_reg(GPMC_IRQSTATUS, wval); > > > + else > > > + *rval = gpmc_read_reg(GPMC_IRQSTATUS); > > > + break; > > > + > > > + case GPMC_PREFETCH_FIFO_CNT: > > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > > > + *rval = GPMC_PREFETCH_STATUS_FIFO_CNT(regval); > > > + break; > > > + > > > + case GPMC_PREFETCH_COUNT: > > > + regval = gpmc_read_reg(GPMC_PREFETCH_STATUS); > > > + *rval = GPMC_PREFETCH_STATUS_COUNT(regval); > > > + break; > > > + > > > + case GPMC_CONFIG_WP: > > > + regval = gpmc_read_reg(GPMC_CONFIG); > > > + if (wval) > > > + regval &= ~GPMC_CONFIG_WRITEPROTECT; /* WP is > ON */ > > > + else > > > + regval |= GPMC_CONFIG_WRITEPROTECT; /* WP is > OFF */ > > > + gpmc_write_reg(GPMC_CONFIG, regval); > > > + break; > > > + > > > + case GPMC_CONFIG_RDY_BSY: > > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > > + regval |= WR_RD_PIN_MONITORING; > > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > > + break; > > > > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). > > On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the > NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the > WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND > accesses [Ghorai] So better keep this feature, > > > > + > > > + case GPMC_CONFIG_DEV_SIZE: > > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > > + regval |= GPMC_CONFIG1_DEVICESIZE(wval); > > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > > + break; > > > + > > > + case GPMC_CONFIG_DEV_TYPE: > > > + regval = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > > > + regval |= GPMC_CONFIG1_DEVICETYPE(wval); > > > + if (wval == GPMC_DEVICETYPE_NOR) > > > + regval |= GPMC_CONFIG1_MUXADDDATA; > > > + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > > > + break; > > > + > > > + case GPMC_NAND_COMMAND: > > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_COMMAND, wval); > > > + break; > > > + > > > + case GPMC_NAND_ADDRESS: > > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_ADDRESS, wval); > > > + break; > > > + > > > + case GPMC_NAND_DATA: > > > + if (write) > > > + gpmc_cs_write_byte(cs, GPMC_CS_NAND_DATA, > wval); > > > + else > > > + *rval = gpmc_cs_read_byte(cs, > GPMC_CS_NAND_DATA); > > > + break; > > > + > > > + default: > > > + printk(KERN_ERR "gpmc_hwcontrol: Not supported\n"); > > > + return -EINVAL; > > > + } > > > + > > > + return 0; > > > +} > > > +EXPORT_SYMBOL(gpmc_hwcontrol); > > > + > > > +/** > > > * gpmc_prefetch_enable - configures and starts prefetch transfer > > > - * @cs: nand cs (chip select) number > > > + * @cs: cs (chip select) number > > > * @dma_mode: dma mode enable (1) or disable (0) > > > * @u32_count: number of bytes to be transferred > > > * @is_write: prefetch read(0) or write post(1) mode > > > @@ -430,6 +541,11 @@ int gpmc_prefetch_enable(int cs, int dma_mode, > > > { > > > uint32_t prefetch_config1; > > > > > > + if (gpmc_pref_used == -EINVAL) > > > + gpmc_pref_used = cs; > > > + else > > > + return -EBUSY; > > > > This is not required. Prefetch engine has just one instance > > > > > + > > > if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) { > > > > and any prefetch request will be done only if above check passes. > > Which actually checks if 'prefetch' is busy or not. > > You can see in NAND driver (omap2.c) code, it understands that. [Ghorai] Agree here and also you mentioned not to use the reset function. So will take all these as 4th patch for cleanup. > > > > > /* Set the amount of bytes to be prefetched */ > > > gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count); > > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > > > /** > > > * gpmc_prefetch_reset - disables and stops the prefetch engine > > > */ > > > -void gpmc_prefetch_reset(void) > > > +int gpmc_prefetch_reset(int cs) > > > { > > > + if (gpmc_pref_used == cs) > > > + gpmc_pref_used = -EINVAL; > > > + else > > > + return -EINVAL; > > > + > > > > This is also not required. As, this function will be called only if > > prefetch was used. [Ghorai] Agree. Can you see this input too? http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html > > > > > /* Stop the PFPW engine */ > > > gpmc_write_reg(GPMC_PREFETCH_CONTROL, 0x0); > > > > > > /* Reset/disable the PFPW engine */ > > > gpmc_write_reg(GPMC_PREFETCH_CONFIG1, 0x0); > > > + > > > + return 0; > > > } > > > EXPORT_SYMBOL(gpmc_prefetch_reset); > > > > > > @@ -615,3 +738,114 @@ void omap3_gpmc_restore_context(void) > > > } > > > } > > > #endif /* CONFIG_ARCH_OMAP3 */ > > > + > > > +/** > > > + * gpmc_ecc_init - initialize hw ecc for device in GPMC controller > > > + * @cs: chip select number > > > + * @ecc_size: number of bytes for ecc generation > > > + */ > > > + > > > +int gpmc_ecc_init(int cs, int ecc_size) > > > +{ > > > + unsigned int val = 0x0; > > > + > > > + /* check if ecc engine already by another cs */ > > > + if (gpmc_ecc_used == -EINVAL) > > > + gpmc_ecc_used = cs; > > > + else > > > + return -EBUSY; > > Here few things need be to consider: > > 1. 'init' is supposed to done once for every instance of driver during > probe > > 2. But ECC engine, too, have only one instance at a time, So > > 3. As long as all NAND chip are supposed to use same ECC machenism, we > > can go for only one time 'init' for all drivers, perhaps in > > gpmc_nand.c. > > 4. But in case, different instances of driver (or NAND chip) requires > > different ECC machenism (for ex. Hamming or BCH, or even with > > different capabilities of error correction), > > this will no longer vailid. Then rather we should have something like > > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > > needs it (something like as it is done for prefetch engine). [Ghorai] a. do you think it will reduce the throughput? b. Moreover I think we will take this as 5th patch as cleanup/ improvemnt. c. And how to know that ECC engine is in used other driver should not use it? Any bit to know that ecc engine is busy, as we check for prefetch? d. any further input on http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html > > > > > + > > > + /* read ecc control register */ > > > + val = gpmc_read_reg(GPMC_ECC_CONTROL); > > > + > > > + /* clear ecc and enable bits */ > > > + val = ((0x00000001<<8) | 0x00000001); > > > + gpmc_write_reg(GPMC_ECC_CONTROL, val); > > > + > > > + /* Read from ECC Size Config Register */ > > > + val = gpmc_read_reg(GPMC_ECC_SIZE_CONFIG); > > > + > > > + /* program ecc and result sizes */ > > > + val = ((((ecc_size >> 1) - 1) << 22) | (0x0000000F)); > > > + gpmc_write_reg(GPMC_ECC_SIZE_CONFIG, val); > > > + > > > + return 0; > > > +} > > > + > > > +/** > > > + * gpmc_calculate_ecc - generate non-inverted ecc bytes > > > + * @cs: chip select number > > > + * @dat: data pointer over which ecc is computed > > > + * @ecc_code: ecc code buffer > > > + * > > > + * Using non-inverted ECC is considered ugly since writing a blank > > > + * page (padding) will clear the ECC bytes. This is not a problem as > long > > > + * no one is trying to write data on the seemingly unused page. > Reading > > > + * an erased page will produce an ECC mismatch between generated and > read > > > + * ECC bytes that has to be dealt with separately. > > > + */ > > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code) > > > +{ > > > + unsigned int val = 0x0; > > > + > > > + if (gpmc_ecc_used != cs) > > > + return -EINVAL; > > > + > > > + /* read ecc result */ > > > + val = gpmc_read_reg(GPMC_ECC1_RESULT); > > > + *ecc_code++ = val; /* P128e, ..., P1e */ > > > + *ecc_code++ = val >> 16; /* P128o, ..., P1o */ > > > + /* P2048o, P1024o, P512o, P256o, P2048e, P1024e, P512e, P256e > */ > > > + *ecc_code++ = ((val >> 8) & 0x0f) | ((val >> 20) & 0xf0); > > > + > > > + return 0; > > > +} > > > + > > > +/** > > > + * gpmc_enable_hwecc - enable hardware ecc functionality > > > + * @cs: chip select number > > > + * @mode: read/write mode > > > + * @dev_width: device bus width(1 for x16, 0 for x8) > > > + */ > > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width) > > > +{ > > > + unsigned int val; > > > + > > > + if (gpmc_ecc_used != cs) > > > + return -EINVAL; > > > + > > > + switch (mode) { > > > + case GPMC_ECC_READ: > > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > > + break; > > > + case GPMC_ECC_READSYN: > > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x100); > > > + break; > > > + case GPMC_ECC_WRITE: > > > + gpmc_write_reg(GPMC_ECC_CONTROL, 0x101); > > > + break; > > > + default: > > > + printk(KERN_INFO "Error: Unrecognized Mode[%d]!\n", > mode); > > > + break; > > > + } > > > + > > > + /* (ECC 16 or 8 bit col) | ( CS ) | ECC Enable */ > > > + val = (dev_width << 7) | (cs << 1) | (0x1); > > > + gpmc_write_reg(GPMC_ECC_CONFIG, val); > > > + return 0; > > > +} > > > + > > > +/** > > > + * gmpc_ecc_reset - release the HW ECC in GPMC controller > > > + * @cs: Chip select number > > > + */ > > > +int gpmc_ecc_reset(int cs) > > > +{ > > > + if (gpmc_ecc_used == cs) > > > + gpmc_ecc_used = -EINVAL; > > > + else > > > + return -EINVAL; > > > + > > > + return 0; > > > +} > > > + > > > diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat- > omap/include/plat/gpmc.h > > > index 145838a..67a3442 > > > --- a/arch/arm/plat-omap/include/plat/gpmc.h > > > +++ b/arch/arm/plat-omap/include/plat/gpmc.h > > > @@ -27,8 +27,24 @@ > > > > > > #define GPMC_CONFIG 0x50 > > > #define GPMC_STATUS 0x54 > > > -#define GPMC_CS0_BASE 0x60 > > > -#define GPMC_CS_SIZE 0x30 > > > + > > > +/* Control Commands */ > > > +#define GPMC_CONFIG_WP 0x00000001 > > > +#define GPMC_CONFIG_RDY_BSY 0x00000002 > > > +#define GPMC_CONFIG_DEV_SIZE 0x00000003 > > > +#define GPMC_CONFIG_DEV_TYPE 0x00000004 > > > +#define GPMC_NAND_COMMAND 0x00000005 > > > +#define GPMC_NAND_ADDRESS 0x00000006 > > > +#define GPMC_NAND_DATA 0x00000007 > > > +#define GPMC_STATUS_BUFFER 0x00000008 /* 1: buffer is available > to write */ > > > +#define GPMC_PREFETCH_FIFO_CNT 0x00000009 /* bytes available in FIFO > for r/w */ > > > +#define GPMC_PREFETCH_COUNT 0x0000000A /* remaining bytes to be > read/write*/ > > > +#define GPMC_GET_SET_IRQ_STATUS 0x0000000B > > > + > > > +/* ECC commands */ > > > +#define GPMC_ECC_READ 0 /* Reset Hardware ECC for read */ > > > +#define GPMC_ECC_WRITE 1 /* Reset Hardware ECC for write */ > > > +#define GPMC_ECC_READSYN 2 /* Reset before syndrom is read back > */ > > > > > > #define GPMC_CONFIG1_WRAPBURST_SUPP (1 << 31) > > > #define GPMC_CONFIG1_READMULTIPLE_SUPP (1 << 30) > > > @@ -56,6 +72,14 @@ > > > #define GPMC_CONFIG1_FCLK_DIV4 (GPMC_CONFIG1_FCLK_DIV(3)) > > > #define GPMC_CONFIG7_CSVALID (1 << 6) > > > > > > +#define GPMC_DEVICETYPE_NOR 0 > > > +#define GPMC_DEVICETYPE_NAND 2 > > > +#define GPMC_CONFIG_WRITEPROTECT 0x00000010 > > > +#define GPMC_STATUS_BUFF_EMPTY 0x00000001 > > > +#define WR_RD_PIN_MONITORING 0x00600000 > > > +#define GPMC_PREFETCH_STATUS_FIFO_CNT(val) ((val & 0x7f000000) >> > 24) > > > +#define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) > > > + > > > /* > > > * Note that all values in this struct are in nanoseconds, while > > > * the register values are in gpmc_fck cycles. > > > @@ -108,10 +132,15 @@ extern int gpmc_cs_set_reserved(int cs, int > reserved); > > > extern int gpmc_cs_reserved(int cs); > > > extern int gpmc_prefetch_enable(int cs, int dma_mode, > > > unsigned int u32_count, int > is_write); > > > -extern void gpmc_prefetch_reset(void); > > > +extern int gpmc_prefetch_reset(int cs); > > > extern int gpmc_prefetch_status(void); > > > extern void omap3_gpmc_save_context(void); > > > extern void omap3_gpmc_restore_context(void); > > > extern void gpmc_init(void); > > > +extern int gpmc_hwcontrol(int cs, int cmd, int write, int wval, int > *rval); > > > > > > +int gpmc_ecc_init(int cs, int ecc_size); > > > +int gpmc_enable_hwecc(int cs, int mode, int dev_width); > > > +int gpmc_calculate_ecc(int cs, const u_char *dat, u_char *ecc_code); > > > +int gpmc_ecc_reset(int cs); > > > #endif > > > diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c > > > index 7545568..206406b > > > --- a/drivers/mtd/nand/omap2.c > > > +++ b/drivers/mtd/nand/omap2.c > > > @@ -316,7 +316,7 @@ static void omap_read_buf_pref(struct mtd_info > *mtd, u_char *buf, int len) > > > } while (len); > > > > > > /* disable and stop the PFPW engine */ > > > - gpmc_prefetch_reset(); > > > + gpmc_prefetch_reset(info->gpmc_cs); > > Not required. see above comments. [Ghorai] agree and will take as 4th patch as cleanup and its not matching with patch description > > > > > } > > > } > > > > > > @@ -360,7 +360,7 @@ static void omap_write_buf_pref(struct mtd_info > *mtd, > > > } > > > > > > /* disable and stop the PFPW engine */ > > > - gpmc_prefetch_reset(); > > > + gpmc_prefetch_reset(info->gpmc_cs); > > Not required. see above comments. [Ghorai] agree and will take as 4th patch as cleanup and its not matching with patch description > > > } > > > } > > > > > > -- > > > To unsubscribe from this list: send the line "unsubscribe linux-omap" > in > > > the body of a message to majordomo at vger.kernel.org > > > More majordomo info at http://vger.kernel.org/majordomo-info.html > > > > > > > > > > From vimal.newwork at gmail.com Wed May 19 14:07:44 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Wed, 19 May 2010 23:37:44 +0530 Subject: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D43@dbde02.ent.ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274181389-7488-3-git-send-email-s-ghorai@ti.com> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D43@dbde02.ent.ti.com> Message-ID: On Wed, May 19, 2010 at 10:54 PM, Ghorai, Sukumar wrote: >> > ? ? ? ?/* take care of subpage reads */ >> > ? ? ? ?for (; len % 4 != 0; ) { >> > ? ? ? ? ? ? ? ?*buf++ = __raw_readb(info->nand.IO_ADDR_R); >> > ? ? ? ? ? ? ? ?len--; >> > ? ? ? ?} >> > - ? ? ? p = (u32 *) buf; >> >> Above code had an issue, which was fixed by this commit: >> http://git.infradead.org/mtd- >> 2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d >> >> I would suggest you to prepare your patch on MTD tree. > [Ghorai] Patches started posting on lo. And lets continue the same. Not sure about this. Its your/Tony's call. >> >> > >> > ? ? ? ?/* configure and start prefetch transfer */ >> > ? ? ? ?ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0); >> > @@ -307,17 +265,18 @@ static void omap_read_buf_pref(struct mtd_info >> *mtd, u_char *buf, int len) >> > ? ? ? ? ? ? ? ?else >> > ? ? ? ? ? ? ? ? ? ? ? ?omap_read_buf8(mtd, buf, len); >> > ? ? ? ?} else { >> > + ? ? ? ? ? ? ? p = (u32 *) buf; >> > ? ? ? ? ? ? ? ?do { >> > - ? ? ? ? ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); >> > - ? ? ? ? ? ? ? ? ? ? ? r_count = ((pfpw_status >> 24) & 0x7F) >> 2; >> > - ? ? ? ? ? ? ? ? ? ? ? ioread32_rep(info->nand_pref_fifo_add, p, >> r_count); >> > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, >> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_FIFO_CNT, 0, 0, &r_count); >> > + ? ? ? ? ? ? ? ? ? ? ? r_count = r_count >> 2; >> > + ? ? ? ? ? ? ? ? ? ? ? ioread32_rep(info->nand.IO_ADDR_R, p, r_count); >> > ? ? ? ? ? ? ? ? ? ? ? ?p += r_count; >> > - ? ? ? ? ? ? ? ? ? ? ? len -= r_count << 2; >> > + ? ? ? ? ? ? ? ? ? ? ? len -= (r_count << 2); >> >> Braces are not required here. > [Ghorai] thanks >> >> > ? ? ? ? ? ? ? ?} while (len); >> > - >> >> After call to 'gpmc_prefetch_enable', next line are: >> ? ? ? ? ? ?if (ret) { >> ? ? ? ? ? ? ? ? ? ? ? ?/* PFPW engine is busy, use cpu copy method */ >> ? ? ? ? ? ? ? ? ? ? ? ?if (info->nand.options & NAND_BUSWIDTH_16) >> ? ? ? ? ? ? ? ? ? ? ? ?... >> ? ? ? ? ? ? ? ? ? ? ? ?... >> > - ? ? ? ? ? ? ? /* disable and stop the PFPW engine */ >> > - ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); >> > ? ? ? ?} >> >> So, if above 'if' fails, driver will not get prefetch engine (it was >> already busy). Then it doesn't makes sense to call for __reset__. > [Ghorai] I will take this clean up as 4th patch. As its not matching with patch description. >> >> > + ? ? ? /* disable and stop the PFPW engine */ >> > + ? ? ? gpmc_prefetch_reset(info->gpmc_cs); >> >> (Also see my comments on your other patch.) > [Ghorai] Agree and I will take this kind of cleanup as 4th patch >> >> > ?} >> > >> > ?/** >> > @@ -331,13 +290,13 @@ static void omap_write_buf_pref(struct mtd_info >> *mtd, >> > ?{ >> > ? ? ? ?struct omap_nand_info *info = container_of(mtd, >> > ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct omap_nand_info, >> mtd); >> > - ? ? ? uint32_t pfpw_status = 0, w_count = 0; >> > + ? ? ? uint32_t pref_count = 0, w_count = 0; >> > ? ? ? ?int i = 0, ret = 0; >> > - ? ? ? u16 *p = (u16 *) buf; >> > + ? ? ? u16 *p; >> > >> > ? ? ? ?/* take care of subpage writes */ >> > ? ? ? ?if (len % 2 != 0) { >> > - ? ? ? ? ? ? ? writeb(*buf, info->nand.IO_ADDR_R); >> > + ? ? ? ? ? ? ? writeb(*buf, info->nand.IO_ADDR_W); >> > ? ? ? ? ? ? ? ?p = (u16 *)(buf + 1); >> > ? ? ? ? ? ? ? ?len--; >> > ? ? ? ?} >> > @@ -351,17 +310,22 @@ static void omap_write_buf_pref(struct mtd_info >> *mtd, >> > ? ? ? ? ? ? ? ?else >> > ? ? ? ? ? ? ? ? ? ? ? ?omap_write_buf8(mtd, buf, len); >> > ? ? ? ?} else { >> > - ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); >> > - ? ? ? ? ? ? ? while (pfpw_status & 0x3FFF) { >> > - ? ? ? ? ? ? ? ? ? ? ? w_count = ((pfpw_status >> 24) & 0x7F) >> 1; >> > + ? ? ? ? ? ? ? p = (u16 *) buf; >> > + ? ? ? ? ? ? ? while (len) { >> > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, >> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_FIFO_CNT, 0, 0, >> &w_count); >> > + ? ? ? ? ? ? ? ? ? ? ? w_count = w_count >> 1; >> > ? ? ? ? ? ? ? ? ? ? ? ?for (i = 0; (i < w_count) && len; i++, len -= 2) >> > - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iowrite16(*p++, info- >> >nand_pref_fifo_add); >> > - ? ? ? ? ? ? ? ? ? ? ? pfpw_status = gpmc_prefetch_status(); >> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? iowrite16(*p++, info->nand.IO_ADDR_W); >> > ? ? ? ? ? ? ? ?} >> > - >> > - ? ? ? ? ? ? ? /* disable and stop the PFPW engine */ >> > - ? ? ? ? ? ? ? gpmc_prefetch_reset(info->gpmc_cs); >> > + ? ? ? ? ? ? ? /* wait for data to flushed-out before reset the >> prefetch */ >> > + ? ? ? ? ? ? ? do { >> > + ? ? ? ? ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, >> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_COUNT, 0, 0, &pref_count); >> > + ? ? ? ? ? ? ? } while (pref_count); >> > ? ? ? ?} >> > + ? ? ? /* disable and stop the PFPW engine */ >> > + ? ? ? gpmc_prefetch_reset(info->gpmc_cs); >> >> Same as above. > [Ghorai] Agree and I will take this kind of cleanup as 4th patch, as its not matching with patch description. >> >> >> > ?} >> > >> > ?#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA >> > @@ -448,8 +412,10 @@ static inline int omap_nand_dma_transfer(struct >> mtd_info *mtd, void *addr, >> > ? ? ? ?/* setup and start DMA using dma_addr */ >> > ? ? ? ?wait_for_completion(&info->comp); >> > >> > - ? ? ? while (0x3fff & (prefetch_status = gpmc_prefetch_status())) >> > - ? ? ? ? ? ? ? ; >> > + ? ? ? do { >> > + ? ? ? ? ? ? ? gpmc_hwcontrol(info->gpmc_cs, >> > + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GPMC_PREFETCH_COUNT, 0, 0, >> &prefetch_status); >> > + ? ? ? } while (prefetch_status); >> > ? ? ? ?/* disable and stop the PFPW engine */ >> > ? ? ? ?gpmc_prefetch_reset(); >> > >> > @@ -502,7 +468,7 @@ static void omap_write_buf_dma_pref(struct mtd_info >> *mtd, >> > ? ? ? ? ? ? ? ?omap_write_buf_pref(mtd, buf, len); >> > ? ? ? ?else >> > ? ? ? ? ? ? ? ?/* start transfer in DMA mode */ >> > - ? ? ? ? ? ? ? omap_nand_dma_transfer(mtd, buf, len, 0x1); >> > + ? ? ? ? ? ? ? omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1); >> >> This is already fixed. See commit: >> http://git.infradead.org/mtd- >> 2.6.git/commitdiff/bdaefc41627b6f2815ef7aa476dfa4ebb3ad499f > [Ghorai] thanks I will omit this from this patch >> >> >> Rest, patches looks good. It is a good clean-up all together. > [Ghorai] Is it possible for you to check once again if you have any additional comments! This is to identify the issue if any at early stage. Yeah, I can understand. I tried to review it fully, but can not say if still something left and gets attention later on. Even sometimes they will become visible when you fix current one. As of now this is all what I had. -- Regards, Vimal Singh From tony at atomide.com Wed May 19 14:19:12 2010 From: tony at atomide.com (Tony Lindgren) Date: Wed, 19 May 2010 11:19:12 -0700 Subject: [PATCH v3 2/3] omap3 nand: cleanup virtual address usages In-Reply-To: References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274181389-7488-3-git-send-email-s-ghorai@ti.com> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D43@dbde02.ent.ti.com> Message-ID: <20100519181912.GF5818@atomide.com> * Vimal Singh [100519 11:02]: > On Wed, May 19, 2010 at 10:54 PM, Ghorai, Sukumar wrote: > >> > ? ? ? ?/* take care of subpage reads */ > >> > ? ? ? ?for (; len % 4 != 0; ) { > >> > ? ? ? ? ? ? ? ?*buf++ = __raw_readb(info->nand.IO_ADDR_R); > >> > ? ? ? ? ? ? ? ?len--; > >> > ? ? ? ?} > >> > - ? ? ? p = (u32 *) buf; > >> > >> Above code had an issue, which was fixed by this commit: > >> http://git.infradead.org/mtd- > >> 2.6.git/commitdiff/c3341d0ceb4de1680572024f50233403c6a8b10d > >> > >> I would suggest you to prepare your patch on MTD tree. > > [Ghorai] Patches started posting on lo. And lets continue the same. > > Not sure about this. Its your/Tony's call. I'd assume that fix is on it's way to the mainline kernel, looks like a trivial rebase after the merge window is over. Anyways, this will not make it this merge window, we're out of time. Regards, Tony From vimal.newwork at gmail.com Wed May 19 14:30:47 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Thu, 20 May 2010 00:00:47 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274284094.6286.17.camel@thunk> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> Message-ID: On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: >> > > + >> > > + ? ? ? case GPMC_CONFIG_RDY_BSY: >> > > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); >> > > + ? ? ? ? ? ? ? regval |= WR_RD_PIN_MONITORING; >> > > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); >> > > + ? ? ? ? ? ? ? break; >> > >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not connected). >> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND >> accesses > [Ghorai] So better keep this feature, Yes, looks like there are some boards which can still take advantage of this. >> [...] >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); >> > > ?/** >> > > ?* gpmc_prefetch_reset - disables and stops the prefetch engine >> > > ?*/ >> > > -void gpmc_prefetch_reset(void) >> > > +int gpmc_prefetch_reset(int cs) >> > > ?{ >> > > + ? ? ? if (gpmc_pref_used == cs) >> > > + ? ? ? ? ? ? ? gpmc_pref_used = -EINVAL; >> > > + ? ? ? else >> > > + ? ? ? ? ? ? ? return -EINVAL; >> > > + >> > >> > This is also not required. As, this function will be called only if >> > prefetch was used. > [Ghorai] Agree. Can you see this input too? > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html Exactly, this is what I am telling here. Enable prefetch engine call is already being check for *busy* or not. > [...] >> > > +int gpmc_ecc_init(int cs, int ecc_size) >> > > +{ >> > > + ? ? ? unsigned int val = 0x0; >> > > + >> > > + ? ? ? /* check if ecc engine already by another cs */ >> > > + ? ? ? if (gpmc_ecc_used == -EINVAL) >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = cs; >> > > + ? ? ? else >> > > + ? ? ? ? ? ? ? return -EBUSY; >> > Here few things need be to consider: >> > 1. 'init' is supposed to done once for every instance of driver during >> probe >> > 2. But ECC engine, too, have only one instance at a time, So >> > 3. As long as all NAND chip are supposed to use same ECC machenism, we >> > can go for only one time 'init' for all drivers, perhaps in >> > gpmc_nand.c. >> > 4. But in case, different instances of driver (or NAND chip) requires >> > different ECC machenism (for ex. Hamming or BCH, or even with >> > different capabilities of error correction), >> > this will no longer vailid. Then rather we should have something like >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver >> > needs it (something like as it is done for prefetch engine). > [Ghorai] > a. do you think it will reduce the throughput? No. But in current implementation it will be called for each instance driver. (see my 3rd point) > b. Moreover I think we will take this as 5th patch as cleanup/ improvemnt. > c. And how to know that ECC engine is in used other driver should not use it? Any bit to know that ecc engine is busy, as we check for prefetch? Do not really remember config registers. Perhaps there is no way. But I guess you should check into register GPMC_ECC_CONFIG at bit 1. This is the bit we are setting to enable ECC calculation, IIRC. > d. any further input on http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html And this what I was suggesting in my point 4. In my example 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. I said *config*, since in such scenario you need to configer HW ECCconfig register everytime as well, rather just checking availability and enabling. > [...] >> > > +int gpmc_ecc_reset(int cs) >> > > +{ >> > > + ? ? ? if (gpmc_ecc_used == cs) >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = -EINVAL; >> > > + ? ? ? else >> > > + ? ? ? ? ? ? ? return -EINVAL; >> > > + >> > > + ? ? ? return 0; >> > > +} I guess in this function you should also clear gpmc ecc config register explicitly. -- Regards, Vimal Singh From joakim.tjernlund at transmode.se Wed May 19 16:06:35 2010 From: joakim.tjernlund at transmode.se (Joakim Tjernlund) Date: Wed, 19 May 2010 22:06:35 +0200 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: <1274287748.6930.10308.camel@macbook.infradead.org> References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> <1274226122.6930.8416.camel@macbook.infradead.org> <1274287748.6930.10308.camel@macbook.infradead.org> Message-ID: David Woodhouse wrote on 2010/05/19 18:49:08: > > On Wed, 2010-05-19 at 11:47 +0200, Joakim Tjernlund wrote: > > > > > It could perhaps be broken into smaller simple patches along the lines > > > of: > > > - Add 'work_done' return value from jffs2_erase_pending_blocks() > > > - Call jffs2_erase_pending_blocks() from jffs2_g_c_pass() > > > - Fix the conditions under which jffs2_g_c_pass() will return -EINVAL, > > > fix the way that jffs2_reserve_space() will respond to that, and fix > > > jffs2_erase_succeeded() to actually wake up the erase_wait queue. > > > - Remove locking from jffs2_garbage_collect_trigger() and require that > > > callers have c->erase_completion_lock already held. > > > - Change most callers of jffs2_erase_pending_trigger() to call > > > jffs2_garbage_collect_trigger() instead. To comply with the locking > > > rules, this may involve moving the call up or down a few lines, or > > > sometimes adding a new lock/unlock pair around it. > > > - Remove jffs2_erase_pending_blocks() call from jffs2_write_super(). > > > - Rename jffs2_erase_pending_trigger() and its only remaining caller > > > in wbuf.c to jffs2_dirty_trigger(). > > > > I have tried this on my 2.6.33 tree and it seems to work OK. > > I am currenltly copying lots of files and deleting them in a loop, > > so far so good :) Needed to "tweak": > > OK, this is now pushed, in some semblance of the above form. I think I > got the attribution right on the bits which you wrote. Thanks again. Thanks, I am sure you get attribution right, but where did you push? Can't find it in http://git.infradead.org/mtd-2.6.git From dwmw2 at infradead.org Wed May 19 17:24:10 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Wed, 19 May 2010 22:24:10 +0100 Subject: [PATCH] jffs2: Move erasing from write_super to GC. In-Reply-To: References: <1269079399-27087-1-git-send-email-Joakim.Tjernlund@transmode.se> <1273771018.12840.7077.camel@macbook.infradead.org> <1273833304.9999.1994.camel@macbook.infradead.org> <1274207844.6930.7754.camel@macbook.infradead.org> <1274209152.6930.7802.camel@macbook.infradead.org> <1274226122.6930.8416.camel@macbook.infradead.org> <1274287748.6930.10308.camel@macbook.infradead.org> Message-ID: <1274304250.6930.10703.camel@macbook.infradead.org> On Wed, 2010-05-19 at 22:06 +0200, Joakim Tjernlund wrote: > > OK, this is now pushed, in some semblance of the above form. I think I > > got the attribution right on the bits which you wrote. Thanks again. > > Thanks, I am sure you get attribution right, but where did you push? > Can't find it in http://git.infradead.org/mtd-2.6.git Oh, looks like I didn't push it anywhere; just committed it locally. It's there now; sorry. -- dwmw2 From stanley.miao at windriver.com Wed May 19 22:17:24 2010 From: stanley.miao at windriver.com (stanley.miao) Date: Thu, 20 May 2010 10:17:24 +0800 Subject: [Yaffs] [PATCH 1/2] Fix the bug of writing a yaffs2 image to NAND In-Reply-To: <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> Message-ID: <4BF49BB4.30306@windriver.com> Hi, Artem, Any comments ? Stanley. Stanley.Miao wrote: > The tool mkyaffs2image doesn't know the oob layout of a NAND flash, so it > puts the yaffs2 tags at the offset 0 of oob area, as a result, the image > generated by mkyaffs2image is different with the image dumped by nanddump. > Now adding a parameter "-r" for nandwrite to differentiate these images. > > Write a image generated by mkyaffs2image: > $> nandwrite -a -o /dev/mtd3 yaffs2.bin > > Write a image dumped by nanddump: > $> nandwrite -a -r /dev/mtd3 image.bin > > Signed-off-by: Stanley.Miao > --- > nandwrite.c | 20 ++++++++++++++++---- > 1 files changed, 16 insertions(+), 4 deletions(-) > > diff --git a/nandwrite.c b/nandwrite.c > index b77edd6..1e30ad1 100644 > --- a/nandwrite.c > +++ b/nandwrite.c > @@ -80,6 +80,7 @@ static void display_help (void) > " -m, --markbad Mark blocks bad if write fails\n" > " -n, --noecc Write without ecc\n" > " -o, --oob Image contains oob data\n" > +" -r, --raw Image contains the raw oob data dumped by nanddump\n" > " -s addr, --start=addr Set start address (default is 0)\n" > " -p, --pad Pad to page size\n" > " -b, --blockalign=1|2|4 Set multiple of eraseblocks to align to\n" > @@ -110,6 +111,7 @@ static const char *mtd_device, *img; > static int mtdoffset = 0; > static bool quiet = false; > static bool writeoob = false; > +static bool rawoob = false; > static bool autoplace = false; > static bool markbad = false; > static bool forcejffs2 = false; > @@ -125,7 +127,7 @@ static void process_options (int argc, char * const argv[]) > > for (;;) { > int option_index = 0; > - static const char *short_options = "ab:fjmnopqs:y"; > + static const char *short_options = "ab:fjmnopqrs:y"; > static const struct option long_options[] = { > {"help", no_argument, 0, 0}, > {"version", no_argument, 0, 0}, > @@ -138,6 +140,7 @@ static void process_options (int argc, char * const argv[]) > {"oob", no_argument, 0, 'o'}, > {"pad", no_argument, 0, 'p'}, > {"quiet", no_argument, 0, 'q'}, > + {"raw", no_argument, 0, 'r'}, > {"start", required_argument, 0, 's'}, > {"yaffs", no_argument, 0, 'y'}, > {0, 0, 0, 0}, > @@ -187,6 +190,10 @@ static void process_options (int argc, char * const argv[]) > case 'p': > pad = true; > break; > + case 'r': > + rawoob = true; > + writeoob = true; > + break; > case 's': > mtdoffset = strtol (optarg, NULL, 0); > break; > @@ -583,6 +590,7 @@ int main(int argc, char * const argv[]) > oob.ptr = oobreadbuf; > } else { > int i, start, len; > + int tags_pos = 0; > /* > * We use autoplacement and have the oobinfo with the autoplacement > * information from the kernel available > @@ -595,9 +603,13 @@ int main(int argc, char * const argv[]) > /* Set the reserved bytes to 0xff */ > start = old_oobinfo.oobfree[i][0]; > len = old_oobinfo.oobfree[i][1]; > - memcpy(oobbuf + start, > - oobreadbuf + start, > - len); > + if (rawoob) > + memcpy(oobbuf + start, > + oobreadbuf + start, len); > + else > + memcpy(oobbuf + start, > + oobreadbuf + tags_pos, len); > + tags_pos += len; > } > } else { > /* Set at least the ecc byte positions to 0xff */ > From stanley.miao at windriver.com Wed May 19 22:24:38 2010 From: stanley.miao at windriver.com (stanley.miao) Date: Thu, 20 May 2010 10:24:38 +0800 Subject: Running jffs2 filesystem on mtd nand flash driver In-Reply-To: References: Message-ID: <4BF49D66.5050206@windriver.com> http://patchwork.ozlabs.org/patch/44340/ http://patchwork.ozlabs.org/patch/44344/ > flash_eraseall -j /dev/mtdx > mount -t jffs2 /dev/mtdblockx /flash Hi, Artem, Are you the maintainer of mtd-utils ? A lot of people suffered from the same issues. Can you merge these patches into mtd-utils ? Thanks. Stanley. Raghu MSRPSR wrote: > Hi, > > Could some one /review post a exact sequence of steps to get jffs2 up > and running on a NAND MTD driver for kernel 2.6.27+ > > 1. load nand (mtd) driver > 2. flash_eraseall -q /dev/mtdx > 3. mount -t jffs2 /dev/mtdblockx /flash > > is this correct sequence? > > Any info shared is appreciated. > > Thanks, > Raghu > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ > > From s-ghorai at ti.com Thu May 20 01:38:29 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Thu, 20 May 2010 11:08:29 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274284094.6286.17.camel@thunk> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030D991ECA@dbde02.ent.ti.com> Vimal, > -----Original Message----- > From: Vimal Singh [mailto:vimal.newwork at gmail.com] > Sent: 2010-05-20 00:01 > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; > tony at atomide.com; sakoman at gmail.com; mike at compulab.co.il; > Artem.Bityutskiy at nokia.com; peter.barada at gmail.com > Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement > > On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: > >> > > + > >> > > + ? ? ? case GPMC_CONFIG_RDY_BSY: > >> > > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > >> > > + ? ? ? ? ? ? ? regval |= WR_RD_PIN_MONITORING; > >> > > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > >> > > + ? ? ? ? ? ? ? break; > >> > > >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not > connected). > >> > >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the > >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the > >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND > >> accesses > > [Ghorai] So better keep this feature, > > Yes, looks like there are some boards which can still take advantage of > this. > > >> > [...] > >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > >> > > ?/** > >> > > ?* gpmc_prefetch_reset - disables and stops the prefetch engine > >> > > ?*/ > >> > > -void gpmc_prefetch_reset(void) > >> > > +int gpmc_prefetch_reset(int cs) > >> > > ?{ > >> > > + ? ? ? if (gpmc_pref_used == cs) > >> > > + ? ? ? ? ? ? ? gpmc_pref_used = -EINVAL; > >> > > + ? ? ? else > >> > > + ? ? ? ? ? ? ? return -EINVAL; > >> > > + > >> > > >> > This is also not required. As, this function will be called only if > >> > prefetch was used. > > [Ghorai] Agree. Can you see this input too? > > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html > > Exactly, this is what I am telling here. Enable prefetch engine call > is already being check for *busy* or not. > > > > [...] > >> > > +int gpmc_ecc_init(int cs, int ecc_size) > >> > > +{ > >> > > + ? ? ? unsigned int val = 0x0; > >> > > + > >> > > + ? ? ? /* check if ecc engine already by another cs */ > >> > > + ? ? ? if (gpmc_ecc_used == -EINVAL) > >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = cs; > >> > > + ? ? ? else > >> > > + ? ? ? ? ? ? ? return -EBUSY; > >> > Here few things need be to consider: > >> > 1. 'init' is supposed to done once for every instance of driver > during > >> probe > >> > 2. But ECC engine, too, have only one instance at a time, So > >> > 3. As long as all NAND chip are supposed to use same ECC machenism, > we > >> > can go for only one time 'init' for all drivers, perhaps in > >> > gpmc_nand.c. > >> > 4. But in case, different instances of driver (or NAND chip) requires > >> > different ECC machenism (for ex. Hamming or BCH, or even with > >> > different capabilities of error correction), > >> > this will no longer vailid. Then rather we should have something like > >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > >> > needs it (something like as it is done for prefetch engine). > > [Ghorai] > > a. do you think it will reduce the throughput? > No. But in current implementation it will be called for each instance > driver. (see my 3rd point) > > > b. Moreover I think we will take this as 5th patch as cleanup/ > improvemnt. > > c. And how to know that ECC engine is in used other driver should not > use it? Any bit to know that ecc engine is busy, as we check for prefetch? > Do not really remember config registers. Perhaps there is no way. > But I guess you should check into register GPMC_ECC_CONFIG at bit 1. > This is the bit we are setting to enable ECC calculation, IIRC. > > > d. any further input on http://www.mail-archive.com/linux- > omap at vger.kernel.org/msg28520.html > And this what I was suggesting in my point 4. In my example > 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. > I said *config*, since in such scenario you need to configer HW > ECCconfig register everytime as well, rather just checking > availability and enabling. [Ghorai] still I feel we should not mix this patch with cleanup. And yes if possible this will be the 5th one as cleanup. 4th one - prefetch cleanup 5th one - ecc cleanup. Do you think still missing anything for this patch? > > > > [...] > >> > > +int gpmc_ecc_reset(int cs) > >> > > +{ > >> > > + ? ? ? if (gpmc_ecc_used == cs) > >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = -EINVAL; > >> > > + ? ? ? else > >> > > + ? ? ? ? ? ? ? return -EINVAL; > >> > > + > >> > > + ? ? ? return 0; > >> > > +} > > I guess in this function you should also clear gpmc ecc config > register explicitly. > > > -- > Regards, > Vimal Singh From pazdnikov at prosoft.ural.ru Thu May 20 09:18:42 2010 From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov) Date: Thu, 20 May 2010 19:18:42 +0600 Subject: ubifs became broken on contigous power-fails In-Reply-To: <201005191636.21845.pazdnikov@prosoft.ural.ru> References: <201005131408.01573.pazdnikov@prosoft.ural.ru> <201005191636.21845.pazdnikov@prosoft.ural.ru> Message-ID: <201005201918.42731.pazdnikov@prosoft.ural.ru> After reboot by poweroff I've got the following: first mount ubi2:dbfs RO then remount RW [ 11.069330] UBIFS: recovery needed [ 13.485344] UBIFS: recovery deferred [ 14.781242] UBIFS: mounted UBI device 2, volume 0, name "dbfs" [ 14.787101] UBIFS: mounted read-only [ 14.791008] UBIFS: file system size: 189149184 bytes (184716 KiB, 180 MiB, 1466 LEBs) [ 14.799797] UBIFS: journal size: 9418752 bytes (9198 KiB, 8 MiB, 73 LEBs) [ 14.806633] UBIFS: media format: w4/r0 (latest is w4/r0) [ 14.813468] UBIFS: default compressor: lzo [ 14.817375] UBIFS: reserved for root: 4952683 bytes (4836 KiB) [ 14.823234] UBIFS DBG (pid 468): mount_ubifs: compiled on: May 12 2010 at 18:34:36 [ 14.823234] UBIFS DBG (pid 468): mount_ubifs: min. I/O unit size: 2048 bytes [ 14.823234] UBIFS DBG (pid 468): mount_ubifs: LEB size: 129024 bytes (126 KiB) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: data journal heads: 1 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: UUID: DC1BB581-CE01-431C-9308-BBA9D0885E3D [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: big_lpt 0 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: log LEBs: 5 (3 - 7) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: LPT area LEBs: 2 (8 - 9) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: orphan area LEBs: 2 (10 - 11) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: main area LEBs: 1466 (12 - 1477) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: index LEBs: 1 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: total index bytes: 46848 (45 KiB, 0 MiB) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: key hash type: 0 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: tree fanout: 8 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: reserved GC LEB: 14 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: first main LEB: 12 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. znode size 240 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. index node size 192 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: node sizes: data 48, inode 160, dentry 56 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: node sizes: trun 56, sb 4096, master 512 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: node sizes: ref 64, cmt. start 32, orph 32 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. node sizes: data 4144, inode 4256 dentry 312 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: dead watermark: 2048 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: dark watermark: 6144 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: LEB overhead: 560 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. dark space: 9007104 (8796 KiB, 8 MiB) [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: maximum bud bytes: 8773632 (8568 KiB, 8 MiB) [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: BG commit bud bytes: 7128576 (6961 KiB, 6 MiB) [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: current bud bytes 2572288 (2512 KiB, 2 MiB) [ 14.826164] UBIFS DBG (pid 468): mount_ubifs: max. seq. number: 6955 [ 14.826164] UBIFS DBG (pid 468): mount_ubifs: commit number: 5 [ 14.890617] UBIFS: completing deferred recovery [ 14.901359] UBIFS DBG (pid 472): ubifs_bg_thread: background thread "ubifs_bgt2_0" started, PID 472 [ 21.676746] UBIFS: deferred recovery completed [ 21.681629] UBIFS error (pid 471): dbg_check_space_info: free space changed from 171535545 to 171830940 [ 21.691395] UBIFS: saved lprops statistics dump [ 21.696277] (pid 471) Lprops statistics: empty_lebs 1350, idx_lebs 1 [ 21.696277] taken_empty_lebs 0, total_free 174458880, total_dirty 9203536 [ 21.696277] total_used 5442288, total_dark 8777552, total_dead 22792 [ 21.696277] UBIFS: current lprops statistics dump [ 21.701160] (pid 471) Lprops statistics: empty_lebs 1360, idx_lebs 1 [ 21.701160] taken_empty_lebs 1, total_free 175742976, total_dirty 7914704 [ 21.701160] total_used 5442288, total_dark 8777552, total_dead 22792 [ 21.701160] UBIFS assert failed in dbg_dump_budg at 617 (pid 471) [ 21.707996] [] (unwind_backtrace+0x0/0xe4) from [] (dbg_dump_budg+0x250/0x334) [ 21.716785] [] (dbg_dump_budg+0x250/0x334) from [] (dbg_check_space_info+0xc0/0x114) [ 21.726551] [] (dbg_check_space_info+0xc0/0x114) from [] (ubifs_remount_fs+0x528/0x8bc) [ 21.737293] [] (ubifs_remount_fs+0x528/0x8bc) from [] (do_remount_sb+0x8c/0x100) [ 21.746082] [] (do_remount_sb+0x8c/0x100) from [] (do_mount+0x4c0/0x7cc) [ 21.754871] [] (do_mount+0x4c0/0x7cc) from [] (sys_mount+0x98/0xc8) [ 21.763660] [] (sys_mount+0x98/0xc8) from [] (ret_fast_syscall+0x0/0x28) [ 21.772449] (pid 471) Budgeting info: budg_data_growth 0, budg_dd_growth 0, budg_idx_growth 0 [ 21.772449] data budget sum 0, total budget sum 0, freeable_cnt 57 [ 21.772449] min_idx_lebs 3, old_idx_sz 49216, calc_idx_sz 49216, idx_gc_cnt 0 [ 21.772449] dirty_pg_cnt 0, dirty_zn_cnt 0, clean_zn_cnt 280 [ 21.772449] dark_wm 6144, dead_wm 2048, max_idx_node_sz 192 [ 21.772449] gc_lnum 109, ihead_lnum 12 [ 21.772449] jhead 0 (GC) LEB -1 [ 21.772449] jhead 1 (base) LEB -1 [ 21.772449] jhead 2 (data) LEB -1 [ 21.772449] commit state 0 [ 21.772449] Budgeting predictions: [ 21.772449] available: 174003384, outstanding 0, free 171830940 [ 21.773426] [] (unwind_backtrace+0x0/0xe4) from [] (dbg_check_space_info+0xd8/0x114) [ 21.783191] [] (dbg_check_space_info+0xd8/0x114) from [] (ubifs_remount_fs+0x528/0x8bc) [ 21.792957] [] (ubifs_remount_fs+0x528/0x8bc) from [] (do_remount_sb+0x8c/0x100) [ 21.802723] [] (do_remount_sb+0x8c/0x100) from [] (do_mount+0x4c0/0x7cc) [ 21.811512] [] (do_mount+0x4c0/0x7cc) from [] (sys_mount+0x98/0xc8) [ 21.819324] [] (sys_mount+0x98/0xc8) from [] (ret_fast_syscall+0x0/0x28) -- Best regards, Sasha -------------- next part -------------- [ 11.069330] UBIFS: recovery needed [ 13.485344] UBIFS: recovery deferred [ 14.781242] UBIFS: mounted UBI device 2, volume 0, name "dbfs" [ 14.787101] UBIFS: mounted read-only [ 14.791008] UBIFS: file system size: 189149184 bytes (184716 KiB, 180 MiB, 1466 LEBs) [ 14.799797] UBIFS: journal size: 9418752 bytes (9198 KiB, 8 MiB, 73 LEBs) [ 14.806633] UBIFS: media format: w4/r0 (latest is w4/r0) [ 14.813468] UBIFS: default compressor: lzo [ 14.817375] UBIFS: reserved for root: 4952683 bytes (4836 KiB) [ 14.823234] UBIFS DBG (pid 468): mount_ubifs: compiled on: May 12 2010 at 18:34:36 [ 14.823234] UBIFS DBG (pid 468): mount_ubifs: min. I/O unit size: 2048 bytes [ 14.823234] UBIFS DBG (pid 468): mount_ubifs: LEB size: 129024 bytes (126 KiB) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: data journal heads: 1 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: UUID: DC1BB581-CE01-431C-9308-BBA9D0885E3D [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: big_lpt 0 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: log LEBs: 5 (3 - 7) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: LPT area LEBs: 2 (8 - 9) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: orphan area LEBs: 2 (10 - 11) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: main area LEBs: 1466 (12 - 1477) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: index LEBs: 1 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: total index bytes: 46848 (45 KiB, 0 MiB) [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: key hash type: 0 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: tree fanout: 8 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: reserved GC LEB: 14 [ 14.824211] UBIFS DBG (pid 468): mount_ubifs: first main LEB: 12 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. znode size 240 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. index node size 192 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: node sizes: data 48, inode 160, dentry 56 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: node sizes: trun 56, sb 4096, master 512 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: node sizes: ref 64, cmt. start 32, orph 32 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. node sizes: data 4144, inode 4256 dentry 312 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: dead watermark: 2048 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: dark watermark: 6144 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: LEB overhead: 560 [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: max. dark space: 9007104 (8796 KiB, 8 MiB) [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: maximum bud bytes: 8773632 (8568 KiB, 8 MiB) [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: BG commit bud bytes: 7128576 (6961 KiB, 6 MiB) [ 14.825187] UBIFS DBG (pid 468): mount_ubifs: current bud bytes 2572288 (2512 KiB, 2 MiB) [ 14.826164] UBIFS DBG (pid 468): mount_ubifs: max. seq. number: 6955 [ 14.826164] UBIFS DBG (pid 468): mount_ubifs: commit number: 5 [ 14.890617] UBIFS: completing deferred recovery [ 14.901359] UBIFS DBG (pid 472): ubifs_bg_thread: background thread "ubifs_bgt2_0" started, PID 472 [ 21.676746] UBIFS: deferred recovery completed [ 21.681629] UBIFS error (pid 471): dbg_check_space_info: free space changed from 171535545 to 171830940 [ 21.691395] UBIFS: saved lprops statistics dump [ 21.696277] (pid 471) Lprops statistics: empty_lebs 1350, idx_lebs 1 [ 21.696277] taken_empty_lebs 0, total_free 174458880, total_dirty 9203536 [ 21.696277] total_used 5442288, total_dark 8777552, total_dead 22792 [ 21.696277] UBIFS: current lprops statistics dump [ 21.701160] (pid 471) Lprops statistics: empty_lebs 1360, idx_lebs 1 [ 21.701160] taken_empty_lebs 1, total_free 175742976, total_dirty 7914704 [ 21.701160] total_used 5442288, total_dark 8777552, total_dead 22792 [ 21.701160] UBIFS assert failed in dbg_dump_budg at 617 (pid 471) [ 21.707996] [] (unwind_backtrace+0x0/0xe4) from [] (dbg_dump_budg+0x250/0x334) [ 21.716785] [] (dbg_dump_budg+0x250/0x334) from [] (dbg_check_space_info+0xc0/0x114) [ 21.726551] [] (dbg_check_space_info+0xc0/0x114) from [] (ubifs_remount_fs+0x528/0x8bc) [ 21.737293] [] (ubifs_remount_fs+0x528/0x8bc) from [] (do_remount_sb+0x8c/0x100) [ 21.746082] [] (do_remount_sb+0x8c/0x100) from [] (do_mount+0x4c0/0x7cc) [ 21.754871] [] (do_mount+0x4c0/0x7cc) from [] (sys_mount+0x98/0xc8) [ 21.763660] [] (sys_mount+0x98/0xc8) from [] (ret_fast_syscall+0x0/0x28) [ 21.772449] (pid 471) Budgeting info: budg_data_growth 0, budg_dd_growth 0, budg_idx_growth 0 [ 21.772449] data budget sum 0, total budget sum 0, freeable_cnt 57 [ 21.772449] min_idx_lebs 3, old_idx_sz 49216, calc_idx_sz 49216, idx_gc_cnt 0 [ 21.772449] dirty_pg_cnt 0, dirty_zn_cnt 0, clean_zn_cnt 280 [ 21.772449] dark_wm 6144, dead_wm 2048, max_idx_node_sz 192 [ 21.772449] gc_lnum 109, ihead_lnum 12 [ 21.772449] jhead 0 (GC) LEB -1 [ 21.772449] jhead 1 (base) LEB -1 [ 21.772449] jhead 2 (data) LEB -1 [ 21.772449] commit state 0 [ 21.772449] Budgeting predictions: [ 21.772449] available: 174003384, outstanding 0, free 171830940 [ 21.773426] [] (unwind_backtrace+0x0/0xe4) from [] (dbg_check_space_info+0xd8/0x114) [ 21.783191] [] (dbg_check_space_info+0xd8/0x114) from [] (ubifs_remount_fs+0x528/0x8bc) [ 21.792957] [] (ubifs_remount_fs+0x528/0x8bc) from [] (do_remount_sb+0x8c/0x100) [ 21.802723] [] (do_remount_sb+0x8c/0x100) from [] (do_mount+0x4c0/0x7cc) [ 21.811512] [] (do_mount+0x4c0/0x7cc) from [] (sys_mount+0x98/0xc8) [ 21.819324] [] (sys_mount+0x98/0xc8) from [] (ret_fast_syscall+0x0/0x28) From vimal.newwork at gmail.com Thu May 20 10:34:23 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Thu, 20 May 2010 20:04:23 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B030D991ECA@dbde02.ent.ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274284094.6286.17.camel@thunk> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991ECA@dbde02.ent.ti.com> Message-ID: On Thu, May 20, 2010 at 11:08 AM, Ghorai, Sukumar wrote: > Vimal, > >> -----Original Message----- >> From: Vimal Singh [mailto:vimal.newwork at gmail.com] >> Sent: 2010-05-20 00:01 >> To: Ghorai, Sukumar >> Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; >> tony at atomide.com; sakoman at gmail.com; mike at compulab.co.il; >> Artem.Bityutskiy at nokia.com; peter.barada at gmail.com >> Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement >> >> On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: >> >> > > + >> >> > > + ? ? ? case GPMC_CONFIG_RDY_BSY: >> >> > > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); >> >> > > + ? ? ? ? ? ? ? regval |= WR_RD_PIN_MONITORING; >> >> > > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); >> >> > > + ? ? ? ? ? ? ? break; >> >> > >> >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not >> connected). >> >> >> >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the >> >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the >> >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND >> >> accesses >> > [Ghorai] So better keep this feature, >> >> Yes, looks like there are some boards which can still take advantage of >> this. >> >> >> >> [...] >> >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); >> >> > > ?/** >> >> > > ?* gpmc_prefetch_reset - disables and stops the prefetch engine >> >> > > ?*/ >> >> > > -void gpmc_prefetch_reset(void) >> >> > > +int gpmc_prefetch_reset(int cs) >> >> > > ?{ >> >> > > + ? ? ? if (gpmc_pref_used == cs) >> >> > > + ? ? ? ? ? ? ? gpmc_pref_used = -EINVAL; >> >> > > + ? ? ? else >> >> > > + ? ? ? ? ? ? ? return -EINVAL; >> >> > > + >> >> > >> >> > This is also not required. As, this function will be called only if >> >> > prefetch was used. >> > [Ghorai] Agree. Can you see this input too? >> > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html >> >> Exactly, this is what I am telling here. Enable prefetch engine call >> is already being check for *busy* or not. >> >> > >> [...] >> >> > > +int gpmc_ecc_init(int cs, int ecc_size) >> >> > > +{ >> >> > > + ? ? ? unsigned int val = 0x0; >> >> > > + >> >> > > + ? ? ? /* check if ecc engine already by another cs */ >> >> > > + ? ? ? if (gpmc_ecc_used == -EINVAL) >> >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = cs; >> >> > > + ? ? ? else >> >> > > + ? ? ? ? ? ? ? return -EBUSY; >> >> > Here few things need be to consider: >> >> > 1. 'init' is supposed to done once for every instance of driver >> during >> >> probe >> >> > 2. But ECC engine, too, have only one instance at a time, So >> >> > 3. As long as all NAND chip are supposed to use same ECC machenism, >> we >> >> > can go for only one time 'init' for all drivers, perhaps in >> >> > gpmc_nand.c. >> >> > 4. But in case, different instances of driver (or NAND chip) requires >> >> > different ECC machenism (for ex. Hamming or BCH, or even with >> >> > different capabilities of error correction), >> >> > this will no longer vailid. Then rather we should have something like >> >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver >> >> > needs it (something like as it is done for prefetch engine). >> > [Ghorai] >> > a. do you think it will reduce the throughput? >> No. But in current implementation it will be called for each instance >> driver. (see my 3rd point) >> >> > b. Moreover I think we will take this as 5th patch as cleanup/ >> improvemnt. >> > c. And how to know that ECC engine is in used other driver should not >> use it? Any bit to know that ecc engine is busy, as we check for prefetch? >> Do not really remember config registers. Perhaps there is no way. >> But I guess you should check into register GPMC_ECC_CONFIG at bit 1. >> This is the bit we are setting to enable ECC calculation, IIRC. >> >> > d. any further input on http://www.mail-archive.com/linux- >> omap at vger.kernel.org/msg28520.html >> And this what I was suggesting in my point 4. In my example >> 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. >> I said *config*, since in such scenario you need to configer HW >> ECCconfig register everytime as well, rather just checking >> availability and enabling. > [Ghorai] still I feel we should not mix this patch with cleanup. And yes if possible this will be the 5th one as cleanup. > 4th one - prefetch cleanup > 5th one - ecc cleanup. > Do you think still missing anything for this patch? As long as you take care of current comments, I do not have any further comment for now. -- Regards, Vimal Singh From glecerf at gmail.com Thu May 20 10:54:05 2010 From: glecerf at gmail.com (Guillaume LECERF) Date: Thu, 20 May 2010 16:54:05 +0200 Subject: [PATCH 1/2] mtd: cfi_cmdset_0002: allow automatic loading of command set 0x0701 from cfi_cmdset_unknown() Message-ID: <20100520145405.6262.90666.stgit@dev.siriade.com> Signed-off-by: Guillaume LECERF --- drivers/mtd/chips/cfi_cmdset_0002.c | 3 +++ 1 files changed, 3 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index 87e86e9..cd905a1 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -489,7 +489,9 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) return cfi_amdstd_setup(mtd); } +struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002"))); EXPORT_SYMBOL_GPL(cfi_cmdset_0002); +EXPORT_SYMBOL_GPL(cfi_cmdset_0701); static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) { @@ -2040,3 +2042,4 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Crossnet Co. et al."); MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips"); +MODULE_ALIAS("cfi_cmdset_0701"); From glecerf at gmail.com Thu May 20 10:54:10 2010 From: glecerf at gmail.com (Guillaume LECERF) Date: Thu, 20 May 2010 16:54:10 +0200 Subject: [PATCH 2/2] mtd: cfi_cmdset_0002: use AMD standard command-set with Winbond flash chips In-Reply-To: <20100520145405.6262.90666.stgit@dev.siriade.com> References: <20100520145405.6262.90666.stgit@dev.siriade.com> Message-ID: <20100520145410.6262.50350.stgit@dev.siriade.com> Tested with W19L320SBT9C [1]. [1] http://www.datasheetarchive.com/pdf-datasheets/Datasheets-40/DSA-795343.pdf Signed-off-by: Obinou Signed-off-by: Guillaume LECERF Acked-by: Florian Fainelli --- drivers/mtd/chips/cfi_cmdset_0002.c | 3 +++ drivers/mtd/chips/gen_probe.c | 1 + 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0002.c b/drivers/mtd/chips/cfi_cmdset_0002.c index cd905a1..d81079e 100644 --- a/drivers/mtd/chips/cfi_cmdset_0002.c +++ b/drivers/mtd/chips/cfi_cmdset_0002.c @@ -489,8 +489,10 @@ struct mtd_info *cfi_cmdset_0002(struct map_info *map, int primary) return cfi_amdstd_setup(mtd); } +struct mtd_info *cfi_cmdset_0006(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002"))); struct mtd_info *cfi_cmdset_0701(struct map_info *map, int primary) __attribute__((alias("cfi_cmdset_0002"))); EXPORT_SYMBOL_GPL(cfi_cmdset_0002); +EXPORT_SYMBOL_GPL(cfi_cmdset_0006); EXPORT_SYMBOL_GPL(cfi_cmdset_0701); static struct mtd_info *cfi_amdstd_setup(struct mtd_info *mtd) @@ -2042,4 +2044,5 @@ static void cfi_amdstd_destroy(struct mtd_info *mtd) MODULE_LICENSE("GPL"); MODULE_AUTHOR("Crossnet Co. et al."); MODULE_DESCRIPTION("MTD chip driver for AMD/Fujitsu flash chips"); +MODULE_ALIAS("cfi_cmdset_0006"); MODULE_ALIAS("cfi_cmdset_0701"); diff --git a/drivers/mtd/chips/gen_probe.c b/drivers/mtd/chips/gen_probe.c index 75a8f9d..3b9a284 100644 --- a/drivers/mtd/chips/gen_probe.c +++ b/drivers/mtd/chips/gen_probe.c @@ -249,6 +249,7 @@ static struct mtd_info *check_cmd_set(struct map_info *map, int primary) #ifdef CONFIG_MTD_CFI_AMDSTD case P_ID_AMD_STD: case P_ID_SST_OLD: + case P_ID_WINBOND: return cfi_cmdset_0002(map, primary); #endif #ifdef CONFIG_MTD_CFI_STAA From rpjday at crashcourse.ca Thu May 20 12:21:04 2010 From: rpjday at crashcourse.ca (Robert P. J. Day) Date: Thu, 20 May 2010 12:21:04 -0400 (EDT) Subject: what should be coming soon WRT Kconfig/Makefile cleanup Message-ID: sorry, not trying to flog this, but as a short followup to what i posted a couple days ago, i'm getting a new kernel janitor to work on some specific projects and, rather than constantly email back and forth with him, i posted his first potential project at my wiki. it's meant to be a general project, but i used the MTD part of the tree as an example: http://www.crashcourse.ca/wiki/index.php/Kconfig/Makefile_redundancy nothing earth-shattering there, just something to get him started and looking at the Kbuild structure. if you think anything else should be added to that page, or changed, let me know. or any other MTD-related janitorial projects i can dump on him. :-) rday -- ======================================================================== Robert P. J. Day Waterloo, Ontario, CANADA Linux Consulting, Training and Kernel Pedantry. Web page: http://crashcourse.ca Twitter: http://twitter.com/rpjday ======================================================================== From dedekind1 at gmail.com Thu May 20 23:53:30 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 21 May 2010 06:53:30 +0300 Subject: 2GB file size limit? In-Reply-To: <4BEE1582.40706@lambsys.com> References: <4BEE1582.40706@lambsys.com> Message-ID: <1274414010.8881.26.camel@localhost.localdomain> On Fri, 2010-05-14 at 22:31 -0500, David Lambert wrote: > Is there any way to increase the file size limit on UBIFS beyond > 2Gbytes? We never tested this, but should not be. AFAIR, UBIFS theoretical limitation should be something like 16TB, but I tried tested the maximum file size. > I have tried enabling the kernel ?Support for large block > devices and files? under ?Enable the block layer?, but the 2G limit > persists. UBIFS has nothing to do with block devices. This is a very specialized FS for bare flashes: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_rednote So that option has no effect for UBIFS. -- Best Regards, Artem Bityutskiy (????? ????????) From taliaferro62 at gmail.com Fri May 21 13:01:12 2010 From: taliaferro62 at gmail.com (twebb) Date: Fri, 21 May 2010 13:01:12 -0400 Subject: back-porting latest UBI/UBIFS to 2.6.29 Message-ID: Are there patches available that support back-porting of newer UBI/UBIFS to 2.6.29? I'm having some issues and see the note under "How to send an UBIFS bugreport" that suggests making sure you're using up-to-date UBIFS. Thanks, twebb From akpm at linux-foundation.org Fri May 21 15:01:06 2010 From: akpm at linux-foundation.org (Andrew Morton) Date: Fri, 21 May 2010 12:01:06 -0700 Subject: [PATCH] Fix Oops with Atmel SPI In-Reply-To: <1274267100l.1747l.1l@i-dmzi_al.realan.de> References: <1271231840l.5270l.0l@i-dmzi_al.realan.de> <20100421152410.0fea5e12.akpm@linux-foundation.org> <1274267100l.1747l.1l@i-dmzi_al.realan.de> Message-ID: <20100521120106.d955c78b.akpm@linux-foundation.org> On Wed, 19 May 2010 13:05:00 +0200 Anders Larsen wrote: > On 2010-04-22 00:24:10, Andrew Morton wrote: > > Finally.. Wouldn't it be better to just fix the atmel SPI driver so > > that it doesn't barf when handed vmalloc'ed memory? Who do we ridicule > > about that? > > You mean something like this instead? That looks simple enough. How do we get it tested, changelogged and merged up? Haavard, can you please take a look? > diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c > index c4e0442..a9ad5e8 100644 > --- a/drivers/spi/atmel_spi.c > +++ b/drivers/spi/atmel_spi.c > @@ -352,16 +352,30 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) > > xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS; > if (xfer->tx_buf) { > - xfer->tx_dma = dma_map_single(dev, > - (void *) xfer->tx_buf, xfer->len, > - DMA_TO_DEVICE); > + if (is_vmalloc_addr(xfer->tx_buf)) > + xfer->tx_dma = dma_map_page(dev, > + vmalloc_to_page(xfer->tx_buf), > + (unsigned long)xfer->tx_buf & (PAGE_SIZE-1), > + xfer->len, > + DMA_TO_DEVICE); > + else > + xfer->tx_dma = dma_map_single(dev, > + (void *) xfer->tx_buf, xfer->len, > + DMA_TO_DEVICE); > if (dma_mapping_error(dev, xfer->tx_dma)) > return -ENOMEM; > } > if (xfer->rx_buf) { > - xfer->rx_dma = dma_map_single(dev, > - xfer->rx_buf, xfer->len, > - DMA_FROM_DEVICE); > + if (is_vmalloc_addr(xfer->rx_buf)) > + xfer->rx_dma = dma_map_page(dev, > + vmalloc_to_page(xfer->rx_buf), > + (unsigned long)xfer->rx_buf & (PAGE_SIZE-1), > + xfer->len, > + DMA_FROM_DEVICE); > + else > + xfer->rx_dma = dma_map_single(dev, > + xfer->rx_buf, xfer->len, > + DMA_FROM_DEVICE); > if (dma_mapping_error(dev, xfer->rx_dma)) { > if (xfer->tx_buf) > dma_unmap_single(dev, > From taliaferro62 at gmail.com Fri May 21 16:56:13 2010 From: taliaferro62 at gmail.com (twebb) Date: Fri, 21 May 2010 16:56:13 -0400 Subject: back-porting latest UBI/UBIFS to 2.6.29 In-Reply-To: References: Message-ID: > Are there patches available that support back-porting of newer > UBI/UBIFS to 2.6.29? ?I'm having some issues and see the note under > "How to send an UBIFS bugreport" that suggests making sure you're > using up-to-date UBIFS. > Please disregard. I found the code at http://git.infradead.org/users/dedekind From hartleys at visionengravers.com Fri May 21 19:24:01 2010 From: hartleys at visionengravers.com (H Hartley Sweeten) Date: Fri, 21 May 2010 18:24:01 -0500 Subject: [PATCH] pcm551.c: use pci_ids.h defines Message-ID: <0D753D10438DA54287A00B0270842697636F3238A0@AUSP01VMBX24.collaborationhost.net> Move the DEVICE id to pci_ids.h and then use the VENDOR/DEVICE ids provided in pci_ids.h instead of creating local ids. Signed-off-by: H Hartley Sweeten Cc: David Woodhouse Cc: Jesse Barnes --- diff --git a/drivers/mtd/devices/pmc551.c b/drivers/mtd/devices/pmc551.c index fc8ea0a..f648e2b 100644 --- a/drivers/mtd/devices/pmc551.c +++ b/drivers/mtd/devices/pmc551.c @@ -697,8 +697,8 @@ static int __init init_pmc551(void) */ for (;;) { - if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3_SEMI, - PCI_DEVICE_ID_V3_SEMI_V370PDC, + if ((PCI_Device = pci_get_device(PCI_VENDOR_ID_V3, + PCI_DEVICE_ID_V3_V370PDC, PCI_Device)) == NULL) { break; } diff --git a/include/linux/mtd/pmc551.h b/include/linux/mtd/pmc551.h index 27ad40a..bc68a9d 100644 --- a/include/linux/mtd/pmc551.h +++ b/include/linux/mtd/pmc551.h @@ -41,18 +41,6 @@ static int pmc551_read(struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int pmc551_write(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); -/* - * Define the PCI ID's if the kernel doesn't define them for us - */ -#ifndef PCI_VENDOR_ID_V3_SEMI -#define PCI_VENDOR_ID_V3_SEMI 0x11b0 -#endif - -#ifndef PCI_DEVICE_ID_V3_SEMI_V370PDC -#define PCI_DEVICE_ID_V3_SEMI_V370PDC 0x0200 -#endif - - #define PMC551_PCI_MEM_MAP0 0x50 #define PMC551_PCI_MEM_MAP1 0x54 #define PMC551_PCI_MEM_MAP_MAP_ADDR_MASK 0x3ff00000 diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9f688d2..3987d96 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1565,6 +1565,7 @@ #define PCI_VENDOR_ID_V3 0x11b0 #define PCI_DEVICE_ID_V3_V960 0x0001 #define PCI_DEVICE_ID_V3_V351 0x0002 +#define PCI_DEVICE_ID_V3_V370PDC 0x0200 #define PCI_VENDOR_ID_ATT 0x11c1 #define PCI_DEVICE_ID_ATT_VENUS_MODEM 0x480 From greg at kroah.com Fri May 21 19:42:32 2010 From: greg at kroah.com (Greg KH) Date: Fri, 21 May 2010 16:42:32 -0700 Subject: [PATCH] pcm551.c: use pci_ids.h defines In-Reply-To: <0D753D10438DA54287A00B0270842697636F3238A0@AUSP01VMBX24.collaborationhost.net> References: <0D753D10438DA54287A00B0270842697636F3238A0@AUSP01VMBX24.collaborationhost.net> Message-ID: <20100521234232.GA31672@kroah.com> On Fri, May 21, 2010 at 06:24:01PM -0500, H Hartley Sweeten wrote: > Move the DEVICE id to pci_ids.h and then use the VENDOR/DEVICE ids provided > in pci_ids.h instead of creating local ids. Did you read the comment at the top of the pci_ids.h file saying not to do this? Just use the vendor id that is already in the pci_ids.h file in the driver, but leave the device id in the driver itself. thanks, greg k-h From hartleys at visionengravers.com Fri May 21 19:46:20 2010 From: hartleys at visionengravers.com (H Hartley Sweeten) Date: Fri, 21 May 2010 18:46:20 -0500 Subject: [PATCH] pcm551.c: use pci_ids.h defines In-Reply-To: <20100521234232.GA31672@kroah.com> References: <0D753D10438DA54287A00B0270842697636F3238A0@AUSP01VMBX24.collaborationhost.net> <20100521234232.GA31672@kroah.com> Message-ID: <0D753D10438DA54287A00B0270842697636F3238BB@AUSP01VMBX24.collaborationhost.net> On Friday, May 21, 2010 4:43 PM, Greg KH wrote: > On Fri, May 21, 2010 at 06:24:01PM -0500, H Hartley Sweeten wrote: >> Move the DEVICE id to pci_ids.h and then use the VENDOR/DEVICE ids provided >> in pci_ids.h instead of creating local ids. > > Did you read the comment at the top of the pci_ids.h file saying not to > do this? Just use the vendor id that is already in the pci_ids.h file > in the driver, but leave the device id in the driver itself. Oops.. My bad, sorry. Please ignore this patch (and the other two). Regards, Hartley From maximlevitsky at gmail.com Fri May 21 21:03:05 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 04:03:05 +0300 Subject: [PATCH] [R852] Few fixes Message-ID: <1274490185.15285.22.camel@maxim-laptop> Hi, This is patch series that implement few fixes in regard to suspend/resume that I finally (after 2 years) managed to fix on my notebook. Currently there are exactly 3 problems, and I am investigating the solutions. 1) I am finally confident that CONFIG_MMC_RICOH_MMC causes the SD/MMC portion of the controller to die (and trigger an interrupt storm). I don't know if this is a regression, because all I did was to execute the code that disables MMC controller a bit earlier, because otherwise my xD driver will bind to wrong pci function. I still continue to investigate this issue, and maybe the only solution to it, is to write a full driver for the MMC controller (this is done in windows). When this happens (it doesn't depend on whether card was in slot or not, controller causes interrupt storm, and continues it till sdhci-pci is reloaded, at which point it refuses to load.) Since r852 shares (at least here) the interrupt with sdhci-pci, if I attempt to reload it, it gets interrupt immediately, and accesses uninitialized spinlock. First patch in that series addresses that issue. 2) For some yet unknown to me reason, DMA stops working on r852 after resume IF the card was inserted during time system was sleeping. Just card reload works around that issue, but my driver still oopses when it tries to complete() an completion that time-outed. The second patch fixes that oops. 3) This is the weirdest problem, and it might be a cause of CONFIG_MMC_RICOH_MMC too. I didn't yet managed to fully understand when it happens. Again when card is inserted during suspend (maybe even in other cases), the controller stops reporting card insert/remove events. You can go ahead, remove the xD card, insert SD card, etc, it still thinks it has xD card. A suspend/resume cycle allows it to detect the card state 'once', for example suspending without card makes it finally understand that there is no card, and allow to insert other cards, but insert of an xD card doesn't make any difference. The above is for reference, I will try soon to fix these problems. (Especially the 2nd). In addition to that i send a patch to fix problem in Kconfig. All nand entries weren't shown under mtd menu + at least for now this driver should depend on smartmedia byte order. (Technically the SM_FTL should depends on it, but this way is safer) Best regards, Maxim Levitsky From maximlevitsky at gmail.com Fri May 21 21:07:54 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 04:07:54 +0300 Subject: [PATCH 1/3] r852: register IRQ as last step In-Reply-To: <1274490185.15285.22.camel@maxim-laptop> References: <1274490185.15285.22.camel@maxim-laptop> Message-ID: <1274490476-16057-1-git-send-email-maximlevitsky@gmail.com> From: Maxim Levitsky Otherwise, if it fires right away, it might access uninitialized spinlock Signed-off-by: Maxim Levitsky --- drivers/mtd/nand/r852.c | 11 ++++++----- 1 files changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 78a4232..20a654a 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -940,18 +940,19 @@ int r852_probe(struct pci_dev *pci_dev, const struct pci_device_id *id) r852_dma_test(dev); + dev->irq = pci_dev->irq; + spin_lock_init(&dev->irqlock); + + dev->card_detected = 0; + r852_card_update_present(dev); + /*register irq handler*/ error = -ENODEV; if (request_irq(pci_dev->irq, &r852_irq, IRQF_SHARED, DRV_NAME, dev)) goto error10; - dev->irq = pci_dev->irq; - spin_lock_init(&dev->irqlock); - /* kick initial present test */ - dev->card_detected = 0; - r852_card_update_present(dev); queue_delayed_work(dev->card_workqueue, &dev->card_detect_work, 0); -- 1.7.0.4 From maximlevitsky at gmail.com Fri May 21 21:07:55 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 04:07:55 +0300 Subject: [PATCH 2/3] r852: Fixes in case of DMA timeout In-Reply-To: <1274490185.15285.22.camel@maxim-laptop> References: <1274490185.15285.22.camel@maxim-laptop> Message-ID: <1274490476-16057-2-git-send-email-maximlevitsky@gmail.com> * Don't call complete on dma completion * do a INIT_COMPLETE before using it each time * Report DMA read error via ecc 'correct' I finally managed to make my system do suspend to ram propertly, and I see that if card was inserted during suspend (while system was off), I get dma timeouts on resume. Simple card reinsert solves the issue. This patch solves a crash that would happen otherwise Signed-off-by: Maxim Levitsky --- drivers/mtd/nand/r852.c | 14 +++++++++++--- 1 files changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 20a654a..3f219e6 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c @@ -150,7 +150,6 @@ static void r852_dma_done(struct r852_device *dev, int error) if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer) pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN, dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); - complete(&dev->dma_done); } /* @@ -182,6 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) /* Set dma direction */ dev->dma_dir = do_read; dev->dma_stage = 1; + INIT_COMPLETION(dev->dma_done); dbg_verbose("doing dma %s ", do_read ? "read" : "write"); @@ -494,6 +494,11 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, if (dev->card_unstable) return 0; + if (dev->dma_error) { + dev->dma_error = 0; + return -1; + } + r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS); ecc_reg = r852_read_reg_dword(dev, R852_DATALINE); r852_write_reg(dev, R852_CTL, dev->ctlreg); @@ -796,6 +801,7 @@ static irqreturn_t r852_irq(int irq, void *data) if (dma_status & R852_DMA_IRQ_ERROR) { dbg("recieved dma error IRQ"); r852_dma_done(dev, -EIO); + complete(&dev->dma_done); goto out; } @@ -825,8 +831,10 @@ static irqreturn_t r852_irq(int irq, void *data) r852_dma_enable(dev); /* Operation done */ - if (dev->dma_stage == 3) + if (dev->dma_stage == 3) { r852_dma_done(dev, 0); + complete(&dev->dma_done); + } goto out; } @@ -1082,7 +1090,7 @@ int r852_resume(struct device *device) dev->card_detected ? "added" : "removed"); queue_delayed_work(dev->card_workqueue, - &dev->card_detect_work, 1000); + &dev->card_detect_work, msecs_to_jiffies(1000)); return 0; } -- 1.7.0.4 From maximlevitsky at gmail.com Fri May 21 21:07:56 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 04:07:56 +0300 Subject: [PATCH 3/3] MTD: Kconfig cleanups In-Reply-To: <1274490185.15285.22.camel@maxim-laptop> References: <1274490185.15285.22.camel@maxim-laptop> Message-ID: <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> Move all nand options under 'if MTD_NAND' otherwise xconfig output is broken. make Ricoh xD driver depend on MTD_NAND_ECC_SMC, untill proper solution is made Signed-off-by: Maxim Levitsky --- drivers/mtd/nand/Kconfig | 5 ++++- 1 files changed, 4 insertions(+), 1 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 98a04b3..8db333f 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -8,6 +8,8 @@ menuconfig MTD_NAND devices. For further information see . +if MTD_NAND + config MTD_NAND_ECC tristate @@ -19,7 +21,7 @@ config MTD_NAND_ECC_SMC Software ECC according to the Smart Media Specification. The original Linux implementation had byte 0 and 1 swapped. -if MTD_NAND + config MTD_NAND_VERIFY_WRITE bool "Verify NAND page writes" @@ -129,6 +131,7 @@ config MTD_NAND_RICOH default n depends on PCI select MTD_SM_COMMON + select MTD_NAND_ECC_SMC help Enable support for Ricoh R5C852 xD card reader You also need to enable ether -- 1.7.0.4 From dedekind1 at gmail.com Sat May 22 01:30:02 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sat, 22 May 2010 08:30:02 +0300 Subject: [PATCH] mtd-utils: Support 4096+64 page sizes. In-Reply-To: <1274176439-22351-1-git-send-email-eballetbo@gmail.com> References: <1274176439-22351-1-git-send-email-eballetbo@gmail.com> Message-ID: <1274506202.8881.30.camel@localhost.localdomain> On Tue, 2010-05-18 at 11:53 +0200, Enric Balletbo i Serra wrote: > + !(meminfo.oobsize == 64 && meminfo.writesize > == 4096) && Are there flashes with the 4096 page / 64 spare combination? Could you refer to one? May be any URL? I thought 4096 comes with 128. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sat May 22 01:39:28 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sat, 22 May 2010 08:39:28 +0300 Subject: [PATCH 2/2] check if the start address is page-aligned. In-Reply-To: <1274185390-3066-3-git-send-email-stanley.miao@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> <1274185390-3066-3-git-send-email-stanley.miao@windriver.com> Message-ID: <1274506768.8881.31.camel@localhost.localdomain> On Tue, 2010-05-18 at 20:23 +0800, Stanley.Miao wrote: > Only page-aligned address is permitted in NAND subsystem. > > Signed-off-by: Stanley.Miao Pushed both patches to the mtd-utils repo, thanks. However, I had to fix a tiny white-space damage for you: Applying: nandwrite: check if the start address is page-aligned. /home/dedekind/git/mtd-utils/.git/rebase-apply/patch:13: trailing whitespace. -- Best Regards, Artem Bityutskiy (????? ????????) From dwmw2 at infradead.org Sat May 22 03:47:10 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Sat, 22 May 2010 08:47:10 +0100 Subject: [PATCH 3/3] MTD: Kconfig cleanups In-Reply-To: <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> References: <1274490185.15285.22.camel@maxim-laptop> <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> Message-ID: <1274514430.11551.13808.camel@macbook.infradead.org> On Sat, 2010-05-22 at 04:07 +0300, Maxim Levitsky wrote: > > @@ -129,6 +131,7 @@ config MTD_NAND_RICOH > default n > depends on PCI > select MTD_SM_COMMON > + select MTD_NAND_ECC_SMC I thought we had a better solution than this -- weren't we going to make it a runtime thing? And default to the 'correct' order? Then, only the legacy devices which need to retain the 'wrong' byteorder for compatibility reasons will need to do it. -- dwmw2 From maximlevitsky at gmail.com Sat May 22 03:58:16 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 10:58:16 +0300 Subject: [PATCH 3/3] MTD: Kconfig cleanups In-Reply-To: <1274514430.11551.13808.camel@macbook.infradead.org> References: <1274490185.15285.22.camel@maxim-laptop> <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> <1274514430.11551.13808.camel@macbook.infradead.org> Message-ID: <1274515096.19375.2.camel@maxim-laptop> On Sat, 2010-05-22 at 08:47 +0100, David Woodhouse wrote: > On Sat, 2010-05-22 at 04:07 +0300, Maxim Levitsky wrote: > > > > @@ -129,6 +131,7 @@ config MTD_NAND_RICOH > > default n > > depends on PCI > > select MTD_SM_COMMON > > + select MTD_NAND_ECC_SMC > > I thought we had a better solution than this -- weren't we going to make > it a runtime thing? And default to the 'correct' order? > > Then, only the legacy devices which need to retain the 'wrong' byteorder > for compatibility reasons will need to do it. > Sure, but I'll need to do several changes to drivers that I can't test. For now this ensures correctness, then I fix all of this. Best regards, Maxim Levitsky From maximlevitsky at gmail.com Sat May 22 04:06:43 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 11:06:43 +0300 Subject: [PATCH 3/3] MTD: Kconfig cleanups In-Reply-To: <1274515096.19375.2.camel@maxim-laptop> References: <1274490185.15285.22.camel@maxim-laptop> <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> <1274514430.11551.13808.camel@macbook.infradead.org> <1274515096.19375.2.camel@maxim-laptop> Message-ID: <1274515603.19696.1.camel@maxim-laptop> On Sat, 2010-05-22 at 10:58 +0300, Maxim Levitsky wrote: > On Sat, 2010-05-22 at 08:47 +0100, David Woodhouse wrote: > > On Sat, 2010-05-22 at 04:07 +0300, Maxim Levitsky wrote: > > > > > > @@ -129,6 +131,7 @@ config MTD_NAND_RICOH > > > default n > > > depends on PCI > > > select MTD_SM_COMMON > > > + select MTD_NAND_ECC_SMC > > > > I thought we had a better solution than this -- weren't we going to make > > it a runtime thing? And default to the 'correct' order? > > > > Then, only the legacy devices which need to retain the 'wrong' byteorder > > for compatibility reasons will need to do it. > > > Sure, but I'll need to do several changes to drivers that I can't test. > For now this ensures correctness, then I fix all of this. In other words, when I get a bit more free time I promise I fix this and other problems. For now this ensures correctness at least of this thing. Best regards, Maxim Levitsky From julia at diku.dk Sat May 22 04:22:49 2010 From: julia at diku.dk (Julia Lawall) Date: Sat, 22 May 2010 10:22:49 +0200 (CEST) Subject: [PATCH 15/27] drivers/mtd: Use memdup_user Message-ID: From: Julia Lawall Use memdup_user when user data is immediately copied into the allocated region. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ expression from,to,size,flag; position p; identifier l1,l2; @@ - to = \(kmalloc at p\|kzalloc at p\)(size,flag); + to = memdup_user(from,size); if ( - to==NULL + IS_ERR(to) || ...) { <+... when != goto l1; - -ENOMEM + PTR_ERR(to) ...+> } - if (copy_from_user(to, from, size) != 0) { - <+... when != goto l2; - -EFAULT - ...+> - } // Signed-off-by: Julia Lawall --- drivers/mtd/mtdchar.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 000d65e..91c8013 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -404,14 +404,9 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) return -EINVAL; - ops.oobbuf = kmalloc(length, GFP_KERNEL); - if (!ops.oobbuf) - return -ENOMEM; - - if (copy_from_user(ops.oobbuf, ptr, length)) { - kfree(ops.oobbuf); - return -EFAULT; - } + ops.oobbuf = memdup_user(ptr, length); + if (IS_ERR(ops.oobbuf)) + return PTR_ERR(ops.oobbuf); start &= ~((uint64_t)mtd->oobsize - 1); ret = mtd->write_oob(mtd, start, &ops); From julia at diku.dk Sat May 22 06:00:21 2010 From: julia at diku.dk (Julia Lawall) Date: Sat, 22 May 2010 12:00:21 +0200 (CEST) Subject: [PATCH 4/8] fs/ubifs: Use ERR_CAST Message-ID: From: Julia Lawall Use ERR_CAST(x) rather than ERR_PTR(PTR_ERR(x)). The former makes more clear what is the purpose of the operation, which otherwise looks like a no-op. The semantic patch that makes this change is as follows: (http://coccinelle.lip6.fr/) // @@ type T; T x; identifier f; @@ T f (...) { <+... - ERR_PTR(PTR_ERR(x)) + x ...+> } @@ expression x; @@ - ERR_PTR(PTR_ERR(x)) + ERR_CAST(x) // Signed-off-by: Julia Lawall --- fs/ubifs/lpt.c | 14 +++++++------- fs/ubifs/lpt_commit.c | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff -u -p a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c --- a/fs/ubifs/lpt.c +++ b/fs/ubifs/lpt.c @@ -1457,13 +1457,13 @@ struct ubifs_lprops *ubifs_lpt_lookup(st shft -= UBIFS_LPT_FANOUT_SHIFT; nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) - return ERR_PTR(PTR_ERR(nnode)); + return ERR_CAST(nnode); } iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); shft -= UBIFS_LPT_FANOUT_SHIFT; pnode = ubifs_get_pnode(c, nnode, iip); if (IS_ERR(pnode)) - return ERR_PTR(PTR_ERR(pnode)); + return ERR_CAST(pnode); iip = (i & (UBIFS_LPT_FANOUT - 1)); dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, pnode->lprops[iip].free, pnode->lprops[iip].dirty, @@ -1586,7 +1586,7 @@ struct ubifs_lprops *ubifs_lpt_lookup_di nnode = c->nroot; nnode = dirty_cow_nnode(c, nnode); if (IS_ERR(nnode)) - return ERR_PTR(PTR_ERR(nnode)); + return ERR_CAST(nnode); i = lnum - c->main_first; shft = c->lpt_hght * UBIFS_LPT_FANOUT_SHIFT; for (h = 1; h < c->lpt_hght; h++) { @@ -1594,19 +1594,19 @@ struct ubifs_lprops *ubifs_lpt_lookup_di shft -= UBIFS_LPT_FANOUT_SHIFT; nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) - return ERR_PTR(PTR_ERR(nnode)); + return ERR_CAST(nnode); nnode = dirty_cow_nnode(c, nnode); if (IS_ERR(nnode)) - return ERR_PTR(PTR_ERR(nnode)); + return ERR_CAST(nnode); } iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); shft -= UBIFS_LPT_FANOUT_SHIFT; pnode = ubifs_get_pnode(c, nnode, iip); if (IS_ERR(pnode)) - return ERR_PTR(PTR_ERR(pnode)); + return ERR_CAST(pnode); pnode = dirty_cow_pnode(c, pnode); if (IS_ERR(pnode)) - return ERR_PTR(PTR_ERR(pnode)); + return ERR_CAST(pnode); iip = (i & (UBIFS_LPT_FANOUT - 1)); dbg_lp("LEB %d, free %d, dirty %d, flags %d", lnum, pnode->lprops[iip].free, pnode->lprops[iip].dirty, diff -u -p a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c --- a/fs/ubifs/lpt_commit.c +++ b/fs/ubifs/lpt_commit.c @@ -646,7 +646,7 @@ static struct ubifs_pnode *pnode_lookup( shft -= UBIFS_LPT_FANOUT_SHIFT; nnode = ubifs_get_nnode(c, nnode, iip); if (IS_ERR(nnode)) - return ERR_PTR(PTR_ERR(nnode)); + return ERR_CAST(nnode); } iip = ((i >> shft) & (UBIFS_LPT_FANOUT - 1)); return ubifs_get_pnode(c, nnode, iip); From maximlevitsky at gmail.com Sat May 22 06:54:21 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 13:54:21 +0300 Subject: [PATCH 3/3] MTD: Kconfig cleanups In-Reply-To: <1274515603.19696.1.camel@maxim-laptop> References: <1274490185.15285.22.camel@maxim-laptop> <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> <1274514430.11551.13808.camel@macbook.infradead.org> <1274515096.19375.2.camel@maxim-laptop> <1274515603.19696.1.camel@maxim-laptop> Message-ID: <1274525661.20615.2.camel@maxim-laptop> On Sat, 2010-05-22 at 11:06 +0300, Maxim Levitsky wrote: > On Sat, 2010-05-22 at 10:58 +0300, Maxim Levitsky wrote: > > On Sat, 2010-05-22 at 08:47 +0100, David Woodhouse wrote: > > > On Sat, 2010-05-22 at 04:07 +0300, Maxim Levitsky wrote: > > > > > > > > @@ -129,6 +131,7 @@ config MTD_NAND_RICOH > > > > default n > > > > depends on PCI > > > > select MTD_SM_COMMON > > > > + select MTD_NAND_ECC_SMC > > > > > > I thought we had a better solution than this -- weren't we going to make > > > it a runtime thing? And default to the 'correct' order? > > > > > > Then, only the legacy devices which need to retain the 'wrong' byteorder > > > for compatibility reasons will need to do it. > > > > > Sure, but I'll need to do several changes to drivers that I can't test. > > For now this ensures correctness, then I fix all of this. > In other words, when I get a bit more free time I promise I fix this and > other problems. For now this ensures correctness at least of this thing. Thinking again about this, this doesn't help much ether, so lets keep it as is, except that 'if MTD_NAND' should be moved higher. Best regards, Maxim Levitsky From maximlevitsky at gmail.com Sat May 22 08:18:03 2010 From: maximlevitsky at gmail.com (Maxim Levitsky) Date: Sat, 22 May 2010 15:18:03 +0300 Subject: [PATCH v2] MTD: Fix NAND submenu In-Reply-To: <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> References: <1274490476-16057-3-git-send-email-maximlevitsky@gmail.com> Message-ID: <1274530683-22294-1-git-send-email-maximlevitsky@gmail.com> Move all nand options under 'if MTD_NAND' otherwise xconfig output is broken. Signed-off-by: Maxim Levitsky --- drivers/mtd/nand/Kconfig | 4 +++- 1 files changed, 3 insertions(+), 1 deletions(-) diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 98a04b3..5927239 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -8,6 +8,8 @@ menuconfig MTD_NAND devices. For further information see . +if MTD_NAND + config MTD_NAND_ECC tristate @@ -19,7 +21,7 @@ config MTD_NAND_ECC_SMC Software ECC according to the Smart Media Specification. The original Linux implementation had byte 0 and 1 swapped. -if MTD_NAND + config MTD_NAND_VERIFY_WRITE bool "Verify NAND page writes" -- 1.7.0.4 From error27 at gmail.com Sat May 22 16:16:26 2010 From: error27 at gmail.com (Dan Carpenter) Date: Sat, 22 May 2010 22:16:26 +0200 Subject: [patch] mtd/sst25l: check for null consistently Message-ID: <20100522201626.GJ22515@bicker> The rest of the function assumes that "data" can be null. I don't know the code well enough to say whether it can actually be null, but there is no harm in checking here. Signed-off-by: Dan Carpenter diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c index ab5d8cd..684247a 100644 --- a/drivers/mtd/devices/sst25l.c +++ b/drivers/mtd/devices/sst25l.c @@ -454,7 +454,7 @@ static int __init sst25l_probe(struct spi_device *spi) parts, nr_parts); } - } else if (data->nr_parts) { + } else if (data && data->nr_parts) { dev_warn(&spi->dev, "ignoring %d default partitions on %s\n", data->nr_parts, data->name); } From dedekind1 at gmail.com Sun May 23 02:16:57 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 09:16:57 +0300 Subject: [PATCH] UBI: fix delete compatible internal volume scan In-Reply-To: References: Message-ID: <1274595417.8881.36.camel@localhost.localdomain> On Tue, 2010-05-18 at 23:10 +0530, Brijesh Singh wrote: > This patch resolves a possible bug. Scan is adding delete compatible > blocks to both corr list and used list. > It should return after adding the block to corr list. > > Signed-off-by: Brijesh Singh I'm not sure this patch is enough. I think we should add a 'compat' flag to the 'struct ubi_mkvol_req' structure, to make it possible to create volumes with different compatibility flags. Then we need to write a test and add it to the UBI test-suite at 'mtd-utils/tests/ubi-tests/'. Then once we have tested and fixed this, we should merge this and also send to the '-stable' trees. I remember I did give the compat option a test, but probably not that good. I'll try to do what I've described as soon as I have time, but you guys could do this as well, if you have bandwidth. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 02:26:36 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 09:26:36 +0300 Subject: how to pre-screen patch submissions from a newbie janitor? In-Reply-To: References: Message-ID: <1274595996.8881.42.camel@localhost.localdomain> On Tue, 2010-05-18 at 19:40 -0400, Robert P. J. Day wrote: > not that long ago, i suggested cleaning up the MTD Kconfig/Makefile > structure since there was some definite redundancy in the inclusion of > source files and subdirectories. now, i could whip up those patches > myself and submit them, but i have a local friend who's itching to get > start doing some simple kernel work and submitting some patches, and > he's more than smart enough to do what i described above. > > however, since he's new to patch creation and submission, i offered > to "vet" his patches first. i realize that my vetting carries no > weight on the MTD list, but given that i've submitted lots and lots of > patches elsewhere, i can still at least sanity check what he comes up > with before it hits the list. > > is there a canonical signage for that nowadays? is it "Reviewed-By" > or something like that? so that by the time it gets to the MTD list, > he would have done the "Signed-Off-By" and i'd sign off as a reviewer. > is that the way it works? or is there an alternative? thanks. Hi, MTD list is not something special, common Linux kernel patch submission practices apply. So obviously, he signs off his patches, you can review, test, ack or sign off it. I am not pedantic about which tag to use, but you can always refer to 'Documentation/SubmittingPatches' and pick the right one. -- Best Regards, Artem Bityutskiy (????? ????????) From vapier.adi at gmail.com Sun May 23 03:23:50 2010 From: vapier.adi at gmail.com (Mike Frysinger) Date: Sun, 23 May 2010 03:23:50 -0400 Subject: [PATCH 2/2] mtd-physmap: add support users can assign the probe type in board files In-Reply-To: <1263541814-6642-2-git-send-email-21cnbao@gmail.com> References: <1263541814-6642-1-git-send-email-21cnbao@gmail.com> <1263541814-6642-2-git-send-email-21cnbao@gmail.com> Message-ID: On Fri, Jan 15, 2010 at 03:50, Barry Song wrote: > There are three reasons to add this support: > 1. users probably know the interface type of their flashs, then probe > can be faster if they give the right type in platform data since wrong > types will not be detected. > 2. sometimes, detecting can cause destory to system. For example, for > kernel XIP, detecting can cause NOR enter a mode instructions can not > be fetched right, which will make kernel crash. > 3. For a new probe which is not listed in the rom_probe_types, if users > assign it in board files, physmap can still probe it. any input on this patch ? doesnt seem to be in post 2.6.34 merges ... -mike From vapier at gentoo.org Sun May 23 03:30:23 2010 From: vapier at gentoo.org (Mike Frysinger) Date: Sun, 23 May 2010 03:30:23 -0400 Subject: [PATCH 1/2] mtd: physmap: add physmap_unmapped_area() for no-mmu XIP Message-ID: <1274599824-17530-1-git-send-email-vapier@gentoo.org> From: Bernd Schmidt Currently, romfs XIP doesn't work in flash memory (the kernel crashes with a null pointer dereference). The problem is that the mtd physmap driver isn't setting up a get_unmapped_area pointer for the mtd partitions it creates. Signed-off-by: Bernd Schmidt Signed-off-by: Mike Frysinger --- drivers/mtd/maps/physmap.c | 16 ++++++++++++++++ 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 09d89ff..370da18 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -72,6 +72,20 @@ static int physmap_flash_remove(struct platform_device *dev) return 0; } +/* + * Allow NOMMU mmap() to directly map the device (if not NULL) + * - return the address to which the offset maps + * - return -ENOSYS to indicate refusal to do the mapping + */ +static unsigned long physmap_unmapped_area(struct mtd_info *mtd, + unsigned long len, + unsigned long offset, + unsigned long flags) +{ + struct map_info *map = mtd->priv; + return (unsigned long) map->virt + offset; +} + static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", @@ -149,6 +163,8 @@ static int physmap_flash_probe(struct platform_device *dev) } else { devices_found++; } + if (info->mtd[i]->get_unmapped_area == NULL) + info->mtd[i]->get_unmapped_area = physmap_unmapped_area; info->mtd[i]->owner = THIS_MODULE; info->mtd[i]->dev.parent = &dev->dev; } -- 1.7.1 From vapier at gentoo.org Sun May 23 03:30:24 2010 From: vapier at gentoo.org (Mike Frysinger) Date: Sun, 23 May 2010 03:30:24 -0400 Subject: [PATCH 2/2] mtd: physmap: allow maps to be read-only mapped In-Reply-To: <1274599824-17530-1-git-send-email-vapier@gentoo.org> References: <1274599824-17530-1-git-send-email-vapier@gentoo.org> Message-ID: <1274599824-17530-2-git-send-email-vapier@gentoo.org> From: Bernd Schmidt Recent changes have made nommu.c more careful about checking device capabilities before attempting to create a direct mapping. This means that the physmap driver has to mark its mtd devices as ro-mappable if we want to support XIP on flash. Signed-off-by: Bernd Schmidt Signed-off-by: Mike Frysinger --- Note: this does semi-undo recent changes that punted the prototypes for these common mtd_bdi's ... drivers/mtd/maps/physmap.c | 2 ++ drivers/mtd/mtdcore.c | 4 ++++ include/linux/mtd/mtdbdi.h | 17 +++++++++++++++++ 3 files changed, 23 insertions(+), 0 deletions(-) create mode 100644 include/linux/mtd/mtdbdi.h diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 370da18..be2dbc2 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #define MAX_RESOURCES 4 @@ -165,6 +166,7 @@ static int physmap_flash_probe(struct platform_device *dev) } if (info->mtd[i]->get_unmapped_area == NULL) info->mtd[i]->get_unmapped_area = physmap_unmapped_area; + info->mtd[i]->backing_dev_info = &mtd_bdi_ro_mappable; info->mtd[i]->owner = THIS_MODULE; info->mtd[i]->dev.parent = &dev->dev; } diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c index a1b8b70..0995819 100644 --- a/drivers/mtd/mtdcore.c +++ b/drivers/mtd/mtdcore.c @@ -24,6 +24,7 @@ #include #include +#include #include "mtdcore.h" /* @@ -33,6 +34,7 @@ struct backing_dev_info mtd_bdi_unmappable = { .capabilities = BDI_CAP_MAP_COPY, }; +EXPORT_SYMBOL(mtd_bdi_unmappable); /* * backing device capabilities for R/O mappable devices (such as ROM) @@ -43,6 +45,7 @@ struct backing_dev_info mtd_bdi_ro_mappable = { .capabilities = (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT | BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP), }; +EXPORT_SYMBOL(mtd_bdi_ro_mappable); /* * backing device capabilities for writable mappable devices (such as RAM) @@ -54,6 +57,7 @@ struct backing_dev_info mtd_bdi_rw_mappable = { BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP), }; +EXPORT_SYMBOL(mtd_bdi_rw_mappable); static int mtd_cls_suspend(struct device *dev, pm_message_t state); static int mtd_cls_resume(struct device *dev); diff --git a/include/linux/mtd/mtdbdi.h b/include/linux/mtd/mtdbdi.h new file mode 100644 index 0000000..ec0dd7e --- /dev/null +++ b/include/linux/mtd/mtdbdi.h @@ -0,0 +1,17 @@ +/* Internal MTD definitions + * + * Copyright ?? 2006 Red Hat, Inc. All Rights Reserved. + * Written by David Howells (dhowells at redhat.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +/* + * mtdcore.c + */ +extern struct backing_dev_info mtd_bdi_unmappable; +extern struct backing_dev_info mtd_bdi_ro_mappable; +extern struct backing_dev_info mtd_bdi_rw_mappable; -- 1.7.1 From dedekind1 at gmail.com Sun May 23 07:28:32 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 14:28:32 +0300 Subject: ubifs became broken on contigous power-fails In-Reply-To: References: Message-ID: <1274614112.22999.17.camel@localhost> On Tue, 2010-05-11 at 18:43 +0400, Alexander Pazdnikov wrote: > Hello. > > We are stress-testing 8 devices by power loss in 5 minutes interval. > Device uses sqlite database to store collected data, every 1 minute accumulated data (500-1000 records) is stored into database in transaction. > > ubifs (ubi2:dbfs on /usr/local/ecom/db bellow) with database on 6 of 8 devices after different time (1-3 days) became broken. > > Any advise for futher debugging or solving this problem is highly appriciated. > > > kernel 2.6.32.12 > > suspicious -> reserved GC LEB: -1 > > # cat /proc/mtd > dev: size erasesize name > mtd0: 00020000 00020000 "bootstrap" > mtd1: 00080000 00020000 "uboot" > mtd2: 00020000 00020000 "uboot_env1" > mtd3: 00020000 00020000 "uboot_env2" > mtd4: 02000000 00020000 "ubi_main" > mtd5: 02000000 00020000 "ubi_var" > mtd6: 0bf00000 00020000 "ubi_database" > > > mounting ubi2:dbfs on startup > [ 14.328117] UBIFS: recovery needed > [ 53.941378] UBIFS error (pid 462): ubifs_rcvry_gc_commit: could not find a dirty LEB This is must be a bug. UBIFS should always have space for GC. I will think how we can track this down, although I have a very limited amount of time. > [ 89.606399] UBIFS: recovery completed This is another small problem - UBIFS actually failed to recover. So instead of continuing, it should return error. I've inlined a patch which should fix this - we basically forgot to check function return code. > [ 89.609329] UBIFS assert failed in mount_ubifs at 1358 (pid 462) > [ 89.616165] [] (unwind_backtrace+0x0/0xe4) from [] (ubifs_fill_super+0x11d0/0x1c4c) > [ 89.625930] [] (ubifs_fill_super+0x11d0/0x1c4c) from [] (ubifs_get_sb+0x1b0/0x354) > [ 89.635696] [] (ubifs_get_sb+0x1b0/0x354) from [] (vfs_kern_mount+0x50/0xe0) > [ 89.644485] [] (vfs_kern_mount+0x50/0xe0) from [] (do_kern_mount+0x34/0xdc) > [ 89.653274] [] (do_kern_mount+0x34/0xdc) from [] (do_mount+0x148/0x7cc) > [ 89.662063] [] (do_mount+0x148/0x7cc) from [] (sys_mount+0x98/0xc8) > [ 89.670852] [] (sys_mount+0x98/0xc8) from [] (ret_fast_syscall+0x0/0x28) Yeah, these further assertion failures are because we did not find GC LEB, and ignored 'ubifs_rcvry_gc_commit()' error code. The below patch will not fix your problem, but should at least make UBIFS fail immidiately, instead of continuing working in a wrong state and spitting a lot of warnings. I've also pushed this patch to the ubifs-2.6.git, and if it is OK, will later merge it upstream. But the root cause of the error you see remains unknown... >From d3cd7a16efce60c8509df7b5f19e7d2fb1b6899c Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 23 May 2010 14:16:13 +0300 Subject: [PATCH] UBIFS: check return code The error code from 'ubifs_rcvry_gc_commit()' was ignored, so UBIFS failed to recover and contunued. Instead, we should refise mounting the file-system. Signed-off-by: Artem Bityutskiy --- fs/ubifs/super.c | 2 ++ 1 files changed, 2 insertions(+), 0 deletions(-) diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c index 4d2f215..010eea0 100644 --- a/fs/ubifs/super.c +++ b/fs/ubifs/super.c @@ -1307,6 +1307,8 @@ static int mount_ubifs(struct ubifs_info *c) if (err) goto out_orphans; err = ubifs_rcvry_gc_commit(c); + if (err) + goto out_orphans; } else { err = take_gc_lnum(c); if (err) -- 1.6.6.1 -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 08:03:13 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 15:03:13 +0300 Subject: [PATCH 0/4] UBI: improve empty flash handling In-Reply-To: <1273210793.2178.4.camel@localhost> References: <1272881582-17196-1-git-send-email-Artem.Bityutskiy@nokia.com> <20100506095218.GB15335@Chamillionaire.breakpoint.cc> <1273210793.2178.4.camel@localhost> Message-ID: <1274616193.22999.19.camel@localhost> On Fri, 2010-05-07 at 08:39 +0300, Artem Bityutskiy wrote: > On Thu, 2010-05-06 at 11:52 +0200, Sebastian Andrzej Siewior wrote: > > * Artem Bityutskiy | 2010-05-03 13:12:58 [+0300]: > > > > >Hi Sebastian, > > Hi Artem, > > > > >Please, review and test the following series. > > > > The code looks fine. I wiped the flash and the test resulted in: > > Thanks, I'll push this to the ubi-2.6.git tree shortly. Will add > > Reviewed-by: Sebastian Andrzej Siewior > Tested-by: Sebastian Andrzej Siewior > > If you object, please, let me know and I'll amend the tags. FYI, because these patches did not have enough exposure in linux-next, I did not merge them so far. But I thing it is fair to consider them as fixes, so I can merge them in the middle of the 2.6.35 cycle. I'll try not to forget about this, but you can always remind :-) -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 08:04:36 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 15:04:36 +0300 Subject: suspend to disk hangs when running from ubifs In-Reply-To: References: <1270042736.15073.28.camel@localhost> <1270043508.15073.31.camel@localhost> Message-ID: <1274616276.22999.21.camel@localhost> On Mon, 2010-04-12 at 11:31 +0300, saeed bishara wrote: > Thanks Artem, your suggestion fixed my issue. > saeed FYI, the reboot notifiers were removed, so your issue has to be fixed in the latest linux kernel trees, or starting from the release version 2.6.35. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 08:23:39 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 15:23:39 +0300 Subject: ubifs became broken on contigous power-fails In-Reply-To: <1274614112.22999.17.camel@localhost> References: <1274614112.22999.17.camel@localhost> Message-ID: <1274617419.22999.24.camel@localhost> On Sun, 2010-05-23 at 14:28 +0300, Artem Bityutskiy wrote: > On Tue, 2010-05-11 at 18:43 +0400, Alexander Pazdnikov wrote: > > Hello. > > > > We are stress-testing 8 devices by power loss in 5 minutes interval. > > Device uses sqlite database to store collected data, every 1 minute accumulated data (500-1000 records) is stored into database in transaction. > > > > ubifs (ubi2:dbfs on /usr/local/ecom/db bellow) with database on 6 of 8 devices after different time (1-3 days) became broken. > > > > Any advise for futher debugging or solving this problem is highly appriciated. > > > > > > kernel 2.6.32.12 > > > > suspicious -> reserved GC LEB: -1 > > > > # cat /proc/mtd > > dev: size erasesize name > > mtd0: 00020000 00020000 "bootstrap" > > mtd1: 00080000 00020000 "uboot" > > mtd2: 00020000 00020000 "uboot_env1" > > mtd3: 00020000 00020000 "uboot_env2" > > mtd4: 02000000 00020000 "ubi_main" > > mtd5: 02000000 00020000 "ubi_var" > > mtd6: 0bf00000 00020000 "ubi_database" > > > > > > mounting ubi2:dbfs on startup > > [ 14.328117] UBIFS: recovery needed > > [ 53.941378] UBIFS error (pid 462): ubifs_rcvry_gc_commit: could not find a dirty LEB > > This is must be a bug. UBIFS should always have space for GC. I will > think how we can track this down, although I have a very limited amount > of time. 'ubifs_rcvry_gc_commit()' is poorly documented and I do not remember how it works already (argh! and it was written by Adrian :-) ), but I cooked up a patch for you. I'll try to look at this issue some more later and make sure I really understand how 'ubifs_rcvry_gc_commit()' works. But for now, try the following patch: >From 019acd23e01e33406eb325fadb9bd89fd4e8c374 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Sun, 23 May 2010 15:20:21 +0300 Subject: [PATCH] UBIFS: try harder to find gc_leb Signed-off-by: Artem Bityutskiy --- fs/ubifs/recovery.c | 6 ++++-- 1 files changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c index 109c6ea..5e2a438 100644 --- a/fs/ubifs/recovery.c +++ b/fs/ubifs/recovery.c @@ -1063,8 +1063,10 @@ int ubifs_rcvry_gc_commit(struct ubifs_info *c) } err = ubifs_find_dirty_leb(c, &lp, wbuf->offs, 2); if (err) { - if (err == -ENOSPC) - dbg_err("could not find a dirty LEB"); + if (err == -ENOSPC) { + dbg_rcvry("could not find a dirty LEB"); + goto find_free; + } return err; } ubifs_assert(!(lp.flags & LPROPS_INDEX)); -- 1.6.6.1 -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 12:01:27 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 19:01:27 +0300 Subject: how to pre-screen patch submissions from a newbie janitor? In-Reply-To: References: <20100519000137.GA18592@pengutronix.de> Message-ID: <1274630487.8881.59.camel@localhost.localdomain> On Wed, 2010-05-19 at 07:40 -0400, Robert P. J. Day wrote: > On Wed, 19 May 2010, Wolfram Sang wrote: > > > > however, since he's new to patch creation and submission, i > > > offered to "vet" his patches first. i realize that my vetting > > > carries no weight on the MTD list, but given that i've submitted > > > lots and lots of patches elsewhere, i can still at least sanity > > > check what he comes up with before it hits the list. > > > > > > is there a canonical signage for that nowadays? is it > > > "Reviewed-By" or something like that? so that by the time it gets > > > to the MTD list, he would have done the "Signed-Off-By" and i'd > > > sign off as a reviewer. is that the way it works? or is there an > > > alternative? thanks. > > > > Yes, that sounds like a good case for Reviewed-by. It will surely > > help these patches knowing there is somebody with experience who > > already had a look at (and in that case probably build-tested) them. > > > > Looking forward to the series, > > what i'm going to have this trainee(?) do is just simplify the > config/Kconfig/Makefile combos, which i openly admit is not > earth-shaking in its complexity. > > for example. in a number of places elsewhere in the kernel tree, > i've submitted patches to change things like this in the config menus: > > OneNAND Device Support ---> > LPDDR flash memory drivers ---> > UBI - Unsorted block images ---> > > note how, to select either LPDDR or UBI, you need to *go* to those > submenus, where you find a top-level selector. it's simpler to just > put that selector right on that menu item, as it's done for "OneNAND" > just above it. no wasting time. Yeah, and I assume it is better to be consistent and use the same style as most of things in the MTD menu have. > and another simplification is to cut down the conditional inclusion > in the makefiles. for instance, here's tests/Makefile: > > obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o > obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o > obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o > ... etc etc ... > > there's little point having every single line in the Makefile test > CONFIG_MTD_TESTS when that can all be done with a single test one > level up that checks whether or not to process the tests/ directory at > all. Yeah, sounds good. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 12:07:45 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 19:07:45 +0300 Subject: what should be coming soon WRT Kconfig/Makefile cleanup In-Reply-To: References: Message-ID: <1274630865.8881.61.camel@localhost.localdomain> On Thu, 2010-05-20 at 12:21 -0400, Robert P. J. Day wrote: > sorry, not trying to flog this, but as a short followup to what i > posted a couple days ago, i'm getting a new kernel janitor to work on > some specific projects and, rather than constantly email back and > forth with him, i posted his first potential project at my wiki. it's > meant to be a general project, but i used the MTD part of the tree as > an example: > > http://www.crashcourse.ca/wiki/index.php/Kconfig/Makefile_redundancy > > nothing earth-shattering there, just something to get him started > and looking at the Kbuild structure. if you think anything else > should be added to that page, or changed, let me know. or any other > MTD-related janitorial projects i can dump on him. :-) Nice write-up, I never payed much attention to Kconfig / Makefile stuff and it was interesting to read your article. I think your suggestions are good. -- Best Regards, Artem Bityutskiy (????? ????????) From eballetbo at gmail.com Sun May 23 13:39:30 2010 From: eballetbo at gmail.com (=?UTF-8?Q?Enric_Balletb=C3=B2_i_Serra?=) Date: Sun, 23 May 2010 19:39:30 +0200 Subject: [PATCH] mtd-utils: Support 4096+64 page sizes. In-Reply-To: <1274506202.8881.30.camel@localhost.localdomain> References: <1274176439-22351-1-git-send-email-eballetbo@gmail.com> <1274506202.8881.30.camel@localhost.localdomain> Message-ID: Hello, 2010/5/22 Artem Bityutskiy : > On Tue, 2010-05-18 at 11:53 +0200, Enric Balletbo i Serra wrote: >> + ? ? ? ? ? ? ? ? ? ? ? !(meminfo.oobsize == 64 && meminfo.writesize >> == 4096) && > > Are there flashes with the 4096 page / 64 spare combination? Could you > refer to one? May be any URL? I thought 4096 comes with 128. Much to my regret I can't provide a URL because is not public. IGEP v2 board has a Onenand with two dice of 2048/64 spare combination but mtd views 4096/64. The minimal write page is 4K (2K from first dice and 2K from second dice). Best regards, Enric > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > > From dedekind1 at gmail.com Mon May 24 01:51:42 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 24 May 2010 08:51:42 +0300 Subject: [Yaffs] [PATCH 1/2] Fix the bug of writing a yaffs2 image to NAND In-Reply-To: <4BF49BB4.30306@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> <4BF49BB4.30306@windriver.com> Message-ID: <1274680302.8881.64.camel@localhost.localdomain> On Thu, 2010-05-20 at 10:17 +0800, stanley.miao wrote: > Hi, Artem, > > Any comments ? > > Stanley. Sorry, but what else kind of comments would you like to see in addition to these: http://lists.infradead.org/pipermail/linux-mtd/2010-May/030280.html ? -- Best Regards, Artem Bityutskiy (????? ????????) From stanley.miao at windriver.com Mon May 24 02:21:40 2010 From: stanley.miao at windriver.com (stanley.miao) Date: Mon, 24 May 2010 14:21:40 +0800 Subject: [Yaffs] [PATCH 1/2] Fix the bug of writing a yaffs2 image to NAND In-Reply-To: <1274680302.8881.64.camel@localhost.localdomain> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> <4BF49BB4.30306@windriver.com> <1274680302.8881.64.camel@localhost.localdomain> Message-ID: <4BFA1AF4.1000603@windriver.com> Sorry, I didn't receive your email. There must be some problems with our mail server. Stanley. Artem Bityutskiy wrote: > On Thu, 2010-05-20 at 10:17 +0800, stanley.miao wrote: > >> Hi, Artem, >> >> Any comments ? >> >> Stanley. >> > > Sorry, but what else kind of comments would you like to see in addition > to these: > > http://lists.infradead.org/pipermail/linux-mtd/2010-May/030280.html > > ? > > From pazdnikov at prosoft.ural.ru Mon May 24 02:49:28 2010 From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov) Date: Mon, 24 May 2010 12:49:28 +0600 Subject: ubifs became broken on contigous power-fails In-Reply-To: <1274617419.22999.24.camel@localhost> References: <1274614112.22999.17.camel@localhost> <1274617419.22999.24.camel@localhost> Message-ID: <201005241249.28629.pazdnikov@prosoft.ural.ru> Artem, thank you very much, now applying your patches and making new stress-tests :-) Also last holidays have caught another issue. We've modified our program to primary mount ubi2:dbfs in RO, then sleep 3 secs, then remount in RW. Today have found half (5/10) of devices with the error : No space left on device If mount by hands this stalled fs primary in RW mode, then everything goes OK. If drop down mount "mount ubi2:dbfs in RO, then sleep 3 secs", leave only mount in RW, everything also goes OK. [ 6.576168] UBIFS: recovery needed [ 6.665035] UBIFS: recovery deferred [ 6.668941] UBIFS: mounted UBI device 2, volume 0, name "dbfs" [ 6.674801] UBIFS: mounted read-only [ 6.678707] UBIFS: file system size: 189407232 bytes (184968 KiB, 180 MiB, 1468 LEBs) [ 6.687496] UBIFS: journal size: 9418752 bytes (9198 KiB, 8 MiB, 73 LEBs) [ 6.694332] UBIFS: media format: w4/r0 (latest is w4/r0) [ 6.700191] UBIFS: default compressor: lzo [ 6.705074] UBIFS: reserved for root: 4952683 bytes (4836 KiB) [ 9.787104] UBIFS: completing deferred recovery Remounting ubi2:dbfs on /usr/local/ecom/db failed: No space left on device # df Filesystem Size Used Available Use% Mounted on ubi0:rootfs 13.2M 7.2M 6.0M 55% / tmpfs 4.0K 0 4.0K 0% /dev shm 1.0M 0 1.0M 0% /dev/shm tmpfs 1.0M 12.0K 1012.0K 1% /tmp tmpfs 1.0M 4.0K 1020.0K 0% /root ubi1:logs 11.5M 2.4M 8.4M 22% /var/log ubi1:tmp 13.4M 16.0K 12.7M 0% /usr/local/ecom/tmp ubi0:local 2.1M 44.0K 1.9M 2% /var/local ubi:config 2.0M 68.0K 1.9M 3% /usr/local/ecom/conf ubi2:dbfs 169.2M 18.7M 145.8M 11% /usr/local/ecom/db -- Best regards, Sasha From mike at compulab.co.il Mon May 24 03:25:45 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 10:25:45 +0300 Subject: [PATCH 02/20] mtd: pxa3xx_nand: introduce common timing to reduce read id times In-Reply-To: References: Message-ID: <4BFA29F9.8000400@compulab.co.il> Haojian Zhuang wrote: > From 35a06a21643049e146aba95057e7fe89c55d4b32 Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Mon, 22 Mar 2010 10:24:48 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: introduce common timing to reduce > read id times > > We certainly don't need to send read id command times by times, since > we already know what the id is after the first read id... > > So create a common timing which could ensure it would successfully read id > out all supported chip. Then follow the build-in table to reconfigure > the timing. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > drivers/mtd/nand/pxa3xx_nand.c | 33 +++++++++++++++++---------------- > 1 files changed, 17 insertions(+), 16 deletions(-) > > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index da40b9a..5658398 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -225,7 +225,13 @@ const static struct pxa3xx_nand_cmdset cmdset = { > .lock_status = 0x007A, > }; > > +/** > + * The timing defined in the builtin_flash_types[0] > + * could be considered as the common timing which is used to > + * detect the chip id before we know how to optimize further > + */ > static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { > +{ 0, 0, 0, 0, 0, 0, { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, }, > { 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > { 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > { 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > @@ -850,12 +856,6 @@ static int pxa3xx_nand_config_flash(struct > pxa3xx_nand_info *info, > struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; > uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ > > - if (f->page_size != 2048 && f->page_size != 512) > - return -EINVAL; > - > - if (f->flash_width != 16 && f->flash_width != 8) > - return -EINVAL; > - > /* calculate flash information */ > info->oob_size = (f->page_size == 2048) ? 64 : 16; > info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; > @@ -967,23 +967,24 @@ static int pxa3xx_nand_detect_flash(struct > pxa3xx_nand_info *info, > if (pxa3xx_nand_detect_config(info) == 0) > return 0; > > - for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { > + f = &builtin_flash_types[0]; > + pxa3xx_nand_config_flash(info, f); > + if (__readid(info, &id)) > + goto fail_detect; > > + for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { > f = &builtin_flash_types[i]; > - > - if (pxa3xx_nand_config_flash(info, f)) > - continue; > - > - if (__readid(info, &id)) > - continue; > - > - if (id == f->chip_id) > + if (f->chip_id == id) { > + dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); > + pxa3xx_nand_config_flash(info, f); > return 0; > + } > } > > dev_warn(&info->pdev->dev, > - "failed to detect configured nand flash; found %04x instead of\n", > + "failed to detect configured nand flash; found %04x instead of\n", Instead of what? And, what if the flash is not listed in the builtin_flash_types? Does it really mean it's -ENODEV? > id); > +fail_detect: > return -ENODEV; > } > -- Sincerely yours, Mike. From mike at compulab.co.il Mon May 24 03:25:50 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 10:25:50 +0300 Subject: [PATCH 04/20] mtd: pxa3xx_nand: make scan procedure more clear In-Reply-To: References: Message-ID: <4BFA29FE.9020001@compulab.co.il> Haojian Zhuang wrote: > From 3c64457df23b222c7f53b7d8f0601606b95b1ad6 Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Mon, 22 Mar 2010 10:35:49 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: make scan procedure more clear The changes below are related mostly to _probe reorganization than to nand scan... > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > drivers/mtd/nand/pxa3xx_nand.c | 66 +++++++++++++++++++++++---------------- > 1 files changed, 39 insertions(+), 27 deletions(-) > > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index 2dfe6d9..0ef9bf9 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -160,6 +160,7 @@ struct pxa3xx_nand_info { > unsigned int buf_start; > unsigned int buf_count; > > + struct mtd_info *mtd; > /* DMA information */ > int drcmr_dat; > int drcmr_cmd; > @@ -1096,21 +1097,13 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, > this->chip_delay = 25; > } > > -static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) > +static int alloc_nand_resource(struct platform_device *pdev) > { > - struct pxa3xx_nand_platform_data *pdata; > + struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; > struct pxa3xx_nand_info *info; > - struct nand_chip *this; > struct mtd_info *mtd; > struct resource *r; > - int ret = 0, irq; > - > - pdata = pdev->dev.platform_data; > - > - if (!pdata) { > - dev_err(&pdev->dev, "no platform data defined\n"); > - return -ENODEV; > - } > + int ret, irq; > > mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), > GFP_KERNEL); > @@ -1122,8 +1115,8 @@ static int __devinit pxa3xx_nand_probe(struct > platform_device *pdev) > info = (struct pxa3xx_nand_info *)(&mtd[1]); > info->pdev = pdev; > > - this = &info->nand_chip; > mtd->priv = info; > + info->mtd = mtd; > mtd->owner = THIS_MODULE; > > info->clk = clk_get(&pdev->dev, NULL); > @@ -1201,16 +1194,9 @@ static int __devinit pxa3xx_nand_probe(struct > platform_device *pdev) > } > > pxa3xx_nand_init_mtd(mtd, info); This, and the pxa3xx_nand_detect_flash call not shown in the patch does not really belong to resource allocation. I'd move it back to the _probe method. > + platform_set_drvdata(pdev, info); > > - platform_set_drvdata(pdev, mtd); > - > - if (nand_scan(mtd, 1)) { > - dev_err(&pdev->dev, "failed to scan nand\n"); > - ret = -ENXIO; > - goto fail_free_irq; > - } > - > - return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); > + return 0; > > fail_free_irq: > free_irq(irq, info); > @@ -1235,8 +1221,8 @@ fail_free_mtd: > > static int pxa3xx_nand_remove(struct platform_device *pdev) > { > - struct mtd_info *mtd = platform_get_drvdata(pdev); > - struct pxa3xx_nand_info *info = mtd->priv; > + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); > + struct mtd_info *mtd = info->mtd; > struct resource *r; > int irq; > > @@ -1265,11 +1251,37 @@ static int pxa3xx_nand_remove(struct > platform_device *pdev) > return 0; > } > > +static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) > +{ > + struct pxa3xx_nand_platform_data *pdata; > + struct pxa3xx_nand_info *info; > + int ret; > + > + pdata = pdev->dev.platform_data; > + if (!pdata) { > + dev_err(&pdev->dev, "no platform data defined\n"); > + return -ENODEV; > + } > + > + ret = alloc_nand_resource(pdev); > + if (ret) > + return ret; > + > + info = platform_get_drvdata(pdev); > + if (nand_scan(info->mtd, 1)) { > + dev_err(&pdev->dev, "failed to scan nand\n"); > + pxa3xx_nand_remove(pdev); > + return -ENODEV; > + } > + > + return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); > +} > + > #ifdef CONFIG_PM > static int pxa3xx_nand_suspend(struct platform_device *pdev, > pm_message_t state) > { > - struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); > - struct pxa3xx_nand_info *info = mtd->priv; > + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); > + struct mtd_info *mtd = info->mtd; > > if (info->state != STATE_READY) { > dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); > @@ -1281,8 +1293,8 @@ static int pxa3xx_nand_suspend(struct > platform_device *pdev, pm_message_t state) > > static int pxa3xx_nand_resume(struct platform_device *pdev) > { > - struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); > - struct pxa3xx_nand_info *info = mtd->priv; > + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); > + struct mtd_info *mtd = info->mtd; > > nand_writel(info, NDTR0CS0, info->ndtr0cs0); > nand_writel(info, NDTR1CS0, info->ndtr1cs0); -- Sincerely yours, Mike. From mike at compulab.co.il Mon May 24 03:25:54 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 10:25:54 +0300 Subject: [PATCH 03/20] mtd: pxa3xx_nand: remove the flash info in driver structure In-Reply-To: References: Message-ID: <4BFA2A02.2040605@compulab.co.il> Haojian Zhuang wrote: > From dd45d508745edb24e9e4129077e9f5bd20415a23 Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Mon, 22 Mar 2010 10:33:49 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: remove the flash info in driver structure > > After probe, all info already transfer to driver structure. > There is no need to keep the original flash info. > So that we could safely free the flash info in memory, which may grows > larger when more flash is suported. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > drivers/mtd/nand/pxa3xx_nand.c | 70 ++++++++++++++++++++++++++-------------- > 1 files changed, 46 insertions(+), 24 deletions(-) > > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index 5658398..2dfe6d9 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -152,7 +152,6 @@ struct pxa3xx_nand_info { > struct nand_chip nand_chip; > > struct platform_device *pdev; > - const struct pxa3xx_nand_flash *flash_info; > > struct clk *clk; > void __iomem *mmio_base; > @@ -166,6 +165,7 @@ struct pxa3xx_nand_info { > int drcmr_cmd; > > unsigned char *data_buff; > + unsigned char *oob_buff; > dma_addr_t data_buff_phys; > size_t data_buff_size; > int data_dma_ch; > @@ -184,7 +184,8 @@ struct pxa3xx_nand_info { > int use_ecc; /* use HW ECC ? */ > int use_dma; /* use DMA ? */ > > - size_t data_size; /* data size in FIFO */ > + unsigned int page_size; /* page size of attached chip */ > + unsigned int data_size; /* data size in FIFO */ > int retcode; > struct completion cmd_complete; > > @@ -193,6 +194,10 @@ struct pxa3xx_nand_info { > uint32_t ndcb1; > uint32_t ndcb2; > > + /* timing calcuted from setting */ > + uint32_t ndtr0cs0; > + uint32_t ndtr1cs0; > + > /* calculated from pxa3xx_nand_flash data */ > size_t oob_size; > size_t read_id_bytes; > @@ -287,6 +292,8 @@ static void pxa3xx_nand_set_timing(struct > pxa3xx_nand_info *info, > NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | > NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); > > + info->ndtr0cs0 = ndtr0; > + info->ndtr1cs0 = ndtr1; > nand_writel(info, NDTR0CS0, ndtr0); > nand_writel(info, NDTR1CS0, ndtr1); > } > @@ -310,22 +317,29 @@ static int wait_for_event(struct > pxa3xx_nand_info *info, uint32_t event) > return -ETIMEDOUT; > } > > -static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, > - uint16_t cmd, int column, int page_addr) > +static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) > { > - const struct pxa3xx_nand_flash *f = info->flash_info; > + int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; > > - /* calculate data size */ > - switch (f->page_size) { > - case 2048: > - info->data_size = (info->use_ecc) ? 2088 : 2112; > - break; > - case 512: > - info->data_size = (info->use_ecc) ? 520 : 528; > - break; > - default: > - return -EINVAL; > + info->data_size = info->page_size; > + if (!oob_enable) { > + info->oob_size = 0; > + return; > } > + switch (info->page_size) { > + case 2048: > + info->oob_size = (info->use_ecc) ? 40 : 64; > + break; > + case 512: > + info->oob_size = (info->use_ecc) ? 8 : 16; > + break; > + } The OOB-related changes do not seem related to the $SUBJ. > +} > + > +static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, > + uint16_t cmd, int column, int page_addr) > +{ > + pxa3xx_set_datasize(info); > > /* generate values for NDCBx registers */ > info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); > @@ -436,6 +450,9 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) > case STATE_PIO_WRITING: > __raw_writesl(info->mmio_base + NDDB, info->data_buff, > DIV_ROUND_UP(info->data_size, 4)); > + if (info->oob_size > 0) > + __raw_writesl(info->mmio_base + NDDB, info->oob_buff, > + DIV_ROUND_UP(info->oob_size, 4)); The same here. > enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); > > @@ -448,6 +465,10 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) > case STATE_PIO_READING: > __raw_readsl(info->mmio_base + NDDB, info->data_buff, > DIV_ROUND_UP(info->data_size, 4)); > + if (info->oob_size > 0) > + __raw_readsl(info->mmio_base + NDDB, info->oob_buff, > + DIV_ROUND_UP(info->oob_size, 4)); > + Ditto. > break; > default: > printk(KERN_ERR "%s: invalid state %d\n", __func__, > @@ -462,7 +483,7 @@ static int handle_data_pio(struct pxa3xx_nand_info *info) > static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) > { > struct pxa_dma_desc *desc = info->data_desc; > - int dma_len = ALIGN(info->data_size, 32); > + int dma_len = ALIGN(info->data_size + info->oob_size, 32); ditto > desc->ddadr = DDADR_STOP; > desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; > @@ -857,6 +878,8 @@ static int pxa3xx_nand_config_flash(struct > pxa3xx_nand_info *info, > uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ > > /* calculate flash information */ > + info->page_size = f->page_size; > + info->oob_buff = info->data_buff + f->page_size; And here as well > info->oob_size = (f->page_size == 2048) ? 64 : 16; > info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; > > @@ -881,7 +904,6 @@ static int pxa3xx_nand_config_flash(struct > pxa3xx_nand_info *info, > info->reg_ndcr = ndcr; > > pxa3xx_nand_set_timing(info, &f->timing); > - info->flash_info = f; > return 0; > } > > @@ -917,7 +939,6 @@ static int pxa3xx_nand_detect_config(struct > pxa3xx_nand_info *info) > default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; > > /* set info fields needed to __readid */ > - info->flash_info = &default_flash; > info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; > info->reg_ndcr = ndcr; > > @@ -1047,10 +1068,9 @@ static struct nand_ecclayout hw_largepage_ecclayout = { > static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, > struct pxa3xx_nand_info *info) > { > - const struct pxa3xx_nand_flash *f = info->flash_info; > struct nand_chip *this = &info->nand_chip; > > - this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; > + this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; > > this->waitfunc = pxa3xx_nand_waitfunc; > this->select_chip = pxa3xx_nand_select_chip; > @@ -1066,9 +1086,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, > this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; > this->ecc.calculate = pxa3xx_nand_ecc_calculate; > this->ecc.correct = pxa3xx_nand_ecc_correct; > - this->ecc.size = f->page_size; > + this->ecc.size = info->page_size; > > - if (f->page_size == 2048) > + if (info->page_size == 2048) > this->ecc.layout = &hw_largepage_ecclayout; > else > this->ecc.layout = &hw_smallpage_ecclayout; > @@ -1076,7 +1096,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, > this->chip_delay = 25; > } > > -static int pxa3xx_nand_probe(struct platform_device *pdev) > +static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) > { > struct pxa3xx_nand_platform_data *pdata; > struct pxa3xx_nand_info *info; > @@ -1264,9 +1284,11 @@ static int pxa3xx_nand_resume(struct > platform_device *pdev) > struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); > struct pxa3xx_nand_info *info = mtd->priv; > > + nand_writel(info, NDTR0CS0, info->ndtr0cs0); > + nand_writel(info, NDTR1CS0, info->ndtr1cs0); > clk_enable(info->clk); > > - return pxa3xx_nand_config_flash(info, info->flash_info); > + return 0; > } > #else > #define pxa3xx_nand_suspend NULL -- Sincerely yours, Mike. From mike at compulab.co.il Mon May 24 03:28:17 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 10:28:17 +0300 Subject: [PATCH 07/20] mtd: pxa3xx_nand: mtd scan id process could be defined by driver itself In-Reply-To: References: Message-ID: <4BFA2A91.1080406@compulab.co.il> Haojian Zhuang wrote: > From f2010885a9d5cebfd3cca63b59fff941502f78b3 Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Thu, 6 May 2010 09:48:30 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: mtd scan id process could be > defined by driver itself > > Different NAND driver may require its unique detection. For pxa3xx_nand, > it use its self id database to get the necessary info. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > drivers/mtd/nand/pxa3xx_nand.c | 257 +++++++++++++++++++++++++++++----------- > 1 files changed, 185 insertions(+), 72 deletions(-) > > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index 854adad..7a8ff38 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -255,6 +255,8 @@ static struct pxa3xx_nand_flash __devinitdata > builtin_flash_types[] = { > { 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, > 60, 10, }, }, > }; > > +static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; > + > #define NDTR0_tCH(c) (min((c), 7) << 19) > #define NDTR0_tCS(c) (min((c), 7) << 16) > #define NDTR0_tWH(c) (min((c), 7) << 11) > @@ -893,37 +895,6 @@ static int pxa3xx_nand_detect_config(struct > pxa3xx_nand_info *info) > return 0; > } > > -static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, > - const struct pxa3xx_nand_platform_data *pdata) > -{ > - const struct pxa3xx_nand_flash *f; > - uint32_t id = -1; > - int i; > - > - if (pdata->keep_config) > - if (pxa3xx_nand_detect_config(info) == 0) > - return 0; NAK. You're breaking platforms that rely on this feature. > - f = &builtin_flash_types[0]; > - pxa3xx_nand_config_flash(info, f); > - pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); > - id = *((uint16_t *)(info->data_buff)); > - > - for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { > - f = &builtin_flash_types[i]; > - if (f->chip_id == id) { > - dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id); > - pxa3xx_nand_config_flash(info, f); > - return 0; > - } > - } > - > - dev_warn(&info->pdev->dev, > - "failed to detect configured nand flash; found %04x instead of\n", > - id); > - return -ENODEV; > -} > - > /* the maximum possible buffer size for large page with OOB data > * is: 2048 + 64 = 2112 bytes, allocate a page here for both the > * data buffer and the DMA descriptor > @@ -980,41 +951,174 @@ static struct nand_ecclayout hw_largepage_ecclayout = { > .oobfree = { {2, 38} } > }; > > -static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, > - struct pxa3xx_nand_info *info) why are you removing the pxa3xx_nand_init_mtd? moving it's entire contents into alloc_nand_resource would make the latter overgrown.... > +static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, > + struct nand_chip *chip, uint8_t *buf, int page) > +{ > + struct pxa3xx_nand_info *info = mtd->priv; > + > + chip->read_buf(mtd, buf, mtd->writesize); > + chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); > + > + if (info->retcode == ERR_SBERR) { > + switch (info->use_ecc) { > + case 1: > + mtd->ecc_stats.corrected ++; > + break; > + > + case 0: > + default: > + break; > + } > + } > + else if (info->retcode == ERR_DBERR) { > + int buf_blank; > + > + buf_blank = is_buf_blank(buf, mtd->writesize); > + if (!buf_blank) > + mtd->ecc_stats.failed++; > + } > + > + return 0; > +} > + > +static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, > + struct nand_chip *chip, const uint8_t *buf) > +{ > + chip->write_buf(mtd, buf, mtd->writesize); > + chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); > +} > + > +static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page) > { > - struct nand_chip *this = &info->nand_chip; > - > - this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0; > - > - this->waitfunc = pxa3xx_nand_waitfunc; > - this->select_chip = pxa3xx_nand_select_chip; > - this->dev_ready = pxa3xx_nand_dev_ready; > - this->cmdfunc = pxa3xx_nand_cmdfunc; > - this->read_word = pxa3xx_nand_read_word; > - this->read_byte = pxa3xx_nand_read_byte; > - this->read_buf = pxa3xx_nand_read_buf; > - this->write_buf = pxa3xx_nand_write_buf; > - this->verify_buf = pxa3xx_nand_verify_buf; > - > - this->ecc.mode = NAND_ECC_HW; > - this->ecc.hwctl = pxa3xx_nand_ecc_hwctl; > - this->ecc.calculate = pxa3xx_nand_ecc_calculate; > - this->ecc.correct = pxa3xx_nand_ecc_correct; > - this->ecc.size = info->page_size; > - > - if (info->page_size == 2048) > - this->ecc.layout = &hw_largepage_ecclayout; > + struct nand_chip *chip = mtd->priv; > + /* Send commands to erase a block */ > + chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); > +} > + > +static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) > +{ > + struct mtd_info *mtd = info->mtd; > + struct nand_chip *chip = mtd->priv; > + > + /* use the common timing to make a try */ > + pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); > + chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); > + if (info->state & STATE_READY) > + return 1; > else > - this->ecc.layout = &hw_smallpage_ecclayout; > + return 0; > +} > + > +static int pxa3xx_nand_scan(struct mtd_info *mtd) > +{ > + struct pxa3xx_nand_info *info = mtd->priv; > + struct pxa3xx_nand_flash *f; > + struct nand_chip *chip = mtd->priv; > + uint32_t id = -1; > + int i, ret; > > - this->chip_delay = 25; > + ret = pxa3xx_nand_sensing(info); > + if (!ret) { > + kfree(mtd); > + info->mtd = NULL; > + printk(KERN_INFO "There is no nand chip on cs 0!\n"); > + > + return -EINVAL; > + } > + > + chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); > + id = *((uint16_t *)(info->data_buff)); > + if (id != 0) > + printk(KERN_INFO "Detect a flash id %x\n", id); > + else { > + kfree(mtd); > + info->mtd = NULL; > + printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n"); > + > + return -EINVAL; > + } > + > + for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { > + > + f = &builtin_flash_types[i]; > + > + /* find the chip in default list */ > + if (f->chip_id == id) { > + pxa3xx_nand_config_flash(info, f); > + chip->cellinfo = info->data_buff[2]; > + mtd->writesize = f->page_size; > + mtd->writesize_shift = ffs(mtd->writesize) - 1; > + mtd->writesize_mask = (1 << mtd->writesize_shift) - 1; > + mtd->oobsize = mtd->writesize / 32; > + mtd->erasesize = f->page_size * f->page_per_block; > + mtd->erasesize_shift = ffs(mtd->erasesize) - 1; > + mtd->erasesize_mask = (1 << mtd->erasesize_shift) - 1; > + > + mtd->name = mtd_names[0]; > + break; > + } > + } > + > + if (i == ARRAY_SIZE(builtin_flash_types)) { > + kfree(mtd); > + info->mtd = NULL; > + printk(KERN_ERR "ERROR!! flash not defined!!!\n"); > + > + return -EINVAL; > + } > + > + chip->ecc.mode = NAND_ECC_HW; > + chip->ecc.size = f->page_size; > + if (f->page_size == 2048) > + chip->ecc.layout = &hw_largepage_ecclayout; > + else > + chip->ecc.layout = &hw_smallpage_ecclayout; > + > + chip->chipsize = (uint64_t)f->num_blocks * \ > + f->page_per_block * \ > + f->page_size; > + > + chip->chip_shift = ffs(chip->chipsize) - 1; > + mtd->size = chip->chipsize; > + > + /* Calculate the address shift from the page size */ > + chip->page_shift = ffs(mtd->writesize) - 1; > + chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; > + chip->numchips = 1; > + chip->chip_delay = 25; > + chip->bbt_erase_shift = chip->phys_erase_shift = ffs(mtd->erasesize) - 1; > + > + /* Set the bad block position */ > + chip->badblockpos = mtd->writesize > 512 ? > + NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; > + > + chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; > + chip->options |= NAND_NO_AUTOINCR; > + chip->options |= NAND_NO_READRDY; > + chip->options |= NAND_USE_FLASH_BBT; > + > + return nand_scan_tail(mtd); > +} > + > +static int pxa3xx_nand_default_block_markbad(struct mtd_info *mtd, loff_t ofs) > +{ > + struct nand_chip *chip = mtd->priv; > + int block; > + > + block = (int)(ofs >> chip->bbt_erase_shift); > + chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); > + return nand_update_bbt(mtd, ofs); > +} > + > +static int pxa3xx_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip) > +{ > + return 0; > } > > static int alloc_nand_resource(struct platform_device *pdev) > { > - struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; > struct pxa3xx_nand_info *info; > + struct nand_chip *chip; > struct mtd_info *mtd; > struct resource *r; > int ret, irq; > @@ -1027,12 +1131,31 @@ static int alloc_nand_resource(struct > platform_device *pdev) > } > > info = (struct pxa3xx_nand_info *)(&mtd[1]); > + chip = (struct nand_chip *)(&mtd[1]); > info->pdev = pdev; > - > - mtd->priv = info; > info->mtd = mtd; > + mtd->priv = info; > mtd->owner = THIS_MODULE; > > + chip->ecc.read_page = pxa3xx_nand_read_page_hwecc; > + chip->ecc.write_page = pxa3xx_nand_write_page_hwecc; > + chip->ecc.hwctl = pxa3xx_nand_ecc_hwctl; > + chip->ecc.calculate = pxa3xx_nand_ecc_calculate; > + chip->ecc.correct = pxa3xx_nand_ecc_correct; > + chip->waitfunc = pxa3xx_nand_waitfunc; > + chip->select_chip = pxa3xx_nand_select_chip; > + chip->dev_ready = pxa3xx_nand_dev_ready; > + chip->cmdfunc = pxa3xx_nand_cmdfunc; > + chip->read_word = pxa3xx_nand_read_word; > + chip->read_byte = pxa3xx_nand_read_byte; > + chip->read_buf = pxa3xx_nand_read_buf; > + chip->write_buf = pxa3xx_nand_write_buf; > + chip->verify_buf = pxa3xx_nand_verify_buf; > + chip->block_markbad = pxa3xx_nand_default_block_markbad; > + chip->block_bad = pxa3xx_nand_block_bad; > + chip->scan_bbt = nand_default_bbt; > + chip->erase_cmd = pxa3xx_nand_erase_cmd; > + this definitely has nothing to do with resource allocation. > info->clk = clk_get(&pdev->dev, NULL); > if (IS_ERR(info->clk)) { > dev_err(&pdev->dev, "failed to get nand clock\n"); > @@ -1100,21 +1223,11 @@ static int alloc_nand_resource(struct > platform_device *pdev) > goto fail_free_buf; > } > > - ret = pxa3xx_nand_detect_flash(info, pdata); > - if (ret) { > - dev_err(&pdev->dev, "failed to detect flash\n"); > - ret = -ENODEV; > - goto fail_free_irq; > - } > - > - pxa3xx_nand_init_mtd(mtd, info); > platform_set_drvdata(pdev, info); > - > return 0; > > -fail_free_irq: > - free_irq(irq, info); > fail_free_buf: > + free_irq(irq, info); > if (use_dma) { > pxa_free_dma(info->data_dma_ch); > dma_free_coherent(&pdev->dev, info->data_buff_size, > @@ -1182,7 +1295,7 @@ static int __devinit pxa3xx_nand_probe(struct > platform_device *pdev) > return ret; > > info = platform_get_drvdata(pdev); > - if (nand_scan(info->mtd, 1)) { > + if (pxa3xx_nand_scan(info->mtd)) { > dev_err(&pdev->dev, "failed to scan nand\n"); > pxa3xx_nand_remove(pdev); > return -ENODEV; -- Sincerely yours, Mike. From mike at compulab.co.il Mon May 24 03:31:39 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 10:31:39 +0300 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: Message-ID: <4BFA2B5B.4080105@compulab.co.il> Hi Haojian, This is a comment to the entire series, and should have been Re: [PATCH 0/20], but there's no cover letter for these patches. The patches are all line-wrapped and do not apply. It's really hard to read them because of hunks added inside the existing functions. Please try to organize your changes in a more straight forward way. Haojian Zhuang wrote: > From 16057e690aa4a2fd8a9c07c70ab48ffc2f76204f Mon Sep 17 00:00:00 2001 > From: Lei Wen > Date: Sat, 20 Mar 2010 19:01:23 +0800 > Subject: [PATCH] mtd: pxa3xx_nand: refuse the flash definition get from platform > > For current usage, it is little reason to use a platform defined flash info > for the flash detection. Flash timing through platform should be the same. > And allow multiple platform to define the same flash chip would be a waste. > > Also condense the flash definition way in the c file to simplify adding a > new chip. > > Signed-off-by: Lei Wen > Signed-off-by: Haojian Zhuang > --- > arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 40 ---- > drivers/mtd/nand/Kconfig | 7 - > drivers/mtd/nand/pxa3xx_nand.c | 262 ++++++-------------------- > 3 files changed, 60 insertions(+), 249 deletions(-) > > diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > index 3478eae..c494f68 100644 > --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h > @@ -4,43 +4,6 @@ > #include > #include > > -struct pxa3xx_nand_timing { > - unsigned int tCH; /* Enable signal hold time */ > - unsigned int tCS; /* Enable signal setup time */ > - unsigned int tWH; /* ND_nWE high duration */ > - unsigned int tWP; /* ND_nWE pulse time */ > - unsigned int tRH; /* ND_nRE high duration */ > - unsigned int tRP; /* ND_nRE pulse width */ > - unsigned int tR; /* ND_nWE high to ND_nRE low for read */ > - unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read */ > - unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ > -}; > - > -struct pxa3xx_nand_cmdset { > - uint16_t read1; > - uint16_t read2; > - uint16_t program; > - uint16_t read_status; > - uint16_t read_id; > - uint16_t erase; > - uint16_t reset; > - uint16_t lock; > - uint16_t unlock; > - uint16_t lock_status; > -}; > - > -struct pxa3xx_nand_flash { > - const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ > - const struct pxa3xx_nand_cmdset *cmdset; > - > - uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ > - uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ > - uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ > - uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ > - uint32_t num_blocks; /* Number of physical blocks in Flash */ > - uint32_t chip_id; > -}; > - > struct pxa3xx_nand_platform_data { > > /* the data flash bus is shared between the Static Memory > @@ -54,9 +17,6 @@ struct pxa3xx_nand_platform_data { > > const struct mtd_partition *parts; > unsigned int nr_parts; > - > - const struct pxa3xx_nand_flash * flash; > - size_t num_flash; > }; > > extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); > diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig > index 98a04b3..9a35d92 100644 > --- a/drivers/mtd/nand/Kconfig > +++ b/drivers/mtd/nand/Kconfig > @@ -399,13 +399,6 @@ config MTD_NAND_PXA3xx > This enables the driver for the NAND flash device found on > PXA3xx processors > > -config MTD_NAND_PXA3xx_BUILTIN > - bool "Use builtin definitions for some NAND chips (deprecated)" > - depends on MTD_NAND_PXA3xx > - help > - This enables builtin definitions for some NAND chips. This > - is deprecated in favor of platform specific data. > - > config MTD_NAND_CM_X270 > tristate "Support for NAND Flash on CM-X270 modules" > depends on MTD_NAND && MACH_ARMCORE > diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c > index e02fa4f..da40b9a 100644 > --- a/drivers/mtd/nand/pxa3xx_nand.c > +++ b/drivers/mtd/nand/pxa3xx_nand.c > @@ -113,6 +113,41 @@ enum { > STATE_PIO_WRITING, > }; > > +struct pxa3xx_nand_timing { > + uint32_t tCH; /* Enable signal hold time */ > + uint32_t tCS; /* Enable signal setup time */ > + uint32_t tWH; /* ND_nWE high duration */ > + uint32_t tWP; /* ND_nWE pulse time */ > + uint32_t tRH; /* ND_nRE high duration */ > + uint32_t tRP; /* ND_nRE pulse width */ > + uint32_t tAR; /* ND_ALE low to ND_nRE low delay */ > + uint32_t tWHR; /* ND_nWE high to ND_nRE low for status read */ > + uint32_t tR; /* ND_nWE high to ND_nRE low for read */ > +}; > + > +struct pxa3xx_nand_cmdset { > + uint16_t read1; > + uint16_t read2; > + uint16_t program; > + uint16_t read_status; > + uint16_t read_id; > + uint16_t erase; > + uint16_t reset; > + uint16_t lock; > + uint16_t unlock; > + uint16_t lock_status; > +}; > + > +struct pxa3xx_nand_flash { > + uint32_t chip_id; > + uint16_t page_per_block; /* Pages per block (PG_PER_BLK) */ > + uint16_t page_size; /* Page size in bytes (PAGE_SZ) */ > + uint8_t flash_width; /* Width of Flash memory (DWIDTH_M) */ > + uint8_t dfc_width; /* Width of flash controller(DWIDTH_C) */ > + uint32_t num_blocks; /* Number of physical blocks in Flash */ > + struct pxa3xx_nand_timing timing; /* NAND Flash timing */ > +}; > + > struct pxa3xx_nand_info { > struct nand_chip nand_chip; > > @@ -177,20 +212,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data > transfering to/from NAND HW"); > static struct pxa3xx_nand_timing default_timing; > static struct pxa3xx_nand_flash default_flash; > > -static struct pxa3xx_nand_cmdset smallpage_cmdset = { > - .read1 = 0x0000, > - .read2 = 0x0050, > - .program = 0x1080, > - .read_status = 0x0070, > - .read_id = 0x0090, > - .erase = 0xD060, > - .reset = 0x00FF, > - .lock = 0x002A, > - .unlock = 0x2423, > - .lock_status = 0x007A, > -}; > - > -static struct pxa3xx_nand_cmdset largepage_cmdset = { > +const static struct pxa3xx_nand_cmdset cmdset = { > .read1 = 0x3000, > .read2 = 0x0050, > .program = 0x1080, > @@ -203,143 +225,17 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = { > .lock_status = 0x007A, > }; > > -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN > -static struct pxa3xx_nand_timing samsung512MbX16_timing = { > - .tCH = 10, > - .tCS = 0, > - .tWH = 20, > - .tWP = 40, > - .tRH = 30, > - .tRP = 40, > - .tR = 11123, > - .tWHR = 110, > - .tAR = 10, > -}; > - > -static struct pxa3xx_nand_flash samsung512MbX16 = { > - .timing = &samsung512MbX16_timing, > - .cmdset = &smallpage_cmdset, > - .page_per_block = 32, > - .page_size = 512, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 4096, > - .chip_id = 0x46ec, > -}; > - > -static struct pxa3xx_nand_flash samsung2GbX8 = { > - .timing = &samsung512MbX16_timing, > - .cmdset = &smallpage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 2048, > - .chip_id = 0xdaec, > -}; > - > -static struct pxa3xx_nand_flash samsung32GbX8 = { > - .timing = &samsung512MbX16_timing, > - .cmdset = &smallpage_cmdset, > - .page_per_block = 128, > - .page_size = 4096, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 8192, > - .chip_id = 0xd7ec, > +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { > +{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, }, }, > +{ 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, > +{ 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, > 60, 10, }, }, > +{ 0xdc2c, 64, 2048, 8, 8, 4096, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, }, }, > +{ 0xcc2c, 64, 2048, 16, 16, 4096, { 10, 25, 15, 25, 15, 30, 25000, > 60, 10, }, }, > +{ 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, > 60, 10, }, }, > }; > > -static struct pxa3xx_nand_timing micron_timing = { > - .tCH = 10, > - .tCS = 25, > - .tWH = 15, > - .tWP = 25, > - .tRH = 15, > - .tRP = 30, > - .tR = 25000, > - .tWHR = 60, > - .tAR = 10, > -}; > - > -static struct pxa3xx_nand_flash micron1GbX8 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 1024, > - .chip_id = 0xa12c, > -}; > - > -static struct pxa3xx_nand_flash micron1GbX16 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 1024, > - .chip_id = 0xb12c, > -}; > - > -static struct pxa3xx_nand_flash micron4GbX8 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 8, > - .dfc_width = 8, > - .num_blocks = 4096, > - .chip_id = 0xdc2c, > -}; > - > -static struct pxa3xx_nand_flash micron4GbX16 = { > - .timing = µn_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 4096, > - .chip_id = 0xcc2c, > -}; > - > -static struct pxa3xx_nand_timing stm2GbX16_timing = { > - .tCH = 10, > - .tCS = 35, > - .tWH = 15, > - .tWP = 25, > - .tRH = 15, > - .tRP = 25, > - .tR = 25000, > - .tWHR = 60, > - .tAR = 10, > -}; > - > -static struct pxa3xx_nand_flash stm2GbX16 = { > - .timing = &stm2GbX16_timing, > - .cmdset = &largepage_cmdset, > - .page_per_block = 64, > - .page_size = 2048, > - .flash_width = 16, > - .dfc_width = 16, > - .num_blocks = 2048, > - .chip_id = 0xba20, > -}; > - > -static struct pxa3xx_nand_flash *builtin_flash_types[] = { > - &samsung512MbX16, > - &samsung2GbX8, > - &samsung32GbX8, > - µn1GbX8, > - µn1GbX16, > - µn4GbX8, > - µn4GbX16, > - &stm2GbX16, > -}; > -#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ > - > #define NDTR0_tCH(c) (min((c), 7) << 19) > #define NDTR0_tCS(c) (min((c), 7) << 16) > #define NDTR0_tWH(c) (min((c), 7) << 11) > @@ -412,7 +308,6 @@ static int prepare_read_prog_cmd(struct > pxa3xx_nand_info *info, > uint16_t cmd, int column, int page_addr) > { > const struct pxa3xx_nand_flash *f = info->flash_info; > - const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; > > /* calculate data size */ > switch (f->page_size) { > @@ -445,7 +340,7 @@ static int prepare_read_prog_cmd(struct > pxa3xx_nand_info *info, > */ > info->ndcb1 = page_addr << 8; > > - if (cmd == cmdset->program) > + if (cmd == cmdset.program) > info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; > > return 0; > @@ -463,20 +358,18 @@ static int prepare_erase_cmd(struct > pxa3xx_nand_info *info, > > static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) > { > - const struct pxa3xx_nand_cmdset *cmdset = info->flash_info->cmdset; > - > info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); > info->ndcb1 = 0; > info->ndcb2 = 0; > > - if (cmd == cmdset->read_id) { > + if (cmd == cmdset.read_id) { > info->ndcb0 |= NDCB0_CMD_TYPE(3); > info->data_size = 8; > - } else if (cmd == cmdset->read_status) { > + } else if (cmd == cmdset.read_status) { > info->ndcb0 |= NDCB0_CMD_TYPE(4); > info->data_size = 8; > - } else if (cmd == cmdset->reset || cmd == cmdset->lock || > - cmd == cmdset->unlock) { > + } else if (cmd == cmdset.reset || cmd == cmdset.lock || > + cmd == cmdset.unlock) { > info->ndcb0 |= NDCB0_CMD_TYPE(5); > } else > return -EINVAL; > @@ -700,8 +593,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > int column, int page_addr) > { > struct pxa3xx_nand_info *info = mtd->priv; > - const struct pxa3xx_nand_flash *flash_info = info->flash_info; > - const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; > int ret; > > info->use_dma = (use_dma) ? 1 : 0; > @@ -718,7 +609,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > info->buf_start = mtd->writesize + column; > memset(info->data_buff, 0xFF, info->buf_count); > > - if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) > + if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); > @@ -735,7 +626,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > info->buf_count = mtd->writesize + mtd->oobsize; > memset(info->data_buff, 0xFF, info->buf_count); > > - if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr)) > + if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); > @@ -761,14 +652,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > case NAND_CMD_PAGEPROG: > info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; > > - if (prepare_read_prog_cmd(info, cmdset->program, > + if (prepare_read_prog_cmd(info, cmdset.program, > info->seqin_column, info->seqin_page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); > break; > case NAND_CMD_ERASE1: > - if (prepare_erase_cmd(info, cmdset->erase, page_addr)) > + if (prepare_erase_cmd(info, cmdset.erase, page_addr)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); > @@ -783,13 +674,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info > *mtd, unsigned command, > info->read_id_bytes : 1; > > if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? > - cmdset->read_id : cmdset->read_status)) > + cmdset.read_id : cmdset.read_status)) > break; > > pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); > break; > case NAND_CMD_RESET: > - if (prepare_other_cmd(info, cmdset->reset)) > + if (prepare_other_cmd(info, cmdset.reset)) > break; > > ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); > @@ -925,12 +816,10 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, > > static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) > { > - const struct pxa3xx_nand_flash *f = info->flash_info; > - const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; > uint32_t ndcr; > uint8_t id_buff[8]; > > - if (prepare_other_cmd(info, cmdset->read_id)) { > + if (prepare_other_cmd(info, cmdset.read_id)) { > printk(KERN_ERR "failed to prepare command\n"); > return -EINVAL; > } > @@ -991,7 +880,7 @@ static int pxa3xx_nand_config_flash(struct > pxa3xx_nand_info *info, > > info->reg_ndcr = ndcr; > > - pxa3xx_nand_set_timing(info, f->timing); > + pxa3xx_nand_set_timing(info, &f->timing); > info->flash_info = f; > return 0; > } > @@ -1027,11 +916,6 @@ static int pxa3xx_nand_detect_config(struct > pxa3xx_nand_info *info) > default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; > default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; > > - if (default_flash.page_size == 2048) > - default_flash.cmdset = &largepage_cmdset; > - else > - default_flash.cmdset = &smallpage_cmdset; > - > /* set info fields needed to __readid */ > info->flash_info = &default_flash; > info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; > @@ -1067,7 +951,7 @@ static int pxa3xx_nand_detect_config(struct > pxa3xx_nand_info *info) > info->row_addr_cycles = 2; > > pxa3xx_nand_detect_timing(info, &default_timing); > - default_flash.timing = &default_timing; > + memcpy(&default_flash.timing, &default_timing, sizeof(default_timing)); > > return 0; > } > @@ -1083,23 +967,9 @@ static int pxa3xx_nand_detect_flash(struct > pxa3xx_nand_info *info, > if (pxa3xx_nand_detect_config(info) == 0) > return 0; > > - for (i = 0; inum_flash; ++i) { > - f = pdata->flash + i; > - > - if (pxa3xx_nand_config_flash(info, f)) > - continue; > - > - if (__readid(info, &id)) > - continue; > - > - if (id == f->chip_id) > - return 0; > - } > - > -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN > for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { > > - f = builtin_flash_types[i]; > + f = &builtin_flash_types[i]; > > if (pxa3xx_nand_config_flash(info, f)) > continue; > @@ -1110,7 +980,6 @@ static int pxa3xx_nand_detect_flash(struct > pxa3xx_nand_info *info, > if (id == f->chip_id) > return 0; > } > -#endif > > dev_warn(&info->pdev->dev, > "failed to detect configured nand flash; found %04x instead of\n", > @@ -1320,17 +1189,6 @@ static int pxa3xx_nand_probe(struct > platform_device *pdev) > goto fail_free_irq; > } > > - if (mtd_has_cmdlinepart()) { > - static const char *probes[] = { "cmdlinepart", NULL }; > - struct mtd_partition *parts; > - int nr_parts; > - > - nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); > - > - if (nr_parts) > - return add_mtd_partitions(mtd, parts, nr_parts); > - } > - > return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); > > fail_free_irq: -- Sincerely yours, Mike. From adrian.wenl at gmail.com Mon May 24 04:20:35 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 16:20:35 +0800 Subject: [PATCH 02/20] mtd: pxa3xx_nand: introduce common timing to reduce read id times In-Reply-To: <4BFA29F9.8000400@compulab.co.il> References: <4BFA29F9.8000400@compulab.co.il> Message-ID: On Mon, May 24, 2010 at 3:25 PM, Mike Rapoport wrote: > Haojian Zhuang wrote: >> >> From 35a06a21643049e146aba95057e7fe89c55d4b32 Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Mon, 22 Mar 2010 10:24:48 +0800 >> Subject: [PATCH] mtd: pxa3xx_nand: introduce common timing to reduce >> read id times >> >> We certainly don't need to send read id command times by times, since >> we already know what the id is after the first read id... >> >> So create a common timing which could ensure it would successfully read id >> out all supported chip. Then follow the build-in table to reconfigure >> the timing. >> >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?drivers/mtd/nand/pxa3xx_nand.c | ? 33 +++++++++++++++++---------------- >> ?1 files changed, 17 insertions(+), 16 deletions(-) >> >> diff --git a/drivers/mtd/nand/pxa3xx_nand.c >> b/drivers/mtd/nand/pxa3xx_nand.c >> index da40b9a..5658398 100644 >> --- a/drivers/mtd/nand/pxa3xx_nand.c >> +++ b/drivers/mtd/nand/pxa3xx_nand.c >> @@ -225,7 +225,13 @@ const static struct pxa3xx_nand_cmdset cmdset = { >> ? ? ? ?.lock_status ? ?= 0x007A, >> ?}; >> >> +/** >> + * The timing defined in the builtin_flash_types[0] >> + * could be considered as the common timing which is used to >> + * detect the chip id before we know how to optimize further >> + */ >> ?static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { >> +{ 0, 0, 0, 0, 0, 0, { 40, 80, 60, 100, 80, 100, 90000, 400, 40, }, }, >> ?{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >> }, }, >> ?{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >> }, }, >> ?{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >> }, }, >> @@ -850,12 +856,6 @@ static int pxa3xx_nand_config_flash(struct >> pxa3xx_nand_info *info, >> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; >> ? ? ? ?uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ >> >> - ? ? ? if (f->page_size != 2048 && f->page_size != 512) >> - ? ? ? ? ? ? ? return -EINVAL; >> - >> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8) >> - ? ? ? ? ? ? ? return -EINVAL; >> - >> ? ? ? ?/* calculate flash information */ >> ? ? ? ?info->oob_size = (f->page_size == 2048) ? 64 : 16; >> ? ? ? ?info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; >> @@ -967,23 +967,24 @@ static int pxa3xx_nand_detect_flash(struct >> pxa3xx_nand_info *info, >> ? ? ? ? ? ? ? ?if (pxa3xx_nand_detect_config(info) == 0) >> ? ? ? ? ? ? ? ? ? ? ? ?return 0; >> >> - ? ? ? for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { >> + ? ? ? f = &builtin_flash_types[0]; >> + ? ? ? pxa3xx_nand_config_flash(info, f); >> + ? ? ? if (__readid(info, &id)) >> + ? ? ? ? ? ? ? goto fail_detect; >> >> + ? ? ? for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { >> ? ? ? ? ? ? ? ?f = &builtin_flash_types[i]; >> - >> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f)) >> - ? ? ? ? ? ? ? ? ? ? ? continue; >> - >> - ? ? ? ? ? ? ? if (__readid(info, &id)) >> - ? ? ? ? ? ? ? ? ? ? ? continue; >> - >> - ? ? ? ? ? ? ? if (id == f->chip_id) >> + ? ? ? ? ? ? ? if (f->chip_id == id) { >> + ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: >> 0x%x\n", id); >> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f); >> ? ? ? ? ? ? ? ? ? ? ? ?return 0; >> + ? ? ? ? ? ? ? } >> ? ? ? ?} >> >> ? ? ? ?dev_warn(&info->pdev->dev, >> - ? ? ? ? ? ? ? ?"failed to detect configured nand flash; found %04x >> instead of\n", >> + ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found >> %04x instead of\n", > > Instead of what? > And, what if the flash is not listed in the builtin_flash_types? Does it > really mean it's > -ENODEV? Yes, when the flash type is not listed in, you should add the new one manually. For now, just add two lines is enough for a new type flash. The reason why we do this is for different flash has different attribute that need to be seperated supported. For example, if one flash need different timing and higher ecc(This function is not included in this patch set, I would submit it later), the driver need to know it to deal in correct behavior. Best regards, Lei From dedekind1 at gmail.com Mon May 24 04:18:00 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 24 May 2010 11:18:00 +0300 Subject: ubifs became broken on contigous power-fails In-Reply-To: <201005241249.28629.pazdnikov@prosoft.ural.ru> References: <1274614112.22999.17.camel@localhost> <1274617419.22999.24.camel@localhost> <201005241249.28629.pazdnikov@prosoft.ural.ru> Message-ID: <1274689080.22999.43.camel@localhost> On Mon, 2010-05-24 at 12:49 +0600, Alexander Pazdnikov wrote: > Artem, thank you very much, now applying your patches and making new stress-tests :-) > > Also last holidays have caught another issue. > > We've modified our program to primary mount ubi2:dbfs in RO, then sleep 3 secs, then remount in RW. > Today have found half (5/10) of devices with the error : No space left on device > If mount by hands this stalled fs primary in RW mode, then everything goes OK. > If drop down mount "mount ubi2:dbfs in RO, then sleep 3 secs", leave only mount in RW, everything also goes OK. > > [ 6.576168] UBIFS: recovery needed > [ 6.665035] UBIFS: recovery deferred > [ 6.668941] UBIFS: mounted UBI device 2, volume 0, name "dbfs" > [ 6.674801] UBIFS: mounted read-only > [ 6.678707] UBIFS: file system size: 189407232 bytes (184968 KiB, 180 MiB, 1468 LEBs) > [ 6.687496] UBIFS: journal size: 9418752 bytes (9198 KiB, 8 MiB, 73 LEBs) > [ 6.694332] UBIFS: media format: w4/r0 (latest is w4/r0) > [ 6.700191] UBIFS: default compressor: lzo > [ 6.705074] UBIFS: reserved for root: 4952683 bytes (4836 KiB) > [ 9.787104] UBIFS: completing deferred recovery > Remounting ubi2:dbfs on /usr/local/ecom/db failed: No space left on device > > # df > Filesystem Size Used Available Use% Mounted on > ubi0:rootfs 13.2M 7.2M 6.0M 55% / > tmpfs 4.0K 0 4.0K 0% /dev > shm 1.0M 0 1.0M 0% /dev/shm > tmpfs 1.0M 12.0K 1012.0K 1% /tmp > tmpfs 1.0M 4.0K 1020.0K 0% /root > ubi1:logs 11.5M 2.4M 8.4M 22% /var/log > ubi1:tmp 13.4M 16.0K 12.7M 0% /usr/local/ecom/tmp > ubi0:local 2.1M 44.0K 1.9M 2% /var/local > ubi:config 2.0M 68.0K 1.9M 3% /usr/local/ecom/conf > ubi2:dbfs 169.2M 18.7M 145.8M 11% /usr/local/ecom/db Could you enable debugging messages when mounging it after power cuts? The messages generate a lot of noise, so you need to disable them before starting the real test. The idea is to get UBIFS debugging messages when errors occur. You can read about how to enable/disable the messages here: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_how_send_bugreport and in the Documentation/filesystems/ubifs.txt The problems you see are probably budgeting bugs. Please, read this section to get some idea what is the UBIFS budgeting subsystem about: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_spaceacc I have a test which reproduces budgeting bugs here: git://git.infradead.org/users/dedekind/ubifs-userspace.git see the "freespace" test and the 'freespace.sh' script which runs the freespace test on various NAND/NOR size and geometry flashes. I never had time to really dig this and fix. Would be nice if you could do this because I will unlikely have time in the nearest future, but I can help you. One think you can do is to make sure you do not fill UBIFS completely, then you will avoid hitting these budgeting bugs, also known as ENOSPC issues (I think btrfs uses this terminology). E.g., if you work under a normal user, you can reserve more space for the root (see -R mkfs.ubifs option). But of course, ideally we should just fix the issues. -- Best Regards, Artem Bityutskiy (????? ????????) From adrian.wenl at gmail.com Mon May 24 04:27:21 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 16:27:21 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <4BFA2B5B.4080105@compulab.co.il> References: <4BFA2B5B.4080105@compulab.co.il> Message-ID: Hi Mike, This patch set is applied to mtd-2.6 git. We submit the patch with a package in attachment already. http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 Best regards, Lei On Mon, May 24, 2010 at 3:31 PM, Mike Rapoport wrote: > Hi Haojian, > This is a comment to the entire series, and should have been Re: [PATCH > 0/20], but there's no cover letter for these patches. > > The patches are all line-wrapped and do not apply. It's really hard to read > them because of hunks added inside the existing functions. Please try to > organize your changes in a more straight ?forward way. > > Haojian Zhuang wrote: >> >> From 16057e690aa4a2fd8a9c07c70ab48ffc2f76204f Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Sat, 20 Mar 2010 19:01:23 +0800 >> Subject: [PATCH] mtd: pxa3xx_nand: refuse the flash definition get from >> platform >> >> For current usage, it is little reason to use a platform defined flash >> info >> for the flash detection. Flash timing through platform should be the same. >> And allow multiple platform to define the same flash chip would be a >> waste. >> >> Also condense the flash definition way in the c file to simplify adding a >> new chip. >> >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 40 ---- >> ?drivers/mtd/nand/Kconfig ? ? ? ? ? ? ? ? ? ? | ? ?7 - >> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?262 >> ++++++-------------------- >> ?3 files changed, 60 insertions(+), 249 deletions(-) >> >> diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >> b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >> index 3478eae..c494f68 100644 >> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >> @@ -4,43 +4,6 @@ >> ?#include >> ?#include >> >> -struct pxa3xx_nand_timing { >> - ? ? ? unsigned int ? ?tCH; ?/* Enable signal hold time */ >> - ? ? ? unsigned int ? ?tCS; ?/* Enable signal setup time */ >> - ? ? ? unsigned int ? ?tWH; ?/* ND_nWE high duration */ >> - ? ? ? unsigned int ? ?tWP; ?/* ND_nWE pulse time */ >> - ? ? ? unsigned int ? ?tRH; ?/* ND_nRE high duration */ >> - ? ? ? unsigned int ? ?tRP; ?/* ND_nRE pulse width */ >> - ? ? ? unsigned int ? ?tR; ? /* ND_nWE high to ND_nRE low for read */ >> - ? ? ? unsigned int ? ?tWHR; /* ND_nWE high to ND_nRE low for status read >> */ >> - ? ? ? unsigned int ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */ >> -}; >> - >> -struct pxa3xx_nand_cmdset { >> - ? ? ? uint16_t ? ? ? ?read1; >> - ? ? ? uint16_t ? ? ? ?read2; >> - ? ? ? uint16_t ? ? ? ?program; >> - ? ? ? uint16_t ? ? ? ?read_status; >> - ? ? ? uint16_t ? ? ? ?read_id; >> - ? ? ? uint16_t ? ? ? ?erase; >> - ? ? ? uint16_t ? ? ? ?reset; >> - ? ? ? uint16_t ? ? ? ?lock; >> - ? ? ? uint16_t ? ? ? ?unlock; >> - ? ? ? uint16_t ? ? ? ?lock_status; >> -}; >> - >> -struct pxa3xx_nand_flash { >> - ? ? ? const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ >> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset; >> - >> - ? ? ? uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ >> - ? ? ? uint32_t page_size; ? ? /* Page size in bytes (PAGE_SZ) */ >> - ? ? ? uint32_t flash_width; ? /* Width of Flash memory (DWIDTH_M) */ >> - ? ? ? uint32_t dfc_width; ? ? /* Width of flash controller(DWIDTH_C) */ >> - ? ? ? uint32_t num_blocks; ? ?/* Number of physical blocks in Flash */ >> - ? ? ? uint32_t chip_id; >> -}; >> - >> ?struct pxa3xx_nand_platform_data { >> >> ? ? ? ?/* the data flash bus is shared between the Static Memory >> @@ -54,9 +17,6 @@ struct pxa3xx_nand_platform_data { >> >> ? ? ? ?const struct mtd_partition ? ? ? ? ? ? ?*parts; >> ? ? ? ?unsigned int ? ? ? ? ? ? ? ? ? ? ? ? ? ?nr_parts; >> - >> - ? ? ? const struct pxa3xx_nand_flash * ? ? ? ?flash; >> - ? ? ? size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash; >> ?}; >> >> ?extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); >> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig >> index 98a04b3..9a35d92 100644 >> --- a/drivers/mtd/nand/Kconfig >> +++ b/drivers/mtd/nand/Kconfig >> @@ -399,13 +399,6 @@ config MTD_NAND_PXA3xx >> ? ? ? ? ?This enables the driver for the NAND flash device found on >> ? ? ? ? ?PXA3xx processors >> >> -config MTD_NAND_PXA3xx_BUILTIN >> - ? ? ? bool "Use builtin definitions for some NAND chips (deprecated)" >> - ? ? ? depends on MTD_NAND_PXA3xx >> - ? ? ? help >> - ? ? ? ? This enables builtin definitions for some NAND chips. This >> - ? ? ? ? is deprecated in favor of platform specific data. >> - >> ?config MTD_NAND_CM_X270 >> ? ? ? ?tristate "Support for NAND Flash on CM-X270 modules" >> ? ? ? ?depends on MTD_NAND && MACH_ARMCORE >> diff --git a/drivers/mtd/nand/pxa3xx_nand.c >> b/drivers/mtd/nand/pxa3xx_nand.c >> index e02fa4f..da40b9a 100644 >> --- a/drivers/mtd/nand/pxa3xx_nand.c >> +++ b/drivers/mtd/nand/pxa3xx_nand.c >> @@ -113,6 +113,41 @@ enum { >> ? ? ? ?STATE_PIO_WRITING, >> ?}; >> >> +struct pxa3xx_nand_timing { >> + ? ? ? uint32_t ? ? ? ?tCH; ?/* Enable signal hold time */ >> + ? ? ? uint32_t ? ? ? ?tCS; ?/* Enable signal setup time */ >> + ? ? ? uint32_t ? ? ? ?tWH; ?/* ND_nWE high duration */ >> + ? ? ? uint32_t ? ? ? ?tWP; ?/* ND_nWE pulse time */ >> + ? ? ? uint32_t ? ? ? ?tRH; ?/* ND_nRE high duration */ >> + ? ? ? uint32_t ? ? ? ?tRP; ?/* ND_nRE pulse width */ >> + ? ? ? uint32_t ? ? ? ?tAR; ?/* ND_ALE low to ND_nRE low delay */ >> + ? ? ? uint32_t ? ? ? ?tWHR; /* ND_nWE high to ND_nRE low for status read >> */ >> + ? ? ? uint32_t ? ? ? ?tR; ? /* ND_nWE high to ND_nRE low for read */ >> +}; >> + >> +struct pxa3xx_nand_cmdset { >> + ? ? ? uint16_t ? ? ? ?read1; >> + ? ? ? uint16_t ? ? ? ?read2; >> + ? ? ? uint16_t ? ? ? ?program; >> + ? ? ? uint16_t ? ? ? ?read_status; >> + ? ? ? uint16_t ? ? ? ?read_id; >> + ? ? ? uint16_t ? ? ? ?erase; >> + ? ? ? uint16_t ? ? ? ?reset; >> + ? ? ? uint16_t ? ? ? ?lock; >> + ? ? ? uint16_t ? ? ? ?unlock; >> + ? ? ? uint16_t ? ? ? ?lock_status; >> +}; >> + >> +struct pxa3xx_nand_flash { >> + ? ? ? uint32_t ? ? ? ?chip_id; >> + ? ? ? uint16_t ? ? ? ?page_per_block; /* Pages per block (PG_PER_BLK) */ >> + ? ? ? uint16_t ? ? ? ?page_size; ? ? ?/* Page size in bytes (PAGE_SZ) */ >> + ? ? ? uint8_t ? ? ? ? flash_width; ? ?/* Width of Flash memory >> (DWIDTH_M) */ >> + ? ? ? uint8_t ? ? ? ? dfc_width; ? ? ?/* Width of flash >> controller(DWIDTH_C) */ >> + ? ? ? uint32_t ? ? ? ?num_blocks; ? ? /* Number of physical blocks in >> Flash */ >> + ? ? ? struct pxa3xx_nand_timing timing; ? ? ? /* NAND Flash timing */ >> +}; >> + >> ?struct pxa3xx_nand_info { >> ? ? ? ?struct nand_chip ? ? ? ?nand_chip; >> >> @@ -177,20 +212,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data >> transfering to/from NAND HW"); >> ?static struct pxa3xx_nand_timing default_timing; >> ?static struct pxa3xx_nand_flash default_flash; >> >> -static struct pxa3xx_nand_cmdset smallpage_cmdset = { >> - ? ? ? .read1 ? ? ? ? ?= 0x0000, >> - ? ? ? .read2 ? ? ? ? ?= 0x0050, >> - ? ? ? .program ? ? ? ?= 0x1080, >> - ? ? ? .read_status ? ?= 0x0070, >> - ? ? ? .read_id ? ? ? ?= 0x0090, >> - ? ? ? .erase ? ? ? ? ?= 0xD060, >> - ? ? ? .reset ? ? ? ? ?= 0x00FF, >> - ? ? ? .lock ? ? ? ? ? = 0x002A, >> - ? ? ? .unlock ? ? ? ? = 0x2423, >> - ? ? ? .lock_status ? ?= 0x007A, >> -}; >> - >> -static struct pxa3xx_nand_cmdset largepage_cmdset = { >> +const static struct pxa3xx_nand_cmdset cmdset = { >> ? ? ? ?.read1 ? ? ? ? ?= 0x3000, >> ? ? ? ?.read2 ? ? ? ? ?= 0x0050, >> ? ? ? ?.program ? ? ? ?= 0x1080, >> @@ -203,143 +225,17 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = >> { >> ? ? ? ?.lock_status ? ?= 0x007A, >> ?}; >> >> -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN >> -static struct pxa3xx_nand_timing samsung512MbX16_timing = { >> - ? ? ? .tCH ? ?= 10, >> - ? ? ? .tCS ? ?= 0, >> - ? ? ? .tWH ? ?= 20, >> - ? ? ? .tWP ? ?= 40, >> - ? ? ? .tRH ? ?= 30, >> - ? ? ? .tRP ? ?= 40, >> - ? ? ? .tR ? ? = 11123, >> - ? ? ? .tWHR ? = 110, >> - ? ? ? .tAR ? ?= 10, >> -}; >> - >> -static struct pxa3xx_nand_flash samsung512MbX16 = { >> - ? ? ? .timing ? ? ? ? = &samsung512MbX16_timing, >> - ? ? ? .cmdset ? ? ? ? = &smallpage_cmdset, >> - ? ? ? .page_per_block = 32, >> - ? ? ? .page_size ? ? ?= 512, >> - ? ? ? .flash_width ? ?= 16, >> - ? ? ? .dfc_width ? ? ?= 16, >> - ? ? ? .num_blocks ? ? = 4096, >> - ? ? ? .chip_id ? ? ? ?= 0x46ec, >> -}; >> - >> -static struct pxa3xx_nand_flash samsung2GbX8 = { >> - ? ? ? .timing ? ? ? ? = &samsung512MbX16_timing, >> - ? ? ? .cmdset ? ? ? ? = &smallpage_cmdset, >> - ? ? ? .page_per_block = 64, >> - ? ? ? .page_size ? ? ?= 2048, >> - ? ? ? .flash_width ? ?= 8, >> - ? ? ? .dfc_width ? ? ?= 8, >> - ? ? ? .num_blocks ? ? = 2048, >> - ? ? ? .chip_id ? ? ? ?= 0xdaec, >> -}; >> - >> -static struct pxa3xx_nand_flash samsung32GbX8 = { >> - ? ? ? .timing ? ? ? ? = &samsung512MbX16_timing, >> - ? ? ? .cmdset ? ? ? ? = &smallpage_cmdset, >> - ? ? ? .page_per_block = 128, >> - ? ? ? .page_size ? ? ?= 4096, >> - ? ? ? .flash_width ? ?= 8, >> - ? ? ? .dfc_width ? ? ?= 8, >> - ? ? ? .num_blocks ? ? = 8192, >> - ? ? ? .chip_id ? ? ? ?= 0xd7ec, >> +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { >> +{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >> }, }, >> +{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >> }, }, >> +{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >> }, }, >> +{ 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, >> }, }, >> +{ 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, >> 60, 10, }, }, >> +{ 0xdc2c, 64, 2048, 8, 8, 4096, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, >> }, }, >> +{ 0xcc2c, 64, 2048, 16, 16, 4096, { 10, 25, 15, 25, 15, 30, 25000, >> 60, 10, }, }, >> +{ 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, >> 60, 10, }, }, >> ?}; >> >> -static struct pxa3xx_nand_timing micron_timing = { >> - ? ? ? .tCH ? ?= 10, >> - ? ? ? .tCS ? ?= 25, >> - ? ? ? .tWH ? ?= 15, >> - ? ? ? .tWP ? ?= 25, >> - ? ? ? .tRH ? ?= 15, >> - ? ? ? .tRP ? ?= 30, >> - ? ? ? .tR ? ? = 25000, >> - ? ? ? .tWHR ? = 60, >> - ? ? ? .tAR ? ?= 10, >> -}; >> - >> -static struct pxa3xx_nand_flash micron1GbX8 = { >> - ? ? ? .timing ? ? ? ? = µn_timing, >> - ? ? ? .cmdset ? ? ? ? = &largepage_cmdset, >> - ? ? ? .page_per_block = 64, >> - ? ? ? .page_size ? ? ?= 2048, >> - ? ? ? .flash_width ? ?= 8, >> - ? ? ? .dfc_width ? ? ?= 8, >> - ? ? ? .num_blocks ? ? = 1024, >> - ? ? ? .chip_id ? ? ? ?= 0xa12c, >> -}; >> - >> -static struct pxa3xx_nand_flash micron1GbX16 = { >> - ? ? ? .timing ? ? ? ? = µn_timing, >> - ? ? ? .cmdset ? ? ? ? = &largepage_cmdset, >> - ? ? ? .page_per_block = 64, >> - ? ? ? .page_size ? ? ?= 2048, >> - ? ? ? .flash_width ? ?= 16, >> - ? ? ? .dfc_width ? ? ?= 16, >> - ? ? ? .num_blocks ? ? = 1024, >> - ? ? ? .chip_id ? ? ? ?= 0xb12c, >> -}; >> - >> -static struct pxa3xx_nand_flash micron4GbX8 = { >> - ? ? ? .timing ? ? ? ? = µn_timing, >> - ? ? ? .cmdset ? ? ? ? = &largepage_cmdset, >> - ? ? ? .page_per_block = 64, >> - ? ? ? .page_size ? ? ?= 2048, >> - ? ? ? .flash_width ? ?= 8, >> - ? ? ? .dfc_width ? ? ?= 8, >> - ? ? ? .num_blocks ? ? = 4096, >> - ? ? ? .chip_id ? ? ? ?= 0xdc2c, >> -}; >> - >> -static struct pxa3xx_nand_flash micron4GbX16 = { >> - ? ? ? .timing ? ? ? ? = µn_timing, >> - ? ? ? .cmdset ? ? ? ? = &largepage_cmdset, >> - ? ? ? .page_per_block = 64, >> - ? ? ? .page_size ? ? ?= 2048, >> - ? ? ? .flash_width ? ?= 16, >> - ? ? ? .dfc_width ? ? ?= 16, >> - ? ? ? .num_blocks ? ? = 4096, >> - ? ? ? .chip_id ? ? ? ?= 0xcc2c, >> -}; >> - >> -static struct pxa3xx_nand_timing stm2GbX16_timing = { >> - ? ? ? .tCH = 10, >> - ? ? ? .tCS = 35, >> - ? ? ? .tWH = 15, >> - ? ? ? .tWP = 25, >> - ? ? ? .tRH = 15, >> - ? ? ? .tRP = 25, >> - ? ? ? .tR = 25000, >> - ? ? ? .tWHR = 60, >> - ? ? ? .tAR = 10, >> -}; >> - >> -static struct pxa3xx_nand_flash stm2GbX16 = { >> - ? ? ? .timing = &stm2GbX16_timing, >> - ? ? ? .cmdset = &largepage_cmdset, >> - ? ? ? .page_per_block = 64, >> - ? ? ? .page_size = 2048, >> - ? ? ? .flash_width = 16, >> - ? ? ? .dfc_width = 16, >> - ? ? ? .num_blocks = 2048, >> - ? ? ? .chip_id = 0xba20, >> -}; >> - >> -static struct pxa3xx_nand_flash *builtin_flash_types[] = { >> - ? ? ? &samsung512MbX16, >> - ? ? ? &samsung2GbX8, >> - ? ? ? &samsung32GbX8, >> - ? ? ? µn1GbX8, >> - ? ? ? µn1GbX16, >> - ? ? ? µn4GbX8, >> - ? ? ? µn4GbX16, >> - ? ? ? &stm2GbX16, >> -}; >> -#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ >> - >> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19) >> ?#define NDTR0_tCS(c) ? (min((c), 7) << 16) >> ?#define NDTR0_tWH(c) ? (min((c), 7) << 11) >> @@ -412,7 +308,6 @@ static int prepare_read_prog_cmd(struct >> pxa3xx_nand_info *info, >> ? ? ? ? ? ? ? ? ? ? ? ?uint16_t cmd, int column, int page_addr) >> ?{ >> ? ? ? ?const struct pxa3xx_nand_flash *f = info->flash_info; >> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; >> >> ? ? ? ?/* calculate data size */ >> ? ? ? ?switch (f->page_size) { >> @@ -445,7 +340,7 @@ static int prepare_read_prog_cmd(struct >> pxa3xx_nand_info *info, >> ? ? ? ? ? ? ? ? */ >> ? ? ? ? ? ? ? ?info->ndcb1 = page_addr << 8; >> >> - ? ? ? if (cmd == cmdset->program) >> + ? ? ? if (cmd == cmdset.program) >> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; >> >> ? ? ? ?return 0; >> @@ -463,20 +358,18 @@ static int prepare_erase_cmd(struct >> pxa3xx_nand_info *info, >> >> ?static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) >> ?{ >> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset = >> info->flash_info->cmdset; >> - >> ? ? ? ?info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); >> ? ? ? ?info->ndcb1 = 0; >> ? ? ? ?info->ndcb2 = 0; >> >> - ? ? ? if (cmd == cmdset->read_id) { >> + ? ? ? if (cmd == cmdset.read_id) { >> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(3); >> ? ? ? ? ? ? ? ?info->data_size = 8; >> - ? ? ? } else if (cmd == cmdset->read_status) { >> + ? ? ? } else if (cmd == cmdset.read_status) { >> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(4); >> ? ? ? ? ? ? ? ?info->data_size = 8; >> - ? ? ? } else if (cmd == cmdset->reset || cmd == cmdset->lock || >> - ? ? ? ? ? ? ? ? ?cmd == cmdset->unlock) { >> + ? ? ? } else if (cmd == cmdset.reset || cmd == cmdset.lock || >> + ? ? ? ? ? ? ? ? ?cmd == cmdset.unlock) { >> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(5); >> ? ? ? ?} else >> ? ? ? ? ? ? ? ?return -EINVAL; >> @@ -700,8 +593,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >> *mtd, unsigned command, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?int column, int page_addr) >> ?{ >> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv; >> - ? ? ? const struct pxa3xx_nand_flash *flash_info = info->flash_info; >> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; >> ? ? ? ?int ret; >> >> ? ? ? ?info->use_dma = (use_dma) ? 1 : 0; >> @@ -718,7 +609,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >> *mtd, unsigned command, >> ? ? ? ? ? ? ? ?info->buf_start = mtd->writesize + column; >> ? ? ? ? ? ? ? ?memset(info->data_buff, 0xFF, info->buf_count); >> >> - ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset->read1, column, >> page_addr)) >> + ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset.read1, column, >> page_addr)) >> ? ? ? ? ? ? ? ? ? ? ? ?break; >> >> ? ? ? ? ? ? ? ?pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | >> NDSR_SBERR); >> @@ -735,7 +626,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >> *mtd, unsigned command, >> ? ? ? ? ? ? ? ?info->buf_count = mtd->writesize + mtd->oobsize; >> ? ? ? ? ? ? ? ?memset(info->data_buff, 0xFF, info->buf_count); >> >> - ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset->read1, column, >> page_addr)) >> + ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset.read1, column, >> page_addr)) >> ? ? ? ? ? ? ? ? ? ? ? ?break; >> >> ? ? ? ? ? ? ? ?pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | >> NDSR_SBERR); >> @@ -761,14 +652,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >> *mtd, unsigned command, >> ? ? ? ?case NAND_CMD_PAGEPROG: >> ? ? ? ? ? ? ? ?info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 >> : 1; >> >> - ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset->program, >> + ? ? ? ? ? ? ? if (prepare_read_prog_cmd(info, cmdset.program, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->seqin_column, info->seqin_page_addr)) >> ? ? ? ? ? ? ? ? ? ? ? ?break; >> >> ? ? ? ? ? ? ? ?pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); >> ? ? ? ? ? ? ? ?break; >> ? ? ? ?case NAND_CMD_ERASE1: >> - ? ? ? ? ? ? ? if (prepare_erase_cmd(info, cmdset->erase, page_addr)) >> + ? ? ? ? ? ? ? if (prepare_erase_cmd(info, cmdset.erase, page_addr)) >> ? ? ? ? ? ? ? ? ? ? ? ?break; >> >> ? ? ? ? ? ? ? ?pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); >> @@ -783,13 +674,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >> *mtd, unsigned command, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->read_id_bytes : 1; >> >> ? ? ? ? ? ? ? ?if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cmdset->read_id : cmdset->read_status)) >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? cmdset.read_id : cmdset.read_status)) >> ? ? ? ? ? ? ? ? ? ? ? ?break; >> >> ? ? ? ? ? ? ? ?pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); >> ? ? ? ? ? ? ? ?break; >> ? ? ? ?case NAND_CMD_RESET: >> - ? ? ? ? ? ? ? if (prepare_other_cmd(info, cmdset->reset)) >> + ? ? ? ? ? ? ? if (prepare_other_cmd(info, cmdset.reset)) >> ? ? ? ? ? ? ? ? ? ? ? ?break; >> >> ? ? ? ? ? ? ? ?ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); >> @@ -925,12 +816,10 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info >> *mtd, >> >> ?static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) >> ?{ >> - ? ? ? const struct pxa3xx_nand_flash *f = info->flash_info; >> - ? ? ? const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; >> ? ? ? ?uint32_t ndcr; >> ? ? ? ?uint8_t ?id_buff[8]; >> >> - ? ? ? if (prepare_other_cmd(info, cmdset->read_id)) { >> + ? ? ? if (prepare_other_cmd(info, cmdset.read_id)) { >> ? ? ? ? ? ? ? ?printk(KERN_ERR "failed to prepare command\n"); >> ? ? ? ? ? ? ? ?return -EINVAL; >> ? ? ? ?} >> @@ -991,7 +880,7 @@ static int pxa3xx_nand_config_flash(struct >> pxa3xx_nand_info *info, >> >> ? ? ? ?info->reg_ndcr = ndcr; >> >> - ? ? ? pxa3xx_nand_set_timing(info, f->timing); >> + ? ? ? pxa3xx_nand_set_timing(info, &f->timing); >> ? ? ? ?info->flash_info = f; >> ? ? ? ?return 0; >> ?} >> @@ -1027,11 +916,6 @@ static int pxa3xx_nand_detect_config(struct >> pxa3xx_nand_info *info) >> ? ? ? ?default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; >> ? ? ? ?default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; >> >> - ? ? ? if (default_flash.page_size == 2048) >> - ? ? ? ? ? ? ? default_flash.cmdset = &largepage_cmdset; >> - ? ? ? else >> - ? ? ? ? ? ? ? default_flash.cmdset = &smallpage_cmdset; >> - >> ? ? ? ?/* set info fields needed to __readid */ >> ? ? ? ?info->flash_info = &default_flash; >> ? ? ? ?info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; >> @@ -1067,7 +951,7 @@ static int pxa3xx_nand_detect_config(struct >> pxa3xx_nand_info *info) >> ? ? ? ? ? ? ? ?info->row_addr_cycles = 2; >> >> ? ? ? ?pxa3xx_nand_detect_timing(info, &default_timing); >> - ? ? ? default_flash.timing = &default_timing; >> + ? ? ? memcpy(&default_flash.timing, &default_timing, >> sizeof(default_timing)); >> >> ? ? ? ?return 0; >> ?} >> @@ -1083,23 +967,9 @@ static int pxa3xx_nand_detect_flash(struct >> pxa3xx_nand_info *info, >> ? ? ? ? ? ? ? ?if (pxa3xx_nand_detect_config(info) == 0) >> ? ? ? ? ? ? ? ? ? ? ? ?return 0; >> >> - ? ? ? for (i = 0; inum_flash; ++i) { >> - ? ? ? ? ? ? ? f = pdata->flash + i; >> - >> - ? ? ? ? ? ? ? if (pxa3xx_nand_config_flash(info, f)) >> - ? ? ? ? ? ? ? ? ? ? ? continue; >> - >> - ? ? ? ? ? ? ? if (__readid(info, &id)) >> - ? ? ? ? ? ? ? ? ? ? ? continue; >> - >> - ? ? ? ? ? ? ? if (id == f->chip_id) >> - ? ? ? ? ? ? ? ? ? ? ? return 0; >> - ? ? ? } >> - >> -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN >> ? ? ? ?for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { >> >> - ? ? ? ? ? ? ? f = builtin_flash_types[i]; >> + ? ? ? ? ? ? ? f = &builtin_flash_types[i]; >> >> ? ? ? ? ? ? ? ?if (pxa3xx_nand_config_flash(info, f)) >> ? ? ? ? ? ? ? ? ? ? ? ?continue; >> @@ -1110,7 +980,6 @@ static int pxa3xx_nand_detect_flash(struct >> pxa3xx_nand_info *info, >> ? ? ? ? ? ? ? ?if (id == f->chip_id) >> ? ? ? ? ? ? ? ? ? ? ? ?return 0; >> ? ? ? ?} >> -#endif >> >> ? ? ? ?dev_warn(&info->pdev->dev, >> ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found %04x >> instead of\n", >> @@ -1320,17 +1189,6 @@ static int pxa3xx_nand_probe(struct >> platform_device *pdev) >> ? ? ? ? ? ? ? ?goto fail_free_irq; >> ? ? ? ?} >> >> - ? ? ? if (mtd_has_cmdlinepart()) { >> - ? ? ? ? ? ? ? static const char *probes[] = { "cmdlinepart", NULL }; >> - ? ? ? ? ? ? ? struct mtd_partition *parts; >> - ? ? ? ? ? ? ? int nr_parts; >> - >> - ? ? ? ? ? ? ? nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); >> - >> - ? ? ? ? ? ? ? if (nr_parts) >> - ? ? ? ? ? ? ? ? ? ? ? return add_mtd_partitions(mtd, parts, nr_parts); >> - ? ? ? } >> - >> ? ? ? ?return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); >> >> ?fail_free_irq: > > > -- > Sincerely yours, > Mike. > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > From adrian.wenl at gmail.com Mon May 24 04:36:13 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 16:36:13 +0800 Subject: [PATCH 07/20] mtd: pxa3xx_nand: mtd scan id process could be defined by driver itself In-Reply-To: <4BFA2A91.1080406@compulab.co.il> References: <4BFA2A91.1080406@compulab.co.il> Message-ID: On Mon, May 24, 2010 at 3:28 PM, Mike Rapoport wrote: > Haojian Zhuang wrote: >> >> From f2010885a9d5cebfd3cca63b59fff941502f78b3 Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Thu, 6 May 2010 09:48:30 +0800 >> Subject: [PATCH] mtd: pxa3xx_nand: mtd scan id process could be >> defined by driver itself >> >> Different NAND driver may require its unique detection. For pxa3xx_nand, >> it use its self id database to get the necessary info. >> >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?drivers/mtd/nand/pxa3xx_nand.c | ?257 >> +++++++++++++++++++++++++++++----------- >> ?1 files changed, 185 insertions(+), 72 deletions(-) >> >> diff --git a/drivers/mtd/nand/pxa3xx_nand.c >> b/drivers/mtd/nand/pxa3xx_nand.c >> index 854adad..7a8ff38 100644 >> --- a/drivers/mtd/nand/pxa3xx_nand.c >> +++ b/drivers/mtd/nand/pxa3xx_nand.c >> @@ -255,6 +255,8 @@ static struct pxa3xx_nand_flash __devinitdata >> builtin_flash_types[] = { >> ?{ 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, >> 60, 10, }, }, >> ?}; >> >> +static const char *mtd_names[] = {"pxa3xx_nand-0", NULL}; >> + >> ?#define NDTR0_tCH(c) ? (min((c), 7) << 19) >> ?#define NDTR0_tCS(c) ? (min((c), 7) << 16) >> ?#define NDTR0_tWH(c) ? (min((c), 7) << 11) >> @@ -893,37 +895,6 @@ static int pxa3xx_nand_detect_config(struct >> pxa3xx_nand_info *info) >> ? ? ? ?return 0; >> ?} >> >> -static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const struct pxa3xx_nand_platform_data >> *pdata) >> -{ >> - ? ? ? const struct pxa3xx_nand_flash *f; >> - ? ? ? uint32_t id = -1; >> - ? ? ? int i; >> - >> - ? ? ? if (pdata->keep_config) >> - ? ? ? ? ? ? ? if (pxa3xx_nand_detect_config(info) == 0) >> - ? ? ? ? ? ? ? ? ? ? ? return 0; > > NAK. You're breaking platforms that rely on this feature. > >> - ? ? ? f = &builtin_flash_types[0]; >> - ? ? ? pxa3xx_nand_config_flash(info, f); >> - ? ? ? pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); >> - ? ? ? id = *((uint16_t *)(info->data_buff)); >> - >> - ? ? ? for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { >> - ? ? ? ? ? ? ? f = &builtin_flash_types[i]; >> - ? ? ? ? ? ? ? if (f->chip_id == id) { >> - ? ? ? ? ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "detect chip id: >> 0x%x\n", id); >> - ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f); >> - ? ? ? ? ? ? ? ? ? ? ? return 0; >> - ? ? ? ? ? ? ? } >> - ? ? ? } >> - >> - ? ? ? dev_warn(&info->pdev->dev, >> - ? ? ? ? ? ? ? ? ? ? ? "failed to detect configured nand flash; found >> %04x instead of\n", >> - ? ? ? ? ? ? ? ?id); >> - ? ? ? return -ENODEV; >> -} >> - >> ?/* the maximum possible buffer size for large page with OOB data >> ?* is: 2048 + 64 = 2112 bytes, allocate a page here for both the >> ?* data buffer and the DMA descriptor >> @@ -980,41 +951,174 @@ static struct nand_ecclayout hw_largepage_ecclayout >> = { >> ? ? ? ?.oobfree = { {2, 38} } >> ?}; >> >> -static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, >> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?struct pxa3xx_nand_info *info) > > why are you removing the pxa3xx_nand_init_mtd? moving it's entire contents > into alloc_nand_resource would make the latter overgrown.... > >> +static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd, >> + ? ? ? ? ? ? ? struct nand_chip *chip, uint8_t *buf, int page) >> +{ >> + ? ? ? struct pxa3xx_nand_info *info = mtd->priv; >> + >> + ? ? ? chip->read_buf(mtd, buf, mtd->writesize); >> + ? ? ? chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); >> + >> + ? ? ? if (info->retcode == ERR_SBERR) { >> + ? ? ? ? ? ? ? switch (info->use_ecc) { >> + ? ? ? ? ? ? ? ? ? ? ? case 1: >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? mtd->ecc_stats.corrected ++; >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; >> + >> + ? ? ? ? ? ? ? ? ? ? ? case 0: >> + ? ? ? ? ? ? ? ? ? ? ? default: >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? break; >> + ? ? ? ? ? ? ? } >> + ? ? ? } >> + ? ? ? else if (info->retcode == ERR_DBERR) { >> + ? ? ? ? ? ? ? int buf_blank; >> + >> + ? ? ? ? ? ? ? buf_blank = is_buf_blank(buf, mtd->writesize); >> + ? ? ? ? ? ? ? if (!buf_blank) >> + ? ? ? ? ? ? ? ? ? ? ? mtd->ecc_stats.failed++; >> + ? ? ? } >> + >> + ? ? ? return 0; >> +} >> + >> +static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd, >> + ? ? ? ? ? ? ? struct nand_chip *chip, const uint8_t *buf) >> +{ >> + ? ? ? chip->write_buf(mtd, buf, mtd->writesize); >> + ? ? ? chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); >> +} >> + >> +static void pxa3xx_nand_erase_cmd(struct mtd_info *mtd, int page) >> ?{ >> - ? ? ? struct nand_chip *this = &info->nand_chip; >> - >> - ? ? ? this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? >> NAND_BUSWIDTH_16: 0; >> - >> - ? ? ? this->waitfunc ? ? ? ? ?= pxa3xx_nand_waitfunc; >> - ? ? ? this->select_chip ? ? ? = pxa3xx_nand_select_chip; >> - ? ? ? this->dev_ready ? ? ? ? = pxa3xx_nand_dev_ready; >> - ? ? ? this->cmdfunc ? ? ? ? ? = pxa3xx_nand_cmdfunc; >> - ? ? ? this->read_word ? ? ? ? = pxa3xx_nand_read_word; >> - ? ? ? this->read_byte ? ? ? ? = pxa3xx_nand_read_byte; >> - ? ? ? this->read_buf ? ? ? ? ?= pxa3xx_nand_read_buf; >> - ? ? ? this->write_buf ? ? ? ? = pxa3xx_nand_write_buf; >> - ? ? ? this->verify_buf ? ? ? ?= pxa3xx_nand_verify_buf; >> - >> - ? ? ? this->ecc.mode ? ? ? ? ?= NAND_ECC_HW; >> - ? ? ? this->ecc.hwctl ? ? ? ? = pxa3xx_nand_ecc_hwctl; >> - ? ? ? this->ecc.calculate ? ? = pxa3xx_nand_ecc_calculate; >> - ? ? ? this->ecc.correct ? ? ? = pxa3xx_nand_ecc_correct; >> - ? ? ? this->ecc.size ? ? ? ? ?= info->page_size; >> - >> - ? ? ? if (info->page_size == 2048) >> - ? ? ? ? ? ? ? this->ecc.layout = &hw_largepage_ecclayout; >> + ? ? ? struct nand_chip *chip = mtd->priv; >> + ? ? ? /* Send commands to erase a block */ >> + ? ? ? chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page); >> +} >> + >> +static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info) >> +{ >> + ? ? ? struct mtd_info *mtd = info->mtd; >> + ? ? ? struct nand_chip *chip = mtd->priv; >> + >> + ? ? ? /* use the common timing to make a try */ >> + ? ? ? pxa3xx_nand_config_flash(info, &builtin_flash_types[0]); >> + ? ? ? chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0); >> + ? ? ? if (info->state & STATE_READY) >> + ? ? ? ? ? ? ? return 1; >> ? ? ? ?else >> - ? ? ? ? ? ? ? this->ecc.layout = &hw_smallpage_ecclayout; >> + ? ? ? ? ? ? ? return 0; >> +} >> + >> +static int pxa3xx_nand_scan(struct mtd_info *mtd) >> +{ >> + ? ? ? struct pxa3xx_nand_info *info = mtd->priv; >> + ? ? ? struct pxa3xx_nand_flash *f; >> + ? ? ? struct nand_chip *chip = mtd->priv; >> + ? ? ? uint32_t id = -1; >> + ? ? ? int i, ret; >> >> - ? ? ? this->chip_delay = 25; >> + ? ? ? ret = pxa3xx_nand_sensing(info); >> + ? ? ? if (!ret) { >> + ? ? ? ? ? ? ? kfree(mtd); >> + ? ? ? ? ? ? ? info->mtd = NULL; >> + ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n"); >> + >> + ? ? ? ? ? ? ? return -EINVAL; >> + ? ? ? } >> + >> + ? ? ? chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0); >> + ? ? ? id = *((uint16_t *)(info->data_buff)); >> + ? ? ? if (id != 0) >> + ? ? ? ? ? ? ? printk(KERN_INFO "Detect a flash id %x\n", id); >> + ? ? ? else { >> + ? ? ? ? ? ? ? kfree(mtd); >> + ? ? ? ? ? ? ? info->mtd = NULL; >> + ? ? ? ? ? ? ? printk(KERN_WARNING "Read out ID 0, potential timing set >> wrong!!\n"); >> + >> + ? ? ? ? ? ? ? return -EINVAL; >> + ? ? ? } >> + >> + ? ? ? for (i = 1; i < ARRAY_SIZE(builtin_flash_types); i++) { >> + >> + ? ? ? ? ? ? ? f = &builtin_flash_types[i]; >> + >> + ? ? ? ? ? ? ? /* find the chip in default list */ >> + ? ? ? ? ? ? ? if (f->chip_id == id) { >> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_config_flash(info, f); >> + ? ? ? ? ? ? ? ? ? ? ? chip->cellinfo = info->data_buff[2]; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->writesize = f->page_size; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->writesize_shift = ffs(mtd->writesize) - 1; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->writesize_mask = (1 << mtd->writesize_shift) >> - 1; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->oobsize = mtd->writesize / 32; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->erasesize = f->page_size * f->page_per_block; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->erasesize_shift = ffs(mtd->erasesize) - 1; >> + ? ? ? ? ? ? ? ? ? ? ? mtd->erasesize_mask = (1 << mtd->erasesize_shift) >> - 1; >> + >> + ? ? ? ? ? ? ? ? ? ? ? mtd->name = mtd_names[0]; >> + ? ? ? ? ? ? ? ? ? ? ? break; >> + ? ? ? ? ? ? ? } >> + ? ? ? } >> + >> + ? ? ? if (i == ARRAY_SIZE(builtin_flash_types)) { >> + ? ? ? ? ? ? ? kfree(mtd); >> + ? ? ? ? ? ? ? info->mtd = NULL; >> + ? ? ? ? ? ? ? printk(KERN_ERR "ERROR!! flash not defined!!!\n"); >> + >> + ? ? ? ? ? ? ? return -EINVAL; >> + ? ? ? } >> + >> + ? ? ? chip->ecc.mode ? ? ? ? ?= NAND_ECC_HW; >> + ? ? ? chip->ecc.size ? ? ? ? ?= f->page_size; >> + ? ? ? if (f->page_size == 2048) >> + ? ? ? ? ? ? ? chip->ecc.layout = &hw_largepage_ecclayout; >> + ? ? ? else >> + ? ? ? ? ? ? ? chip->ecc.layout = &hw_smallpage_ecclayout; >> + >> + ? ? ? chip->chipsize ? ? ? ? ?= (uint64_t)f->num_blocks ? ? ? * \ >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? f->page_per_block ? ? ? ? ? ? * \ >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? f->page_size; >> + >> + ? ? ? chip->chip_shift ? ? ? ?= ffs(chip->chipsize) - 1; >> + ? ? ? mtd->size ? ? ? ? ? ? ? = chip->chipsize; >> + >> + ? ? ? /* Calculate the address shift from the page size */ >> + ? ? ? chip->page_shift = ffs(mtd->writesize) - 1; >> + ? ? ? chip->pagemask = mtd_div_by_ws(chip->chipsize, mtd) - 1; >> + ? ? ? chip->numchips ? ? ? ? ?= 1; >> + ? ? ? chip->chip_delay ? ? ? ?= 25; >> + ? ? ? chip->bbt_erase_shift = chip->phys_erase_shift = >> ffs(mtd->erasesize) - 1; >> + >> + ? ? ? /* Set the bad block position */ >> + ? ? ? chip->badblockpos = mtd->writesize > 512 ? >> + ? ? ? ? ? ? ? NAND_LARGE_BADBLOCK_POS : NAND_SMALL_BADBLOCK_POS; >> + >> + ? ? ? chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; >> + ? ? ? chip->options |= NAND_NO_AUTOINCR; >> + ? ? ? chip->options |= NAND_NO_READRDY; >> + ? ? ? chip->options |= NAND_USE_FLASH_BBT; >> + >> + ? ? ? return nand_scan_tail(mtd); >> +} >> + >> +static int pxa3xx_nand_default_block_markbad(struct mtd_info *mtd, loff_t >> ofs) >> +{ >> + ? ? ? struct nand_chip *chip = mtd->priv; >> + ? ? ? int block; >> + >> + ? ? ? block = (int)(ofs >> chip->bbt_erase_shift); >> + ? ? ? chip->bbt[block >> 2] |= 0x01 << ((block & 0x03) << 1); >> + ? ? ? return nand_update_bbt(mtd, ofs); >> +} >> + >> +static int pxa3xx_nand_block_bad(struct mtd_info *mtd, loff_t ofs, int >> getchip) >> +{ >> + ? ? ? return 0; >> ?} >> >> ?static int alloc_nand_resource(struct platform_device *pdev) >> ?{ >> - ? ? ? struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; >> ? ? ? ?struct pxa3xx_nand_info *info; >> + ? ? ? struct nand_chip *chip; >> ? ? ? ?struct mtd_info *mtd; >> ? ? ? ?struct resource *r; >> ? ? ? ?int ret, irq; >> @@ -1027,12 +1131,31 @@ static int alloc_nand_resource(struct >> platform_device *pdev) >> ? ? ? ?} >> >> ? ? ? ?info = (struct pxa3xx_nand_info *)(&mtd[1]); >> + ? ? ? chip = (struct nand_chip *)(&mtd[1]); >> ? ? ? ?info->pdev = pdev; >> - >> - ? ? ? mtd->priv = info; >> ? ? ? ?info->mtd = mtd; >> + ? ? ? mtd->priv = info; >> ? ? ? ?mtd->owner = THIS_MODULE; >> >> + ? ? ? chip->ecc.read_page ? ? = pxa3xx_nand_read_page_hwecc; >> + ? ? ? chip->ecc.write_page ? ?= pxa3xx_nand_write_page_hwecc; >> + ? ? ? chip->ecc.hwctl ? ? ? ? = pxa3xx_nand_ecc_hwctl; >> + ? ? ? chip->ecc.calculate ? ? = pxa3xx_nand_ecc_calculate; >> + ? ? ? chip->ecc.correct ? ? ? = pxa3xx_nand_ecc_correct; >> + ? ? ? chip->waitfunc ? ? ? ? ?= pxa3xx_nand_waitfunc; >> + ? ? ? chip->select_chip ? ? ? = pxa3xx_nand_select_chip; >> + ? ? ? chip->dev_ready ? ? ? ? = pxa3xx_nand_dev_ready; >> + ? ? ? chip->cmdfunc ? ? ? ? ? = pxa3xx_nand_cmdfunc; >> + ? ? ? chip->read_word ? ? ? ? = pxa3xx_nand_read_word; >> + ? ? ? chip->read_byte ? ? ? ? = pxa3xx_nand_read_byte; >> + ? ? ? chip->read_buf ? ? ? ? ?= pxa3xx_nand_read_buf; >> + ? ? ? chip->write_buf ? ? ? ? = pxa3xx_nand_write_buf; >> + ? ? ? chip->verify_buf ? ? ? ?= pxa3xx_nand_verify_buf; >> + ? ? ? chip->block_markbad ? ? = pxa3xx_nand_default_block_markbad; >> + ? ? ? chip->block_bad ? ? ? ? = pxa3xx_nand_block_bad; >> + ? ? ? chip->scan_bbt ? ? ? ? ?= nand_default_bbt; >> + ? ? ? chip->erase_cmd ? ? ? ? = pxa3xx_nand_erase_cmd; >> + > > this definitely has nothing to do with resource allocation. > This patch is just a code clean. In theory, alloc_nand_resource would not overgrow for from whole code aspect, the most complex part is in command handling. Also we need know the status of nand chip in two chip select. Only by this, than we can alloc proper resource. Thanks, Lei From adrian.wenl at gmail.com Mon May 24 04:41:03 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 16:41:03 +0800 Subject: [PATCH 03/20] mtd: pxa3xx_nand: remove the flash info in driver structure In-Reply-To: <4BFA2A02.2040605@compulab.co.il> References: <4BFA2A02.2040605@compulab.co.il> Message-ID: On Mon, May 24, 2010 at 3:25 PM, Mike Rapoport wrote: > Haojian Zhuang wrote: >> >> From dd45d508745edb24e9e4129077e9f5bd20415a23 Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Mon, 22 Mar 2010 10:33:49 +0800 >> Subject: [PATCH] mtd: pxa3xx_nand: remove the flash info in driver >> structure >> >> After probe, all info already transfer to driver structure. >> There is no need to keep the original flash info. >> So that we could safely free the flash info in memory, which may grows >> larger when more flash is suported. >> >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?drivers/mtd/nand/pxa3xx_nand.c | ? 70 >> ++++++++++++++++++++++++++-------------- >> ?1 files changed, 46 insertions(+), 24 deletions(-) >> >> diff --git a/drivers/mtd/nand/pxa3xx_nand.c >> b/drivers/mtd/nand/pxa3xx_nand.c >> index 5658398..2dfe6d9 100644 >> --- a/drivers/mtd/nand/pxa3xx_nand.c >> +++ b/drivers/mtd/nand/pxa3xx_nand.c >> @@ -152,7 +152,6 @@ struct pxa3xx_nand_info { >> ? ? ? ?struct nand_chip ? ? ? ?nand_chip; >> >> ? ? ? ?struct platform_device ? *pdev; >> - ? ? ? const struct pxa3xx_nand_flash *flash_info; >> >> ? ? ? ?struct clk ? ? ? ? ? ? ?*clk; >> ? ? ? ?void __iomem ? ? ? ? ? ?*mmio_base; >> @@ -166,6 +165,7 @@ struct pxa3xx_nand_info { >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_cmd; >> >> ? ? ? ?unsigned char ? ? ? ? ? *data_buff; >> + ? ? ? unsigned char ? ? ? ? ? *oob_buff; >> ? ? ? ?dma_addr_t ? ? ? ? ? ? ?data_buff_phys; >> ? ? ? ?size_t ? ? ? ? ? ? ? ? ?data_buff_size; >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? data_dma_ch; >> @@ -184,7 +184,8 @@ struct pxa3xx_nand_info { >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_ecc; ? ? ? ?/* use HW ECC ? */ >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_dma; ? ? ? ?/* use DMA ? */ >> >> - ? ? ? size_t ? ? ? ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */ >> + ? ? ? unsigned int ? ? ? ? ? ?page_size; ? ? ?/* page size of attached >> chip */ >> + ? ? ? unsigned int ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */ >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? retcode; >> ? ? ? ?struct completion ? ? ? cmd_complete; >> >> @@ -193,6 +194,10 @@ struct pxa3xx_nand_info { >> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?ndcb1; >> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?ndcb2; >> >> + ? ? ? /* timing calcuted from setting */ >> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr0cs0; >> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr1cs0; >> + >> ? ? ? ?/* calculated from pxa3xx_nand_flash data */ >> ? ? ? ?size_t ? ? ? ? ?oob_size; >> ? ? ? ?size_t ? ? ? ? ?read_id_bytes; >> @@ -287,6 +292,8 @@ static void pxa3xx_nand_set_timing(struct >> pxa3xx_nand_info *info, >> ? ? ? ? ? ? ? ?NDTR1_tWHR(ns2cycle(t->tWHR, nand_clk)) | >> ? ? ? ? ? ? ? ?NDTR1_tAR(ns2cycle(t->tAR, nand_clk)); >> >> + ? ? ? info->ndtr0cs0 = ndtr0; >> + ? ? ? info->ndtr1cs0 = ndtr1; >> ? ? ? ?nand_writel(info, NDTR0CS0, ndtr0); >> ? ? ? ?nand_writel(info, NDTR1CS0, ndtr1); >> ?} >> @@ -310,22 +317,29 @@ static int wait_for_event(struct >> pxa3xx_nand_info *info, uint32_t event) >> ? ? ? ?return -ETIMEDOUT; >> ?} >> >> -static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, >> - ? ? ? ? ? ? ? ? ? ? ? uint16_t cmd, int column, int page_addr) >> +static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) >> ?{ >> - ? ? ? const struct pxa3xx_nand_flash *f = info->flash_info; >> + ? ? ? int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; >> >> - ? ? ? /* calculate data size */ >> - ? ? ? switch (f->page_size) { >> - ? ? ? case 2048: >> - ? ? ? ? ? ? ? info->data_size = (info->use_ecc) ? 2088 : 2112; >> - ? ? ? ? ? ? ? break; >> - ? ? ? case 512: >> - ? ? ? ? ? ? ? info->data_size = (info->use_ecc) ? 520 : 528; >> - ? ? ? ? ? ? ? break; >> - ? ? ? default: >> - ? ? ? ? ? ? ? return -EINVAL; >> + ? ? ? info->data_size = info->page_size; >> + ? ? ? if (!oob_enable) { >> + ? ? ? ? ? ? ? info->oob_size = 0; >> + ? ? ? ? ? ? ? return; >> ? ? ? ?} >> + ? ? ? switch (info->page_size) { >> + ? ? ? ? ? ? ? case 2048: >> + ? ? ? ? ? ? ? ? ? ? ? info->oob_size = (info->use_ecc) ? 40 : 64; >> + ? ? ? ? ? ? ? ? ? ? ? break; >> + ? ? ? ? ? ? ? case 512: >> + ? ? ? ? ? ? ? ? ? ? ? info->oob_size = (info->use_ecc) ? 8 : 16; >> + ? ? ? ? ? ? ? ? ? ? ? break; >> + ? ? ? } > > The OOB-related changes do not seem related to the $SUBJ. > >> +} >> + >> +static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, >> + ? ? ? ? ? ? ? uint16_t cmd, int column, int page_addr) >> +{ >> + ? ? ? pxa3xx_set_datasize(info); >> >> ? ? ? ?/* generate values for NDCBx registers */ >> ? ? ? ?info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); >> @@ -436,6 +450,9 @@ static int handle_data_pio(struct pxa3xx_nand_info >> *info) >> ? ? ? ?case STATE_PIO_WRITING: >> ? ? ? ? ? ? ? ?__raw_writesl(info->mmio_base + NDDB, info->data_buff, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->data_size, 4)); >> + ? ? ? ? ? ? ? if (info->oob_size > 0) >> + ? ? ? ? ? ? ? ? ? ? ? __raw_writesl(info->mmio_base + NDDB, >> info->oob_buff, >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(info->oob_size, 4)); > > The same here. > >> ? ? ? ? ? ? ? ?enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); >> >> @@ -448,6 +465,10 @@ static int handle_data_pio(struct pxa3xx_nand_info >> *info) >> ? ? ? ?case STATE_PIO_READING: >> ? ? ? ? ? ? ? ?__raw_readsl(info->mmio_base + NDDB, info->data_buff, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->data_size, 4)); >> + ? ? ? ? ? ? ? if (info->oob_size > 0) >> + ? ? ? ? ? ? ? ? ? ? ? __raw_readsl(info->mmio_base + NDDB, >> info->oob_buff, >> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(info->oob_size, 4)); >> + > > Ditto. > >> ? ? ? ? ? ? ? ?break; >> ? ? ? ?default: >> ? ? ? ? ? ? ? ?printk(KERN_ERR "%s: invalid state %d\n", __func__, >> @@ -462,7 +483,7 @@ static int handle_data_pio(struct pxa3xx_nand_info >> *info) >> ?static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) >> ?{ >> ? ? ? ?struct pxa_dma_desc *desc = info->data_desc; >> - ? ? ? int dma_len = ALIGN(info->data_size, 32); >> + ? ? ? int dma_len = ALIGN(info->data_size + info->oob_size, 32); > > ditto > >> ? ? ? ?desc->ddadr = DDADR_STOP; >> ? ? ? ?desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len; >> @@ -857,6 +878,8 @@ static int pxa3xx_nand_config_flash(struct >> pxa3xx_nand_info *info, >> ? ? ? ?uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ >> >> ? ? ? ?/* calculate flash information */ >> + ? ? ? info->page_size = f->page_size; >> + ? ? ? info->oob_buff = info->data_buff + f->page_size; > > And here as well > >> ? ? ? ?info->oob_size = (f->page_size == 2048) ? 64 : 16; >> ? ? ? ?info->read_id_bytes = (f->page_size == 2048) ? 4 : 2; >> >> @@ -881,7 +904,6 @@ static int pxa3xx_nand_config_flash(struct >> pxa3xx_nand_info *info, >> ? ? ? ?info->reg_ndcr = ndcr; >> >> ? ? ? ?pxa3xx_nand_set_timing(info, &f->timing); >> - ? ? ? info->flash_info = f; >> ? ? ? ?return 0; >> ?} >> >> @@ -917,7 +939,6 @@ static int pxa3xx_nand_detect_config(struct >> pxa3xx_nand_info *info) >> ? ? ? ?default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; >> >> ? ? ? ?/* set info fields needed to __readid */ >> - ? ? ? info->flash_info = &default_flash; >> ? ? ? ?info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; >> ? ? ? ?info->reg_ndcr = ndcr; >> >> @@ -1047,10 +1068,9 @@ static struct nand_ecclayout hw_largepage_ecclayout >> = { >> ?static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, >> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct pxa3xx_nand_info *info) >> ?{ >> - ? ? ? const struct pxa3xx_nand_flash *f = info->flash_info; >> ? ? ? ?struct nand_chip *this = &info->nand_chip; >> >> - ? ? ? this->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16: 0; >> + ? ? ? this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? >> NAND_BUSWIDTH_16: 0; >> >> ? ? ? ?this->waitfunc ? ? ? ? ?= pxa3xx_nand_waitfunc; >> ? ? ? ?this->select_chip ? ? ? = pxa3xx_nand_select_chip; >> @@ -1066,9 +1086,9 @@ static void pxa3xx_nand_init_mtd(struct mtd_info >> *mtd, >> ? ? ? ?this->ecc.hwctl ? ? ? ? = pxa3xx_nand_ecc_hwctl; >> ? ? ? ?this->ecc.calculate ? ? = pxa3xx_nand_ecc_calculate; >> ? ? ? ?this->ecc.correct ? ? ? = pxa3xx_nand_ecc_correct; >> - ? ? ? this->ecc.size ? ? ? ? ?= f->page_size; >> + ? ? ? this->ecc.size ? ? ? ? ?= info->page_size; >> >> - ? ? ? if (f->page_size == 2048) >> + ? ? ? if (info->page_size == 2048) >> ? ? ? ? ? ? ? ?this->ecc.layout = &hw_largepage_ecclayout; >> ? ? ? ?else >> ? ? ? ? ? ? ? ?this->ecc.layout = &hw_smallpage_ecclayout; >> @@ -1076,7 +1096,7 @@ static void pxa3xx_nand_init_mtd(struct mtd_info >> *mtd, >> ? ? ? ?this->chip_delay = 25; >> ?} >> >> -static int pxa3xx_nand_probe(struct platform_device *pdev) >> +static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) >> ?{ >> ? ? ? ?struct pxa3xx_nand_platform_data *pdata; >> ? ? ? ?struct pxa3xx_nand_info *info; >> @@ -1264,9 +1284,11 @@ static int pxa3xx_nand_resume(struct >> platform_device *pdev) >> ? ? ? ?struct mtd_info *mtd = (struct mtd_info >> *)platform_get_drvdata(pdev); >> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv; >> >> + ? ? ? nand_writel(info, NDTR0CS0, info->ndtr0cs0); >> + ? ? ? nand_writel(info, NDTR1CS0, info->ndtr1cs0); >> ? ? ? ?clk_enable(info->clk); >> >> - ? ? ? return pxa3xx_nand_config_flash(info, info->flash_info); >> + ? ? ? return 0; >> ?} >> ?#else >> ?#define pxa3xx_nand_suspend ? ?NULL > > > -- > Sincerely yours, > Mike. For this patch set change the original c file greatly, more than half of original code is changed, I cannot create a patch for each change. (If so, this patch set would grow to be a very large one. Maybe 30+?) So some of code change is not exactly follow the patch subject... Best regards, Lei From adrian.wenl at gmail.com Mon May 24 04:43:18 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 16:43:18 +0800 Subject: [PATCH 04/20] mtd: pxa3xx_nand: make scan procedure more clear In-Reply-To: <4BFA29FE.9020001@compulab.co.il> References: <4BFA29FE.9020001@compulab.co.il> Message-ID: On Mon, May 24, 2010 at 3:25 PM, Mike Rapoport wrote: > Haojian Zhuang wrote: >> >> From 3c64457df23b222c7f53b7d8f0601606b95b1ad6 Mon Sep 17 00:00:00 2001 >> From: Lei Wen >> Date: Mon, 22 Mar 2010 10:35:49 +0800 >> Subject: [PATCH] mtd: pxa3xx_nand: make scan procedure more clear > > The changes below are related mostly to _probe reorganization than to > nand scan... > > >> Signed-off-by: Lei Wen >> Signed-off-by: Haojian Zhuang >> --- >> ?drivers/mtd/nand/pxa3xx_nand.c | ? 66 >> +++++++++++++++++++++++---------------- >> ?1 files changed, 39 insertions(+), 27 deletions(-) >> >> diff --git a/drivers/mtd/nand/pxa3xx_nand.c >> b/drivers/mtd/nand/pxa3xx_nand.c >> index 2dfe6d9..0ef9bf9 100644 >> --- a/drivers/mtd/nand/pxa3xx_nand.c >> +++ b/drivers/mtd/nand/pxa3xx_nand.c >> @@ -160,6 +160,7 @@ struct pxa3xx_nand_info { >> ? ? ? ?unsigned int ? ? ? ? ? ?buf_start; >> ? ? ? ?unsigned int ? ? ? ? ? ?buf_count; >> >> + ? ? ? struct mtd_info ? ? ? ? *mtd; >> ? ? ? ?/* DMA information */ >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_dat; >> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_cmd; >> @@ -1096,21 +1097,13 @@ static void pxa3xx_nand_init_mtd(struct mtd_info >> *mtd, >> ? ? ? ?this->chip_delay = 25; >> ?} >> >> -static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) >> +static int alloc_nand_resource(struct platform_device *pdev) >> ?{ >> - ? ? ? struct pxa3xx_nand_platform_data *pdata; >> + ? ? ? struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; >> ? ? ? ?struct pxa3xx_nand_info *info; >> - ? ? ? struct nand_chip *this; >> ? ? ? ?struct mtd_info *mtd; >> ? ? ? ?struct resource *r; >> - ? ? ? int ret = 0, irq; >> - >> - ? ? ? pdata = pdev->dev.platform_data; >> - >> - ? ? ? if (!pdata) { >> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "no platform data defined\n"); >> - ? ? ? ? ? ? ? return -ENODEV; >> - ? ? ? } >> + ? ? ? int ret, irq; >> >> ? ? ? ?mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct >> pxa3xx_nand_info), >> ? ? ? ? ? ? ? ? ? ? ? ?GFP_KERNEL); >> @@ -1122,8 +1115,8 @@ static int __devinit pxa3xx_nand_probe(struct >> platform_device *pdev) >> ? ? ? ?info = (struct pxa3xx_nand_info *)(&mtd[1]); >> ? ? ? ?info->pdev = pdev; >> >> - ? ? ? this = &info->nand_chip; >> ? ? ? ?mtd->priv = info; >> + ? ? ? info->mtd = mtd; >> ? ? ? ?mtd->owner = THIS_MODULE; >> >> ? ? ? ?info->clk = clk_get(&pdev->dev, NULL); >> @@ -1201,16 +1194,9 @@ static int __devinit pxa3xx_nand_probe(struct >> platform_device *pdev) >> ? ? ? ?} >> >> ? ? ? ?pxa3xx_nand_init_mtd(mtd, info); > > This, and the pxa3xx_nand_detect_flash call not shown in the patch does > not really belong to resource allocation. I'd move it back to the _probe > method. > >> + ? ? ? platform_set_drvdata(pdev, info); >> >> - ? ? ? platform_set_drvdata(pdev, mtd); >> - >> - ? ? ? if (nand_scan(mtd, 1)) { >> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n"); >> - ? ? ? ? ? ? ? ret = -ENXIO; >> - ? ? ? ? ? ? ? goto fail_free_irq; >> - ? ? ? } >> - >> - ? ? ? return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); >> + ? ? ? return 0; >> >> ?fail_free_irq: >> ? ? ? ?free_irq(irq, info); >> @@ -1235,8 +1221,8 @@ fail_free_mtd: >> >> ?static int pxa3xx_nand_remove(struct platform_device *pdev) >> ?{ >> - ? ? ? struct mtd_info *mtd = platform_get_drvdata(pdev); >> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv; >> + ? ? ? struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); >> + ? ? ? struct mtd_info *mtd = info->mtd; >> ? ? ? ?struct resource *r; >> ? ? ? ?int irq; >> >> @@ -1265,11 +1251,37 @@ static int pxa3xx_nand_remove(struct >> platform_device *pdev) >> ? ? ? ?return 0; >> ?} >> >> +static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) >> +{ >> + ? ? ? struct pxa3xx_nand_platform_data *pdata; >> + ? ? ? struct pxa3xx_nand_info *info; >> + ? ? ? int ret; >> + >> + ? ? ? pdata = pdev->dev.platform_data; >> + ? ? ? if (!pdata) { >> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "no platform data defined\n"); >> + ? ? ? ? ? ? ? return -ENODEV; >> + ? ? ? } >> + >> + ? ? ? ret = alloc_nand_resource(pdev); >> + ? ? ? if (ret) >> + ? ? ? ? ? ? ? return ret; >> + >> + ? ? ? info = platform_get_drvdata(pdev); >> + ? ? ? if (nand_scan(info->mtd, 1)) { >> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n"); >> + ? ? ? ? ? ? ? pxa3xx_nand_remove(pdev); >> + ? ? ? ? ? ? ? return -ENODEV; >> + ? ? ? } >> + >> + ? ? ? return add_mtd_partitions(info->mtd, pdata->parts, >> pdata->nr_parts); >> +} >> + >> ?#ifdef CONFIG_PM >> ?static int pxa3xx_nand_suspend(struct platform_device *pdev, >> pm_message_t state) >> ?{ >> - ? ? ? struct mtd_info *mtd = (struct mtd_info >> *)platform_get_drvdata(pdev); >> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv; >> + ? ? ? struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); >> + ? ? ? struct mtd_info *mtd = info->mtd; >> >> ? ? ? ?if (info->state != STATE_READY) { >> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "driver busy, state = %d\n", >> info->state); >> @@ -1281,8 +1293,8 @@ static int pxa3xx_nand_suspend(struct >> platform_device *pdev, pm_message_t state) >> >> ?static int pxa3xx_nand_resume(struct platform_device *pdev) >> ?{ >> - ? ? ? struct mtd_info *mtd = (struct mtd_info >> *)platform_get_drvdata(pdev); >> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv; >> + ? ? ? struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); >> + ? ? ? struct mtd_info *mtd = info->mtd; >> >> ? ? ? ?nand_writel(info, NDTR0CS0, info->ndtr0cs0); >> ? ? ? ?nand_writel(info, NDTR1CS0, info->ndtr1cs0); > > > -- > Sincerely yours, > Mike. > > Like I said in last mail, the resource allocation need to be done with the judgement of the status of nand chip in both chip select. Current our nand driver support two chip select, not the only one in the past, so the code logic is also changed. Thanks, Lei From dwmw2 at infradead.org Mon May 24 05:45:05 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Mon, 24 May 2010 10:45:05 +0100 Subject: [PATCH 03/20] mtd: pxa3xx_nand: remove the flash info in driver structure In-Reply-To: References: <4BFA2A02.2040605@compulab.co.il> Message-ID: <1274694305.20576.2854.camel@macbook.infradead.org> On Mon, 2010-05-24 at 09:41 +0100, Lei Wen wrote: > For this patch set change the original c file greatly, more than half > of original code is changed, > I cannot create a patch for each change. (If so, this patch set would > grow to be a very large one. Maybe 30+?) Yes you can -- large patch sets are fine. If email becomes cumbersome, feel free to just publish it as a git tree. Once Mike approves I can pull from it. Let me have a SSH public key if you want to be able to publish a git tree on git.infradead.org. -- David Woodhouse Open Source Technology Centre David.Woodhouse at intel.com Intel Corporation From pazdnikov at prosoft.ural.ru Mon May 24 05:50:48 2010 From: pazdnikov at prosoft.ural.ru (Alexander Pazdnikov) Date: Mon, 24 May 2010 15:50:48 +0600 Subject: ubifs became broken on contigous power-fails In-Reply-To: <1274689080.22999.43.camel@localhost> References: <201005241249.28629.pazdnikov@prosoft.ural.ru> <1274689080.22999.43.camel@localhost> Message-ID: <201005241550.48074.pazdnikov@prosoft.ural.ru> > Could you enable debugging messages when mounging it after power cuts? > The messages generate a lot of noise, so you need to disable them before > starting the real test. The idea is to get UBIFS debugging messages when > errors occur. Sorry, I've hurried up, and after applying your pathes reflash all of the devices with new firmware. But I'll setup some devices with all firmware to catch this issue again. > I never had time to really dig this and fix. Would be nice if you could > do this because I will unlikely have time in the nearest future, but I > can help you. Thank you, I'll continue testings and can supply with debug information. > One think you can do is to make sure you do not fill UBIFS completely, > then you will avoid hitting these budgeting bugs, also known as ENOSPC > issues (I think btrfs uses this terminology). In the issue above there is 11% used space and 89% free space. I've got this issue only when mounting fs in RO and then remounting it in RW. -- Best regards, Sasha From dedekind1 at gmail.com Mon May 24 05:56:31 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 24 May 2010 12:56:31 +0300 Subject: ubifs became broken on contigous power-fails In-Reply-To: <201005241550.48074.pazdnikov@prosoft.ural.ru> References: <201005241249.28629.pazdnikov@prosoft.ural.ru> <1274689080.22999.43.camel@localhost> <201005241550.48074.pazdnikov@prosoft.ural.ru> Message-ID: <1274694991.22999.52.camel@localhost> On Mon, 2010-05-24 at 15:50 +0600, Alexander Pazdnikov wrote: > > Could you enable debugging messages when mounging it after power cuts? > > The messages generate a lot of noise, so you need to disable them before > > starting the real test. The idea is to get UBIFS debugging messages when > > errors occur. > Sorry, I've hurried up, and after applying your pathes reflash all of the > devices with new firmware. > But I'll setup some devices with all firmware to catch this issue again. > > > I never had time to really dig this and fix. Would be nice if you could > > do this because I will unlikely have time in the nearest future, but I > > can help you. > Thank you, I'll continue testings and can supply with debug information. > > > One think you can do is to make sure you do not fill UBIFS completely, > > then you will avoid hitting these budgeting bugs, also known as ENOSPC > > issues (I think btrfs uses this terminology). > In the issue above there is 11% used space and 89% free space. > I've got this issue only when mounting fs in RO and then remounting it in RW. OK. Try my patch. Also, it is worth running your tests with UBIFS extra self checks enabled. -- Best Regards, Artem Bityutskiy (????? ????????) From mike at compulab.co.il Mon May 24 07:00:40 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 14:00:40 +0300 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> Message-ID: <4BFA5C58.7050109@compulab.co.il> Hi Lei, Lei Wen wrote: > Hi Mike, > > This patch set is applied to mtd-2.6 git. We submit the patch with a > package in attachment already. > http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 After applying the patch set I've reviewed the entire pxa3xx-nand as a whole and there are several major points I don't like: 1) Two chip selects support is not robust enough. You allocate a lot of resources for both chip selects, although not necessarily both have NAND chip connected 2) I don't like hadrcoding of NAND parameters into the driver. You remove *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and instead you enforce use of built-in definitions. The driver in its current state is robust enough to allow platforms to define optimized NAND timings either in the bootloader or in the kernel. If you don't like that multiple platforms define the same flash chip create an enumeration of built-in types and let platforms to use this enumeration to select the NAND chip. But, anyway, there should be a fallback mode that will support NAND chips that are not defined in the driver, probably with suboptimal timings. 3) The functions prepare_command_pool and alloc_nand_resource seem overgrown too me. Consolidation of prepare_*_cmd into one huge function does not seem right. And mixing between resource allocation and mtd struct initialization does not seem right either. > Best regards, > Lei > > On Mon, May 24, 2010 at 3:31 PM, Mike Rapoport wrote: >> Hi Haojian, >> This is a comment to the entire series, and should have been Re: [PATCH >> 0/20], but there's no cover letter for these patches. >> >> The patches are all line-wrapped and do not apply. It's really hard to read >> them because of hunks added inside the existing functions. Please try to >> organize your changes in a more straight forward way. >> >> Haojian Zhuang wrote: >>> From 16057e690aa4a2fd8a9c07c70ab48ffc2f76204f Mon Sep 17 00:00:00 2001 >>> From: Lei Wen >>> Date: Sat, 20 Mar 2010 19:01:23 +0800 >>> Subject: [PATCH] mtd: pxa3xx_nand: refuse the flash definition get from >>> platform >>> >>> For current usage, it is little reason to use a platform defined flash >>> info >>> for the flash detection. Flash timing through platform should be the same. >>> And allow multiple platform to define the same flash chip would be a >>> waste. >>> >>> Also condense the flash definition way in the c file to simplify adding a >>> new chip. >>> >>> Signed-off-by: Lei Wen >>> Signed-off-by: Haojian Zhuang >>> --- >>> arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | 40 ---- >>> drivers/mtd/nand/Kconfig | 7 - >>> drivers/mtd/nand/pxa3xx_nand.c | 262 >>> ++++++-------------------- >>> 3 files changed, 60 insertions(+), 249 deletions(-) >>> >>> diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >>> b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >>> index 3478eae..c494f68 100644 >>> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >>> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h >>> @@ -4,43 +4,6 @@ >>> #include >>> #include >>> >>> -struct pxa3xx_nand_timing { >>> - unsigned int tCH; /* Enable signal hold time */ >>> - unsigned int tCS; /* Enable signal setup time */ >>> - unsigned int tWH; /* ND_nWE high duration */ >>> - unsigned int tWP; /* ND_nWE pulse time */ >>> - unsigned int tRH; /* ND_nRE high duration */ >>> - unsigned int tRP; /* ND_nRE pulse width */ >>> - unsigned int tR; /* ND_nWE high to ND_nRE low for read */ >>> - unsigned int tWHR; /* ND_nWE high to ND_nRE low for status read >>> */ >>> - unsigned int tAR; /* ND_ALE low to ND_nRE low delay */ >>> -}; >>> - >>> -struct pxa3xx_nand_cmdset { >>> - uint16_t read1; >>> - uint16_t read2; >>> - uint16_t program; >>> - uint16_t read_status; >>> - uint16_t read_id; >>> - uint16_t erase; >>> - uint16_t reset; >>> - uint16_t lock; >>> - uint16_t unlock; >>> - uint16_t lock_status; >>> -}; >>> - >>> -struct pxa3xx_nand_flash { >>> - const struct pxa3xx_nand_timing *timing; /* NAND Flash timing */ >>> - const struct pxa3xx_nand_cmdset *cmdset; >>> - >>> - uint32_t page_per_block;/* Pages per block (PG_PER_BLK) */ >>> - uint32_t page_size; /* Page size in bytes (PAGE_SZ) */ >>> - uint32_t flash_width; /* Width of Flash memory (DWIDTH_M) */ >>> - uint32_t dfc_width; /* Width of flash controller(DWIDTH_C) */ >>> - uint32_t num_blocks; /* Number of physical blocks in Flash */ >>> - uint32_t chip_id; >>> -}; >>> - >>> struct pxa3xx_nand_platform_data { >>> >>> /* the data flash bus is shared between the Static Memory >>> @@ -54,9 +17,6 @@ struct pxa3xx_nand_platform_data { >>> >>> const struct mtd_partition *parts; >>> unsigned int nr_parts; >>> - >>> - const struct pxa3xx_nand_flash * flash; >>> - size_t num_flash; >>> }; >>> >>> extern void pxa3xx_set_nand_info(struct pxa3xx_nand_platform_data *info); >>> diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig >>> index 98a04b3..9a35d92 100644 >>> --- a/drivers/mtd/nand/Kconfig >>> +++ b/drivers/mtd/nand/Kconfig >>> @@ -399,13 +399,6 @@ config MTD_NAND_PXA3xx >>> This enables the driver for the NAND flash device found on >>> PXA3xx processors >>> >>> -config MTD_NAND_PXA3xx_BUILTIN >>> - bool "Use builtin definitions for some NAND chips (deprecated)" >>> - depends on MTD_NAND_PXA3xx >>> - help >>> - This enables builtin definitions for some NAND chips. This >>> - is deprecated in favor of platform specific data. >>> - >>> config MTD_NAND_CM_X270 >>> tristate "Support for NAND Flash on CM-X270 modules" >>> depends on MTD_NAND && MACH_ARMCORE >>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c >>> b/drivers/mtd/nand/pxa3xx_nand.c >>> index e02fa4f..da40b9a 100644 >>> --- a/drivers/mtd/nand/pxa3xx_nand.c >>> +++ b/drivers/mtd/nand/pxa3xx_nand.c >>> @@ -113,6 +113,41 @@ enum { >>> STATE_PIO_WRITING, >>> }; >>> >>> +struct pxa3xx_nand_timing { >>> + uint32_t tCH; /* Enable signal hold time */ >>> + uint32_t tCS; /* Enable signal setup time */ >>> + uint32_t tWH; /* ND_nWE high duration */ >>> + uint32_t tWP; /* ND_nWE pulse time */ >>> + uint32_t tRH; /* ND_nRE high duration */ >>> + uint32_t tRP; /* ND_nRE pulse width */ >>> + uint32_t tAR; /* ND_ALE low to ND_nRE low delay */ >>> + uint32_t tWHR; /* ND_nWE high to ND_nRE low for status read >>> */ >>> + uint32_t tR; /* ND_nWE high to ND_nRE low for read */ >>> +}; >>> + >>> +struct pxa3xx_nand_cmdset { >>> + uint16_t read1; >>> + uint16_t read2; >>> + uint16_t program; >>> + uint16_t read_status; >>> + uint16_t read_id; >>> + uint16_t erase; >>> + uint16_t reset; >>> + uint16_t lock; >>> + uint16_t unlock; >>> + uint16_t lock_status; >>> +}; >>> + >>> +struct pxa3xx_nand_flash { >>> + uint32_t chip_id; >>> + uint16_t page_per_block; /* Pages per block (PG_PER_BLK) */ >>> + uint16_t page_size; /* Page size in bytes (PAGE_SZ) */ >>> + uint8_t flash_width; /* Width of Flash memory >>> (DWIDTH_M) */ >>> + uint8_t dfc_width; /* Width of flash >>> controller(DWIDTH_C) */ >>> + uint32_t num_blocks; /* Number of physical blocks in >>> Flash */ >>> + struct pxa3xx_nand_timing timing; /* NAND Flash timing */ >>> +}; >>> + >>> struct pxa3xx_nand_info { >>> struct nand_chip nand_chip; >>> >>> @@ -177,20 +212,7 @@ MODULE_PARM_DESC(use_dma, "enable DMA for data >>> transfering to/from NAND HW"); >>> static struct pxa3xx_nand_timing default_timing; >>> static struct pxa3xx_nand_flash default_flash; >>> >>> -static struct pxa3xx_nand_cmdset smallpage_cmdset = { >>> - .read1 = 0x0000, >>> - .read2 = 0x0050, >>> - .program = 0x1080, >>> - .read_status = 0x0070, >>> - .read_id = 0x0090, >>> - .erase = 0xD060, >>> - .reset = 0x00FF, >>> - .lock = 0x002A, >>> - .unlock = 0x2423, >>> - .lock_status = 0x007A, >>> -}; >>> - >>> -static struct pxa3xx_nand_cmdset largepage_cmdset = { >>> +const static struct pxa3xx_nand_cmdset cmdset = { >>> .read1 = 0x3000, >>> .read2 = 0x0050, >>> .program = 0x1080, >>> @@ -203,143 +225,17 @@ static struct pxa3xx_nand_cmdset largepage_cmdset = >>> { >>> .lock_status = 0x007A, >>> }; >>> >>> -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN >>> -static struct pxa3xx_nand_timing samsung512MbX16_timing = { >>> - .tCH = 10, >>> - .tCS = 0, >>> - .tWH = 20, >>> - .tWP = 40, >>> - .tRH = 30, >>> - .tRP = 40, >>> - .tR = 11123, >>> - .tWHR = 110, >>> - .tAR = 10, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash samsung512MbX16 = { >>> - .timing = &samsung512MbX16_timing, >>> - .cmdset = &smallpage_cmdset, >>> - .page_per_block = 32, >>> - .page_size = 512, >>> - .flash_width = 16, >>> - .dfc_width = 16, >>> - .num_blocks = 4096, >>> - .chip_id = 0x46ec, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash samsung2GbX8 = { >>> - .timing = &samsung512MbX16_timing, >>> - .cmdset = &smallpage_cmdset, >>> - .page_per_block = 64, >>> - .page_size = 2048, >>> - .flash_width = 8, >>> - .dfc_width = 8, >>> - .num_blocks = 2048, >>> - .chip_id = 0xdaec, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash samsung32GbX8 = { >>> - .timing = &samsung512MbX16_timing, >>> - .cmdset = &smallpage_cmdset, >>> - .page_per_block = 128, >>> - .page_size = 4096, >>> - .flash_width = 8, >>> - .dfc_width = 8, >>> - .num_blocks = 8192, >>> - .chip_id = 0xd7ec, >>> +static struct pxa3xx_nand_flash __devinitdata builtin_flash_types[] = { >>> +{ 0x46ec, 32, 512, 16, 16, 4096, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >>> }, }, >>> +{ 0xdaec, 64, 2048, 8, 8, 2048, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >>> }, }, >>> +{ 0xd7ec, 128, 4096, 8, 8, 8192, { 10, 0, 20, 40, 30, 40, 11123, 110, 10, >>> }, }, >>> +{ 0xa12c, 64, 2048, 8, 8, 1024, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, >>> }, }, >>> +{ 0xb12c, 64, 2048, 16, 16, 1024, { 10, 25, 15, 25, 15, 30, 25000, >>> 60, 10, }, }, >>> +{ 0xdc2c, 64, 2048, 8, 8, 4096, { 10, 25, 15, 25, 15, 30, 25000, 60, 10, >>> }, }, >>> +{ 0xcc2c, 64, 2048, 16, 16, 4096, { 10, 25, 15, 25, 15, 30, 25000, >>> 60, 10, }, }, >>> +{ 0xba20, 64, 2048, 16, 16, 2048, { 10, 35, 15, 25, 15, 25, 25000, >>> 60, 10, }, }, >>> }; >>> >>> -static struct pxa3xx_nand_timing micron_timing = { >>> - .tCH = 10, >>> - .tCS = 25, >>> - .tWH = 15, >>> - .tWP = 25, >>> - .tRH = 15, >>> - .tRP = 30, >>> - .tR = 25000, >>> - .tWHR = 60, >>> - .tAR = 10, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash micron1GbX8 = { >>> - .timing = µn_timing, >>> - .cmdset = &largepage_cmdset, >>> - .page_per_block = 64, >>> - .page_size = 2048, >>> - .flash_width = 8, >>> - .dfc_width = 8, >>> - .num_blocks = 1024, >>> - .chip_id = 0xa12c, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash micron1GbX16 = { >>> - .timing = µn_timing, >>> - .cmdset = &largepage_cmdset, >>> - .page_per_block = 64, >>> - .page_size = 2048, >>> - .flash_width = 16, >>> - .dfc_width = 16, >>> - .num_blocks = 1024, >>> - .chip_id = 0xb12c, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash micron4GbX8 = { >>> - .timing = µn_timing, >>> - .cmdset = &largepage_cmdset, >>> - .page_per_block = 64, >>> - .page_size = 2048, >>> - .flash_width = 8, >>> - .dfc_width = 8, >>> - .num_blocks = 4096, >>> - .chip_id = 0xdc2c, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash micron4GbX16 = { >>> - .timing = µn_timing, >>> - .cmdset = &largepage_cmdset, >>> - .page_per_block = 64, >>> - .page_size = 2048, >>> - .flash_width = 16, >>> - .dfc_width = 16, >>> - .num_blocks = 4096, >>> - .chip_id = 0xcc2c, >>> -}; >>> - >>> -static struct pxa3xx_nand_timing stm2GbX16_timing = { >>> - .tCH = 10, >>> - .tCS = 35, >>> - .tWH = 15, >>> - .tWP = 25, >>> - .tRH = 15, >>> - .tRP = 25, >>> - .tR = 25000, >>> - .tWHR = 60, >>> - .tAR = 10, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash stm2GbX16 = { >>> - .timing = &stm2GbX16_timing, >>> - .cmdset = &largepage_cmdset, >>> - .page_per_block = 64, >>> - .page_size = 2048, >>> - .flash_width = 16, >>> - .dfc_width = 16, >>> - .num_blocks = 2048, >>> - .chip_id = 0xba20, >>> -}; >>> - >>> -static struct pxa3xx_nand_flash *builtin_flash_types[] = { >>> - &samsung512MbX16, >>> - &samsung2GbX8, >>> - &samsung32GbX8, >>> - µn1GbX8, >>> - µn1GbX16, >>> - µn4GbX8, >>> - µn4GbX16, >>> - &stm2GbX16, >>> -}; >>> -#endif /* CONFIG_MTD_NAND_PXA3xx_BUILTIN */ >>> - >>> #define NDTR0_tCH(c) (min((c), 7) << 19) >>> #define NDTR0_tCS(c) (min((c), 7) << 16) >>> #define NDTR0_tWH(c) (min((c), 7) << 11) >>> @@ -412,7 +308,6 @@ static int prepare_read_prog_cmd(struct >>> pxa3xx_nand_info *info, >>> uint16_t cmd, int column, int page_addr) >>> { >>> const struct pxa3xx_nand_flash *f = info->flash_info; >>> - const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; >>> >>> /* calculate data size */ >>> switch (f->page_size) { >>> @@ -445,7 +340,7 @@ static int prepare_read_prog_cmd(struct >>> pxa3xx_nand_info *info, >>> */ >>> info->ndcb1 = page_addr << 8; >>> >>> - if (cmd == cmdset->program) >>> + if (cmd == cmdset.program) >>> info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; >>> >>> return 0; >>> @@ -463,20 +358,18 @@ static int prepare_erase_cmd(struct >>> pxa3xx_nand_info *info, >>> >>> static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) >>> { >>> - const struct pxa3xx_nand_cmdset *cmdset = >>> info->flash_info->cmdset; >>> - >>> info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); >>> info->ndcb1 = 0; >>> info->ndcb2 = 0; >>> >>> - if (cmd == cmdset->read_id) { >>> + if (cmd == cmdset.read_id) { >>> info->ndcb0 |= NDCB0_CMD_TYPE(3); >>> info->data_size = 8; >>> - } else if (cmd == cmdset->read_status) { >>> + } else if (cmd == cmdset.read_status) { >>> info->ndcb0 |= NDCB0_CMD_TYPE(4); >>> info->data_size = 8; >>> - } else if (cmd == cmdset->reset || cmd == cmdset->lock || >>> - cmd == cmdset->unlock) { >>> + } else if (cmd == cmdset.reset || cmd == cmdset.lock || >>> + cmd == cmdset.unlock) { >>> info->ndcb0 |= NDCB0_CMD_TYPE(5); >>> } else >>> return -EINVAL; >>> @@ -700,8 +593,6 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >>> *mtd, unsigned command, >>> int column, int page_addr) >>> { >>> struct pxa3xx_nand_info *info = mtd->priv; >>> - const struct pxa3xx_nand_flash *flash_info = info->flash_info; >>> - const struct pxa3xx_nand_cmdset *cmdset = flash_info->cmdset; >>> int ret; >>> >>> info->use_dma = (use_dma) ? 1 : 0; >>> @@ -718,7 +609,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >>> *mtd, unsigned command, >>> info->buf_start = mtd->writesize + column; >>> memset(info->data_buff, 0xFF, info->buf_count); >>> >>> - if (prepare_read_prog_cmd(info, cmdset->read1, column, >>> page_addr)) >>> + if (prepare_read_prog_cmd(info, cmdset.read1, column, >>> page_addr)) >>> break; >>> >>> pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | >>> NDSR_SBERR); >>> @@ -735,7 +626,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >>> *mtd, unsigned command, >>> info->buf_count = mtd->writesize + mtd->oobsize; >>> memset(info->data_buff, 0xFF, info->buf_count); >>> >>> - if (prepare_read_prog_cmd(info, cmdset->read1, column, >>> page_addr)) >>> + if (prepare_read_prog_cmd(info, cmdset.read1, column, >>> page_addr)) >>> break; >>> >>> pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | >>> NDSR_SBERR); >>> @@ -761,14 +652,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >>> *mtd, unsigned command, >>> case NAND_CMD_PAGEPROG: >>> info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 >>> : 1; >>> >>> - if (prepare_read_prog_cmd(info, cmdset->program, >>> + if (prepare_read_prog_cmd(info, cmdset.program, >>> info->seqin_column, info->seqin_page_addr)) >>> break; >>> >>> pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); >>> break; >>> case NAND_CMD_ERASE1: >>> - if (prepare_erase_cmd(info, cmdset->erase, page_addr)) >>> + if (prepare_erase_cmd(info, cmdset.erase, page_addr)) >>> break; >>> >>> pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); >>> @@ -783,13 +674,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info >>> *mtd, unsigned command, >>> info->read_id_bytes : 1; >>> >>> if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? >>> - cmdset->read_id : cmdset->read_status)) >>> + cmdset.read_id : cmdset.read_status)) >>> break; >>> >>> pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); >>> break; >>> case NAND_CMD_RESET: >>> - if (prepare_other_cmd(info, cmdset->reset)) >>> + if (prepare_other_cmd(info, cmdset.reset)) >>> break; >>> >>> ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); >>> @@ -925,12 +816,10 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info >>> *mtd, >>> >>> static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) >>> { >>> - const struct pxa3xx_nand_flash *f = info->flash_info; >>> - const struct pxa3xx_nand_cmdset *cmdset = f->cmdset; >>> uint32_t ndcr; >>> uint8_t id_buff[8]; >>> >>> - if (prepare_other_cmd(info, cmdset->read_id)) { >>> + if (prepare_other_cmd(info, cmdset.read_id)) { >>> printk(KERN_ERR "failed to prepare command\n"); >>> return -EINVAL; >>> } >>> @@ -991,7 +880,7 @@ static int pxa3xx_nand_config_flash(struct >>> pxa3xx_nand_info *info, >>> >>> info->reg_ndcr = ndcr; >>> >>> - pxa3xx_nand_set_timing(info, f->timing); >>> + pxa3xx_nand_set_timing(info, &f->timing); >>> info->flash_info = f; >>> return 0; >>> } >>> @@ -1027,11 +916,6 @@ static int pxa3xx_nand_detect_config(struct >>> pxa3xx_nand_info *info) >>> default_flash.flash_width = ndcr & NDCR_DWIDTH_M ? 16 : 8; >>> default_flash.dfc_width = ndcr & NDCR_DWIDTH_C ? 16 : 8; >>> >>> - if (default_flash.page_size == 2048) >>> - default_flash.cmdset = &largepage_cmdset; >>> - else >>> - default_flash.cmdset = &smallpage_cmdset; >>> - >>> /* set info fields needed to __readid */ >>> info->flash_info = &default_flash; >>> info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; >>> @@ -1067,7 +951,7 @@ static int pxa3xx_nand_detect_config(struct >>> pxa3xx_nand_info *info) >>> info->row_addr_cycles = 2; >>> >>> pxa3xx_nand_detect_timing(info, &default_timing); >>> - default_flash.timing = &default_timing; >>> + memcpy(&default_flash.timing, &default_timing, >>> sizeof(default_timing)); >>> >>> return 0; >>> } >>> @@ -1083,23 +967,9 @@ static int pxa3xx_nand_detect_flash(struct >>> pxa3xx_nand_info *info, >>> if (pxa3xx_nand_detect_config(info) == 0) >>> return 0; >>> >>> - for (i = 0; inum_flash; ++i) { >>> - f = pdata->flash + i; >>> - >>> - if (pxa3xx_nand_config_flash(info, f)) >>> - continue; >>> - >>> - if (__readid(info, &id)) >>> - continue; >>> - >>> - if (id == f->chip_id) >>> - return 0; >>> - } >>> - >>> -#ifdef CONFIG_MTD_NAND_PXA3xx_BUILTIN >>> for (i = 0; i < ARRAY_SIZE(builtin_flash_types); i++) { >>> >>> - f = builtin_flash_types[i]; >>> + f = &builtin_flash_types[i]; >>> >>> if (pxa3xx_nand_config_flash(info, f)) >>> continue; >>> @@ -1110,7 +980,6 @@ static int pxa3xx_nand_detect_flash(struct >>> pxa3xx_nand_info *info, >>> if (id == f->chip_id) >>> return 0; >>> } >>> -#endif >>> >>> dev_warn(&info->pdev->dev, >>> "failed to detect configured nand flash; found %04x >>> instead of\n", >>> @@ -1320,17 +1189,6 @@ static int pxa3xx_nand_probe(struct >>> platform_device *pdev) >>> goto fail_free_irq; >>> } >>> >>> - if (mtd_has_cmdlinepart()) { >>> - static const char *probes[] = { "cmdlinepart", NULL }; >>> - struct mtd_partition *parts; >>> - int nr_parts; >>> - >>> - nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); >>> - >>> - if (nr_parts) >>> - return add_mtd_partitions(mtd, parts, nr_parts); >>> - } >>> - >>> return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); >>> >>> fail_free_irq: >> >> -- >> Sincerely yours, >> Mike. >> >> _______________________________________________ >> linux-arm-kernel mailing list >> linux-arm-kernel at lists.infradead.org >> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel >> -- Sincerely yours, Mike. From adrian.wenl at gmail.com Mon May 24 07:53:46 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 19:53:46 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <4BFA5C58.7050109@compulab.co.il> References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> Message-ID: Hi Mike, On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport wrote: > Hi Lei, > > Lei Wen wrote: >> >> Hi Mike, >> >> This patch set is applied to mtd-2.6 git. We submit the patch with a >> package in attachment already. >> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 > > After applying the patch set I've reviewed the entire pxa3xx-nand as a whole > and there are several major points I don't like: > 1) Two chip selects support is not robust enough. You allocate a lot of > resources for both chip selects, although not necessarily both have NAND > chip connected I agree. I prepare to submit another patch set to fix it. Let more resource go to pxa3xx_nand structure instead of pxa3xx_nand_info. > 2) I don't like hadrcoding of NAND parameters into the driver. You remove > *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and instead > you enforce use of built-in definitions. The driver in its current state is > robust enough to allow platforms to define optimized NAND timings either in > the bootloader or in the kernel. If you don't like that multiple platforms > define the same flash chip create an enumeration of built-in types and let > platforms to use this enumeration to select the NAND chip. But, anyway, > there should be a fallback mode that will support NAND chips that are not > defined in the driver, probably with suboptimal timings. Original driver also use hardcoding. And in bootloader, this timing parameter is also hard coding. We cannot deduce a parameter set only from the nand id, that is why we need a table to preset it. If one nand chip is not listed in that table, the chip id would still be printed out, so that we can do something for that. If we encourage people to continue on this, we would not able to really "driver" that nand. As I said, different nand chip may have different requirement. And in bootloader and kernel, may have different requirement of timing parameter. > 3) The functions prepare_command_pool and alloc_nand_resource seem overgrown > too me. Consolidation of prepare_*_cmd into one huge function does not seem > right. And mixing between resource allocation and mtd struct initialization > does not seem right either. The reason why I consolidate those prepare_*_cmd into one is for if separate into several functions, it would create many code duplication. And with one function, the code execution path would be always one way. This would greatly promote the code quality, for the same code path is run by many commands in the same time. If not by this, some errors may not be discovered in the first time... Thanks, Lei From marek.vasut at gmail.com Mon May 24 08:11:31 2010 From: marek.vasut at gmail.com (Marek Vasut) Date: Mon, 24 May 2010 14:11:31 +0200 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA5C58.7050109@compulab.co.il> Message-ID: <201005241411.31825.marek.vasut@gmail.com> Dne Po 24. kv?tna 2010 13:53:46 Lei Wen napsal(a): > Hi Mike, > > On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport wrote: > > Hi Lei, > > > > Lei Wen wrote: > >> Hi Mike, > >> > >> This patch set is applied to mtd-2.6 git. We submit the patch with a > >> package in attachment already. > >> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 > > > > After applying the patch set I've reviewed the entire pxa3xx-nand as a > > whole and there are several major points I don't like: > > 1) Two chip selects support is not robust enough. You allocate a lot of > > resources for both chip selects, although not necessarily both have NAND > > chip connected > > I agree. I prepare to submit another patch set to fix it. Let more > resource go to pxa3xx_nand structure instead of pxa3xx_nand_info. > > > 2) I don't like hadrcoding of NAND parameters into the driver. You remove > > *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and > > instead you enforce use of built-in definitions. The driver in its > > current state is robust enough to allow platforms to define optimized > > NAND timings either in the bootloader or in the kernel. If you don't > > like that multiple platforms define the same flash chip create an > > enumeration of built-in types and let platforms to use this enumeration > > to select the NAND chip. But, anyway, there should be a fallback mode > > that will support NAND chips that are not defined in the driver, > > probably with suboptimal timings. > > Original driver also use hardcoding. And in bootloader, this timing > parameter is also hard coding. Not necessarily. If you use uboot on pxa3xx, it passes the bootrom-detected timing to the kernel. > We cannot deduce a parameter set only from the nand id, that is why we > need a table to preset it. > If one nand chip is not listed in that table, the chip id would still > be printed out, so that we can do something for that. > If we encourage people to continue on this, we would not able to > really "driver" that nand. > > As I said, different nand chip may have different requirement. And in > bootloader and kernel, may have different requirement > of timing parameter. In bootloader and kernel? Why would that be so? > > > 3) The functions prepare_command_pool and alloc_nand_resource seem > > overgrown too me. Consolidation of prepare_*_cmd into one huge function > > does not seem right. And mixing between resource allocation and mtd > > struct initialization does not seem right either. > > The reason why I consolidate those prepare_*_cmd into one is for if > separate into several functions, it would create many code > duplication. > And with one function, the code execution path would be always one > way. This would greatly promote the code quality, for the same code > path is run by many commands in the same time. If not by this, some > errors may not be discovered in the first time... > > Thanks, > Lei > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel From adrian.wenl at gmail.com Mon May 24 08:31:39 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 20:31:39 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <201005241411.31825.marek.vasut@gmail.com> References: <4BFA5C58.7050109@compulab.co.il> <201005241411.31825.marek.vasut@gmail.com> Message-ID: Hi Marek, On Mon, May 24, 2010 at 8:11 PM, Marek Vasut wrote: > Dne Po 24. kv?tna 2010 13:53:46 Lei Wen napsal(a): >> Hi Mike, >> >> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport wrote: >> > Hi Lei, >> > >> > Lei Wen wrote: >> >> Hi Mike, >> >> >> >> This patch set is applied to mtd-2.6 git. We submit the patch with a >> >> package in attachment already. >> >> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 >> > >> > After applying the patch set I've reviewed the entire pxa3xx-nand as a >> > whole and there are several major points I don't like: >> > 1) Two chip selects support is not robust enough. You allocate a lot of >> > resources for both chip selects, although not necessarily both have NAND >> > chip connected >> >> I agree. I prepare to submit another patch set to fix it. Let more >> resource go to pxa3xx_nand structure instead of pxa3xx_nand_info. >> >> > 2) I don't like hadrcoding of NAND parameters into the driver. You remove >> > *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and >> > instead you enforce use of built-in definitions. The driver in its >> > current state is robust enough to allow platforms to define optimized >> > NAND timings either in the bootloader or in the kernel. If you don't >> > like that multiple platforms define the same flash chip create an >> > enumeration of built-in types and let platforms to use this enumeration >> > to select the NAND chip. But, anyway, there should be a fallback mode >> > that will support NAND chips that are not defined in the driver, >> > probably with suboptimal timings. >> >> Original driver also use hardcoding. And in bootloader, this timing >> parameter is also hard coding. > > Not necessarily. If you use uboot on pxa3xx, it passes the bootrom-detected > timing to the kernel. > >> We cannot deduce a parameter set only from the nand id, that is why we >> need a table to preset it. >> If one nand chip is not listed in that table, the chip id would still >> be printed out, so that we can do something for that. >> If we encourage people to continue on this, we would not able to >> really "driver" that nand. >> >> As I said, different nand chip may have different requirement. And in >> bootloader and kernel, may have different requirement >> of timing parameter. > > In bootloader and kernel? Why would that be so? The bootrom timing setting is not very satisfied. We have compared the most optimized timing setting and what the timing setting is set in bootrom. The read speed would be several times gap.(3x, or 4x). For kernel is the place we want the most optimized performance, we may adjust the timing according to our need. Thanks, Lei >> >> > 3) The functions prepare_command_pool and alloc_nand_resource seem >> > overgrown too me. Consolidation of prepare_*_cmd into one huge function >> > does not seem right. And mixing between resource allocation and mtd >> > struct initialization does not seem right either. >> >> The reason why I consolidate those prepare_*_cmd into one is for if >> separate into several functions, it would create many code >> duplication. >> And with one function, the code execution path would be always one >> way. This would greatly promote the code quality, for the same code >> path is run by many commands in the same time. If not by this, some >> errors may not be discovered in the first time... >> >> Thanks, >> Lei >> >> _______________________________________________ >> linux-arm-kernel mailing list >> linux-arm-kernel at lists.infradead.org >> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel > From marek.vasut at gmail.com Mon May 24 09:05:27 2010 From: marek.vasut at gmail.com (Marek Vasut) Date: Mon, 24 May 2010 15:05:27 +0200 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <201005241411.31825.marek.vasut@gmail.com> Message-ID: <201005241505.27545.marek.vasut@gmail.com> Dne Po 24. kv?tna 2010 14:31:39 Lei Wen napsal(a): > Hi Marek, > > On Mon, May 24, 2010 at 8:11 PM, Marek Vasut wrote: > > Dne Po 24. kv?tna 2010 13:53:46 Lei Wen napsal(a): > >> Hi Mike, > >> > >> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport wrote: > >> > Hi Lei, > >> > > >> > Lei Wen wrote: > >> >> Hi Mike, > >> >> > >> >> This patch set is applied to mtd-2.6 git. We submit the patch with a > >> >> package in attachment already. > >> >> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 > >> > > >> > After applying the patch set I've reviewed the entire pxa3xx-nand as a > >> > whole and there are several major points I don't like: > >> > 1) Two chip selects support is not robust enough. You allocate a lot > >> > of resources for both chip selects, although not necessarily both > >> > have NAND chip connected > >> > >> I agree. I prepare to submit another patch set to fix it. Let more > >> resource go to pxa3xx_nand structure instead of pxa3xx_nand_info. > >> > >> > 2) I don't like hadrcoding of NAND parameters into the driver. You > >> > remove *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration > >> > option and instead you enforce use of built-in definitions. The > >> > driver in its current state is robust enough to allow platforms to > >> > define optimized NAND timings either in the bootloader or in the > >> > kernel. If you don't like that multiple platforms define the same > >> > flash chip create an enumeration of built-in types and let platforms > >> > to use this enumeration to select the NAND chip. But, anyway, there > >> > should be a fallback mode that will support NAND chips that are not > >> > defined in the driver, probably with suboptimal timings. > >> > >> Original driver also use hardcoding. And in bootloader, this timing > >> parameter is also hard coding. > > > > Not necessarily. If you use uboot on pxa3xx, it passes the > > bootrom-detected timing to the kernel. > > > >> We cannot deduce a parameter set only from the nand id, that is why we > >> need a table to preset it. > >> If one nand chip is not listed in that table, the chip id would still > >> be printed out, so that we can do something for that. > >> If we encourage people to continue on this, we would not able to > >> really "driver" that nand. > >> > >> As I said, different nand chip may have different requirement. And in > >> bootloader and kernel, may have different requirement > >> of timing parameter. > > > > In bootloader and kernel? Why would that be so? > > The bootrom timing setting is not very satisfied. We have compared the > most optimized timing setting and what the timing setting is set in > bootrom. The read speed would be several times gap.(3x, or 4x). That's expectable. > For kernel is the place we want the most optimized performance, we may > adjust the timing according to our need. Yeah, that I'm aware of. But if that's the case, why don't you move the timing setup into the bootloader altogether and be done with it ? Kernel relies on the BootROM if the NAND chip definition is missing ... therefore if the platform set it up correctly in the bootloader, all this goo could go away from the driver. (And you can possibly only leave that 'platform can adjust NAND timing' part for worst cases). Maybe I'm missing something, it's hard to review. If that's the case, just ignore what I said. Cheers! > > Thanks, > Lei > > >> > 3) The functions prepare_command_pool and alloc_nand_resource seem > >> > overgrown too me. Consolidation of prepare_*_cmd into one huge > >> > function does not seem right. And mixing between resource allocation > >> > and mtd struct initialization does not seem right either. > >> > >> The reason why I consolidate those prepare_*_cmd into one is for if > >> separate into several functions, it would create many code > >> duplication. > >> And with one function, the code execution path would be always one > >> way. This would greatly promote the code quality, for the same code > >> path is run by many commands in the same time. If not by this, some > >> errors may not be discovered in the first time... > >> > >> Thanks, > >> Lei > >> > >> _______________________________________________ > >> linux-arm-kernel mailing list > >> linux-arm-kernel at lists.infradead.org > >> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel From adrian.wenl at gmail.com Mon May 24 09:18:38 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 21:18:38 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <201005241505.27545.marek.vasut@gmail.com> References: <201005241411.31825.marek.vasut@gmail.com> <201005241505.27545.marek.vasut@gmail.com> Message-ID: On Mon, May 24, 2010 at 9:05 PM, Marek Vasut wrote: > Dne Po 24. kv?tna 2010 14:31:39 Lei Wen napsal(a): >> Hi Marek, >> >> On Mon, May 24, 2010 at 8:11 PM, Marek Vasut wrote: >> > Dne Po 24. kv?tna 2010 13:53:46 Lei Wen napsal(a): >> >> Hi Mike, >> >> >> >> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport wrote: >> >> > Hi Lei, >> >> > >> >> > Lei Wen wrote: >> >> >> Hi Mike, >> >> >> >> >> >> This patch set is applied to mtd-2.6 git. We submit the patch with a >> >> >> package in attachment already. >> >> >> http://permalink.gmane.org/gmane.linux.ports.arm.kernel/79818 >> >> > >> >> > After applying the patch set I've reviewed the entire pxa3xx-nand as a >> >> > whole and there are several major points I don't like: >> >> > 1) Two chip selects support is not robust enough. You allocate a lot >> >> > of resources for both chip selects, although not necessarily both >> >> > have NAND chip connected >> >> >> >> I agree. I prepare to submit another patch set to fix it. Let more >> >> resource go to pxa3xx_nand structure instead of pxa3xx_nand_info. >> >> >> >> > 2) I don't like hadrcoding of NAND parameters into the driver. You >> >> > remove *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration >> >> > option and instead you enforce use of built-in definitions. The >> >> > driver in its current state is robust enough to allow platforms to >> >> > define optimized NAND timings either in the bootloader or in the >> >> > kernel. If you don't like that multiple platforms define the same >> >> > flash chip create an enumeration of built-in types and let platforms >> >> > to use this enumeration to select the NAND chip. But, anyway, there >> >> > should be a fallback mode that will support NAND chips that are not >> >> > defined in the driver, probably with suboptimal timings. >> >> >> >> Original driver also use hardcoding. And in bootloader, this timing >> >> parameter is also hard coding. >> > >> > Not necessarily. If you use uboot on pxa3xx, it passes the >> > bootrom-detected timing to the kernel. >> > >> >> We cannot deduce a parameter set only from the nand id, that is why we >> >> need a table to preset it. >> >> If one nand chip is not listed in that table, the chip id would still >> >> be printed out, so that we can do something for that. >> >> If we encourage people to continue on this, we would not able to >> >> really "driver" that nand. >> >> >> >> As I said, different nand chip may have different requirement. And in >> >> bootloader and kernel, may have different requirement >> >> of timing parameter. >> > >> > In bootloader and kernel? Why would that be so? >> >> The bootrom timing setting is not very satisfied. We have compared the >> most optimized timing setting and what the timing setting is set in >> bootrom. The read speed would be several times gap.(3x, or 4x). > > That's expectable. > >> For kernel is the place we want the most optimized performance, we may >> adjust the timing according to our need. > > Yeah, that I'm aware of. But if that's the case, why don't you move the timing > setup into the bootloader altogether and be done with it ? Kernel relies on the > BootROM if the NAND chip definition is missing ... therefore if the platform set > it up correctly in the bootloader, all this goo could go away from the driver. > (And you can possibly only leave that 'platform can adjust NAND timing' part for > worst cases). > > Maybe I'm missing something, it's hard to review. If that's the case, just > ignore what I said. This back to what Mike ask me... The reason why we need the built_in_table, is for we need tell what the special nand chip want which cannot be gotten from bootloader setting. For the nand chip may need higher ecc strength, like 8bit per 512 bytes. This require kernel use different approach to deal with. It is better that kernel could be standalone, so that we would be troubled by the mistake of bootloader. For UBOOT or blob, it is not a must thing, we could load kernel directly from OBM. (If you want to do that, like kernel as bootloader...) Thanks, Lei From mike at compulab.co.il Mon May 24 09:21:36 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Mon, 24 May 2010 16:21:36 +0300 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> Message-ID: <4BFA7D60.6020703@compulab.co.il> Lei Wen wrote: > Hi Mike, > > On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport wrote: >> Hi Lei, >> >> Lei Wen wrote: >>> Hi Mike, >>> >> 2) I don't like hadrcoding of NAND parameters into the driver. You remove >> *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and instead >> you enforce use of built-in definitions. The driver in its current state is >> robust enough to allow platforms to define optimized NAND timings either in >> the bootloader or in the kernel. If you don't like that multiple platforms >> define the same flash chip create an enumeration of built-in types and let >> platforms to use this enumeration to select the NAND chip. But, anyway, >> there should be a fallback mode that will support NAND chips that are not >> defined in the driver, probably with suboptimal timings. > > Original driver also use hardcoding. And in bootloader, this timing > parameter is also hard coding. > We cannot deduce a parameter set only from the nand id, that is why we > need a table to preset it. > If one nand chip is not listed in that table, the chip id would still > be printed out, so that we can do something for that. > If we encourage people to continue on this, we would not able to > really "driver" that nand. Currently pxa3xx-nand has three operational modes: - use NAND parameters supplied by the platform - use presets configured by the bootloader chain - use built-in NAND parameters, marked as deprecated in favor of the first two You remove the first two modes completely and require that each and every NAND chip used on pxa3xx based platform will be added to the driver. This way you make the driver less robust and harder to use for platform developers, not mentioning you're breaking the existing platforms. In my opinion, the driver *may* support built-in definitions for certain NAND flashes and *must* support configuration of the NAND parameters by the platform code and bootloader. > As I said, different nand chip may have different requirement. And in > bootloader and kernel, may have different requirement > of timing parameter. > > >> 3) The functions prepare_command_pool and alloc_nand_resource seem overgrown >> too me. Consolidation of prepare_*_cmd into one huge function does not seem >> right. And mixing between resource allocation and mtd struct initialization >> does not seem right either. > > The reason why I consolidate those prepare_*_cmd into one is for if > separate into several functions, it would create many code > duplication. > And with one function, the code execution path would be always one > way. This would greatly promote the code quality, for the same code > path is run by many commands in the same time. If not by this, some > errors may not be discovered in the first time... > > Thanks, > Lei -- Sincerely yours, Mike. From adrian.wenl at gmail.com Mon May 24 09:40:57 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Mon, 24 May 2010 21:40:57 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <4BFA7D60.6020703@compulab.co.il> References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> Message-ID: On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport wrote: > Lei Wen wrote: >> >> Hi Mike, >> >> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport >> wrote: >>> >>> Hi Lei, >>> >>> Lei Wen wrote: >>>> >>>> Hi Mike, >>>> >>> 2) I don't like hadrcoding of NAND parameters into the driver. You remove >>> *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and >>> instead >>> you enforce use of built-in definitions. The driver in its current state >>> is >>> robust enough to allow platforms to define optimized NAND timings either >>> in >>> the bootloader or in the kernel. If you don't like that multiple >>> platforms >>> define the same flash chip create an enumeration of built-in types and >>> let >>> platforms to use this enumeration to select the NAND chip. But, anyway, >>> there should be a fallback mode that will support NAND chips that are not >>> defined in the driver, probably with suboptimal timings. >> >> Original driver also use hardcoding. And in bootloader, this timing >> parameter is also hard coding. >> We cannot deduce a parameter set only from the nand id, that is why we >> need a table to preset it. >> If one nand chip is not listed in that table, the chip id would still >> be printed out, so that we can do something for that. >> If we encourage people to continue on this, we would not able to >> really "driver" that nand. > > Currently pxa3xx-nand has three operational modes: > - use NAND parameters supplied by the platform > - use presets configured by the bootloader chain > - use built-in NAND parameters, marked as deprecated in favor of the first > two > You remove the first two modes completely and require that each and every > NAND chip used on pxa3xx based platform will be added to the driver. This > way you make the driver less robust and harder to use for platform > developers, not mentioning you're breaking the existing platforms. > In my opinion, the driver *may* support built-in definitions for certain > NAND flashes and *must* support configuration of the NAND parameters by the > platform code and bootloader. > Hi Mike, Well... I would submit another patch set which would reserve a way that platform could pass its parameter setting. Like specify the certain type of nand chip parameter for each chip select. Is that ok for you? For bootloader pass parameter method, I think this way should be dropped... For there is attributed which we could not tell from registers... What do you think of this? Thanks, Lei From ian at brightstareng.com Mon May 24 11:09:20 2010 From: ian at brightstareng.com (Ian McDonnell) Date: Mon, 24 May 2010 11:09:20 -0400 Subject: [PATCH] Fix Oops with Atmel SPI In-Reply-To: <20100521120106.d955c78b.akpm@linux-foundation.org> References: <1271231840l.5270l.0l@i-dmzi_al.realan.de> <1274267100l.1747l.1l@i-dmzi_al.realan.de> <20100521120106.d955c78b.akpm@linux-foundation.org> Message-ID: <201005241109.20290.ian@brightstareng.com> Anders, I just tested one path, the "if (xfer->rx_buf)...", on 2.6.33 plus the at91 patch http://maxim.org.za/AT91RM9200/2.6/2.6.33-at91.patch.gz running on AT91SAM9260. The test case involved doing i/o via the /dev/mtdblock interface -- but this only exercises the rx_buf/vmalloc path -- MTD reads a block into the cache-buf to merge the write data. Not sure that we have any use cases for the tx_buf path using MTD. -Ian On Friday 21 May 2010, Andrew Morton wrote: > On Wed, 19 May 2010 13:05:00 +0200 > > Anders Larsen wrote: > > On 2010-04-22 00:24:10, Andrew Morton wrote: > > > Finally.. Wouldn't it be better to just fix the atmel SPI > > > driver so that it doesn't barf when handed vmalloc'ed > > > memory? Who do we ridicule about that? > > > > You mean something like this instead? > > That looks simple enough. How do we get it tested, > changelogged and merged up? Haavard, can you please take a > look? > > > diff --git a/drivers/spi/atmel_spi.c > > b/drivers/spi/atmel_spi.c index c4e0442..a9ad5e8 100644 > > --- a/drivers/spi/atmel_spi.c > > +++ b/drivers/spi/atmel_spi.c > > @@ -352,16 +352,30 @@ atmel_spi_dma_map_xfer(struct > > atmel_spi *as, struct spi_transfer *xfer) > > > > xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS; > > if (xfer->tx_buf) { > > - xfer->tx_dma = dma_map_single(dev, > > - (void *) xfer->tx_buf, xfer->len, > > - DMA_TO_DEVICE); > > + if (is_vmalloc_addr(xfer->tx_buf)) > > + xfer->tx_dma = dma_map_page(dev, > > + vmalloc_to_page(xfer->tx_buf), > > + (unsigned long)xfer->tx_buf & (PAGE_SIZE-1), > > + xfer->len, > > + DMA_TO_DEVICE); > > + else > > + xfer->tx_dma = dma_map_single(dev, > > + (void *) xfer->tx_buf, xfer->len, > > + DMA_TO_DEVICE); > > if (dma_mapping_error(dev, xfer->tx_dma)) > > return -ENOMEM; > > } > > if (xfer->rx_buf) { > > - xfer->rx_dma = dma_map_single(dev, > > - xfer->rx_buf, xfer->len, > > - DMA_FROM_DEVICE); > > + if (is_vmalloc_addr(xfer->rx_buf)) > > + xfer->rx_dma = dma_map_page(dev, > > + vmalloc_to_page(xfer->rx_buf), > > + (unsigned long)xfer->rx_buf & (PAGE_SIZE-1), > > + xfer->len, > > + DMA_FROM_DEVICE); > > + else > > + xfer->rx_dma = dma_map_single(dev, > > + xfer->rx_buf, xfer->len, > > + DMA_FROM_DEVICE); > > if (dma_mapping_error(dev, xfer->rx_dma)) { > > if (xfer->tx_buf) > > dma_unmap_single(dev, From taliaferro62 at gmail.com Mon May 24 11:22:02 2010 From: taliaferro62 at gmail.com (twebb) Date: Mon, 24 May 2010 11:22:02 -0400 Subject: UBIFS failed to recover master node Message-ID: I've had several cases where our MLC NAND flash appears corrupted in such a way that one of three UBIFS volumes can not be mounted due to "failed to recover master node". I haven't been able to reproduce the problem, but we've had at least 5 incidents where this has occurred. (A partial capture from one of the failures is below.) I'm starting to investigate this problem and don't know if this is a UBIFS/UBI problem or a NAND driver problem. I'm starting the process of back-porting the latest UBIFS code to our 2.6.29 kernel - hoping that new UBIFS code will solve the problem. However, this may also be a driver problem and I wonder if I also need to update that driver (pxa3xx_nand). Any suggestions for debugging this problem? Thanks, twebb capture: [root at ESIedge mtd-utils]# mount -t ubifs ubi0_0 /mnt/ [ 239.605869] UBI error: ubi_io_read: error -74 while reading 516096 bytes from PEB 4:8192, read 516096 bytes [ 239.616317] UBIFS error (pid 676): ubifs_scan: corrupt empty space at LEB 2:268135 [ 239.623996] UBIFS error (pid 676): ubifs_scanned_corruption: corruption at LEB 2:268135 [ 239.642101] UBIFS error (pid 676): ubifs_scan: LEB 2 scanning failed [ 239.976396] UBI error: ubi_io_read: error -74 while reading 516096 bytes from PEB 4:8192, read 516096 bytes [ 239.986742] UBIFS error (pid 676): ubifs_recover_master_node: failed to recover master node mount: mounting ubi0_0 on /mnt/ failed: Invalid argument From daniel at caiaq.de Mon May 24 11:44:29 2010 From: daniel at caiaq.de (Daniel Mack) Date: Mon, 24 May 2010 17:44:29 +0200 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> Message-ID: <20100524154429.GM30801@buzzloop.caiaq.de> On Mon, May 24, 2010 at 09:40:57PM +0800, Lei Wen wrote: > On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport wrote: > > Currently pxa3xx-nand has three operational modes: > > - use NAND parameters supplied by the platform > > - use presets configured by the bootloader chain > > - use built-in NAND parameters, marked as deprecated in favor of the first > > two > > You remove the first two modes completely and require that each and every > > NAND chip used on pxa3xx based platform will be added to the driver. This > > way you make the driver less robust and harder to use for platform > > developers, not mentioning you're breaking the existing platforms. > > In my opinion, the driver *may* support built-in definitions for certain > > NAND flashes and *must* support configuration of the NAND parameters by the > > platform code and bootloader. > > > > Hi Mike, > > Well... I would submit another patch set which would reserve a way > that platform could pass its parameter setting. > Like specify the certain type of nand chip parameter for each chip > select. Is that ok for you? > > For bootloader pass parameter method, I think this way should be > dropped... For there is attributed which we could not tell from > registers... No, please don't drop this, as critical procedures in production lines depend on this. Think about replacing a certain type of NAND chip in the middle of a production. You would probably need to update the bootloader for that in order to make the PXA boot from NAND. That's bad enough. In the current system, you're done by just providing a bootloader which sets up the NAND correctly. If you deprecate that way, the kernel would also need an update, for actually no good reason, as all necessary settings have already been cared for earlier. While that's not the end of the world, it's still extra work that can be avoided. I still haven't got your point for removing this feature. Why not leave it in? Daniel From dedekind1 at gmail.com Tue May 25 01:05:14 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 25 May 2010 08:05:14 +0300 Subject: UBIFS failed to recover master node In-Reply-To: References: Message-ID: <1274763914.2106.1.camel@localhost> On Mon, 2010-05-24 at 11:22 -0400, twebb wrote: > I've had several cases where our MLC NAND flash appears corrupted in > such a way that one of three UBIFS volumes can not be mounted due to > "failed to recover master node". I haven't been able to reproduce the > problem, but we've had at least 5 incidents where this has occurred. > (A partial capture from one of the failures is below.) > > I'm starting to investigate this problem and don't know if this is a > UBIFS/UBI problem or a NAND driver problem. I'm starting the process > of back-porting the latest UBIFS code to our 2.6.29 kernel - hoping > that new UBIFS code will solve the problem. However, this may also be > a driver problem and I wonder if I also need to update that driver > (pxa3xx_nand). Any suggestions for debugging this problem? > > Thanks, > twebb > > > capture: > [root at ESIedge mtd-utils]# mount -t ubifs ubi0_0 /mnt/ > [ 239.605869] UBI error: ubi_io_read: error -74 while reading 516096 > bytes from PEB 4:8192, read 516096 bytes > [ 239.616317] UBIFS error (pid 676): ubifs_scan: corrupt empty space > at LEB 2:268135 > [ 239.623996] UBIFS error (pid 676): ubifs_scanned_corruption: > corruption at LEB 2:268135 > [ 239.642101] UBIFS error (pid 676): ubifs_scan: LEB 2 scanning failed > [ 239.976396] UBI error: ubi_io_read: error -74 while reading 516096 > bytes from PEB 4:8192, read 516096 bytes > [ 239.986742] UBIFS error (pid 676): ubifs_recover_master_node: > failed to recover master node > mount: mounting ubi0_0 on /mnt/ failed: Invalid argument Please, enable all debugging messages, mount this flash again, and send the messages. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Tue May 25 01:06:22 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Tue, 25 May 2010 08:06:22 +0300 Subject: UBIFS failed to recover master node In-Reply-To: References: Message-ID: <1274763982.2106.2.camel@localhost> On Mon, 2010-05-24 at 11:22 -0400, twebb wrote: > I've had several cases where our MLC NAND flash appears corrupted in > such a way that one of three UBIFS volumes can not be mounted due to > "failed to recover master node". I haven't been able to reproduce the > problem, but we've had at least 5 incidents where this has occurred. > (A partial capture from one of the failures is below.) > > I'm starting to investigate this problem and don't know if this is a > UBIFS/UBI problem or a NAND driver problem. I'm starting the process > of back-porting the latest UBIFS code to our 2.6.29 kernel - hoping > that new UBIFS code will solve the problem. However, this may also be > a driver problem and I wonder if I also need to update that driver > (pxa3xx_nand). Any suggestions for debugging this problem? > > Thanks, > twebb > > > capture: > [root at ESIedge mtd-utils]# mount -t ubifs ubi0_0 /mnt/ > [ 239.605869] UBI error: ubi_io_read: error -74 while reading 516096 > bytes from PEB 4:8192, read 516096 bytes > [ 239.616317] UBIFS error (pid 676): ubifs_scan: corrupt empty space > at LEB 2:268135 > [ 239.623996] UBIFS error (pid 676): ubifs_scanned_corruption: > corruption at LEB 2:268135 > [ 239.642101] UBIFS error (pid 676): ubifs_scan: LEB 2 scanning failed > [ 239.976396] UBI error: ubi_io_read: error -74 while reading 516096 > bytes from PEB 4:8192, read 516096 bytes > [ 239.986742] UBIFS error (pid 676): ubifs_recover_master_node: > failed to recover master node > mount: mounting ubi0_0 on /mnt/ failed: Invalid argument And BTW, it is a good idea not to erase/re-flash this device if you want to fix this problem. -- Best Regards, Artem Bityutskiy (????? ????????) From randy.dunlap at oracle.com Tue May 25 01:22:51 2010 From: randy.dunlap at oracle.com (Randy Dunlap) Date: Mon, 24 May 2010 22:22:51 -0700 Subject: [PATCH] mtd/nand_base: fix kernel-doc warnings & typos Message-ID: <20100524222251.5c99b939.randy.dunlap@oracle.com> From: Randy Dunlap Fix mtd/nand_base.c kernel-doc warnings and typos. Warning(drivers/mtd/nand/nand_base.c:893): No description found for parameter 'mtd' Warning(drivers/mtd/nand/nand_base.c:893): No description found for parameter 'ofs' Warning(drivers/mtd/nand/nand_base.c:893): No description found for parameter 'len' Warning(drivers/mtd/nand/nand_base.c:893): No description found for parameter 'invert' Warning(drivers/mtd/nand/nand_base.c:930): No description found for parameter 'mtd' Warning(drivers/mtd/nand/nand_base.c:930): No description found for parameter 'ofs' Warning(drivers/mtd/nand/nand_base.c:930): No description found for parameter 'len' Warning(drivers/mtd/nand/nand_base.c:987): No description found for parameter 'mtd' Warning(drivers/mtd/nand/nand_base.c:987): No description found for parameter 'ofs' Warning(drivers/mtd/nand/nand_base.c:987): No description found for parameter 'len' Warning(drivers/mtd/nand/nand_base.c:2087): No description found for parameter 'len' Signed-off-by: Randy Dunlap Cc: David Woodhouse Cc: linux-mtd at lists.infradead.org --- drivers/mtd/nand/nand_base.c | 39 ++++++++++++++++----------------- scripts/kernel-doc | 2 + 2 files changed, 22 insertions(+), 19 deletions(-) --- lnx-2634-g8-kerndoc.orig/drivers/mtd/nand/nand_base.c +++ lnx-2634-g8-kerndoc/drivers/mtd/nand/nand_base.c @@ -876,17 +876,17 @@ static int nand_wait(struct mtd_info *mt } /** - * __nand_unlock - [REPLACABLE] unlocks specified locked blockes + * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks * - * @param mtd - mtd info - * @param ofs - offset to start unlock from - * @param len - length to unlock - * @invert - when = 0, unlock the range of blocks within the lower and + * @mtd: mtd info + * @ofs: offset to start unlock from + * @len: length to unlock + * @invert: when = 0, unlock the range of blocks within the lower and * upper boundary address - * whne = 1, unlock the range of blocks outside the boundaries + * when = 1, unlock the range of blocks outside the boundaries * of the lower and upper boundary address * - * @return - unlock status + * return - unlock status */ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len, int invert) @@ -918,13 +918,13 @@ static int __nand_unlock(struct mtd_info } /** - * nand_unlock - [REPLACABLE] unlocks specified locked blockes + * nand_unlock - [REPLACEABLE] unlocks specified locked blocks * - * @param mtd - mtd info - * @param ofs - offset to start unlock from - * @param len - length to unlock + * @mtd: mtd info + * @ofs: offset to start unlock from + * @len: length to unlock * - * @return - unlock status + * return - unlock status */ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) { @@ -969,16 +969,16 @@ out: } /** - * nand_lock - [REPLACABLE] locks all blockes present in the device + * nand_lock - [REPLACEABLE] locks all blocks present in the device * - * @param mtd - mtd info - * @param ofs - offset to start unlock from - * @param len - length to unlock + * @mtd: mtd info + * @ofs: offset to start unlock from + * @len: length to unlock * - * @return - lock status + * return - lock status * - * This feature is not support in many NAND parts. 'Micron' NAND parts - * do have this feature, but it allows only to lock all blocks not for + * This feature is not supported in many NAND parts. 'Micron' NAND parts + * do have this feature, but it allows only to lock all blocks, not for * specified range for block. * * Implementing 'lock' feature by making use of 'unlock', for now. @@ -2080,6 +2080,7 @@ static int nand_write_page(struct mtd_in * nand_fill_oob - [Internal] Transfer client buffer to oob * @chip: nand chip structure * @oob: oob data buffer + * @len: oob data write length * @ops: oob ops structure */ static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob, size_t len, --- lnx-2634-g8-kerndoc.orig/scripts/kernel-doc +++ lnx-2634-g8-kerndoc/scripts/kernel-doc @@ -1454,6 +1454,8 @@ sub dump_enum($$) { my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. + $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums + if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { $declaration_name = $1; my $members = $2; From ffainelli at freebox.fr Tue May 25 04:36:12 2010 From: ffainelli at freebox.fr (Florian Fainelli) Date: Tue, 25 May 2010 10:36:12 +0200 Subject: [PATCH] NAND: add Toshiba TC58NVG0 device ID In-Reply-To: <201005071909.13259.florian@openwrt.org> References: <201005071909.13259.florian@openwrt.org> Message-ID: <201005251036.12238.ffainelli@freebox.fr> On Friday 07 May 2010 19:09:13 Florian Fainelli wrote: > This NAND flash part advertises 0xD1 as an identifier but is still a > working 128MBytes x 8bits 3.3V NAND part. David, Artem, anything wrong with this patch? > > Signed-off-by: Florian Fainelli > --- > diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c > index 69ee2c9..89907ed 100644 > --- a/drivers/mtd/nand/nand_ids.c > +++ b/drivers/mtd/nand/nand_ids.c > @@ -82,6 +82,7 @@ struct nand_flash_dev nand_flash_ids[] = { > /* 1 Gigabit */ > {"NAND 128MiB 1,8V 8-bit", 0xA1, 0, 128, 0, LP_OPTIONS}, > {"NAND 128MiB 3,3V 8-bit", 0xF1, 0, 128, 0, LP_OPTIONS}, > + {"NAND 128MiB 3,3V 8-bit", 0xD1, 0, 128, 0, LP_OPTIONS}, > {"NAND 128MiB 1,8V 16-bit", 0xB1, 0, 128, 0, LP_OPTIONS16}, > {"NAND 128MiB 3,3V 16-bit", 0xC1, 0, 128, 0, LP_OPTIONS16}, From glecerf at gmail.com Tue May 25 04:50:13 2010 From: glecerf at gmail.com (Guillaume LECERF) Date: Tue, 25 May 2010 10:50:13 +0200 Subject: [PATCH] NAND: add Toshiba TC58NVG0 device ID In-Reply-To: <201005251036.12238.ffainelli@freebox.fr> References: <201005071909.13259.florian@openwrt.org> <201005251036.12238.ffainelli@freebox.fr> Message-ID: 2010/5/25 Florian Fainelli : > David, Artem, anything wrong with this patch? http://git.infradead.org/mtd-2.6.git/commitdiff/f6b173cc9d73c00a3182ec3fdb0f03909cad4b5b -- Guillaume LECERF GeeXboX developer - www.geexbox.org From dwmw2 at infradead.org Tue May 25 05:18:36 2010 From: dwmw2 at infradead.org (David Woodhouse) Date: Tue, 25 May 2010 10:18:36 +0100 Subject: [PATCH] NAND: add Toshiba TC58NVG0 device ID In-Reply-To: References: <201005071909.13259.florian@openwrt.org> <201005251036.12238.ffainelli@freebox.fr> Message-ID: <1274779116.20576.8470.camel@macbook.infradead.org> On Tue, 2010-05-25 at 09:50 +0100, Guillaume LECERF wrote: > 2010/5/25 Florian Fainelli : > > David, Artem, anything wrong with this patch? > > http://git.infradead.org/mtd-2.6.git/commitdiff/f6b173cc9d73c00a3182ec3fdb0f03909cad4b5b http://git.kernel.org/linus/f6b173cc9d73c00a3182ec3fdb0f03909cad4b5b -- dwmw2 From ffainelli at freebox.fr Tue May 25 05:22:14 2010 From: ffainelli at freebox.fr (Florian Fainelli) Date: Tue, 25 May 2010 11:22:14 +0200 (CEST) Subject: [PATCH] NAND: add Toshiba TC58NVG0 device ID In-Reply-To: Message-ID: <823959486.313781274779334977.JavaMail.root@zimbra-corp-1-b7> Hi Guillaume, ----- Mail d'origine ----- De: Guillaume LECERF ?: Florian Fainelli Cc: David Woodhouse , linux-mtd at lists.infradead.org, Artem Bityutskiy Envoy?: Tue, 25 May 2010 10:50:13 +0200 (CEST) Objet: Re: [PATCH] NAND: add Toshiba TC58NVG0 device ID 2010/5/25 Florian Fainelli : > David, Artem, anything wrong with this patch? http://git.infradead.org/mtd-2.6.git/commitdiff/f6b173cc9d73c00a3182ec3fdb0f03909cad4b5b Oh, I did not see that, thanks! -- Florian From mike at compulab.co.il Tue May 25 06:21:46 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Tue, 25 May 2010 13:21:46 +0300 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> Message-ID: <4BFBA4BA.9020502@compulab.co.il> Lei Wen wrote: > On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport wrote: >> Lei Wen wrote: >>> Hi Mike, >>> >>> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport >>> wrote: >>>> Hi Lei, >>>> >>>> Lei Wen wrote: >>>>> Hi Mike, >>>>> >>>> 2) I don't like hadrcoding of NAND parameters into the driver. You remove >>>> *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and >>>> instead >>>> you enforce use of built-in definitions. The driver in its current state >>>> is >>>> robust enough to allow platforms to define optimized NAND timings either >>>> in >>>> the bootloader or in the kernel. If you don't like that multiple >>>> platforms >>>> define the same flash chip create an enumeration of built-in types and >>>> let >>>> platforms to use this enumeration to select the NAND chip. But, anyway, >>>> there should be a fallback mode that will support NAND chips that are not >>>> defined in the driver, probably with suboptimal timings. >>> Original driver also use hardcoding. And in bootloader, this timing >>> parameter is also hard coding. >>> We cannot deduce a parameter set only from the nand id, that is why we >>> need a table to preset it. >>> If one nand chip is not listed in that table, the chip id would still >>> be printed out, so that we can do something for that. >>> If we encourage people to continue on this, we would not able to >>> really "driver" that nand. >> Currently pxa3xx-nand has three operational modes: >> - use NAND parameters supplied by the platform >> - use presets configured by the bootloader chain >> - use built-in NAND parameters, marked as deprecated in favor of the first >> two >> You remove the first two modes completely and require that each and every >> NAND chip used on pxa3xx based platform will be added to the driver. This >> way you make the driver less robust and harder to use for platform >> developers, not mentioning you're breaking the existing platforms. >> In my opinion, the driver *may* support built-in definitions for certain >> NAND flashes and *must* support configuration of the NAND parameters by the >> platform code and bootloader. >> > > Hi Mike, > > Well... I would submit another patch set which would reserve a way > that platform could pass its parameter setting. > Like specify the certain type of nand chip parameter for each chip > select. Is that ok for you? > > For bootloader pass parameter method, I think this way should be > dropped... For there is attributed which we could not tell from > registers... > What do you think of this? Can you please elaborate what are the attributes that cannot be detected? > Thanks, > Lei -- Sincerely yours, Mike. From marek.vasut at gmail.com Tue May 25 08:18:21 2010 From: marek.vasut at gmail.com (Marek Vasut) Date: Tue, 25 May 2010 14:18:21 +0200 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <4BFBA4BA.9020502@compulab.co.il> References: <4BFBA4BA.9020502@compulab.co.il> Message-ID: <201005251418.21630.marek.vasut@gmail.com> Dne ?t 25. kv?tna 2010 12:21:46 Mike Rapoport napsal(a): > Lei Wen wrote: > > On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport wrote: > >> Lei Wen wrote: > >>> Hi Mike, > >>> > >>> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport > >>> > >>> wrote: > >>>> Hi Lei, > >>>> > >>>> Lei Wen wrote: > >>>>> Hi Mike, > >>>> > >>>> 2) I don't like hadrcoding of NAND parameters into the driver. You > >>>> remove *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration > >>>> option and instead > >>>> you enforce use of built-in definitions. The driver in its current > >>>> state is > >>>> robust enough to allow platforms to define optimized NAND timings > >>>> either in > >>>> the bootloader or in the kernel. If you don't like that multiple > >>>> platforms > >>>> define the same flash chip create an enumeration of built-in types and > >>>> let > >>>> platforms to use this enumeration to select the NAND chip. But, > >>>> anyway, there should be a fallback mode that will support NAND chips > >>>> that are not defined in the driver, probably with suboptimal timings. > >>> > >>> Original driver also use hardcoding. And in bootloader, this timing > >>> parameter is also hard coding. > >>> We cannot deduce a parameter set only from the nand id, that is why we > >>> need a table to preset it. > >>> If one nand chip is not listed in that table, the chip id would still > >>> be printed out, so that we can do something for that. > >>> If we encourage people to continue on this, we would not able to > >>> really "driver" that nand. > >> > >> Currently pxa3xx-nand has three operational modes: > >> - use NAND parameters supplied by the platform > >> - use presets configured by the bootloader chain > >> - use built-in NAND parameters, marked as deprecated in favor of the > >> first two > >> You remove the first two modes completely and require that each and > >> every NAND chip used on pxa3xx based platform will be added to the > >> driver. This way you make the driver less robust and harder to use for > >> platform developers, not mentioning you're breaking the existing > >> platforms. In my opinion, the driver *may* support built-in definitions > >> for certain NAND flashes and *must* support configuration of the NAND > >> parameters by the platform code and bootloader. > > > > Hi Mike, > > > > Well... I would submit another patch set which would reserve a way > > that platform could pass its parameter setting. > > Like specify the certain type of nand chip parameter for each chip > > select. Is that ok for you? > > > > For bootloader pass parameter method, I think this way should be > > dropped... For there is attributed which we could not tell from > > registers... > > What do you think of this? > > Can you please elaborate what are the attributes that cannot be detected? MFPR drive strength maybe ? That's none of kernel's concern (as of now). > > > Thanks, > > Lei From adrian.wenl at gmail.com Tue May 25 09:01:00 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Tue, 25 May 2010 21:01:00 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <4BFBA4BA.9020502@compulab.co.il> References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> <4BFBA4BA.9020502@compulab.co.il> Message-ID: On Tue, May 25, 2010 at 6:21 PM, Mike Rapoport wrote: > Lei Wen wrote: >> >> On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport >> wrote: >>> >>> Lei Wen wrote: >>>> >>>> Hi Mike, >>>> >>>> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport >>>> wrote: >>>>> >>>>> Hi Lei, >>>>> >>>>> Lei Wen wrote: >>>>>> >>>>>> Hi Mike, >>>>>> >>>>> 2) I don't like hadrcoding of NAND parameters into the driver. You >>>>> remove >>>>> *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and >>>>> instead >>>>> you enforce use of built-in definitions. The driver in its current >>>>> state >>>>> is >>>>> robust enough to allow platforms to define optimized NAND timings >>>>> either >>>>> in >>>>> the bootloader or in the kernel. If you don't like that multiple >>>>> platforms >>>>> define the same flash chip create an enumeration of built-in types and >>>>> let >>>>> platforms to use this enumeration to select the NAND chip. But, anyway, >>>>> there should be a fallback mode that will support NAND chips that are >>>>> not >>>>> defined in the driver, probably with suboptimal timings. >>>> >>>> Original driver also use hardcoding. And in bootloader, this timing >>>> parameter is also hard coding. >>>> We cannot deduce a parameter set only from the nand id, that is why we >>>> need a table to preset it. >>>> If one nand chip is not listed in that table, the chip id would still >>>> be printed out, so that we can do something for that. >>>> If we encourage people to continue on this, we would not able to >>>> really "driver" that nand. >>> >>> Currently pxa3xx-nand has three operational modes: >>> - use NAND parameters supplied by the platform >>> - use presets configured by the bootloader chain >>> - use built-in NAND parameters, marked as deprecated in favor of the >>> first >>> two >>> You remove the first two modes completely and require that each and every >>> NAND chip used on pxa3xx based platform will be added to the driver. This >>> way you make the driver less robust and harder to use for platform >>> developers, not mentioning you're breaking the existing platforms. >>> In my opinion, the driver *may* support built-in definitions for certain >>> NAND flashes and *must* support configuration of the NAND parameters by >>> the >>> platform code and bootloader. >>> >> >> Hi Mike, >> >> Well... I would submit another patch set which would reserve a way >> that platform could pass its parameter setting. >> Like specify the certain type of nand chip parameter for each chip >> select. Is that ok for you? >> >> For bootloader pass parameter method, I think this way should be >> dropped... For there is attributed which we could not tell from >> registers... >> What do you think of this? > > Can you please elaborate what are the attributes that cannot be detected? The attributes comes from two new features that would be included into pxa3xx_nand: BCH support and 8bit per 512bytes ECC. Originally, our pxa3xx_nand only support Hamming ECC way. So no doubt just read the timing register, and just set use ecc bit in NDCR is enough. But for now there is two type of ECC type. For distinguish, we introduce a new register called NDECCCTRL. NDECCCTRL_BCH_EN in the bit 0 of that register control whether use the BCH ECC. You may ask me why not just read from NDECCCTRL to know the ECC type. It is right, but not always to be true. It the last command executed for nand before kernel take control is not read or write operation, the bootloader has no reason to set the NDECCCTRL register. So our kernel also unable to detect whether to use BCH or HAMMING ECC. This two type of ecc has different character, if use hamming ecc for reading while that page is written by BCH, it would instant report of DB error... This is not the worst case., for we may ask the bootloader to always set the NDECCCTRL. (There is no reason to apply ECC when do command except the read and write although) The worst would comes at the supporting of 8bit per 512 bytes ECC. Our BCH engine only support 16bit corroction per 2k data, aka 4bit per 512bytes. If we need to support 8bit per 512bytes feature, which is needed by a lot of newest flash which require such high ecc strength. Then we have to apply the BCH to 1k data instead of 2k. The layout of content on flash would change. Original BCH apply to 2k nand, the layout may like: | 2k data | + | 30 bytes ECC | Now after apply BCH to 1k range, the layout would be like: | 1k data | + | 30 bytes ECC| + | 1k data| + |30 bytes ECC|. Even as I said let the bootloader to always set the NDECCCTRL. The kernel would still cannot distinguish the two use case of 4bit per 512bytes and 8bit per 512 bytes ECC strength requirement. For they both use BCH, the only difference could be told on the nand layout, not by register reading. Those two new feature would lead different nand content layout. So if not distinguish properly, nand would not be able to work functional. And obviously, the two features cannot get from register reading, and that is the reason why I suggest drop the feature. Thanks, Lei From eric.y.miao at gmail.com Tue May 25 09:21:13 2010 From: eric.y.miao at gmail.com (Eric Miao) Date: Tue, 25 May 2010 21:21:13 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> <4BFBA4BA.9020502@compulab.co.il> Message-ID: On Tue, May 25, 2010 at 9:01 PM, Lei Wen wrote: > On Tue, May 25, 2010 at 6:21 PM, Mike Rapoport wrote: >> Lei Wen wrote: >>> >>> On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport >>> wrote: >>>> >>>> Lei Wen wrote: >>>>> >>>>> Hi Mike, >>>>> >>>>> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport >>>>> wrote: >>>>>> >>>>>> Hi Lei, >>>>>> >>>>>> Lei Wen wrote: >>>>>>> >>>>>>> Hi Mike, >>>>>>> >>>>>> 2) I don't like hadrcoding of NAND parameters into the driver. You >>>>>> remove >>>>>> *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and >>>>>> instead >>>>>> you enforce use of built-in definitions. The driver in its current >>>>>> state >>>>>> is >>>>>> robust enough to allow platforms to define optimized NAND timings >>>>>> either >>>>>> in >>>>>> the bootloader or in the kernel. If you don't like that multiple >>>>>> platforms >>>>>> define the same flash chip create an enumeration of built-in types and >>>>>> let >>>>>> platforms to use this enumeration to select the NAND chip. But, anyway, >>>>>> there should be a fallback mode that will support NAND chips that are >>>>>> not >>>>>> defined in the driver, probably with suboptimal timings. >>>>> >>>>> Original driver also use hardcoding. And in bootloader, this timing >>>>> parameter is also hard coding. >>>>> We cannot deduce a parameter set only from the nand id, that is why we >>>>> need a table to preset it. >>>>> If one nand chip is not listed in that table, the chip id would still >>>>> be printed out, so that we can do something for that. >>>>> If we encourage people to continue on this, we would not able to >>>>> really "driver" that nand. >>>> >>>> Currently pxa3xx-nand has three operational modes: >>>> - use NAND parameters supplied by the platform >>>> - use presets configured by the bootloader chain >>>> - use built-in NAND parameters, marked as deprecated in favor of the >>>> first >>>> two >>>> You remove the first two modes completely and require that each and every >>>> NAND chip used on pxa3xx based platform will be added to the driver. This >>>> way you make the driver less robust and harder to use for platform >>>> developers, not mentioning you're breaking the existing platforms. >>>> In my opinion, the driver *may* support built-in definitions for certain >>>> NAND flashes and *must* support configuration of the NAND parameters by >>>> the >>>> platform code and bootloader. >>>> >>> >>> Hi Mike, >>> >>> Well... I would submit another patch set which would reserve a way >>> that platform could pass its parameter setting. >>> Like specify the certain type of nand chip parameter for each chip >>> select. Is that ok for you? >>> >>> For bootloader pass parameter method, I think this way should be >>> dropped... For there is attributed which we could not tell from >>> registers... >>> What do you think of this? >> >> Can you please elaborate what are the attributes that cannot be detected? > > The attributes comes from two new features that would be included into > pxa3xx_nand: BCH support and 8bit per 512bytes ECC. > Originally, our pxa3xx_nand only support Hamming ECC way. So no doubt > just read the timing register, and just set use ecc bit in NDCR is > enough. > But for now there is two type of ECC type. For distinguish, we > introduce a new register called NDECCCTRL. NDECCCTRL_BCH_EN in the bit > 0 of that register control whether use the BCH ECC. > You may ask me why not just read from NDECCCTRL to know the ECC type. > It is right, but not always to be true. It the last command executed > for nand before kernel take control is not read or write operation, > the bootloader has no reason to set the NDECCCTRL register. So our > kernel also unable to detect whether to use BCH or HAMMING ECC. > > This two type of ecc has different character, if use hamming ecc for > reading while that page is written by BCH, it would instant report of > DB error... > This is not the worst case., for we may ask the bootloader to always > set the NDECCCTRL. (There is no reason to apply ECC when do command > except the read and write although) > > The worst would comes at the supporting of 8bit per 512 bytes ECC. Our > BCH engine only support 16bit corroction per 2k data, aka 4bit per > 512bytes. > If we need to support 8bit per 512bytes feature, which is needed by a > lot of newest flash which require such high ecc strength. > Then we have to apply the BCH to 1k data instead of 2k. The layout of > content on flash would change. > Original BCH apply to 2k nand, the layout may like: | 2k data | + | 30 > bytes ECC | > Now after apply BCH to 1k range, the layout would be like: | 1k data | > + | 30 bytes ECC| + | 1k data| + |30 bytes ECC|. > Even as I said let the bootloader to always set the NDECCCTRL. The > kernel would still cannot distinguish the two use case of 4bit per > 512bytes and 8bit per 512 bytes ECC strength requirement. > For they both use BCH, the only difference could be told on the nand > layout, not by register reading. > > Those two new feature would lead different nand content layout. So if > not distinguish properly, nand would not be able to work functional. > And obviously, the two features cannot get from register reading, and > that is the reason why I suggest drop the feature. > Then would it be possible to just drop the feature for pxa168 and onward? I guess there might be some existing usages out there for pxa3xx already, so not to affect existing systems. Actually, it's now quite easy for a single driver to distinguish this, through platform_device_id table please, see drivers/i2c/busses/i2c-pxa.c for an example. I'd like to call the device pxa168-nand or something. From s-ghorai at ti.com Tue May 25 10:37:42 2010 From: s-ghorai at ti.com (Ghorai, Sukumar) Date: Tue, 25 May 2010 20:07:42 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274284094.6286.17.camel@thunk> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> Message-ID: <2A3DCF3DA181AD40BDE86A3150B27B6B030DA9F8EB@dbde02.ent.ti.com> Vimal, > -----Original Message----- > From: Vimal Singh [mailto:vimal.newwork at gmail.com] > Sent: Thursday, May 20, 2010 12:01 AM > To: Ghorai, Sukumar > Cc: linux-omap at vger.kernel.org; linux-mtd at lists.infradead.org; > tony at atomide.com; sakoman at gmail.com; mike at compulab.co.il; > Artem.Bityutskiy at nokia.com; peter.barada at gmail.com > Subject: Re: [PATCH v3 1/3] omap3 gpmc: functionality enhancement > > On Wed, May 19, 2010 at 11:34 PM, Ghorai, Sukumar wrote: > >> > > + > >> > > + ? ? ? case GPMC_CONFIG_RDY_BSY: > >> > > + ? ? ? ? ? ? ? regval ?= gpmc_cs_read_reg(cs, GPMC_CS_CONFIG1); > >> > > + ? ? ? ? ? ? ? regval |= WR_RD_PIN_MONITORING; > >> > > + ? ? ? ? ? ? ? gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, regval); > >> > > + ? ? ? ? ? ? ? break; > >> > > >> > IIRC, at least in OMAP2/3, ready/busy pin is not in use (not > connected). > >> > >> On the Logic OMAP3530 LV SOM and Torpedo modules, the R/B# pin of the > >> NAND in the Micron mt29c2g4maklajg-6it POP part is connected to the > >> WAIT0 pin on the OMAP3530 and I'm looking to use it to speed up NAND > >> accesses > > [Ghorai] So better keep this feature, > > Yes, looks like there are some boards which can still take advantage of > this. > > >> > [...] > >> > > @@ -456,13 +572,20 @@ EXPORT_SYMBOL(gpmc_prefetch_enable); > >> > > ?/** > >> > > ?* gpmc_prefetch_reset - disables and stops the prefetch engine > >> > > ?*/ > >> > > -void gpmc_prefetch_reset(void) > >> > > +int gpmc_prefetch_reset(int cs) > >> > > ?{ > >> > > + ? ? ? if (gpmc_pref_used == cs) > >> > > + ? ? ? ? ? ? ? gpmc_pref_used = -EINVAL; > >> > > + ? ? ? else > >> > > + ? ? ? ? ? ? ? return -EINVAL; > >> > > + > >> > > >> > This is also not required. As, this function will be called only if > >> > prefetch was used. > > [Ghorai] Agree. Can you see this input too? > > http://www.mail-archive.com/linux-omap at vger.kernel.org/msg28520.html > > Exactly, this is what I am telling here. Enable prefetch engine call > is already being check for *busy* or not. [Ghorai] Agree. > > > > [...] > >> > > +int gpmc_ecc_init(int cs, int ecc_size) > >> > > +{ > >> > > + ? ? ? unsigned int val = 0x0; > >> > > + > >> > > + ? ? ? /* check if ecc engine already by another cs */ > >> > > + ? ? ? if (gpmc_ecc_used == -EINVAL) > >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = cs; > >> > > + ? ? ? else > >> > > + ? ? ? ? ? ? ? return -EBUSY; > >> > Here few things need be to consider: > >> > 1. 'init' is supposed to done once for every instance of driver > during > >> probe > >> > 2. But ECC engine, too, have only one instance at a time, So > >> > 3. As long as all NAND chip are supposed to use same ECC machenism, > we > >> > can go for only one time 'init' for all drivers, perhaps in > >> > gpmc_nand.c. > >> > 4. But in case, different instances of driver (or NAND chip) requires > >> > different ECC machenism (for ex. Hamming or BCH, or even with > >> > different capabilities of error correction), > >> > this will no longer vailid. Then rather we should have something like > >> > 'gpmc_ecc_config' call to configer ECC engine for everytime a driver > >> > needs it (something like as it is done for prefetch engine). > > [Ghorai] > > a. do you think it will reduce the throughput? > No. But in current implementation it will be called for each instance > driver. (see my 3rd point) > > > b. Moreover I think we will take this as 5th patch as cleanup/ > improvemnt. > > c. And how to know that ECC engine is in used other driver should not > use it? Any bit to know that ecc engine is busy, as we check for prefetch? > Do not really remember config registers. Perhaps there is no way. > But I guess you should check into register GPMC_ECC_CONFIG at bit 1. > This is the bit we are setting to enable ECC calculation, IIRC. [Ghorai] there are two functions - info->nand.ecc.calculate = omap_calculate_ecc; info->nand.ecc.hwctl = omap_enable_hwecc; And GPMC_ECC_CONFIG register.. 3:1 ECCCS Selects the CS where ECC is computed 0 ECCENABLE Enables the ECC feature Now we enable omap_enable_hwecc (with GPMC_ECC_CONFIG[ECCENABLE]=1); and its get disabled (automatically) when ecc_size data transfer over. But say still it did not read the ecc value yet (omap_calculate_ecc). So how to protect following omap_enable_hwecc() before omap_calculate_ecc() without additional flag? Any input is welcome. > > > d. any further input on http://www.mail-archive.com/linux- > omap at vger.kernel.org/msg28520.html > And this what I was suggesting in my point 4. In my example > 'gpmc_ecc_config' is analogy to 'gpmc_ecc_request'. > I said *config*, since in such scenario you need to configer HW > ECCconfig register everytime as well, rather just checking > availability and enabling. [Ghorai] As above. > > > > [...] > >> > > +int gpmc_ecc_reset(int cs) > >> > > +{ > >> > > + ? ? ? if (gpmc_ecc_used == cs) > >> > > + ? ? ? ? ? ? ? gpmc_ecc_used = -EINVAL; > >> > > + ? ? ? else > >> > > + ? ? ? ? ? ? ? return -EINVAL; > >> > > + > >> > > + ? ? ? return 0; > >> > > +} > > I guess in this function you should also clear gpmc ecc config > register explicitly. > > > -- > Regards, > Vimal Singh From vimal.newwork at gmail.com Tue May 25 11:34:37 2010 From: vimal.newwork at gmail.com (Vimal Singh) Date: Tue, 25 May 2010 21:04:37 +0530 Subject: [PATCH v3 1/3] omap3 gpmc: functionality enhancement In-Reply-To: <2A3DCF3DA181AD40BDE86A3150B27B6B030DA9F8EB@dbde02.ent.ti.com> References: <1274181389-7488-1-git-send-email-s-ghorai@ti.com> <1274181389-7488-2-git-send-email-s-ghorai@ti.com> <1274284094.6286.17.camel@thunk> <2A3DCF3DA181AD40BDE86A3150B27B6B030D991D50@dbde02.ent.ti.com> <2A3DCF3DA181AD40BDE86A3150B27B6B030DA9F8EB@dbde02.ent.ti.com> Message-ID: On Tue, May 25, 2010 at 8:07 PM, Ghorai, Sukumar wrote: [...] >> > c. And how to know that ECC engine is in used other driver should not >> use it? Any bit to know that ecc engine is busy, as we check for prefetch? >> Do not really remember config registers. Perhaps there is no way. >> But I guess you should check into register GPMC_ECC_CONFIG at bit 1. >> This is the bit we are setting to enable ECC calculation, IIRC. > [Ghorai] there are two functions - > ? ? ? info->nand.ecc.calculate ? ? ? ?= omap_calculate_ecc; > ? ? ? info->nand.ecc.hwctl ? ? ? ? ? ?= omap_enable_hwecc; > And GPMC_ECC_CONFIG register.. > ? ? ? ?3:1 ECCCS Selects the CS where ECC is computed > ? ? ? ?0 ECCENABLE Enables the ECC feature > Now we enable omap_enable_hwecc (with GPMC_ECC_CONFIG[ECCENABLE]=1); and its get disabled (automatically) when ecc_size data transfer over. > But say still it did not read the ecc value yet (omap_calculate_ecc). > So how to protect following omap_enable_hwecc() before omap_calculate_ecc() ?without additional flag? Any input is welcome. Oh yes, that's is a problem. Perhaps in that case you have to protect it in very much same way you already did. -- Regards, Vimal Singh From mike at compulab.co.il Wed May 26 05:57:02 2010 From: mike at compulab.co.il (Mike Rapoport) Date: Wed, 26 May 2010 12:57:02 +0300 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> <4BFBA4BA.9020502@compulab.co.il> Message-ID: <4BFCF06E.5010809@compulab.co.il> Lei Wen wrote: > On Tue, May 25, 2010 at 6:21 PM, Mike Rapoport wrote: >> Can you please elaborate what are the attributes that cannot be detected? > > The attributes comes from two new features that would be included into > pxa3xx_nand: BCH support and 8bit per 512bytes ECC. > Originally, our pxa3xx_nand only support Hamming ECC way. So no doubt > just read the timing register, and just set use ecc bit in NDCR is > enough. > But for now there is two type of ECC type. For distinguish, we > introduce a new register called NDECCCTRL. NDECCCTRL_BCH_EN in the bit > 0 of that register control whether use the BCH ECC. > You may ask me why not just read from NDECCCTRL to know the ECC type. > It is right, but not always to be true. It the last command executed > for nand before kernel take control is not read or write operation, > the bootloader has no reason to set the NDECCCTRL register. So our > kernel also unable to detect whether to use BCH or HAMMING ECC. > > This two type of ecc has different character, if use hamming ecc for > reading while that page is written by BCH, it would instant report of > DB error... > This is not the worst case., for we may ask the bootloader to always > set the NDECCCTRL. (There is no reason to apply ECC when do command > except the read and write although) > > The worst would comes at the supporting of 8bit per 512 bytes ECC. Our > BCH engine only support 16bit corroction per 2k data, aka 4bit per > 512bytes. > If we need to support 8bit per 512bytes feature, which is needed by a > lot of newest flash which require such high ecc strength. > Then we have to apply the BCH to 1k data instead of 2k. The layout of > content on flash would change. > Original BCH apply to 2k nand, the layout may like: | 2k data | + | 30 > bytes ECC | > Now after apply BCH to 1k range, the layout would be like: | 1k data | > + | 30 bytes ECC| + | 1k data| + |30 bytes ECC|. > Even as I said let the bootloader to always set the NDECCCTRL. The > kernel would still cannot distinguish the two use case of 4bit per > 512bytes and 8bit per 512 bytes ECC strength requirement. > For they both use BCH, the only difference could be told on the nand > layout, not by register reading. > > Those two new feature would lead different nand content layout. So if > not distinguish properly, nand would not be able to work functional. > And obviously, the two features cannot get from register reading, and > that is the reason why I suggest drop the feature. Why not make the ECC type and strength part of the pxa3xx_nand_platform_data? This way you can ensure NAND layout consistency for particular platform without reduction in the driver robustness. > Thanks, > Lei -- Sincerely yours, Mike. From adrian.wenl at gmail.com Wed May 26 09:35:07 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Wed, 26 May 2010 21:35:07 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> <4BFBA4BA.9020502@compulab.co.il> Message-ID: On Tue, May 25, 2010 at 9:21 PM, Eric Miao wrote: > On Tue, May 25, 2010 at 9:01 PM, Lei Wen wrote: >> On Tue, May 25, 2010 at 6:21 PM, Mike Rapoport wrote: >>> Lei Wen wrote: >>>> >>>> On Mon, May 24, 2010 at 9:21 PM, Mike Rapoport >>>> wrote: >>>>> >>>>> Lei Wen wrote: >>>>>> >>>>>> Hi Mike, >>>>>> >>>>>> On Mon, May 24, 2010 at 7:00 PM, Mike Rapoport >>>>>> wrote: >>>>>>> >>>>>>> Hi Lei, >>>>>>> >>>>>>> Lei Wen wrote: >>>>>>>> >>>>>>>> Hi Mike, >>>>>>>> >>>>>>> 2) I don't like hadrcoding of NAND parameters into the driver. You >>>>>>> remove >>>>>>> *deprecetad* CONFIG_MTD_NAND_PXA3xx_BUILTIN configuration option and >>>>>>> instead >>>>>>> you enforce use of built-in definitions. The driver in its current >>>>>>> state >>>>>>> is >>>>>>> robust enough to allow platforms to define optimized NAND timings >>>>>>> either >>>>>>> in >>>>>>> the bootloader or in the kernel. If you don't like that multiple >>>>>>> platforms >>>>>>> define the same flash chip create an enumeration of built-in types and >>>>>>> let >>>>>>> platforms to use this enumeration to select the NAND chip. But, anyway, >>>>>>> there should be a fallback mode that will support NAND chips that are >>>>>>> not >>>>>>> defined in the driver, probably with suboptimal timings. >>>>>> >>>>>> Original driver also use hardcoding. And in bootloader, this timing >>>>>> parameter is also hard coding. >>>>>> We cannot deduce a parameter set only from the nand id, that is why we >>>>>> need a table to preset it. >>>>>> If one nand chip is not listed in that table, the chip id would still >>>>>> be printed out, so that we can do something for that. >>>>>> If we encourage people to continue on this, we would not able to >>>>>> really "driver" that nand. >>>>> >>>>> Currently pxa3xx-nand has three operational modes: >>>>> - use NAND parameters supplied by the platform >>>>> - use presets configured by the bootloader chain >>>>> - use built-in NAND parameters, marked as deprecated in favor of the >>>>> first >>>>> two >>>>> You remove the first two modes completely and require that each and every >>>>> NAND chip used on pxa3xx based platform will be added to the driver. This >>>>> way you make the driver less robust and harder to use for platform >>>>> developers, not mentioning you're breaking the existing platforms. >>>>> In my opinion, the driver *may* support built-in definitions for certain >>>>> NAND flashes and *must* support configuration of the NAND parameters by >>>>> the >>>>> platform code and bootloader. >>>>> >>>> >>>> Hi Mike, >>>> >>>> Well... I would submit another patch set which would reserve a way >>>> that platform could pass its parameter setting. >>>> Like specify the certain type of nand chip parameter for each chip >>>> select. Is that ok for you? >>>> >>>> For bootloader pass parameter method, I think this way should be >>>> dropped... For there is attributed which we could not tell from >>>> registers... >>>> What do you think of this? >>> >>> Can you please elaborate what are the attributes that cannot be detected? >> >> The attributes comes from two new features that would be included into >> pxa3xx_nand: BCH support and 8bit per 512bytes ECC. >> Originally, our pxa3xx_nand only support Hamming ECC way. So no doubt >> just read the timing register, and just set use ecc bit in NDCR is >> enough. >> But for now there is two type of ECC type. For distinguish, we >> introduce a new register called NDECCCTRL. NDECCCTRL_BCH_EN in the bit >> 0 of that register control whether use the BCH ECC. >> You may ask me why not just read from NDECCCTRL to know the ECC type. >> It is right, but not always to be true. It the last command executed >> for nand before kernel take control is not read or write operation, >> the bootloader has no reason to set the NDECCCTRL register. So our >> kernel also unable to detect whether to use BCH or HAMMING ECC. >> >> This two type of ecc has different character, if use hamming ecc for >> reading while that page is written by BCH, it would instant report of >> DB error... >> This is not the worst case., for we may ask the bootloader to always >> set the NDECCCTRL. (There is no reason to apply ECC when do command >> except the read and write although) >> >> The worst would comes at the supporting of 8bit per 512 bytes ECC. Our >> BCH engine only support 16bit corroction per 2k data, aka 4bit per >> 512bytes. >> If we need to support 8bit per 512bytes feature, which is needed by a >> lot of newest flash which require such high ecc strength. >> Then we have to apply the BCH to 1k data instead of 2k. The layout of >> content on flash would change. >> Original BCH apply to 2k nand, the layout may like: | 2k data | + | 30 >> bytes ECC | >> Now after apply BCH to 1k range, the layout would be like: | 1k data | >> + | 30 bytes ECC| + | 1k data| + |30 bytes ECC|. >> Even as I said let the bootloader to always set the NDECCCTRL. The >> kernel would still cannot distinguish the two use case of 4bit per >> 512bytes and 8bit per 512 bytes ECC strength requirement. >> For they both use BCH, the only difference could be told on the nand >> layout, not by register reading. >> >> Those two new feature would lead different nand content layout. So if >> not distinguish properly, nand would not be able to work functional. >> And obviously, the two features cannot get from register reading, and >> that is the reason why I suggest drop the feature. >> > > Then would it be possible to just drop the feature for pxa168 and onward? > I guess there might be some existing usages out there for pxa3xx already, > so not to affect existing systems. > > Actually, it's now quite easy for a single driver to distinguish this, through > platform_device_id table please, see drivers/i2c/busses/i2c-pxa.c for an > example. I'd like to call the device pxa168-nand or something. Yes, that is also what I want. Just put another attributes like ecc strength into flash_info structure. This info could be revealed in the built_in_table or flash info passed from platform data. Also this ecc strength could take place the ecc type used in the flash info structure. Thanks, Lei From adrian.wenl at gmail.com Wed May 26 09:42:28 2010 From: adrian.wenl at gmail.com (Lei Wen) Date: Wed, 26 May 2010 21:42:28 +0800 Subject: [PATCH 01/20] mtd: pxa3xx_nand: refuse the flash definition get from platform In-Reply-To: <4BFCF06E.5010809@compulab.co.il> References: <4BFA2B5B.4080105@compulab.co.il> <4BFA5C58.7050109@compulab.co.il> <4BFA7D60.6020703@compulab.co.il> <4BFBA4BA.9020502@compulab.co.il> <4BFCF06E.5010809@compulab.co.il> Message-ID: On Wed, May 26, 2010 at 5:57 PM, Mike Rapoport wrote: > Lei Wen wrote: >> >> On Tue, May 25, 2010 at 6:21 PM, Mike Rapoport >> wrote: > >>> Can you please elaborate what are the attributes that cannot be detected? >> >> The attributes comes from two new features that would be included into >> pxa3xx_nand: BCH support and 8bit per 512bytes ECC. >> Originally, our pxa3xx_nand only support Hamming ECC way. So no doubt >> just read the timing register, and just set use ecc bit in NDCR is >> enough. >> But for now there is two type of ECC type. For distinguish, we >> introduce a new register called NDECCCTRL. NDECCCTRL_BCH_EN in the bit >> 0 of that register control whether use the BCH ECC. >> You may ask me why not just read from NDECCCTRL to know the ECC type. >> It is right, but not always to be true. It the last command executed >> for nand before kernel take control is not read or write operation, >> the bootloader has no reason to set the NDECCCTRL register. So our >> kernel also unable to detect whether to use BCH or HAMMING ECC. >> >> This two type of ecc has different character, if use hamming ecc for >> reading while that page is written by BCH, it would instant report of >> DB error... >> This is not the worst case., for we may ask the bootloader to always >> set the NDECCCTRL. (There is no reason to apply ECC when do command >> except the read and write although) >> >> The worst would comes at the supporting of 8bit per 512 bytes ECC. Our >> BCH engine only support 16bit corroction per 2k data, aka 4bit per >> 512bytes. >> If we need to support 8bit per 512bytes feature, which is needed by a >> lot of newest flash which require such high ecc strength. >> Then we have to apply the BCH to 1k data instead of 2k. The layout of >> content on flash would change. >> Original BCH apply to 2k nand, the layout may like: | 2k data | + | 30 >> bytes ECC | >> Now after apply BCH to 1k range, the layout would be like: | 1k data | >> + | 30 bytes ECC| + | 1k data| + |30 bytes ECC|. >> Even as I said let the bootloader to always set the NDECCCTRL. The >> kernel would still cannot distinguish the two use case of 4bit per >> 512bytes and 8bit per 512 bytes ECC strength requirement. >> For they both use BCH, the only difference could be told on the nand >> layout, not by register reading. >> >> Those two new feature would lead different nand content layout. So if >> not distinguish properly, nand would not be able to work functional. >> And obviously, the two features cannot get from register reading, and >> that is the reason why I suggest drop the feature. > > Why not make the ECC type and strength part of the > pxa3xx_nand_platform_data? This way you can ensure NAND layout consistency > for particular platform without reduction in the driver robustness. > The reason why we need define different ecc type and ecc strength is for those different kind of ecc strength could give different performance cost. For data safe consideration, the higher of ecc strength would be safer. But you must notice that the higher ecc strength would bring to us more performance downgrade. For flash that only need 1bit correction per 512 bytes, we certainly don't need the 8bit ECC, or we would suffer from the performance. One table with the ECC strength description would solve all the problem we have, and also no risk in the driver robustness. Thanks, Lei From taliaferro62 at gmail.com Wed May 26 12:06:15 2010 From: taliaferro62 at gmail.com (twebb) Date: Wed, 26 May 2010 12:06:15 -0400 Subject: UBIFS failed to recover master node In-Reply-To: <1274763914.2106.1.camel@localhost> References: <1274763914.2106.1.camel@localhost> Message-ID: >> I've had several cases where our MLC NAND flash appears corrupted in >> such a way that one of three UBIFS volumes can not be mounted due to >> "failed to recover master node". ?I haven't been able to reproduce the >> problem, but we've had at least 5 incidents where this has occurred. >> (A partial capture from one of the failures is below.) >> >> I'm starting to investigate this problem and don't know if this is a >> UBIFS/UBI problem or a NAND driver problem. ?I'm starting the process >> of back-porting the latest UBIFS code to our 2.6.29 kernel - hoping >> that new UBIFS code will solve the problem. ?However, this may also be >> a driver problem and I wonder if I also need to update that driver >> (pxa3xx_nand). ?Any suggestions for debugging this problem? >> >> Thanks, >> twebb >> >> >> capture: >> [root at ESIedge mtd-utils]# mount -t ubifs ubi0_0 /mnt/ >> [ ?239.605869] UBI error: ubi_io_read: error -74 while reading 516096 >> bytes from PEB 4:8192, read 516096 bytes >> [ ?239.616317] UBIFS error (pid 676): ubifs_scan: corrupt empty space >> at LEB 2:268135 >> [ ?239.623996] UBIFS error (pid 676): ubifs_scanned_corruption: >> corruption at LEB 2:268135 >> [ ?239.642101] UBIFS error (pid 676): ubifs_scan: LEB 2 scanning failed >> [ ?239.976396] UBI error: ubi_io_read: error -74 while reading 516096 >> bytes from PEB 4:8192, read 516096 bytes >> [ ?239.986742] UBIFS error (pid 676): ubifs_recover_master_node: >> failed to recover master node >> mount: mounting ubi0_0 on /mnt/ failed: Invalid argument > > Please, enable all debugging messages, mount this flash again, and send > the messages. > > -- > Best Regards, > Artem Bityutskiy (????? ????????) > I have enabled... CONFIG_MTD_UBI_DEBUG=y CONFIG_UBIFS_FS_DEBUG=y Should I enable CONFIG_UBIFS_FS_DEBUG_CHKS ? From dedekind1 at gmail.com Tue May 11 23:32:55 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 12 May 2010 06:32:55 +0300 Subject: Erase race? In-Reply-To: References: <1272373142.7750.5.camel@localhost> Message-ID: <1273635175.8881.3.camel@localhost.localdomain> On Tue, 2010-05-11 at 22:30 -0400, Jon Ringle wrote: > On Tue, Apr 27, 2010 at 8:59 AM, Artem Bityutskiy wrote: > > On Tue, 2010-04-20 at 16:24 -0400, Jon Ringle wrote: > >> On Tue, Apr 13, 2010 at 4:15 PM, Jon Ringle wrote: > >> > Hi, > >> > I have a few machines that have UBI and UBIFS on NOR flash that are > >> > undergoing continuous reboot testing. > >> > One of them just caught the following failure: > >> > > >> > [ 51.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) > >> > [ 51.250000] UBI error: ubi_io_write: error -22 while writing 64 > >> > bytes to PEB 226:0, written 0 bytes > >> > [ 51.270000] UBI error: erase_worker: failed to erase PEB 226, error -22 > >> > [ 51.270000] UBI warning: ubi_ro_mode: switch to read-only mode > >> > [ 51.290000] UBI error: do_work: work failed with error code -22 > >> > [ 51.290000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 > >> > > >> > Looking at this it appears that the failure might have been caused due > >> > to the erase_worker and ubi_io_write occurring out of order... since > >> > it looks like ubi_io_write was trying to write at offset 0 of the PEB, > >> > which I imagine would have to be the EC header, which should happen > >> > after the block is erased. But it doesn't seem to be the case here. > >> > >> I had this issue occur again on another system: > >> [ 48.250000] IXP4XX-Flash.0: buffer write error (status 0xd0) > >> [ 48.250000] UBI error: ubi_io_write: error -22 while writing 64 > >> bytes to PEB 111:0, written 0 bytes > >> [ 48.280000] UBI error: erase_worker: failed to erase PEB 111, error -22 > >> [ 48.280000] UBI warning: ubi_ro_mode: switch to read-only mode > >> [ 48.310000] UBI error: do_work: work failed with error code -22 > >> [ 48.310000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 > >> > >> Can anyone comment as to my theory that this is a race condition > >> between ubi_io_write and erase_worker occurring out of order? > > > > Did you debug this further? Any new findings? > > I finally got a capture of this with CONFIG_MTD_UBI_DEBUG turned on: > > [ 61.710000] IXP4XX-Flash.0: buffer write error (status 0xd0) > [ 61.710000] UBI error: ubi_io_write: error -22 while writing 64 > bytes to PEB 136:0, written 0 bytes > [ 61.740000] [] (unwind_backtrace+0x0/0x170) from > [] (ubi_io_write+0x1ec/0x214 [ubi]) > [ 61.770000] [] (ubi_io_write+0x1ec/0x214 [ubi]) from > [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) > [ 61.800000] [] (ubi_io_write_vid_hdr+0x1cc/0x20c [ubi]) > from [] (sync_erase+0xd4/0x128 [ubi]) > [ 61.830000] [] (sync_erase+0xd4/0x128 [ubi]) from > [] (erase_worker+0x28/0x2d8 [ubi]) > [ 61.860000] [] (erase_worker+0x28/0x2d8 [ubi]) from > [] (do_work+0x98/0x13c [ubi]) > [ 61.860000] [] (do_work+0x98/0x13c [ubi]) from > [] (ubi_thread+0xc4/0x158 [ubi]) > [ 61.890000] [] (ubi_thread+0xc4/0x158 [ubi]) from > [] (kthread+0x7c/0x84) > [ 61.890000] [] (kthread+0x7c/0x84) from [] > (kernel_thread_exit+0x0/0x8) > [ 61.920000] UBI error: erase_worker: failed to erase PEB 136, error -22 > [ 61.920000] UBI warning: ubi_ro_mode: switch to read-only mode > [ 61.950000] UBI error: do_work: work failed with error code -22 > [ 61.950000] UBI error: ubi_thread: ubi_bgt0d: work failed with error code -22 So it is probably not a kind of race you assumed before. Your flash for some reasons encounters an error, dunno why. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Thu May 20 23:53:30 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Fri, 21 May 2010 06:53:30 +0300 Subject: 2GB file size limit? In-Reply-To: <4BEE1582.40706@lambsys.com> References: <4BEE1582.40706@lambsys.com> Message-ID: <1274414010.8881.26.camel@localhost.localdomain> On Fri, 2010-05-14 at 22:31 -0500, David Lambert wrote: > Is there any way to increase the file size limit on UBIFS beyond > 2Gbytes? We never tested this, but should not be. AFAIR, UBIFS theoretical limitation should be something like 16TB, but I tried tested the maximum file size. > I have tried enabling the kernel ?Support for large block > devices and files? under ?Enable the block layer?, but the 2G limit > persists. UBIFS has nothing to do with block devices. This is a very specialized FS for bare flashes: http://www.linux-mtd.infradead.org/doc/ubifs.html#L_rednote So that option has no effect for UBIFS. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sat May 22 01:30:02 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sat, 22 May 2010 08:30:02 +0300 Subject: [PATCH] mtd-utils: Support 4096+64 page sizes. In-Reply-To: <1274176439-22351-1-git-send-email-eballetbo@gmail.com> References: <1274176439-22351-1-git-send-email-eballetbo@gmail.com> Message-ID: <1274506202.8881.30.camel@localhost.localdomain> On Tue, 2010-05-18 at 11:53 +0200, Enric Balletbo i Serra wrote: > + !(meminfo.oobsize == 64 && meminfo.writesize > == 4096) && Are there flashes with the 4096 page / 64 spare combination? Could you refer to one? May be any URL? I thought 4096 comes with 128. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sat May 22 01:39:28 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sat, 22 May 2010 08:39:28 +0300 Subject: [PATCH 2/2] check if the start address is page-aligned. In-Reply-To: <1274185390-3066-3-git-send-email-stanley.miao@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> <1274185390-3066-3-git-send-email-stanley.miao@windriver.com> Message-ID: <1274506768.8881.31.camel@localhost.localdomain> On Tue, 2010-05-18 at 20:23 +0800, Stanley.Miao wrote: > Only page-aligned address is permitted in NAND subsystem. > > Signed-off-by: Stanley.Miao Pushed both patches to the mtd-utils repo, thanks. However, I had to fix a tiny white-space damage for you: Applying: nandwrite: check if the start address is page-aligned. /home/dedekind/git/mtd-utils/.git/rebase-apply/patch:13: trailing whitespace. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 02:26:36 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 09:26:36 +0300 Subject: how to pre-screen patch submissions from a newbie janitor? In-Reply-To: References: Message-ID: <1274595996.8881.42.camel@localhost.localdomain> On Tue, 2010-05-18 at 19:40 -0400, Robert P. J. Day wrote: > not that long ago, i suggested cleaning up the MTD Kconfig/Makefile > structure since there was some definite redundancy in the inclusion of > source files and subdirectories. now, i could whip up those patches > myself and submit them, but i have a local friend who's itching to get > start doing some simple kernel work and submitting some patches, and > he's more than smart enough to do what i described above. > > however, since he's new to patch creation and submission, i offered > to "vet" his patches first. i realize that my vetting carries no > weight on the MTD list, but given that i've submitted lots and lots of > patches elsewhere, i can still at least sanity check what he comes up > with before it hits the list. > > is there a canonical signage for that nowadays? is it "Reviewed-By" > or something like that? so that by the time it gets to the MTD list, > he would have done the "Signed-Off-By" and i'd sign off as a reviewer. > is that the way it works? or is there an alternative? thanks. Hi, MTD list is not something special, common Linux kernel patch submission practices apply. So obviously, he signs off his patches, you can review, test, ack or sign off it. I am not pedantic about which tag to use, but you can always refer to 'Documentation/SubmittingPatches' and pick the right one. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 02:16:57 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 09:16:57 +0300 Subject: [PATCH] UBI: fix delete compatible internal volume scan In-Reply-To: References: Message-ID: <1274595417.8881.36.camel@localhost.localdomain> On Tue, 2010-05-18 at 23:10 +0530, Brijesh Singh wrote: > This patch resolves a possible bug. Scan is adding delete compatible > blocks to both corr list and used list. > It should return after adding the block to corr list. > > Signed-off-by: Brijesh Singh I'm not sure this patch is enough. I think we should add a 'compat' flag to the 'struct ubi_mkvol_req' structure, to make it possible to create volumes with different compatibility flags. Then we need to write a test and add it to the UBI test-suite at 'mtd-utils/tests/ubi-tests/'. Then once we have tested and fixed this, we should merge this and also send to the '-stable' trees. I remember I did give the compat option a test, but probably not that good. I'll try to do what I've described as soon as I have time, but you guys could do this as well, if you have bandwidth. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 12:01:27 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 19:01:27 +0300 Subject: how to pre-screen patch submissions from a newbie janitor? In-Reply-To: References: <20100519000137.GA18592@pengutronix.de> Message-ID: <1274630487.8881.59.camel@localhost.localdomain> On Wed, 2010-05-19 at 07:40 -0400, Robert P. J. Day wrote: > On Wed, 19 May 2010, Wolfram Sang wrote: > > > > however, since he's new to patch creation and submission, i > > > offered to "vet" his patches first. i realize that my vetting > > > carries no weight on the MTD list, but given that i've submitted > > > lots and lots of patches elsewhere, i can still at least sanity > > > check what he comes up with before it hits the list. > > > > > > is there a canonical signage for that nowadays? is it > > > "Reviewed-By" or something like that? so that by the time it gets > > > to the MTD list, he would have done the "Signed-Off-By" and i'd > > > sign off as a reviewer. is that the way it works? or is there an > > > alternative? thanks. > > > > Yes, that sounds like a good case for Reviewed-by. It will surely > > help these patches knowing there is somebody with experience who > > already had a look at (and in that case probably build-tested) them. > > > > Looking forward to the series, > > what i'm going to have this trainee(?) do is just simplify the > config/Kconfig/Makefile combos, which i openly admit is not > earth-shaking in its complexity. > > for example. in a number of places elsewhere in the kernel tree, > i've submitted patches to change things like this in the config menus: > > OneNAND Device Support ---> > LPDDR flash memory drivers ---> > UBI - Unsorted block images ---> > > note how, to select either LPDDR or UBI, you need to *go* to those > submenus, where you find a top-level selector. it's simpler to just > put that selector right on that menu item, as it's done for "OneNAND" > just above it. no wasting time. Yeah, and I assume it is better to be consistent and use the same style as most of things in the MTD menu have. > and another simplification is to cut down the conditional inclusion > in the makefiles. for instance, here's tests/Makefile: > > obj-$(CONFIG_MTD_TESTS) += mtd_oobtest.o > obj-$(CONFIG_MTD_TESTS) += mtd_pagetest.o > obj-$(CONFIG_MTD_TESTS) += mtd_readtest.o > ... etc etc ... > > there's little point having every single line in the Makefile test > CONFIG_MTD_TESTS when that can all be done with a single test one > level up that checks whether or not to process the tests/ directory at > all. Yeah, sounds good. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Sun May 23 12:07:45 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Sun, 23 May 2010 19:07:45 +0300 Subject: what should be coming soon WRT Kconfig/Makefile cleanup In-Reply-To: References: Message-ID: <1274630865.8881.61.camel@localhost.localdomain> On Thu, 2010-05-20 at 12:21 -0400, Robert P. J. Day wrote: > sorry, not trying to flog this, but as a short followup to what i > posted a couple days ago, i'm getting a new kernel janitor to work on > some specific projects and, rather than constantly email back and > forth with him, i posted his first potential project at my wiki. it's > meant to be a general project, but i used the MTD part of the tree as > an example: > > http://www.crashcourse.ca/wiki/index.php/Kconfig/Makefile_redundancy > > nothing earth-shattering there, just something to get him started > and looking at the Kbuild structure. if you think anything else > should be added to that page, or changed, let me know. or any other > MTD-related janitorial projects i can dump on him. :-) Nice write-up, I never payed much attention to Kconfig / Makefile stuff and it was interesting to read your article. I think your suggestions are good. -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Mon May 24 01:51:42 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 24 May 2010 08:51:42 +0300 Subject: [Yaffs] [PATCH 1/2] Fix the bug of writing a yaffs2 image to NAND In-Reply-To: <4BF49BB4.30306@windriver.com> References: <1274185390-3066-1-git-send-email-stanley.miao@windriver.com> <1274185390-3066-2-git-send-email-stanley.miao@windriver.com> <4BF49BB4.30306@windriver.com> Message-ID: <1274680302.8881.64.camel@localhost.localdomain> On Thu, 2010-05-20 at 10:17 +0800, stanley.miao wrote: > Hi, Artem, > > Any comments ? > > Stanley. Sorry, but what else kind of comments would you like to see in addition to these: http://lists.infradead.org/pipermail/linux-mtd/2010-May/030280.html ? -- Best Regards, Artem Bityutskiy (????? ????????) From dedekind1 at gmail.com Wed May 26 12:32:21 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 26 May 2010 19:32:21 +0300 Subject: UBIFS failed to recover master node In-Reply-To: References: <1274763914.2106.1.camel@localhost> Message-ID: <1274891541.2668.4.camel@localhost.localdomain> On Wed, 2010-05-26 at 12:06 -0400, twebb wrote: > > Please, enable all debugging messages, mount this flash again, and send > > the messages. > Should I enable CONFIG_UBIFS_FS_DEBUG_CHKS ? You may enable checks as well, but I was talking about messages. And enable them before mounting the corrupted flash, not when you are trying to reproduce this. Refer Documentation/filesystems/ubifs.txt -- Best Regards, Artem Bityutskiy (????? ????????) From w.sang at pengutronix.de Wed May 26 13:53:20 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Wed, 26 May 2010 19:53:20 +0200 Subject: Do we remove from jedec_probe.c? Message-ID: <20100526175320.GD24167@pengutronix.de> Hi, now that Guillaume introduced cfi-support for some SST-flashes, I wonder if those can be removed from jedec_probe.c? Or should they stay for backward-compatibility? Proposed patch would look like this: diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c index d72a5fb..37fdff3 100644 --- a/drivers/mtd/chips/jedec_probe.c +++ b/drivers/mtd/chips/jedec_probe.c @@ -146,8 +146,6 @@ #define SST29LE512 0x003d #define SST39LF800 0x2781 #define SST39LF160 0x2782 -#define SST39VF1601 0x234b -#define SST39VF3201 0x235b #define SST39WF1601 0x274b #define SST39WF1602 0x274a #define SST39LF512 0x00D4 @@ -1500,19 +1498,6 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x1000,256) } }, { - .mfr_id = CFI_MFR_SST, /* should be CFI */ - .dev_id = SST39VF1601, - .name = "SST 39VF1601", - .devtypes = CFI_DEVICETYPE_X16, - .uaddr = MTD_UADDR_0xAAAA_0x5555, - .dev_size = SIZE_2MiB, - .cmd_set = P_ID_AMD_STD, - .nr_regions = 2, - .regions = { - ERASEINFO(0x1000,256), - ERASEINFO(0x1000,256) - } - }, { /* CFI is broken: reports AMD_STD, but needs custom uaddr */ .mfr_id = CFI_MFR_SST, .dev_id = SST39WF1601, @@ -1541,21 +1526,6 @@ static const struct amd_flash_info jedec_table[] = { ERASEINFO(0x1000,256) } }, { - .mfr_id = CFI_MFR_SST, /* should be CFI */ - .dev_id = SST39VF3201, - .name = "SST 39VF3201", - .devtypes = CFI_DEVICETYPE_X16, - .uaddr = MTD_UADDR_0xAAAA_0x5555, - .dev_size = SIZE_4MiB, - .cmd_set = P_ID_AMD_STD, - .nr_regions = 4, - .regions = { - ERASEINFO(0x1000,256), - ERASEINFO(0x1000,256), - ERASEINFO(0x1000,256), - ERASEINFO(0x1000,256) - } - }, { .mfr_id = CFI_MFR_SST, .dev_id = SST36VF3203, .name = "SST 36VF3203", -- Pengutronix e.K. | Wolfram Sang | Industrial Linux Solutions | http://www.pengutronix.de/ | -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: application/pgp-signature Size: 197 bytes Desc: Digital signature URL: From mware at elphinstone.net Wed May 26 21:45:39 2010 From: mware at elphinstone.net (Mark Ware) Date: Thu, 27 May 2010 11:45:39 +1000 Subject: [RFC/PATCH] doc2000: Fix uninitialized variable in doc_ecc_decode() Message-ID: <4BFDCEC3.7070601@elphinstone.net> The variable 'syn' was being used uninitialized. Also fixed incorrect use of syn[] vs s[]. Tested on powerpc board with 64MB DOC2000. --- I am porting from a 2.4.18 kernel to 2.6.32, and I saw random media header mismatches causing a failure to detect the DOC device partitions. Tracing through, I saw this variable being used uninitialized and I suspect incorrectly also. I do not really understand how the ecc/syndrome code works, so I do not know if this patch is the correct solution, but it did make my problem go away... CC: Thomas Gleixner as I believe he may have written this function initially. drivers/mtd/nand/diskonchip.c | 5 +++-- 1 files changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index a5bf9ff..7da2321 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -145,6 +145,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) uint8_t parity; uint16_t ds[4], s[5], tmp, errval[8], syn[4]; + memset(syn, 0, sizeof(syn)); /* Convert the ecc bytes into words */ ds[0] = ((ecc[4] & 0xff) >> 0) | ((ecc[5] & 0x03) << 8); ds[1] = ((ecc[5] & 0xfc) >> 2) | ((ecc[2] & 0x0f) << 6); @@ -168,9 +169,9 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) s[i] ^= rs->alpha_to[rs_modnn(rs, tmp + (FCR + i) * j)]; } - /* Calc s[i] = s[i] / alpha^(v + i) */ + /* Calc syn[i] = s[i] / alpha^(v + i) */ for (i = 0; i < NROOTS; i++) { - if (syn[i]) + if (s[i]) syn[i] = rs_modnn(rs, rs->index_of[s[i]] + (NN - FCR - i)); } /* Call the decoder library */ -- 1.5.6.5 From baruch at tkos.co.il Thu May 27 04:50:27 2010 From: baruch at tkos.co.il (Baruch Siach) Date: Thu, 27 May 2010 11:50:27 +0300 Subject: [PATCH] mxc_nand: add support for platform defined partitions Message-ID: <7d46e3bafd160eaa9c5d9a09b88ea1cb4a2d5b89.1274950000.git.baruch@tkos.co.il> Signed-off-by: Baruch Siach --- arch/arm/plat-mxc/include/mach/mxc_nand.h | 4 ++++ drivers/mtd/nand/mxc_nand.c | 2 ++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h index 5d2d21d..a07bae9 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_nand.h +++ b/arch/arm/plat-mxc/include/mach/mxc_nand.h @@ -20,9 +20,13 @@ #ifndef __ASM_ARCH_NAND_H #define __ASM_ARCH_NAND_H +#include + struct mxc_nand_platform_data { int width; /* data bus width in bytes */ int hw_ecc:1; /* 0 if supress hardware ECC */ int flash_bbt:1; /* set to 1 to use a flash based bbt */ + struct mtd_partition *parts; /* partition table */ + int nr_parts; /* size of parts */ }; #endif /* __ASM_ARCH_NAND_H */ diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index b2900d8..4f615d2 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -838,6 +838,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) parse_mtd_partitions(mtd, part_probes, &host->parts, 0); if (nr_parts > 0) add_mtd_partitions(mtd, host->parts, nr_parts); + else if (pdata->parts) + add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); else #endif { -- 1.7.1 From mkl at pengutronix.de Thu May 27 07:11:34 2010 From: mkl at pengutronix.de (Marc Kleine-Budde) Date: Thu, 27 May 2010 13:11:34 +0200 Subject: [PATCH] mxc_nand: add support for platform defined partitions In-Reply-To: <7d46e3bafd160eaa9c5d9a09b88ea1cb4a2d5b89.1274950000.git.baruch@tkos.co.il> References: <7d46e3bafd160eaa9c5d9a09b88ea1cb4a2d5b89.1274950000.git.baruch@tkos.co.il> Message-ID: <4BFE5366.3000705@pengutronix.de> Baruch Siach wrote: > Signed-off-by: Baruch Siach Just coding style comments from me, see inline > --- > arch/arm/plat-mxc/include/mach/mxc_nand.h | 4 ++++ > drivers/mtd/nand/mxc_nand.c | 2 ++ > 2 files changed, 6 insertions(+), 0 deletions(-) > > diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h > index 5d2d21d..a07bae9 100644 > --- a/arch/arm/plat-mxc/include/mach/mxc_nand.h > +++ b/arch/arm/plat-mxc/include/mach/mxc_nand.h > @@ -20,9 +20,13 @@ > #ifndef __ASM_ARCH_NAND_H > #define __ASM_ARCH_NAND_H > > +#include > + > struct mxc_nand_platform_data { > int width; /* data bus width in bytes */ > int hw_ecc:1; /* 0 if supress hardware ECC */ > int flash_bbt:1; /* set to 1 to use a flash based bbt */ > + struct mtd_partition *parts; /* partition table */ > + int nr_parts; /* size of parts */ Please don't use tab(s) between type and variable name. Use tabs to align the comment though. (Just like the other members of the struct do.) > }; > #endif /* __ASM_ARCH_NAND_H */ > diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c > index b2900d8..4f615d2 100644 > --- a/drivers/mtd/nand/mxc_nand.c > +++ b/drivers/mtd/nand/mxc_nand.c > @@ -838,6 +838,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) > parse_mtd_partitions(mtd, part_probes, &host->parts, 0); > if (nr_parts > 0) > add_mtd_partitions(mtd, host->parts, nr_parts); > + else if (pdata->parts) > + add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); > else > #endif > { Cheers, Marc -- Pengutronix e.K. | Marc Kleine-Budde | Industrial Linux Solutions | Phone: +49-231-2826-924 | Vertretung West/Dortmund | Fax: +49-5121-206917-5555 | Amtsgericht Hildesheim, HRA 2686 | http://www.pengutronix.de | -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 260 bytes Desc: OpenPGP digital signature URL: From slapinid at gmail.com Thu May 27 08:35:52 2010 From: slapinid at gmail.com (Sergey Lapin) Date: Thu, 27 May 2010 16:35:52 +0400 Subject: protecting and unprotecting of NOR flash Message-ID: hi, all! I'm new to mtd kernel code base, where could I fond code, which protects and unprotects my NOR flash chip? it is AT49BV642D u-boot is capable of protecting it with protect command, I need to find where it is being un-protected in Linux, because I can erase and write blocks which I protected in u-boot before I don't want for kernel to touch protection status so I'd like to find which code to disable and protect/unprotect chip using boot loader. Thanks a lot, S. From siribarne at grid-net.com Thu May 27 11:25:00 2010 From: siribarne at grid-net.com (Steve Iribarne) Date: Thu, 27 May 2010 08:25:00 -0700 Subject: SELinux and UBIFS Message-ID: <4BFE8ECC.8080404@grid-net.com> I've been searching the net and have yet to find any sort of reliable "HOWTO" or "does it work" regarding SELinux, UBIFS and the extended attributes. We have need to use this here at Grid-Net and I'm trying to get a handle on if the work is done or is there something else I need to do to complete it. I see that there is extended attribute support in the UBIFS, but I've also seen articles (emails/etc..) claiming that the support is not fully there. Can someone point me to the right place if there is a right place? Thanks. -stv -- Steve Iribarne Sr. Software Engineer Embedded Devices This e-mail and any of its attachments may contain proprietary information, which is privileged, confidential or subject to copyright belonging to Grid Net, Inc. This e-mail is intended solely for the use of the individual or entity to which it is addressed. If you are not the intended recipient, you are hereby notified that any dissemination, distribution, copying or action taken in relation to the contents of this e-mail is strictly prohibited and may be unlawful. If you have received this e-mail in error, please notify the sender immediately and permanently delete. From dedekind1 at gmail.com Thu May 27 11:34:43 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Thu, 27 May 2010 18:34:43 +0300 Subject: SELinux and UBIFS In-Reply-To: <4BFE8ECC.8080404@grid-net.com> References: <4BFE8ECC.8080404@grid-net.com> Message-ID: <1274974483.15516.72.camel@localhost> On Thu, 2010-05-27 at 08:25 -0700, Steve Iribarne wrote: > I've been searching the net and have yet to find any sort of reliable > "HOWTO" or "does it work" regarding SELinux, UBIFS and the extended > attributes. > > We have need to use this here at Grid-Net and I'm trying to get a handle > on if the work is done or is there something else I need to do to > complete it. > > I see that there is extended attribute support in the UBIFS, but I've > also seen articles (emails/etc..) claiming that the support is not fully > there. > > Can someone point me to the right place if there is a right place? Hi, I added basic xattr support, but never tested xattrs very well. I did not implement ACL support. And I do not really know SELinux requirements. So just try it and let us know, better with a patch to the UBIFS FAQ which you can find here: http://www.linux-mtd.infradead.org/faq/ubifs.html and the website sources here: http://git.infradead.org/mtd-www.git Here is a comment from fs/ubifs/xattr.c: /* * This file implements UBIFS extended attributes support. * * Extended attributes are implemented as regular inodes with attached data, * which limits extended attribute size to UBIFS block size (4KiB). Names of * extended attributes are described by extended attribute entries (xentries), * which are almost identical to directory entries, but have different key type. * * In other words, the situation with extended attributes is very similar to * directories. Indeed, any inode (but of course not xattr inodes) may have a * number of associated xentries, just like directory inodes have associated * directory entries. Extended attribute entries store the name of the extended * attribute, the host inode number, and the extended attribute inode number. * Similarly, direntries store the name, the parent and the target inode * numbers. Thus, most of the common UBIFS mechanisms may be re-used for * extended attributes. * * The number of extended attributes is not limited, but there is Linux * limitation on the maximum possible size of the list of all extended * attributes associated with an inode (%XATTR_LIST_MAX), so UBIFS makes sure * the sum of all extended attribute names of the inode does not exceed that * limit. * * Extended attributes are synchronous, which means they are written to the * flash media synchronously and there is no write-back for extended attribute * inodes. The extended attribute values are not stored in compressed form on * the media. * * Since extended attributes are represented by regular inodes, they are cached * in the VFS inode cache. The xentries are cached in the LNC cache (see * tnc.c). * * ACL support is not implemented. */ It seems like the following xattr namespaces are supported: /* * Extended attribute type constants. * * USER_XATTR: user extended attribute ("user.*") * TRUSTED_XATTR: trusted extended attribute ("trusted.*) * SECURITY_XATTR: security extended attribute ("security.*") */ -- Best Regards, Artem Bityutskiy (????? ????????) From eric at eukrea.com Thu May 27 13:55:19 2010 From: eric at eukrea.com (=?utf-8?q?Eric=20B=C3=A9nard?=) Date: Thu, 27 May 2010 19:55:19 +0200 Subject: [PATCH] mxc_nand: fix PM In-Reply-To: <1274942000-3580-2-git-send-email-eric@eukrea.com> References: <1274942000-3580-2-git-send-email-eric@eukrea.com> Message-ID: <1274982919-13251-1-git-send-email-eric@eukrea.com> * when resuming, we get the following log : nand_resume called for a chip which is not in suspended state * this happens because mtd->suspend and mtd->resume are already called from the mtd layer, thus they were called a second time in mxc_nand so mtd complains when trying to resume for the second time * the fix is to remove these call and thus remove the supend and resume functions of mxc_nand Signed-off-by: Eric B?nard Cc: s.hauer at pengutronix.de Cc: linux-arm-kernel at lists.infradead.org Cc: linux-mtd at lists.infradead.org --- drivers/mtd/nand/mxc_nand.c | 44 +------------------------------------------ 1 files changed, 1 insertions(+), 43 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 314e2bf..217b247 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -892,53 +892,11 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM -static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct mtd_info *mtd = platform_get_drvdata(pdev); - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - int ret = 0; - - DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); - - ret = mtd->suspend(mtd); - - /* - * nand_suspend locks the device for exclusive access, so - * the clock must already be off. - */ - BUG_ON(!ret && host->clk_act); - - return ret; -} - -static int mxcnd_resume(struct platform_device *pdev) -{ - struct mtd_info *mtd = platform_get_drvdata(pdev); - struct nand_chip *nand_chip = mtd->priv; - struct mxc_nand_host *host = nand_chip->priv; - int ret = 0; - - DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); - - mtd->resume(mtd); - - return ret; -} - -#else -# define mxcnd_suspend NULL -# define mxcnd_resume NULL -#endif /* CONFIG_PM */ - static struct platform_driver mxcnd_driver = { .driver = { .name = DRIVER_NAME, - }, + }, .remove = __devexit_p(mxcnd_remove), - .suspend = mxcnd_suspend, - .resume = mxcnd_resume, }; static int __init mxc_nd_init(void) -- 1.6.3.3 From kmpark at infradead.org Thu May 27 22:03:11 2010 From: kmpark at infradead.org (Kyungmin Park) Date: Fri, 28 May 2010 11:03:11 +0900 Subject: [PATCH] OneNAND: Introduce chip_probe function Message-ID: <20100528020311.GA1608@july> Samsung SoCs use the own OneNAND controler and detect OneNAND chip at power on. To use this feature, introduce the chip_probe function. Also remove workaround for Samsung SoCs. Signed-off-by: Kyungmin Park --- diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c index 26caf25..0b12102 100644 --- a/drivers/mtd/onenand/onenand_base.c +++ b/drivers/mtd/onenand/onenand_base.c @@ -3730,17 +3730,16 @@ out: } /** - * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * onenand_chip_probe - [OneNAND Interface] The generic chip probe * @param mtd MTD device structure * * OneNAND detection method: * Compare the values from command with ones from register */ -static int onenand_probe(struct mtd_info *mtd) +static int onenand_chip_probe(struct mtd_info *mtd) { struct onenand_chip *this = mtd->priv; - int bram_maf_id, bram_dev_id, maf_id, dev_id, ver_id; - int density; + int bram_maf_id, bram_dev_id, maf_id, dev_id; int syscfg; /* Save system configuration 1 */ @@ -3763,12 +3762,6 @@ static int onenand_probe(struct mtd_info *mtd) /* Restore system configuration 1 */ this->write_word(syscfg, this->base + ONENAND_REG_SYS_CFG1); - /* Workaround */ - if (syscfg & ONENAND_SYS_CFG1_SYNC_WRITE) { - bram_maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); - bram_dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); - } - /* Check manufacturer ID */ if (onenand_check_maf(bram_maf_id)) return -ENXIO; @@ -3776,13 +3769,35 @@ static int onenand_probe(struct mtd_info *mtd) /* Read manufacturer and device IDs from Register */ maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); - ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); - this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); /* Check OneNAND device */ if (maf_id != bram_maf_id || dev_id != bram_dev_id) return -ENXIO; + return 0; +} + +/** + * onenand_probe - [OneNAND Interface] Probe the OneNAND device + * @param mtd MTD device structure + */ +static int onenand_probe(struct mtd_info *mtd) +{ + struct onenand_chip *this = mtd->priv; + int maf_id, dev_id, ver_id; + int density; + int ret; + + ret = this->chip_probe(mtd); + if (ret) + return ret; + + /* Read manufacturer and device IDs from Register */ + maf_id = this->read_word(this->base + ONENAND_REG_MANUFACTURER_ID); + dev_id = this->read_word(this->base + ONENAND_REG_DEVICE_ID); + ver_id = this->read_word(this->base + ONENAND_REG_VERSION_ID); + this->technology = this->read_word(this->base + ONENAND_REG_TECHNOLOGY); + /* Flash device information */ onenand_print_device_info(dev_id, ver_id); this->device_id = dev_id; @@ -3909,6 +3924,9 @@ int onenand_scan(struct mtd_info *mtd, int maxchips) if (!this->unlock_all) this->unlock_all = onenand_unlock_all; + if (!this->chip_probe) + this->chip_probe = onenand_chip_probe; + if (!this->read_bufferram) this->read_bufferram = onenand_read_bufferram; if (!this->write_bufferram) diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h index c26ff86..0c8815b 100644 --- a/include/linux/mtd/onenand.h +++ b/include/linux/mtd/onenand.h @@ -68,6 +68,7 @@ struct onenand_bufferram { * @write_word: [REPLACEABLE] hardware specific function for write * register of OneNAND * @mmcontrol: sync burst read function + * @chip_probe: [REPLACEABLE] hardware specific function for chip probe * @block_markbad: function to mark a block as bad * @scan_bbt: [REPLACEALBE] hardware specific function for scanning * Bad block Table @@ -114,6 +115,7 @@ struct onenand_chip { unsigned short (*read_word)(void __iomem *addr); void (*write_word)(unsigned short value, void __iomem *addr); void (*mmcontrol)(struct mtd_info *mtd, int sync_read); + int (*chip_probe)(struct mtd_info *mtd); int (*block_markbad)(struct mtd_info *mtd, loff_t ofs); int (*scan_bbt)(struct mtd_info *mtd); From kmpark at infradead.org Thu May 27 22:15:35 2010 From: kmpark at infradead.org (Kyungmin Park) Date: Fri, 28 May 2010 11:15:35 +0900 Subject: [PATCH] OneNAND: Samsung SoCs use own chip_probe function Message-ID: <20100528021535.GA8117@july> Samsung SoCs use own chip_probe function. Don't touch the memory configuration at probe time. Signed-off-by: Kyungmin Park --- diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c index 2750317..cb443af 100644 --- a/drivers/mtd/onenand/samsung.c +++ b/drivers/mtd/onenand/samsung.c @@ -630,6 +630,12 @@ normal: return 0; } +static int s5pc110_chip_probe(struct mtd_info *mtd) +{ + /* Now just return 0 */ + return 0; +} + static int s3c_onenand_bbt_wait(struct mtd_info *mtd, int state) { unsigned int flags = INT_ACT | LOAD_CMP; @@ -757,6 +763,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd) /* Use generic onenand functions */ onenand->cmd_map = s5pc1xx_cmd_map; this->read_bufferram = s5pc110_read_bufferram; + this->chip_probe = s5pc110_chip_probe; return; } else { BUG(); @@ -781,7 +788,6 @@ static int s3c_onenand_probe(struct platform_device *pdev) struct mtd_info *mtd; struct resource *r; int size, err; - unsigned long onenand_ctrl_cfg = 0; pdata = pdev->dev.platform_data; /* No need to check pdata. the platform data is optional */ @@ -900,14 +906,6 @@ static int s3c_onenand_probe(struct platform_device *pdev) } onenand->phys_base = onenand->base_res->start; - - onenand_ctrl_cfg = readl(onenand->dma_addr + 0x100); - if ((onenand_ctrl_cfg & ONENAND_SYS_CFG1_SYNC_WRITE) && - onenand->dma_addr) - writel(onenand_ctrl_cfg & ~ONENAND_SYS_CFG1_SYNC_WRITE, - onenand->dma_addr + 0x100); - else - onenand_ctrl_cfg = 0; } if (onenand_scan(mtd, 1)) { @@ -915,10 +913,7 @@ static int s3c_onenand_probe(struct platform_device *pdev) goto scan_failed; } - if (onenand->type == TYPE_S5PC110) { - if (onenand_ctrl_cfg && onenand->dma_addr) - writel(onenand_ctrl_cfg, onenand->dma_addr + 0x100); - } else { + if (onenand->type != TYPE_S5PC110) { /* S3C doesn't handle subpage write */ mtd->subpage_sft = 0; this->subpagesize = mtd->writesize; From s.hauer at pengutronix.de Fri May 28 04:02:17 2010 From: s.hauer at pengutronix.de (Sascha Hauer) Date: Fri, 28 May 2010 10:02:17 +0200 Subject: [PATCH] mxc_nand: Fix OOB accesses on i.MX27 Message-ID: <20100528080217.GH23664@pengutronix.de> Hi all, The OOB handling in the mxc_nand driver is broken for v1 type controllers (i.MX27/31) with 512 byte page size. This perhaps did not show up because ubi does not use OOB. Update the driver to always read/write a whole page even if only OOB is requested. With this patch the driver passes the mtd_oobtest on i.MX27 with 512 byte page size. Also tested with 2048 byte page size and on i.MX35 (v2 type controller) Signed-off-by: Sascha Hauer --- drivers/mtd/nand/mxc_nand.c | 31 +++++-------------------------- 1 files changed, 5 insertions(+), 26 deletions(-) diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 82e9438..6e8aa34 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -623,8 +623,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, else host->buf_start = column + mtd->writesize; - if (mtd->writesize > 512) - command = NAND_CMD_READ0; /* only READ0 is valid */ + command = NAND_CMD_READ0; /* only READ0 is valid */ send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); @@ -639,31 +638,11 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, break; case NAND_CMD_SEQIN: - if (column >= mtd->writesize) { - /* - * FIXME: before send SEQIN command for write OOB, - * We must read one page out. - * For K9F1GXX has no READ1 command to set current HW - * pointer to spare area, we must write the whole page - * including OOB together. - */ - if (mtd->writesize > 512) - /* call ourself to read a page */ - mxc_nand_command(mtd, NAND_CMD_READ0, 0, - page_addr); - - host->buf_start = column; - - /* Set program pointer to spare region */ - if (mtd->writesize == 512) - send_cmd(host, NAND_CMD_READOOB, false); - } else { - host->buf_start = column; + if (column >= mtd->writesize) + /* call ourself to read a page */ + mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); - /* Set program pointer to page start */ - if (mtd->writesize == 512) - send_cmd(host, NAND_CMD_READ0, false); - } + host->buf_start = column; send_cmd(host, command, false); mxc_do_addr_cycle(mtd, column, page_addr); -- 1.7.1 -- Pengutronix e.K. | | Industrial Linux Solutions | http://www.pengutronix.de/ | Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | From haavard.skinnemoen at atmel.com Fri May 28 05:27:44 2010 From: haavard.skinnemoen at atmel.com (Haavard Skinnemoen) Date: Fri, 28 May 2010 11:27:44 +0200 Subject: [PATCH] Fix Oops with Atmel SPI In-Reply-To: <20100521120106.d955c78b.akpm@linux-foundation.org> References: <1271231840l.5270l.0l@i-dmzi_al.realan.de> <20100421152410.0fea5e12.akpm@linux-foundation.org> <1274267100l.1747l.1l@i-dmzi_al.realan.de> <20100521120106.d955c78b.akpm@linux-foundation.org> Message-ID: <20100528112744.579dc556@hskinnemoen-d830> Andrew Morton wrote: > On Wed, 19 May 2010 13:05:00 +0200 > Anders Larsen wrote: > > > On 2010-04-22 00:24:10, Andrew Morton wrote: > > > Finally.. Wouldn't it be better to just fix the atmel SPI driver so > > > that it doesn't barf when handed vmalloc'ed memory? Who do we ridicule > > > about that? > > > > You mean something like this instead? > > That looks simple enough. How do we get it tested, changelogged and > merged up? Haavard, can you please take a look? Sure. Sorry for the late response; I've been traveling for the last two weeks. Did anyone check what other drivers do to handle this case? Surely this isn't the only driver which supports DMA? > > diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c > > index c4e0442..a9ad5e8 100644 > > --- a/drivers/spi/atmel_spi.c > > +++ b/drivers/spi/atmel_spi.c > > @@ -352,16 +352,30 @@ atmel_spi_dma_map_xfer(struct atmel_spi *as, struct spi_transfer *xfer) > > > > xfer->tx_dma = xfer->rx_dma = INVALID_DMA_ADDRESS; > > if (xfer->tx_buf) { > > - xfer->tx_dma = dma_map_single(dev, > > - (void *) xfer->tx_buf, xfer->len, > > - DMA_TO_DEVICE); > > + if (is_vmalloc_addr(xfer->tx_buf)) > > + xfer->tx_dma = dma_map_page(dev, > > + vmalloc_to_page(xfer->tx_buf), > > + (unsigned long)xfer->tx_buf & (PAGE_SIZE-1), > > + xfer->len, > > + DMA_TO_DEVICE); Ok, this should be fine for small transfers, but what happens if the transfer crosses a page boundary? Are there any guarantees that this will never happen? What callers are passing vmalloc'ed memory in the first place? Ditto for the rx path. Haavard From beavers at anx.com Fri May 28 17:26:43 2010 From: beavers at anx.com (Stephen Beaver) Date: Fri, 28 May 2010 17:26:43 -0400 Subject: Mtd_debug patch Message-ID: The attached patch to the current version of mtd_debug (grabbed on5/28/2010) adds two new capabilities: usage: mtd_debug info mtd_debug read mtd_debug write mtd_debug verify mtd_debug erase mtd_debug blank mtd_debug blank ... checks that an area of flash memory if blank (all 0xFFs) ie it verifies that an erase succeeded. mtd_debug verify ... checks that the contents of the flash memory match the specified file. Ie it verifies that a write succeeded. These functions allow things like: #!/bin/sh mtd_debug erase /dev/mtd1 0 0x200000 mtd_debug write /dev/mtd1 0 0x150000 uImage if ( mtd_debug verifiy /dev/mtd1 0 uImage ) ; then reboot else # Better try again, or we will die fi Both have been tested on NOR and NAND flash, and are just simple modifications to the existing file_from_flash() function. Steve -- Stephen Beaver | ANXeBusiness | Engineering |219 232-8371 | www.anx.com | beavers at anx.com Think Green...do you really need to print this email? Reduce, reuse, recycle! -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: verify-blank.patch Type: video/x-flv Size: 6669 bytes Desc: not available URL: From baruch at tkos.co.il Mon May 31 01:41:43 2010 From: baruch at tkos.co.il (Baruch Siach) Date: Mon, 31 May 2010 08:41:43 +0300 Subject: [PATCH] mxc_nand: Fix OOB accesses on i.MX27 In-Reply-To: <20100528080217.GH23664@pengutronix.de> References: <20100528080217.GH23664@pengutronix.de> Message-ID: <20100531054142.GA6514@jasper.tkos.co.il> Hi Sascha, On Fri, May 28, 2010 at 10:02:17AM +0200, Sascha Hauer wrote: > The OOB handling in the mxc_nand driver is broken for v1 type > controllers (i.MX27/31) with 512 byte page size. This perhaps > did not show up because ubi does not use OOB. > Update the driver to always read/write a whole page even if > only OOB is requested. With this patch the driver passes the > mtd_oobtest on i.MX27 with 512 byte page size. Also tested > with 2048 byte page size and on i.MX35 (v2 type controller) > > Signed-off-by: Sascha Hauer Tested on i.MX25 with 2K page size. baruch > --- > drivers/mtd/nand/mxc_nand.c | 31 +++++-------------------------- > 1 files changed, 5 insertions(+), 26 deletions(-) > > diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c > index 82e9438..6e8aa34 100644 > --- a/drivers/mtd/nand/mxc_nand.c > +++ b/drivers/mtd/nand/mxc_nand.c > @@ -623,8 +623,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, > else > host->buf_start = column + mtd->writesize; > > - if (mtd->writesize > 512) > - command = NAND_CMD_READ0; /* only READ0 is valid */ > + command = NAND_CMD_READ0; /* only READ0 is valid */ > > send_cmd(host, command, false); > mxc_do_addr_cycle(mtd, column, page_addr); > @@ -639,31 +638,11 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, > break; > > case NAND_CMD_SEQIN: > - if (column >= mtd->writesize) { > - /* > - * FIXME: before send SEQIN command for write OOB, > - * We must read one page out. > - * For K9F1GXX has no READ1 command to set current HW > - * pointer to spare area, we must write the whole page > - * including OOB together. > - */ > - if (mtd->writesize > 512) > - /* call ourself to read a page */ > - mxc_nand_command(mtd, NAND_CMD_READ0, 0, > - page_addr); > - > - host->buf_start = column; > - > - /* Set program pointer to spare region */ > - if (mtd->writesize == 512) > - send_cmd(host, NAND_CMD_READOOB, false); > - } else { > - host->buf_start = column; > + if (column >= mtd->writesize) > + /* call ourself to read a page */ > + mxc_nand_command(mtd, NAND_CMD_READ0, 0, page_addr); > > - /* Set program pointer to page start */ > - if (mtd->writesize == 512) > - send_cmd(host, NAND_CMD_READ0, false); > - } > + host->buf_start = column; > > send_cmd(host, command, false); > mxc_do_addr_cycle(mtd, column, page_addr); > -- > 1.7.1 > > -- > Pengutronix e.K. | | > Industrial Linux Solutions | http://www.pengutronix.de/ | > Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | > Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel at lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel -- ~. .~ Tk Open Systems =}------------------------------------------------ooO--U--Ooo------------{= - baruch at tkos.co.il - tel: +972.2.679.5364, http://www.tkos.co.il - From baruch at tkos.co.il Mon May 31 01:49:40 2010 From: baruch at tkos.co.il (Baruch Siach) Date: Mon, 31 May 2010 08:49:40 +0300 Subject: [PATCHv2] mxc_nand: add support for platform defined partitions Message-ID: Signed-off-by: Baruch Siach --- Changes v1 -> v2 Changed the indentation of new fields in mxc_nand_platform_data as suggested by Marc Kleine-Budde arch/arm/plat-mxc/include/mach/mxc_nand.h | 4 ++++ drivers/mtd/nand/mxc_nand.c | 2 ++ 2 files changed, 6 insertions(+), 0 deletions(-) diff --git a/arch/arm/plat-mxc/include/mach/mxc_nand.h b/arch/arm/plat-mxc/include/mach/mxc_nand.h index 5d2d21d..2d74748 100644 --- a/arch/arm/plat-mxc/include/mach/mxc_nand.h +++ b/arch/arm/plat-mxc/include/mach/mxc_nand.h @@ -20,9 +20,13 @@ #ifndef __ASM_ARCH_NAND_H #define __ASM_ARCH_NAND_H +#include + struct mxc_nand_platform_data { int width; /* data bus width in bytes */ int hw_ecc:1; /* 0 if supress hardware ECC */ int flash_bbt:1; /* set to 1 to use a flash based bbt */ + struct mtd_partition *parts; /* partition table */ + int nr_parts; /* size of parts */ }; #endif /* __ASM_ARCH_NAND_H */ diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index 82e9438..8bfe158 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c @@ -853,6 +853,8 @@ static int __init mxcnd_probe(struct platform_device *pdev) parse_mtd_partitions(mtd, part_probes, &host->parts, 0); if (nr_parts > 0) add_mtd_partitions(mtd, host->parts, nr_parts); + else if (pdata->parts) + add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); else #endif { -- 1.7.1 From barnes.leo at gmail.com Mon May 31 02:51:50 2010 From: barnes.leo at gmail.com (Leo Barnes) Date: Mon, 31 May 2010 08:51:50 +0200 Subject: Expected capabilities of MTD-layer drivers? Message-ID: Hello! I have recently run into trouble with what I now believe is a buggy driver in the MTD-layer. The driver in question is the msm_nand driver in the MSM android kernel: http://android.git.kernel.org/?p=kernel/msm.git;a=blob;f=drivers/mtd/devices/msm_nand.h;h=b5e6293e929ab0cab0fc1c1b35a5526915b64086;hb=HEAD It seems to be written with YAFFS2 entirely in mind, which means that when trying to access it in other ways results in errors. So, in order to tell if it is in fact the driver that is buggy, I need to find out what the expected capabilities of nand_read/nand_read_oob and nand_write/nand_write_oob actually are. 1. What are the allowed amount of bytes that can be read with nand_read? In the driver, this seems to be multiples of the pagesize, but I have spotted the UBI driver trying to read 64 byte chunks when trying to scan all the EC headers (which fails). When studying the OneNAND drivers, an arbitrary amount of bytes seems to be allowed, but OneNAND is after all quite different from regular NAND. 2. What are the allowed amount of bytes that can be written with nand_write/nand_write_oob? 3. When running the mtd_readtest, the test fails on every page on every block when it asks the driver to read OOB-data. What is the expected behaviour when ops.mode = MTD_OOB_PLACE, ops.datbuf = ops.len = 0 and ops.ooblen = mtd->oobsize (64 bytes in this case)? At the moment, the driver returns EBADMSG whenever mtd_readtest tries to do this. Best regards, //Leo From dedekind1 at gmail.com Mon May 31 03:02:35 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Mon, 31 May 2010 10:02:35 +0300 Subject: Expected capabilities of MTD-layer drivers? In-Reply-To: References: Message-ID: <1275289355.2678.29.camel@localhost> On Mon, 2010-05-31 at 08:51 +0200, Leo Barnes wrote: > Hello! > > I have recently run into trouble with what I now believe is a buggy > driver in the MTD-layer. The driver in question is the msm_nand driver > in the MSM android kernel: > > http://android.git.kernel.org/?p=kernel/msm.git;a=blob;f=drivers/mtd/devices/msm_nand.h;h=b5e6293e929ab0cab0fc1c1b35a5526915b64086;hb=HEAD > > It seems to be written with YAFFS2 entirely in mind, which means that > when trying to access it in other ways results in errors. So, in order > to tell if it is in fact the driver that is buggy, I need to find out > what the expected capabilities of nand_read/nand_read_oob and > nand_write/nand_write_oob actually are. > > 1. What are the allowed amount of bytes that can be read with > nand_read? In the driver, this seems to be multiples of the pagesize, > but I have spotted the UBI driver trying to read 64 byte chunks when > trying to scan all the EC headers (which fails). When studying the > OneNAND drivers, an arbitrary amount of bytes seems to be allowed, but > OneNAND is after all quite different from regular NAND. MTD interface assumes that arbitrary amount of bytes can be read. I'm not sure this is a good idea, but this is historical. > 2. What are the allowed amount of bytes that can be written with > nand_write/nand_write_oob? Any amount, but aligned to the min I/O unit size (mtd->writesize). > 3. When running the mtd_readtest, the test fails on every page on > every block when it asks the driver to read OOB-data. What is the > expected behaviour when ops.mode = MTD_OOB_PLACE, ops.datbuf = ops.len > = 0 and ops.ooblen = mtd->oobsize (64 bytes in this case)? At the > moment, the driver returns EBADMSG whenever mtd_readtest tries to do > this. Sorry, not sure, I do not use OOB and already forgot. But the OneNAND driver or nand_base.c is a good reference. -- Best Regards, Artem Bityutskiy (????? ????????) From w.sang at pengutronix.de Mon May 31 08:55:48 2010 From: w.sang at pengutronix.de (Wolfram Sang) Date: Mon, 31 May 2010 14:55:48 +0200 Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL) Message-ID: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> I2C-drivers can use the clientdata-pointer to point to private data. As I2C devices are not really unregistered, but merely detached from their driver, it used to be the drivers obligation to clear this pointer during remove() or a failed probe(). As a couple of drivers forgot to do this, it was agreed that it was cleaner if the i2c-core does this clearance when appropriate, as there is no guarantee for the lifetime of the clientdata-pointer after remove() anyhow. This feature was added to the core with commit e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers. As there is no need anymore to clear the clientdata-pointer, remove all current occurrences in the drivers to simplify the code and prevent confusion. Signed-off-by: Wolfram Sang Cc: Jean Delvare --- Some more notes: I waited for rc1 as I knew there were some drivers/patches coming along which needed to be processed, too. I'd suggest that this goes via the i2c-tree, so we get rid of all occurences at once. I used get_maintainers with --no-git, otherwise the cc-list would have gotten too excessive IMHO. I think the number of included mailing-lists will do. The removal was done using coccinelle and reviewed manually. drivers/hwmon/adt7411.c | 2 -- drivers/hwmon/asc7621.c | 2 -- drivers/hwmon/f75375s.c | 2 -- drivers/hwmon/g760a.c | 2 -- drivers/hwmon/lm73.c | 1 - drivers/hwmon/lm75.c | 2 -- drivers/hwmon/lm95241.c | 1 - drivers/hwmon/tmp102.c | 2 -- drivers/hwmon/tmp421.c | 2 -- drivers/hwmon/w83781d.c | 2 -- drivers/i2c/i2c-smbus.c | 1 - drivers/input/keyboard/adp5588-keys.c | 1 - drivers/input/keyboard/lm8323.c | 2 -- drivers/input/keyboard/max7359_keypad.c | 1 - drivers/input/keyboard/qt2160.c | 1 - drivers/input/keyboard/tca6416-keypad.c | 2 -- drivers/input/misc/ad714x-i2c.c | 1 - drivers/input/misc/pcf8574_keypad.c | 2 -- drivers/input/mouse/synaptics_i2c.c | 1 - drivers/input/touchscreen/ad7879.c | 5 +---- drivers/input/touchscreen/eeti_ts.c | 2 -- drivers/input/touchscreen/mcs5000_ts.c | 1 - drivers/input/touchscreen/tsc2007.c | 2 -- drivers/leds/leds-bd2802.c | 2 -- drivers/leds/leds-lp3944.c | 1 - drivers/leds/leds-pca9532.c | 5 +---- drivers/leds/leds-pca955x.c | 2 -- drivers/macintosh/therm_adt746x.c | 2 -- drivers/macintosh/windfarm_lm75_sensor.c | 5 +---- drivers/macintosh/windfarm_max6690_sensor.c | 1 - drivers/macintosh/windfarm_smu_sat.c | 1 - drivers/media/radio/si470x/radio-si470x-i2c.c | 1 - drivers/media/video/mt9m001.c | 2 -- drivers/media/video/mt9m111.c | 2 -- drivers/media/video/mt9t031.c | 2 -- drivers/media/video/mt9t112.c | 2 -- drivers/media/video/mt9v022.c | 2 -- drivers/media/video/ov772x.c | 2 -- drivers/media/video/ov9640.c | 2 -- drivers/media/video/rj54n1cb0c.c | 2 -- drivers/media/video/tcm825x.c | 8 +------- drivers/media/video/tw9910.c | 2 -- drivers/mfd/88pm860x-i2c.c | 2 -- drivers/mfd/ab3100-core.c | 2 -- drivers/mfd/ab3550-core.c | 1 - drivers/mfd/adp5520.c | 2 -- drivers/mfd/da903x.c | 2 -- drivers/mfd/max8925-i2c.c | 1 - drivers/mfd/menelaus.c | 2 -- drivers/mfd/pcf50633-core.c | 2 -- drivers/mfd/tc35892.c | 2 -- drivers/mfd/tps65010.c | 1 - drivers/mfd/wm8350-i2c.c | 2 -- drivers/mfd/wm8400-core.c | 2 -- drivers/misc/eeprom/at24.c | 1 - drivers/mtd/maps/pismo.c | 2 -- drivers/power/max17040_battery.c | 2 -- drivers/regulator/lp3971.c | 2 -- drivers/regulator/max1586.c | 1 - drivers/regulator/max8649.c | 2 -- drivers/regulator/max8660.c | 1 - drivers/regulator/tps65023-regulator.c | 3 --- drivers/rtc/rtc-ds1374.c | 2 -- drivers/rtc/rtc-rx8025.c | 2 -- drivers/rtc/rtc-s35390a.c | 2 -- drivers/staging/dream/synaptics_i2c_rmi.c | 2 -- drivers/staging/go7007/wis-saa7113.c | 2 -- drivers/staging/go7007/wis-saa7115.c | 2 -- drivers/staging/go7007/wis-sony-tuner.c | 1 - drivers/staging/go7007/wis-tw2804.c | 1 - drivers/staging/go7007/wis-tw9903.c | 2 -- drivers/staging/iio/adc/max1363_core.c | 2 -- drivers/staging/iio/light/tsl2563.c | 2 -- drivers/video/backlight/adp8860_bl.c | 2 -- drivers/video/backlight/tosa_bl.c | 2 -- 75 files changed, 4 insertions(+), 141 deletions(-) diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c index 4086c72..f13c843 100644 --- a/drivers/hwmon/adt7411.c +++ b/drivers/hwmon/adt7411.c @@ -316,7 +316,6 @@ static int __devinit adt7411_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); exit_free: - i2c_set_clientdata(client, NULL); kfree(data); return ret; } @@ -327,7 +326,6 @@ static int __devexit adt7411_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - i2c_set_clientdata(client, NULL); kfree(data); return 0; } diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 0f388ad..3b973f3 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -1141,7 +1141,6 @@ exit_remove: &(asc7621_params[i].sda.dev_attr)); } - i2c_set_clientdata(client, NULL); kfree(data); return err; } @@ -1196,7 +1195,6 @@ static int asc7621_remove(struct i2c_client *client) &(asc7621_params[i].sda.dev_attr)); } - i2c_set_clientdata(client, NULL); kfree(data); return 0; } diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index bad2cf3..0f58ecc 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -662,7 +662,6 @@ exit_remove: sysfs_remove_group(&client->dev.kobj, &f75375_group); exit_free: kfree(data); - i2c_set_clientdata(client, NULL); return err; } @@ -672,7 +671,6 @@ static int f75375_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &f75375_group); kfree(data); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index 09ea12e..1f63d1a 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c @@ -236,7 +236,6 @@ error_hwmon_device_register: sysfs_remove_group(&client->dev.kobj, &g760a_group); error_sysfs_create_group: kfree(data); - i2c_set_clientdata(client, NULL); return err; } @@ -247,7 +246,6 @@ static int g760a_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &g760a_group); kfree(data); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c index 4d1b76b..29b9030 100644 --- a/drivers/hwmon/lm73.c +++ b/drivers/hwmon/lm73.c @@ -136,7 +136,6 @@ static int lm73_remove(struct i2c_client *client) hwmon_device_unregister(hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm73_group); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 5646342..393f354 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -192,7 +192,6 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) exit_remove: sysfs_remove_group(&client->dev.kobj, &lm75_group); exit_free: - i2c_set_clientdata(client, NULL); kfree(data); return status; } @@ -204,7 +203,6 @@ static int lm75_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm75_group); lm75_write_value(client, LM75_REG_CONF, data->orig_conf); - i2c_set_clientdata(client, NULL); kfree(data); return 0; } diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index 8fc8eb8..94741d4 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -399,7 +399,6 @@ static int lm95241_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm95241_group); - i2c_set_clientdata(client, NULL); kfree(data); return 0; } diff --git a/drivers/hwmon/tmp102.c b/drivers/hwmon/tmp102.c index 8013895..93187c3 100644 --- a/drivers/hwmon/tmp102.c +++ b/drivers/hwmon/tmp102.c @@ -224,7 +224,6 @@ fail_remove_sysfs: fail_restore_config: tmp102_write_reg(client, TMP102_CONF_REG, tmp102->config_orig); fail_free: - i2c_set_clientdata(client, NULL); kfree(tmp102); return status; @@ -247,7 +246,6 @@ static int __devexit tmp102_remove(struct i2c_client *client) config | TMP102_CONF_SD); } - i2c_set_clientdata(client, NULL); kfree(tmp102); return 0; diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 738c472..6b4165c 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -295,7 +295,6 @@ exit_remove: sysfs_remove_group(&client->dev.kobj, &tmp421_group); exit_free: - i2c_set_clientdata(client, NULL); kfree(data); return err; @@ -308,7 +307,6 @@ static int tmp421_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &tmp421_group); - i2c_set_clientdata(client, NULL); kfree(data); return 0; diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c index 32d4ade..c84b9b4 100644 --- a/drivers/hwmon/w83781d.c +++ b/drivers/hwmon/w83781d.c @@ -1197,7 +1197,6 @@ ERROR4: if (data->lm75[1]) i2c_unregister_device(data->lm75[1]); ERROR3: - i2c_set_clientdata(client, NULL); kfree(data); ERROR1: return err; @@ -1219,7 +1218,6 @@ w83781d_remove(struct i2c_client *client) if (data->lm75[1]) i2c_unregister_device(data->lm75[1]); - i2c_set_clientdata(client, NULL); kfree(data); return 0; diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index a24e0bf..f61ccc1 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -173,7 +173,6 @@ static int smbalert_remove(struct i2c_client *ara) cancel_work_sync(&alert->alert); - i2c_set_clientdata(ara, NULL); kfree(alert); return 0; } diff --git a/drivers/input/keyboard/adp5588-keys.c b/drivers/input/keyboard/adp5588-keys.c index 4771ab1..744600e 100644 --- a/drivers/input/keyboard/adp5588-keys.c +++ b/drivers/input/keyboard/adp5588-keys.c @@ -287,7 +287,6 @@ static int __devexit adp5588_remove(struct i2c_client *client) free_irq(client->irq, kpad); cancel_delayed_work_sync(&kpad->work); input_unregister_device(kpad->input); - i2c_set_clientdata(client, NULL); kfree(kpad); return 0; diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index bc69693..40b032f 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c @@ -778,8 +778,6 @@ static int __devexit lm8323_remove(struct i2c_client *client) struct lm8323_chip *lm = i2c_get_clientdata(client); int i; - i2c_set_clientdata(client, NULL); - disable_irq_wake(client->irq); free_irq(client->irq, lm); cancel_work_sync(&lm->work); diff --git a/drivers/input/keyboard/max7359_keypad.c b/drivers/input/keyboard/max7359_keypad.c index 7fc8185..9091ff5 100644 --- a/drivers/input/keyboard/max7359_keypad.c +++ b/drivers/input/keyboard/max7359_keypad.c @@ -265,7 +265,6 @@ static int __devexit max7359_remove(struct i2c_client *client) free_irq(client->irq, keypad); input_unregister_device(keypad->input_dev); - i2c_set_clientdata(client, NULL); kfree(keypad); return 0; diff --git a/drivers/input/keyboard/qt2160.c b/drivers/input/keyboard/qt2160.c index 31f3008..fac6951 100644 --- a/drivers/input/keyboard/qt2160.c +++ b/drivers/input/keyboard/qt2160.c @@ -358,7 +358,6 @@ static int __devexit qt2160_remove(struct i2c_client *client) input_unregister_device(qt2160->input); kfree(qt2160); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/input/keyboard/tca6416-keypad.c b/drivers/input/keyboard/tca6416-keypad.c index 493c93f..00137be 100644 --- a/drivers/input/keyboard/tca6416-keypad.c +++ b/drivers/input/keyboard/tca6416-keypad.c @@ -316,8 +316,6 @@ static int __devexit tca6416_keypad_remove(struct i2c_client *client) input_unregister_device(chip->input); kfree(chip); - i2c_set_clientdata(client, NULL); - return 0; } diff --git a/drivers/input/misc/ad714x-i2c.c b/drivers/input/misc/ad714x-i2c.c index e9adbe4..2bef8fa 100644 --- a/drivers/input/misc/ad714x-i2c.c +++ b/drivers/input/misc/ad714x-i2c.c @@ -97,7 +97,6 @@ static int __devexit ad714x_i2c_remove(struct i2c_client *client) struct ad714x_chip *chip = i2c_get_clientdata(client); ad714x_remove(chip); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/input/misc/pcf8574_keypad.c b/drivers/input/misc/pcf8574_keypad.c index 5c3ac4e..0ac47d2 100644 --- a/drivers/input/misc/pcf8574_keypad.c +++ b/drivers/input/misc/pcf8574_keypad.c @@ -168,8 +168,6 @@ static int __devexit pcf8574_kp_remove(struct i2c_client *client) input_unregister_device(lp->idev); kfree(lp); - i2c_set_clientdata(client, NULL); - return 0; } diff --git a/drivers/input/mouse/synaptics_i2c.c b/drivers/input/mouse/synaptics_i2c.c index 8291e73..0ae62f0 100644 --- a/drivers/input/mouse/synaptics_i2c.c +++ b/drivers/input/mouse/synaptics_i2c.c @@ -613,7 +613,6 @@ static int __devexit synaptics_i2c_remove(struct i2c_client *client) free_irq(client->irq, touch); input_unregister_device(touch->input); - i2c_set_clientdata(client, NULL); kfree(touch); return 0; diff --git a/drivers/input/touchscreen/ad7879.c b/drivers/input/touchscreen/ad7879.c index 794d070..4b32fb4 100644 --- a/drivers/input/touchscreen/ad7879.c +++ b/drivers/input/touchscreen/ad7879.c @@ -812,10 +812,8 @@ static int __devinit ad7879_probe(struct i2c_client *client, ts->bus = client; error = ad7879_construct(client, ts); - if (error) { - i2c_set_clientdata(client, NULL); + if (error) kfree(ts); - } return error; } @@ -825,7 +823,6 @@ static int __devexit ad7879_remove(struct i2c_client *client) struct ad7879 *ts = dev_get_drvdata(&client->dev); ad7879_destroy(client, ts); - i2c_set_clientdata(client, NULL); kfree(ts); return 0; diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 75f8b73..7a3a916 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c @@ -238,7 +238,6 @@ err2: input = NULL; /* so we dont try to free it below */ err1: input_free_device(input); - i2c_set_clientdata(client, NULL); kfree(priv); err0: return err; @@ -256,7 +255,6 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) enable_irq(priv->irq); input_unregister_device(priv->input); - i2c_set_clientdata(client, NULL); kfree(priv); return 0; diff --git a/drivers/input/touchscreen/mcs5000_ts.c b/drivers/input/touchscreen/mcs5000_ts.c index ce8ab02..1fb0c2f 100644 --- a/drivers/input/touchscreen/mcs5000_ts.c +++ b/drivers/input/touchscreen/mcs5000_ts.c @@ -256,7 +256,6 @@ static int __devexit mcs5000_ts_remove(struct i2c_client *client) free_irq(client->irq, data); input_unregister_device(data->input_dev); kfree(data); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/input/touchscreen/tsc2007.c b/drivers/input/touchscreen/tsc2007.c index 769b479..be23780 100644 --- a/drivers/input/touchscreen/tsc2007.c +++ b/drivers/input/touchscreen/tsc2007.c @@ -347,8 +347,6 @@ static int __devexit tsc2007_remove(struct i2c_client *client) struct tsc2007 *ts = i2c_get_clientdata(client); struct tsc2007_platform_data *pdata = client->dev.platform_data; - i2c_set_clientdata(client, NULL); - tsc2007_free_irq(ts); if (pdata->exit_platform_hw) diff --git a/drivers/leds/leds-bd2802.c b/drivers/leds/leds-bd2802.c index 286b501..5dcdf9d 100644 --- a/drivers/leds/leds-bd2802.c +++ b/drivers/leds/leds-bd2802.c @@ -742,7 +742,6 @@ failed_unregister_dev_file: for (i--; i >= 0; i--) device_remove_file(&led->client->dev, bd2802_attributes[i]); failed_free: - i2c_set_clientdata(client, NULL); kfree(led); return ret; @@ -759,7 +758,6 @@ static int __exit bd2802_remove(struct i2c_client *client) bd2802_disable_adv_conf(led); for (i = 0; i < ARRAY_SIZE(bd2802_attributes); i++) device_remove_file(&led->client->dev, bd2802_attributes[i]); - i2c_set_clientdata(client, NULL); kfree(led); return 0; diff --git a/drivers/leds/leds-lp3944.c b/drivers/leds/leds-lp3944.c index 932a58d..9010c05 100644 --- a/drivers/leds/leds-lp3944.c +++ b/drivers/leds/leds-lp3944.c @@ -432,7 +432,6 @@ static int __devexit lp3944_remove(struct i2c_client *client) } kfree(data); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/leds/leds-pca9532.c b/drivers/leds/leds-pca9532.c index 6682175..43d0875 100644 --- a/drivers/leds/leds-pca9532.c +++ b/drivers/leds/leds-pca9532.c @@ -320,10 +320,8 @@ static int pca9532_probe(struct i2c_client *client, mutex_init(&data->update_lock); err = pca9532_configure(client, data, pca9532_pdata); - if (err) { + if (err) kfree(data); - i2c_set_clientdata(client, NULL); - } return err; } @@ -351,7 +349,6 @@ static int pca9532_remove(struct i2c_client *client) } kfree(data); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/leds/leds-pca955x.c b/drivers/leds/leds-pca955x.c index 8ff50f2..66aa3e8 100644 --- a/drivers/leds/leds-pca955x.c +++ b/drivers/leds/leds-pca955x.c @@ -342,7 +342,6 @@ exit: } kfree(pca955x); - i2c_set_clientdata(client, NULL); return err; } @@ -358,7 +357,6 @@ static int __devexit pca955x_remove(struct i2c_client *client) } kfree(pca955x); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/macintosh/therm_adt746x.c b/drivers/macintosh/therm_adt746x.c index 16d82f1..c42eeb4 100644 --- a/drivers/macintosh/therm_adt746x.c +++ b/drivers/macintosh/therm_adt746x.c @@ -182,7 +182,6 @@ remove_thermostat(struct i2c_client *client) thermostat = NULL; - i2c_set_clientdata(client, NULL); kfree(th); return 0; @@ -400,7 +399,6 @@ static int probe_thermostat(struct i2c_client *client, rc = read_reg(th, CONFIG_REG); if (rc < 0) { dev_err(&client->dev, "Thermostat failed to read config!\n"); - i2c_set_clientdata(client, NULL); kfree(th); return -ENODEV; } diff --git a/drivers/macintosh/windfarm_lm75_sensor.c b/drivers/macintosh/windfarm_lm75_sensor.c index d8257d3..647c6ad 100644 --- a/drivers/macintosh/windfarm_lm75_sensor.c +++ b/drivers/macintosh/windfarm_lm75_sensor.c @@ -107,10 +107,8 @@ static int wf_lm75_probe(struct i2c_client *client, i2c_set_clientdata(client, lm); rc = wf_register_sensor(&lm->sens); - if (rc) { - i2c_set_clientdata(client, NULL); + if (rc) kfree(lm); - } return rc; } @@ -216,7 +214,6 @@ static int wf_lm75_remove(struct i2c_client *client) /* release sensor */ wf_unregister_sensor(&lm->sens); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/macintosh/windfarm_max6690_sensor.c b/drivers/macintosh/windfarm_max6690_sensor.c index b486eb9..8204113 100644 --- a/drivers/macintosh/windfarm_max6690_sensor.c +++ b/drivers/macintosh/windfarm_max6690_sensor.c @@ -81,7 +81,6 @@ static int wf_max6690_probe(struct i2c_client *client, rc = wf_register_sensor(&max->sens); if (rc) { - i2c_set_clientdata(client, NULL); kfree(max); } diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index e20330a..65a8ff3 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -376,7 +376,6 @@ static int wf_sat_remove(struct i2c_client *client) /* XXX TODO */ sat->i2c = NULL; - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/media/radio/si470x/radio-si470x-i2c.c b/drivers/media/radio/si470x/radio-si470x-i2c.c index a5844d0..67a4ec8 100644 --- a/drivers/media/radio/si470x/radio-si470x-i2c.c +++ b/drivers/media/radio/si470x/radio-si470x-i2c.c @@ -482,7 +482,6 @@ static __devexit int si470x_i2c_remove(struct i2c_client *client) cancel_work_sync(&radio->radio_work); video_unregister_device(radio->videodev); kfree(radio); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/media/video/mt9m001.c b/drivers/media/video/mt9m001.c index b62c0bd..e3b9a8a 100644 --- a/drivers/media/video/mt9m001.c +++ b/drivers/media/video/mt9m001.c @@ -785,7 +785,6 @@ static int mt9m001_probe(struct i2c_client *client, ret = mt9m001_video_probe(icd, client); if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(mt9m001); } @@ -799,7 +798,6 @@ static int mt9m001_remove(struct i2c_client *client) icd->ops = NULL; mt9m001_video_remove(icd); - i2c_set_clientdata(client, NULL); client->driver = NULL; kfree(mt9m001); diff --git a/drivers/media/video/mt9m111.c b/drivers/media/video/mt9m111.c index d35f536..e42162c 100644 --- a/drivers/media/video/mt9m111.c +++ b/drivers/media/video/mt9m111.c @@ -1068,7 +1068,6 @@ static int mt9m111_probe(struct i2c_client *client, ret = mt9m111_video_probe(icd, client); if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(mt9m111); } @@ -1081,7 +1080,6 @@ static int mt9m111_remove(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; - i2c_set_clientdata(client, NULL); client->driver = NULL; kfree(mt9m111); diff --git a/drivers/media/video/mt9t031.c b/drivers/media/video/mt9t031.c index 78b4e09..9f5ff25 100644 --- a/drivers/media/video/mt9t031.c +++ b/drivers/media/video/mt9t031.c @@ -883,7 +883,6 @@ static int mt9t031_probe(struct i2c_client *client, if (ret) { if (icd) icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(mt9t031); } @@ -897,7 +896,6 @@ static int mt9t031_remove(struct i2c_client *client) if (icd) icd->ops = NULL; - i2c_set_clientdata(client, NULL); client->driver = NULL; kfree(mt9t031); diff --git a/drivers/media/video/mt9t112.c b/drivers/media/video/mt9t112.c index 7438f8d..aa4fce9 100644 --- a/drivers/media/video/mt9t112.c +++ b/drivers/media/video/mt9t112.c @@ -1119,7 +1119,6 @@ static int mt9t112_probe(struct i2c_client *client, ret = mt9t112_camera_probe(icd, client); if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); } @@ -1132,7 +1131,6 @@ static int mt9t112_remove(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); return 0; } diff --git a/drivers/media/video/mt9v022.c b/drivers/media/video/mt9v022.c index e5bae4c..fb44ff0 100644 --- a/drivers/media/video/mt9v022.c +++ b/drivers/media/video/mt9v022.c @@ -920,7 +920,6 @@ static int mt9v022_probe(struct i2c_client *client, ret = mt9v022_video_probe(icd, client); if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(mt9v022); } @@ -934,7 +933,6 @@ static int mt9v022_remove(struct i2c_client *client) icd->ops = NULL; mt9v022_video_remove(icd); - i2c_set_clientdata(client, NULL); client->driver = NULL; kfree(mt9v022); diff --git a/drivers/media/video/ov772x.c b/drivers/media/video/ov772x.c index 7f8ece3..c33acc9 100644 --- a/drivers/media/video/ov772x.c +++ b/drivers/media/video/ov772x.c @@ -1159,7 +1159,6 @@ static int ov772x_probe(struct i2c_client *client, ret = ov772x_video_probe(icd, client); if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); } @@ -1172,7 +1171,6 @@ static int ov772x_remove(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); return 0; } diff --git a/drivers/media/video/ov9640.c b/drivers/media/video/ov9640.c index 36599a6..035e9ec 100644 --- a/drivers/media/video/ov9640.c +++ b/drivers/media/video/ov9640.c @@ -783,7 +783,6 @@ static int ov9640_probe(struct i2c_client *client, if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); } @@ -794,7 +793,6 @@ static int ov9640_remove(struct i2c_client *client) { struct ov9640_priv *priv = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(priv); return 0; } diff --git a/drivers/media/video/rj54n1cb0c.c b/drivers/media/video/rj54n1cb0c.c index bbd9c11..2c3b58c 100644 --- a/drivers/media/video/rj54n1cb0c.c +++ b/drivers/media/video/rj54n1cb0c.c @@ -1444,7 +1444,6 @@ static int rj54n1_probe(struct i2c_client *client, ret = rj54n1_video_probe(icd, client, rj54n1_priv); if (ret < 0) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(rj54n1); return ret; } @@ -1461,7 +1460,6 @@ static int rj54n1_remove(struct i2c_client *client) icd->ops = NULL; if (icl->free_bus) icl->free_bus(icl); - i2c_set_clientdata(client, NULL); client->driver = NULL; kfree(rj54n1); diff --git a/drivers/media/video/tcm825x.c b/drivers/media/video/tcm825x.c index b90e9da..54681a5 100644 --- a/drivers/media/video/tcm825x.c +++ b/drivers/media/video/tcm825x.c @@ -850,7 +850,6 @@ static int tcm825x_probe(struct i2c_client *client, const struct i2c_device_id *did) { struct tcm825x_sensor *sensor = &tcm825x; - int rval; if (i2c_get_clientdata(client)) return -EBUSY; @@ -871,11 +870,7 @@ static int tcm825x_probe(struct i2c_client *client, sensor->pix.height = tcm825x_sizes[QVGA].height; sensor->pix.pixelformat = V4L2_PIX_FMT_RGB565; - rval = v4l2_int_device_register(sensor->v4l2_int_device); - if (rval) - i2c_set_clientdata(client, NULL); - - return rval; + return v4l2_int_device_register(sensor->v4l2_int_device); } static int tcm825x_remove(struct i2c_client *client) @@ -886,7 +881,6 @@ static int tcm825x_remove(struct i2c_client *client) return -ENODEV; /* our client isn't attached */ v4l2_int_device_unregister(sensor->v4l2_int_device); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/media/video/tw9910.c b/drivers/media/video/tw9910.c index 76be733..6eb3395 100644 --- a/drivers/media/video/tw9910.c +++ b/drivers/media/video/tw9910.c @@ -977,7 +977,6 @@ static int tw9910_probe(struct i2c_client *client, ret = tw9910_video_probe(icd, client); if (ret) { icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); } @@ -990,7 +989,6 @@ static int tw9910_remove(struct i2c_client *client) struct soc_camera_device *icd = client->dev.platform_data; icd->ops = NULL; - i2c_set_clientdata(client, NULL); kfree(priv); return 0; } diff --git a/drivers/mfd/88pm860x-i2c.c b/drivers/mfd/88pm860x-i2c.c index c933b64..bc02e6b 100644 --- a/drivers/mfd/88pm860x-i2c.c +++ b/drivers/mfd/88pm860x-i2c.c @@ -200,8 +200,6 @@ static int __devexit pm860x_remove(struct i2c_client *client) pm860x_device_exit(chip); i2c_unregister_device(chip->companion); - i2c_set_clientdata(chip->client, NULL); - i2c_set_clientdata(client, NULL); kfree(chip); return 0; } diff --git a/drivers/mfd/ab3100-core.c b/drivers/mfd/ab3100-core.c index 53ebfee..66379b4 100644 --- a/drivers/mfd/ab3100-core.c +++ b/drivers/mfd/ab3100-core.c @@ -957,7 +957,6 @@ static int __init ab3100_probe(struct i2c_client *client, i2c_unregister_device(ab3100->testreg_client); exit_no_testreg_client: exit_no_detect: - i2c_set_clientdata(client, NULL); kfree(ab3100); return err; } @@ -979,7 +978,6 @@ static int __exit ab3100_remove(struct i2c_client *client) * their notifiers so deactivate IRQ */ free_irq(client->irq, ab3100); - i2c_set_clientdata(client, NULL); kfree(ab3100); return 0; } diff --git a/drivers/mfd/ab3550-core.c b/drivers/mfd/ab3550-core.c index 1060f8e..f54ab62 100644 --- a/drivers/mfd/ab3550-core.c +++ b/drivers/mfd/ab3550-core.c @@ -1362,7 +1362,6 @@ static int __exit ab3550_remove(struct i2c_client *client) * their notifiers so deactivate IRQ */ free_irq(client->irq, ab); - i2c_set_clientdata(client, NULL); kfree(ab); return 0; } diff --git a/drivers/mfd/adp5520.c b/drivers/mfd/adp5520.c index 0055328..3122139 100644 --- a/drivers/mfd/adp5520.c +++ b/drivers/mfd/adp5520.c @@ -302,7 +302,6 @@ out_free_irq: free_irq(chip->irq, chip); out_free_chip: - i2c_set_clientdata(client, NULL); kfree(chip); return ret; @@ -317,7 +316,6 @@ static int __devexit adp5520_remove(struct i2c_client *client) adp5520_remove_subdevs(chip); adp5520_write(chip->dev, ADP5520_MODE_STATUS, 0); - i2c_set_clientdata(client, NULL); kfree(chip); return 0; } diff --git a/drivers/mfd/da903x.c b/drivers/mfd/da903x.c index 3ad915d..c07aece 100644 --- a/drivers/mfd/da903x.c +++ b/drivers/mfd/da903x.c @@ -534,7 +534,6 @@ static int __devinit da903x_probe(struct i2c_client *client, out_free_irq: free_irq(client->irq, chip); out_free_chip: - i2c_set_clientdata(client, NULL); kfree(chip); return ret; } @@ -544,7 +543,6 @@ static int __devexit da903x_remove(struct i2c_client *client) struct da903x_chip *chip = i2c_get_clientdata(client); da903x_remove_subdevs(chip); - i2c_set_clientdata(client, NULL); kfree(chip); return 0; } diff --git a/drivers/mfd/max8925-i2c.c b/drivers/mfd/max8925-i2c.c index e73f3f5..0219115 100644 --- a/drivers/mfd/max8925-i2c.c +++ b/drivers/mfd/max8925-i2c.c @@ -173,7 +173,6 @@ static int __devexit max8925_remove(struct i2c_client *client) max8925_device_exit(chip); i2c_unregister_device(chip->adc); i2c_unregister_device(chip->rtc); - i2c_set_clientdata(chip->i2c, NULL); kfree(chip); return 0; } diff --git a/drivers/mfd/menelaus.c b/drivers/mfd/menelaus.c index 721948b..a3fb4bc 100644 --- a/drivers/mfd/menelaus.c +++ b/drivers/mfd/menelaus.c @@ -1228,7 +1228,6 @@ fail2: free_irq(client->irq, menelaus); flush_scheduled_work(); fail1: - i2c_set_clientdata(client, NULL); kfree(menelaus); return err; } @@ -1238,7 +1237,6 @@ static int __exit menelaus_remove(struct i2c_client *client) struct menelaus_chip *menelaus = i2c_get_clientdata(client); free_irq(client->irq, menelaus); - i2c_set_clientdata(client, NULL); kfree(menelaus); the_menelaus = NULL; return 0; diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 704736e..23e5855 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c @@ -336,7 +336,6 @@ static int __devinit pcf50633_probe(struct i2c_client *client, return 0; err_free: - i2c_set_clientdata(client, NULL); kfree(pcf); return ret; @@ -357,7 +356,6 @@ static int __devexit pcf50633_remove(struct i2c_client *client) for (i = 0; i < PCF50633_NUM_REGULATORS; i++) platform_device_unregister(pcf->regulator_pdev[i]); - i2c_set_clientdata(client, NULL); kfree(pcf); return 0; diff --git a/drivers/mfd/tc35892.c b/drivers/mfd/tc35892.c index 715f095..e619e2a 100644 --- a/drivers/mfd/tc35892.c +++ b/drivers/mfd/tc35892.c @@ -296,7 +296,6 @@ out_freeirq: out_removeirq: tc35892_irq_remove(tc35892); out_free: - i2c_set_clientdata(i2c, NULL); kfree(tc35892); return ret; } @@ -310,7 +309,6 @@ static int __devexit tc35892_remove(struct i2c_client *client) free_irq(tc35892->i2c->irq, tc35892); tc35892_irq_remove(tc35892); - i2c_set_clientdata(client, NULL); kfree(tc35892); return 0; diff --git a/drivers/mfd/tps65010.c b/drivers/mfd/tps65010.c index 9b22a77..d0016b6 100644 --- a/drivers/mfd/tps65010.c +++ b/drivers/mfd/tps65010.c @@ -530,7 +530,6 @@ static int __exit tps65010_remove(struct i2c_client *client) cancel_delayed_work(&tps->work); flush_scheduled_work(); debugfs_remove(tps->file); - i2c_set_clientdata(client, NULL); kfree(tps); the_tps = NULL; return 0; diff --git a/drivers/mfd/wm8350-i2c.c b/drivers/mfd/wm8350-i2c.c index 7795af4..5fe5de1 100644 --- a/drivers/mfd/wm8350-i2c.c +++ b/drivers/mfd/wm8350-i2c.c @@ -80,7 +80,6 @@ static int wm8350_i2c_probe(struct i2c_client *i2c, return ret; err: - i2c_set_clientdata(i2c, NULL); kfree(wm8350); return ret; } @@ -90,7 +89,6 @@ static int wm8350_i2c_remove(struct i2c_client *i2c) struct wm8350 *wm8350 = i2c_get_clientdata(i2c); wm8350_device_exit(wm8350); - i2c_set_clientdata(i2c, NULL); kfree(wm8350); return 0; diff --git a/drivers/mfd/wm8400-core.c b/drivers/mfd/wm8400-core.c index e08aafa..1bfef48 100644 --- a/drivers/mfd/wm8400-core.c +++ b/drivers/mfd/wm8400-core.c @@ -415,7 +415,6 @@ static int wm8400_i2c_probe(struct i2c_client *i2c, return 0; struct_err: - i2c_set_clientdata(i2c, NULL); kfree(wm8400); err: return ret; @@ -426,7 +425,6 @@ static int wm8400_i2c_remove(struct i2c_client *i2c) struct wm8400 *wm8400 = i2c_get_clientdata(i2c); wm8400_release(wm8400); - i2c_set_clientdata(i2c, NULL); kfree(wm8400); return 0; diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index f7ca3a4..559b0b3 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -643,7 +643,6 @@ static int __devexit at24_remove(struct i2c_client *client) kfree(at24->writebuf); kfree(at24); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/mtd/maps/pismo.c b/drivers/mtd/maps/pismo.c index eb476b7..f4ce273 100644 --- a/drivers/mtd/maps/pismo.c +++ b/drivers/mtd/maps/pismo.c @@ -234,7 +234,6 @@ static int __devexit pismo_remove(struct i2c_client *client) /* FIXME: set_vpp needs saner arguments */ pismo_setvpp_remove_fix(pismo); - i2c_set_clientdata(client, NULL); kfree(pismo); return 0; @@ -286,7 +285,6 @@ static int __devinit pismo_probe(struct i2c_client *client, return 0; exit_free: - i2c_set_clientdata(client, NULL); kfree(pismo); return ret; } diff --git a/drivers/power/max17040_battery.c b/drivers/power/max17040_battery.c index f3e22c9..2f2f9a6 100644 --- a/drivers/power/max17040_battery.c +++ b/drivers/power/max17040_battery.c @@ -225,7 +225,6 @@ static int __devinit max17040_probe(struct i2c_client *client, ret = power_supply_register(&client->dev, &chip->battery); if (ret) { dev_err(&client->dev, "failed: power supply register\n"); - i2c_set_clientdata(client, NULL); kfree(chip); return ret; } @@ -245,7 +244,6 @@ static int __devexit max17040_remove(struct i2c_client *client) power_supply_unregister(&chip->battery); cancel_delayed_work(&chip->work); - i2c_set_clientdata(client, NULL); kfree(chip); return 0; } diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 671a7d1..8ae3732 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c @@ -519,8 +519,6 @@ static int __devexit lp3971_i2c_remove(struct i2c_client *i2c) struct lp3971 *lp3971 = i2c_get_clientdata(i2c); int i; - i2c_set_clientdata(i2c, NULL); - for (i = 0; i < lp3971->num_regulators; i++) regulator_unregister(lp3971->rdev[i]); diff --git a/drivers/regulator/max1586.c b/drivers/regulator/max1586.c index b3c1afc..2b54d9d 100644 --- a/drivers/regulator/max1586.c +++ b/drivers/regulator/max1586.c @@ -244,7 +244,6 @@ static int __devexit max1586_pmic_remove(struct i2c_client *client) for (i = 0; i <= MAX1586_V6; i++) if (rdev[i]) regulator_unregister(rdev[i]); - i2c_set_clientdata(client, NULL); kfree(rdev); return 0; diff --git a/drivers/regulator/max8649.c b/drivers/regulator/max8649.c index bfc4c5f..4520ace 100644 --- a/drivers/regulator/max8649.c +++ b/drivers/regulator/max8649.c @@ -357,7 +357,6 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client, dev_info(info->dev, "Max8649 regulator device is detected.\n"); return 0; out: - i2c_set_clientdata(client, NULL); kfree(info); return ret; } @@ -369,7 +368,6 @@ static int __devexit max8649_regulator_remove(struct i2c_client *client) if (info) { if (info->regulator) regulator_unregister(info->regulator); - i2c_set_clientdata(client, NULL); kfree(info); } diff --git a/drivers/regulator/max8660.c b/drivers/regulator/max8660.c index 3790b21..d97220e 100644 --- a/drivers/regulator/max8660.c +++ b/drivers/regulator/max8660.c @@ -471,7 +471,6 @@ static int __devexit max8660_remove(struct i2c_client *client) for (i = 0; i < MAX8660_V_END; i++) if (rdev[i]) regulator_unregister(rdev[i]); - i2c_set_clientdata(client, NULL); kfree(rdev); return 0; diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c index 8e2f209..f50afc9 100644 --- a/drivers/regulator/tps65023-regulator.c +++ b/drivers/regulator/tps65023-regulator.c @@ -538,9 +538,6 @@ static int __devexit tps_65023_remove(struct i2c_client *client) struct tps_pmic *tps = i2c_get_clientdata(client); int i; - /* clear the client data in i2c */ - i2c_set_clientdata(client, NULL); - for (i = 0; i < TPS65023_NUM_REGULATOR; i++) regulator_unregister(tps->rdev[i]); diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 6194573..1f0007f 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -403,7 +403,6 @@ out_irq: free_irq(client->irq, client); out_free: - i2c_set_clientdata(client, NULL); kfree(ds1374); return ret; } @@ -422,7 +421,6 @@ static int __devexit ds1374_remove(struct i2c_client *client) } rtc_device_unregister(ds1374->rtc); - i2c_set_clientdata(client, NULL); kfree(ds1374); return 0; } diff --git a/drivers/rtc/rtc-rx8025.c b/drivers/rtc/rtc-rx8025.c index b65c82f..789f62f 100644 --- a/drivers/rtc/rtc-rx8025.c +++ b/drivers/rtc/rtc-rx8025.c @@ -632,7 +632,6 @@ errout_reg: rtc_device_unregister(rx8025->rtc); errout_free: - i2c_set_clientdata(client, NULL); kfree(rx8025); errout: @@ -656,7 +655,6 @@ static int __devexit rx8025_remove(struct i2c_client *client) rx8025_sysfs_unregister(&client->dev); rtc_device_unregister(rx8025->rtc); - i2c_set_clientdata(client, NULL); kfree(rx8025); return 0; } diff --git a/drivers/rtc/rtc-s35390a.c b/drivers/rtc/rtc-s35390a.c index def4d39..f789e00 100644 --- a/drivers/rtc/rtc-s35390a.c +++ b/drivers/rtc/rtc-s35390a.c @@ -275,7 +275,6 @@ exit_dummy: if (s35390a->client[i]) i2c_unregister_device(s35390a->client[i]); kfree(s35390a); - i2c_set_clientdata(client, NULL); exit: return err; @@ -292,7 +291,6 @@ static int s35390a_remove(struct i2c_client *client) rtc_device_unregister(s35390a->rtc); kfree(s35390a); - i2c_set_clientdata(client, NULL); return 0; } diff --git a/drivers/staging/dream/synaptics_i2c_rmi.c b/drivers/staging/dream/synaptics_i2c_rmi.c index 1f020da..3320359 100644 --- a/drivers/staging/dream/synaptics_i2c_rmi.c +++ b/drivers/staging/dream/synaptics_i2c_rmi.c @@ -519,7 +519,6 @@ err_input_register_device_failed: err_input_dev_alloc_failed: err_detect_failed: err_power_failed: - i2c_set_clientdata(client, NULL); kfree(ts); err_alloc_data_failed: err_check_functionality_failed: @@ -537,7 +536,6 @@ static int synaptics_ts_remove(struct i2c_client *client) else hrtimer_cancel(&ts->timer); input_unregister_device(ts->input_dev); - i2c_set_clientdata(client, NULL); kfree(ts); return 0; } diff --git a/drivers/staging/go7007/wis-saa7113.c b/drivers/staging/go7007/wis-saa7113.c index bd92545..72f5c1f 100644 --- a/drivers/staging/go7007/wis-saa7113.c +++ b/drivers/staging/go7007/wis-saa7113.c @@ -289,7 +289,6 @@ static int wis_saa7113_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-saa7113: error initializing SAA7113\n"); - i2c_set_clientdata(client, NULL); kfree(dec); return -ENODEV; } @@ -301,7 +300,6 @@ static int wis_saa7113_remove(struct i2c_client *client) { struct wis_saa7113 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/go7007/wis-saa7115.c b/drivers/staging/go7007/wis-saa7115.c index b2eb804..cd950b6 100644 --- a/drivers/staging/go7007/wis-saa7115.c +++ b/drivers/staging/go7007/wis-saa7115.c @@ -422,7 +422,6 @@ static int wis_saa7115_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-saa7115: error initializing SAA7115\n"); - i2c_set_clientdata(client, NULL); kfree(dec); return -ENODEV; } @@ -434,7 +433,6 @@ static int wis_saa7115_remove(struct i2c_client *client) { struct wis_saa7115 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/go7007/wis-sony-tuner.c b/drivers/staging/go7007/wis-sony-tuner.c index b101329..981c9b3 100644 --- a/drivers/staging/go7007/wis-sony-tuner.c +++ b/drivers/staging/go7007/wis-sony-tuner.c @@ -684,7 +684,6 @@ static int wis_sony_tuner_remove(struct i2c_client *client) { struct wis_sony_tuner *t = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(t); return 0; } diff --git a/drivers/staging/go7007/wis-tw2804.c b/drivers/staging/go7007/wis-tw2804.c index 315268d..ee28a99 100644 --- a/drivers/staging/go7007/wis-tw2804.c +++ b/drivers/staging/go7007/wis-tw2804.c @@ -323,7 +323,6 @@ static int wis_tw2804_remove(struct i2c_client *client) { struct wis_tw2804 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/go7007/wis-tw9903.c b/drivers/staging/go7007/wis-tw9903.c index 2afea09..80d4726 100644 --- a/drivers/staging/go7007/wis-tw9903.c +++ b/drivers/staging/go7007/wis-tw9903.c @@ -294,7 +294,6 @@ static int wis_tw9903_probe(struct i2c_client *client, if (write_regs(client, initial_registers) < 0) { printk(KERN_ERR "wis-tw9903: error initializing TW9903\n"); - i2c_set_clientdata(client, NULL); kfree(dec); return -ENODEV; } @@ -306,7 +305,6 @@ static int wis_tw9903_remove(struct i2c_client *client) { struct wis_tw9903 *dec = i2c_get_clientdata(client); - i2c_set_clientdata(client, NULL); kfree(dec); return 0; } diff --git a/drivers/staging/iio/adc/max1363_core.c b/drivers/staging/iio/adc/max1363_core.c index 20e2674..905f856 100644 --- a/drivers/staging/iio/adc/max1363_core.c +++ b/drivers/staging/iio/adc/max1363_core.c @@ -1011,7 +1011,6 @@ error_put_reg: if (!IS_ERR(st->reg)) regulator_put(st->reg); error_free_st: - i2c_set_clientdata(client, NULL); kfree(st); error_ret: @@ -1030,7 +1029,6 @@ static int max1363_remove(struct i2c_client *client) regulator_disable(st->reg); regulator_put(st->reg); } - i2c_set_clientdata(client, NULL); kfree(st); return 0; diff --git a/drivers/staging/iio/light/tsl2563.c b/drivers/staging/iio/light/tsl2563.c index 43aaacf..e4b0a5e 100644 --- a/drivers/staging/iio/light/tsl2563.c +++ b/drivers/staging/iio/light/tsl2563.c @@ -694,7 +694,6 @@ static int __devinit tsl2563_probe(struct i2c_client *client, fail2: iio_device_unregister(chip->indio_dev); fail1: - i2c_set_clientdata(client, NULL); kfree(chip); return err; } @@ -705,7 +704,6 @@ static int tsl2563_remove(struct i2c_client *client) iio_device_unregister(chip->indio_dev); - i2c_set_clientdata(client, NULL); kfree(chip); return 0; } diff --git a/drivers/video/backlight/adp8860_bl.c b/drivers/video/backlight/adp8860_bl.c index 921ca37..3ec2460 100644 --- a/drivers/video/backlight/adp8860_bl.c +++ b/drivers/video/backlight/adp8860_bl.c @@ -756,7 +756,6 @@ out: out1: backlight_device_unregister(bl); out2: - i2c_set_clientdata(client, NULL); kfree(data); return ret; @@ -776,7 +775,6 @@ static int __devexit adp8860_remove(struct i2c_client *client) &adp8860_bl_attr_group); backlight_device_unregister(data->bl); - i2c_set_clientdata(client, NULL); kfree(data); return 0; diff --git a/drivers/video/backlight/tosa_bl.c b/drivers/video/backlight/tosa_bl.c index e03e60b..2a04b38 100644 --- a/drivers/video/backlight/tosa_bl.c +++ b/drivers/video/backlight/tosa_bl.c @@ -119,7 +119,6 @@ static int __devinit tosa_bl_probe(struct i2c_client *client, err_reg: data->bl = NULL; - i2c_set_clientdata(client, NULL); err_gpio_dir: gpio_free(TOSA_GPIO_BL_C20MA); err_gpio_bl: @@ -133,7 +132,6 @@ static int __devexit tosa_bl_remove(struct i2c_client *client) backlight_device_unregister(data->bl); data->bl = NULL; - i2c_set_clientdata(client, NULL); gpio_free(TOSA_GPIO_BL_C20MA); -- 1.7.0 From broonie at opensource.wolfsonmicro.com Mon May 31 09:01:58 2010 From: broonie at opensource.wolfsonmicro.com (Mark Brown) Date: Mon, 31 May 2010 14:01:58 +0100 Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL) In-Reply-To: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> Message-ID: <20100531130157.GA10507@rakim.wolfsonmicro.main> On Mon, May 31, 2010 at 02:55:48PM +0200, Wolfram Sang wrote: > I2C-drivers can use the clientdata-pointer to point to private data. As I2C > devices are not really unregistered, but merely detached from their driver, it > used to be the drivers obligation to clear this pointer during remove() or a > failed probe(). As a couple of drivers forgot to do this, it was agreed that it > was cleaner if the i2c-core does this clearance when appropriate, as there is > no guarantee for the lifetime of the clientdata-pointer after remove() anyhow. > This feature was added to the core with commit > e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers. > > As there is no need anymore to clear the clientdata-pointer, remove all current > occurrences in the drivers to simplify the code and prevent confusion. > > Signed-off-by: Wolfram Sang Acked-by: Mark Brown From muehlfelder at enertex.de Mon May 31 09:03:42 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Mon, 31 May 2010 15:03:42 +0200 Subject: How stable is jffs2 summarize option? Message-ID: <201005311503.42629.muehlfelder@enertex.de> Hi, to reduce boot time of a device I want to use the jffs2 summarize option on my root file system. Currently 'm using Linux 2.6.24 on that specific device and the summarize option is marked as "experimental", so I wonder if it is stable enough for a productive system? Are there any well known devices that use this option, too? Do I have to use a newer kernel version? Thanks for any information From richardcochran at gmail.com Mon May 31 09:12:14 2010 From: richardcochran at gmail.com (Richard Cochran) Date: Mon, 31 May 2010 15:12:14 +0200 Subject: [PATCH] mtd: Added an ioctl to query the lock status of a flash sector. Message-ID: <20100531131214.GA15887@riccoc20.at.omicron.at> This patchs adds a way for user space programs to find out whether a flash sector is locked. An optional driver method in the mtd_info struct provides the information. Signed-off-by: Richard Cochran --- drivers/mtd/chips/cfi_cmdset_0001.c | 8 ++++++++ drivers/mtd/mtdchar.c | 14 ++++++++++++++ drivers/mtd/mtdpart.c | 10 ++++++++++ include/linux/mtd/mtd.h | 1 + include/mtd/mtd-abi.h | 1 + 5 files changed, 34 insertions(+), 0 deletions(-) diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 5fbf29e..67caca7 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -63,6 +63,7 @@ static int cfi_intelext_erase_varsize(struct mtd_info *, struct erase_info *); static void cfi_intelext_sync (struct mtd_info *); static int cfi_intelext_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len); static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len); +static int cfi_intelext_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len); #ifdef CONFIG_MTD_OTP static int cfi_intelext_read_fact_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_intelext_read_user_prot_reg (struct mtd_info *, loff_t, size_t, size_t *, u_char *); @@ -448,6 +449,7 @@ struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary) mtd->sync = cfi_intelext_sync; mtd->lock = cfi_intelext_lock; mtd->unlock = cfi_intelext_unlock; + mtd->locked = cfi_intelext_locked; mtd->suspend = cfi_intelext_suspend; mtd->resume = cfi_intelext_resume; mtd->flags = MTD_CAP_NORFLASH; @@ -2142,6 +2144,12 @@ static int cfi_intelext_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) return ret; } +static int cfi_intelext_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + return cfi_varsize_frob(mtd, do_getlockstatus_oneblock, + ofs, len, NULL) ? 1 : 0; +} + #ifdef CONFIG_MTD_OTP typedef int (*otp_op_t)(struct map_info *map, struct flchip *chip, diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 5b081cb..2c7bdcf 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -663,6 +663,20 @@ static int mtd_ioctl(struct inode *inode, struct file *file, break; } + case MEMISLOCKED: + { + struct erase_info_user einfo; + + if (copy_from_user(&einfo, argp, sizeof(einfo))) + return -EFAULT; + + if (!mtd->locked) + ret = -EOPNOTSUPP; + else + ret = mtd->locked(mtd, einfo.start, einfo.length); + break; + } + /* Legacy interface */ case MEMGETOOBSEL: { diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c index b8043a9..020b153 100644 --- a/drivers/mtd/mtdpart.c +++ b/drivers/mtd/mtdpart.c @@ -264,6 +264,14 @@ static int part_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len) return part->master->unlock(part->master, ofs + part->offset, len); } +static int part_locked(struct mtd_info *mtd, loff_t ofs, uint64_t len) +{ + struct mtd_part *part = PART(mtd); + if ((len + ofs) > mtd->size) + return -EINVAL; + return part->master->locked(part->master, ofs + part->offset, len); +} + static void part_sync(struct mtd_info *mtd) { struct mtd_part *part = PART(mtd); @@ -402,6 +410,8 @@ static struct mtd_part *add_one_partition(struct mtd_info *master, slave->mtd.lock = part_lock; if (master->unlock) slave->mtd.unlock = part_unlock; + if (master->locked) + slave->mtd.locked = part_locked; if (master->block_isbad) slave->mtd.block_isbad = part_block_isbad; if (master->block_markbad) diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h index 0f32a9b..a40546c 100644 --- a/include/linux/mtd/mtd.h +++ b/include/linux/mtd/mtd.h @@ -219,6 +219,7 @@ struct mtd_info { /* Chip-supported device locking */ int (*lock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); int (*unlock) (struct mtd_info *mtd, loff_t ofs, uint64_t len); + int (*locked) (struct mtd_info *mtd, loff_t ofs, uint64_t len); /* Power Management functions */ int (*suspend) (struct mtd_info *mtd); diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h index be51ae2..e12872e 100644 --- a/include/mtd/mtd-abi.h +++ b/include/mtd/mtd-abi.h @@ -110,6 +110,7 @@ struct otp_info { #define MEMERASE64 _IOW('M', 20, struct erase_info_user64) #define MEMWRITEOOB64 _IOWR('M', 21, struct mtd_oob_buf64) #define MEMREADOOB64 _IOWR('M', 22, struct mtd_oob_buf64) +#define MEMISLOCKED _IOR('M', 23, struct erase_info_user) /* * Obsolete legacy interface. Keep it in order not to break userspace -- 1.6.3.3 From error27 at gmail.com Mon May 31 10:03:38 2010 From: error27 at gmail.com (Dan Carpenter) Date: Mon, 31 May 2010 16:03:38 +0200 Subject: [patch] mtd: return success on blktrans_ioctl() Message-ID: <20100531140337.GV5483@bicker> There was a break missing so we returned -ENOTTY on success instead of zero. This was introduced by 048d8719956: "mtd: blktrans: Hotplug fixes" Signed-off-by: Dan Carpenter diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 03e19c1..a6bb586 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c @@ -245,6 +245,7 @@ static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, switch (cmd) { case BLKFLSBUF: ret = dev->tr->flush ? dev->tr->flush(dev) : 0; + break; default: ret = -ENOTTY; } From muehlfelder at enertex.de Mon May 31 11:17:37 2010 From: muehlfelder at enertex.de (Thorsten =?iso-8859-1?q?M=FChlfelder?=) Date: Mon, 31 May 2010 17:17:37 +0200 Subject: How stable is jffs2 summarize option? In-Reply-To: <201005311503.42629.muehlfelder@enertex.de> References: <201005311503.42629.muehlfelder@enertex.de> Message-ID: <201005311717.38056.muehlfelder@enertex.de> And is this an error, a warning or just debug output: jffs2_sum_write_sumnode: Not enough space for summary, padsize -45 Am Monday 31 May 2010 15:03:42 schrieb Thorsten M?hlfelder: > Hi, > > to reduce boot time of a device I want to use the jffs2 summarize option on > my root file system. Currently 'm using Linux 2.6.24 on that specific > device and the summarize option is marked as "experimental", so I wonder if > it is stable enough for a productive system? > Are there any well known devices that use this option, too? > Do I have to use a newer kernel version? > > Thanks for any information > > ______________________________________________________ > Linux MTD discussion mailing list > http://lists.infradead.org/mailman/listinfo/linux-mtd/ -- -- ____________________________________________________ Dipl.-Ing. (FH) Thorsten M?hlfelder Hard- und Softwareentwicklung Enertex Bayern GmbH Innovative Systeml?sungen der Energie- und Elektrotechnik www.enertex.de ? ? ? ? ? Erlachstra?e 13 ? ? ? ? ? ? ? ? 91301 Forchheim St.-Nr. 9216/125/50473 ? ? ?UST-ID DE 216 837 306 Registergericht Bamberg ? HRB 4569 Volksbank Forchheim eG, BLZ 763 910 00, Kto.-Nr. 7200480 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? Tel: 0049 9191 974637 Fax: 0049 9191 974687 ?Mob:0175 5151913 From richardcochran at gmail.com Mon May 31 12:24:34 2010 From: richardcochran at gmail.com (Richard Cochran) Date: Mon, 31 May 2010 18:24:34 +0200 Subject: [PATCH] ixp4xx: add support for static flash partitions Message-ID: <20100531162434.GA4599@riccoc20.at.omicron.at> This patch adds support for static flash partitioning from a platform device. Also, we clean up some weirdness where statements were separated by commas instead of semicolons. While we are at it, fix some minor bad white space, too. Signed-off-by: Richard Cochran --- drivers/mtd/maps/ixp4xx.c | 37 ++++++++++++++++++++++++++++--------- 1 files changed, 28 insertions(+), 9 deletions(-) diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c index 7b05152..5345d11 100644 --- a/drivers/mtd/maps/ixp4xx.c +++ b/drivers/mtd/maps/ixp4xx.c @@ -108,7 +108,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, if (from & 1) { *dest++ = BYTE1(flash_read16(src)); - src++; + src++; --len; } @@ -118,7 +118,7 @@ static void ixp4xx_copy_from(struct map_info *map, void *to, *dest++ = BYTE1(data); src += 2; len -= 2; - } + } if (len > 0) *dest++ = BYTE0(flash_read16(src)); @@ -185,6 +185,8 @@ static int ixp4xx_flash_probe(struct platform_device *dev) { struct flash_platform_data *plat = dev->dev.platform_data; struct ixp4xx_flash_info *info; + const char *part_type = NULL; + int nr_parts = 0; int err = -1; if (!plat) @@ -219,9 +221,9 @@ static int ixp4xx_flash_probe(struct platform_device *dev) */ info->map.bankwidth = 2; info->map.name = dev_name(&dev->dev); - info->map.read = ixp4xx_read16, - info->map.write = ixp4xx_probe_write16, - info->map.copy_from = ixp4xx_copy_from, + info->map.read = ixp4xx_read16; + info->map.write = ixp4xx_probe_write16; + info->map.copy_from = ixp4xx_copy_from; info->res = request_mem_region(dev->resource->start, resource_size(dev->resource), @@ -249,11 +251,28 @@ static int ixp4xx_flash_probe(struct platform_device *dev) info->mtd->owner = THIS_MODULE; /* Use the fast version */ - info->map.write = ixp4xx_write16, + info->map.write = ixp4xx_write16; + +#ifdef CONFIG_MTD_PARTITIONS + nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions, + dev->resource->start); +#endif + if (nr_parts > 0) { + part_type = "dynamic"; + } else { + info->partitions = plat->parts; + nr_parts = plat->nr_parts; + part_type = "static"; + } + if (nr_parts == 0) { + printk(KERN_NOTICE "IXP4xx flash: no partition info " + "available, registering whole flash\n"); + err = add_mtd_device(info->mtd); + } else { + printk(KERN_NOTICE "IXP4xx flash: using %s partition " + "definition\n", part_type); + err = add_mtd_partitions(info->mtd, info->partitions, nr_parts); - err = parse_mtd_partitions(info->mtd, probes, &info->partitions, dev->resource->start); - if (err > 0) { - err = add_mtd_partitions(info->mtd, info->partitions, err); if(err) printk(KERN_ERR "Could not parse partitions\n"); } -- 1.6.3.3 From agust at denx.de Mon May 31 12:37:15 2010 From: agust at denx.de (Anatolij Gustschin) Date: Mon, 31 May 2010 18:37:15 +0200 Subject: [PATCH] mtd: nand: mpc5121_nfc.c: Fix build failures Message-ID: <1275323836-15711-1-git-send-email-agust@denx.de> Fixes build errors caused by the: - OF device_node pointer being moved into struct device - removal of the match_table field from struct of_platform_driver Signed-off-by: Anatolij Gustschin Cc: Grant Likely --- drivers/mtd/nand/mpc5121_nfc.c | 8 ++++---- 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c index 3d0867d..0a130dc 100644 --- a/drivers/mtd/nand/mpc5121_nfc.c +++ b/drivers/mtd/nand/mpc5121_nfc.c @@ -650,7 +650,7 @@ static void mpc5121_nfc_free(struct device *dev, struct mtd_info *mtd) static int __devinit mpc5121_nfc_probe(struct of_device *op, const struct of_device_id *match) { - struct device_node *rootnode, *dn = op->node; + struct device_node *rootnode, *dn = op->dev.of_node; struct device *dev = &op->dev; struct mpc5121_nfc_prv *prv; struct resource res; @@ -889,12 +889,12 @@ static struct of_device_id mpc5121_nfc_match[] __devinitdata = { }; static struct of_platform_driver mpc5121_nfc_driver = { - .match_table = mpc5121_nfc_match, .probe = mpc5121_nfc_probe, .remove = __devexit_p(mpc5121_nfc_remove), .driver = { - .name = DRV_NAME, - .owner = THIS_MODULE, + .name = DRV_NAME, + .owner = THIS_MODULE, + .of_match_table = mpc5121_nfc_match, }, }; -- 1.7.0.4 From gregkh at suse.de Mon May 31 12:54:52 2010 From: gregkh at suse.de (Greg KH) Date: Mon, 31 May 2010 09:54:52 -0700 Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL) In-Reply-To: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> Message-ID: <20100531165452.GA14066@suse.de> On Mon, May 31, 2010 at 02:55:48PM +0200, Wolfram Sang wrote: > I2C-drivers can use the clientdata-pointer to point to private data. As I2C > devices are not really unregistered, but merely detached from their driver, it > used to be the drivers obligation to clear this pointer during remove() or a > failed probe(). As a couple of drivers forgot to do this, it was agreed that it > was cleaner if the i2c-core does this clearance when appropriate, as there is > no guarantee for the lifetime of the clientdata-pointer after remove() anyhow. > This feature was added to the core with commit > e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers. > > As there is no need anymore to clear the clientdata-pointer, remove all current > occurrences in the drivers to simplify the code and prevent confusion. > > Signed-off-by: Wolfram Sang > Cc: Jean Delvare Acked-by: Greg Kroah-Hartman From dmitry.torokhov at gmail.com Mon May 31 15:09:12 2010 From: dmitry.torokhov at gmail.com (Dmitry Torokhov) Date: Mon, 31 May 2010 12:09:12 -0700 Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL) In-Reply-To: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> Message-ID: <20100531190911.GC30712@core.coreip.homeip.net> Hi Wolfram, On Mon, May 31, 2010 at 02:55:48PM +0200, Wolfram Sang wrote: > I2C-drivers can use the clientdata-pointer to point to private data. As I2C > devices are not really unregistered, but merely detached from their driver, it > used to be the drivers obligation to clear this pointer during remove() or a > failed probe(). As a couple of drivers forgot to do this, it was agreed that it > was cleaner if the i2c-core does this clearance when appropriate, as there is > no guarantee for the lifetime of the clientdata-pointer after remove() anyhow. > This feature was added to the core with commit > e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers. > > As there is no need anymore to clear the clientdata-pointer, remove all current > occurrences in the drivers to simplify the code and prevent confusion. > > Signed-off-by: Wolfram Sang > Cc: Jean Delvare > --- > > Some more notes: > > I waited for rc1 as I knew there were some drivers/patches coming along which > needed to be processed, too. > > I'd suggest that this goes via the i2c-tree, so we get rid of all occurences at > once. > Frankly I'd prefer taking input stuff through my tree with the goal of .36 merge window just to minimize potential merge issues. This is a simple cleanup patch that has no dependencies, so there is little gain from doing it all in one go. Thanks. -- Dmitry From vitalywool at gmail.com Mon May 31 15:59:56 2010 From: vitalywool at gmail.com (Vitaly Wool) Date: Mon, 31 May 2010 21:59:56 +0200 Subject: How stable is jffs2 summarize option? In-Reply-To: <201005311503.42629.muehlfelder@enertex.de> References: <201005311503.42629.muehlfelder@enertex.de> Message-ID: Hi, 2010/5/31 Thorsten M?hlfelder : > Are there any well known devices that use this option, too? Yes, there are :) > Do I have to use a newer kernel version? Better do so :) ~Vitaly From vitalywool at gmail.com Mon May 31 16:00:29 2010 From: vitalywool at gmail.com (Vitaly Wool) Date: Mon, 31 May 2010 22:00:29 +0200 Subject: How stable is jffs2 summarize option? In-Reply-To: <201005311717.38056.muehlfelder@enertex.de> References: <201005311503.42629.muehlfelder@enertex.de> <201005311717.38056.muehlfelder@enertex.de> Message-ID: 2010/5/31 Thorsten M?hlfelder : > And is this an error, a warning or just debug output: > jffs2_sum_write_sumnode: Not enough space for summary, padsize -45 That's completely harmless. ~Vitaly From khali at linux-fr.org Mon May 31 16:57:50 2010 From: khali at linux-fr.org (Jean Delvare) Date: Mon, 31 May 2010 22:57:50 +0200 Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL) In-Reply-To: <20100531190911.GC30712@core.coreip.homeip.net> References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> <20100531190911.GC30712@core.coreip.homeip.net> Message-ID: <20100531225750.0dc18950@hyperion.delvare> Hi Dmitry, On Mon, 31 May 2010 12:09:12 -0700, Dmitry Torokhov wrote: > Frankly I'd prefer taking input stuff through my tree with the goal of > .36 merge window just to minimize potential merge issues. This is a > simple cleanup patch that has no dependencies, so there is little gain > from doing it all in one go. If I take the patch in my i2c tree, the aim is to merge it upstream immediately, so merge issues won't exist. -- Jean Delvare From rpurdie at rpsys.net Mon May 31 17:48:32 2010 From: rpurdie at rpsys.net (Richard Purdie) Date: Mon, 31 May 2010 22:48:32 +0100 Subject: [PATCH] drivers: remove all i2c_set_clientdata(client, NULL) In-Reply-To: <20100531190911.GC30712@core.coreip.homeip.net> References: <1275310552-14685-1-git-send-email-w.sang@pengutronix.de> <20100531190911.GC30712@core.coreip.homeip.net> Message-ID: <1275342512.24079.1559.camel@rex> On Mon, 2010-05-31 at 12:09 -0700, Dmitry Torokhov wrote: > On Mon, May 31, 2010 at 02:55:48PM +0200, Wolfram Sang wrote: > > I2C-drivers can use the clientdata-pointer to point to private data. As I2C > > devices are not really unregistered, but merely detached from their driver, it > > used to be the drivers obligation to clear this pointer during remove() or a > > failed probe(). As a couple of drivers forgot to do this, it was agreed that it > > was cleaner if the i2c-core does this clearance when appropriate, as there is > > no guarantee for the lifetime of the clientdata-pointer after remove() anyhow. > > This feature was added to the core with commit > > e4a7b9b04de15f6b63da5ccdd373ffa3057a3681 to fix the faulty drivers. > > > > As there is no need anymore to clear the clientdata-pointer, remove all current > > occurrences in the drivers to simplify the code and prevent confusion. > > > > Signed-off-by: Wolfram Sang > > Cc: Jean Delvare > > --- > > > > Some more notes: > > > > I waited for rc1 as I knew there were some drivers/patches coming along which > > needed to be processed, too. > > > > I'd suggest that this goes via the i2c-tree, so we get rid of all occurences at > > once. > > > > Frankly I'd prefer taking input stuff through my tree with the goal of > .36 merge window just to minimize potential merge issues. This is a > simple cleanup patch that has no dependencies, so there is little gain > from doing it all in one go. How about asking Linus to take this one now, then its done and we can all move on rather than queuing up problems for the next merge window? Acked-by: Richard Purdie Cheers, Richard From leiwen at marvell.com Sun May 16 05:03:52 2010 From: leiwen at marvell.com (Lei Wen) Date: Sun, 16 May 2010 17:03:52 +0800 Subject: [PATCH 04/25] pxa3xx_nand: make scan procedure more clear Message-ID: Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 88 ++++++++++++++++++++++----------------- 1 files changed, 50 insertions(+), 38 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 291610a..1f52701 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -160,6 +160,7 @@ struct pxa3xx_nand_info { unsigned int buf_start; unsigned int buf_count; + struct mtd_info *mtd; /* DMA information */ int drcmr_dat; int drcmr_cmd; @@ -1105,21 +1106,13 @@ static void pxa3xx_nand_init_mtd(struct mtd_info *mtd, this->chip_delay = 25; } -static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) +static int alloc_nand_resource(struct platform_device *pdev) { - struct pxa3xx_nand_platform_data *pdata; + struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; struct pxa3xx_nand_info *info; - struct nand_chip *this; struct mtd_info *mtd; struct resource *r; - int ret = 0, irq; - - pdata = pdev->dev.platform_data; - - if (!pdata) { - dev_err(&pdev->dev, "no platform data defined\n"); - return -ENODEV; - } + int ret, irq; mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info), GFP_KERNEL); @@ -1131,8 +1124,8 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) info = (struct pxa3xx_nand_info *)(&mtd[1]); info->pdev = pdev; - this = &info->nand_chip; mtd->priv = info; + info->mtd = mtd; mtd->owner = THIS_MODULE; info->clk = clk_get(&pdev->dev, NULL); @@ -1210,27 +1203,9 @@ static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) } pxa3xx_nand_init_mtd(mtd, info); + platform_set_drvdata(pdev, info); - platform_set_drvdata(pdev, mtd); - - if (nand_scan(mtd, 1)) { - dev_err(&pdev->dev, "failed to scan nand\n"); - ret = -ENXIO; - goto fail_free_irq; - } - - if (mtd_has_cmdlinepart()) { - static const char *probes[] = { "cmdlinepart", NULL }; - struct mtd_partition *parts; - int nr_parts; - - nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); - - if (nr_parts) - return add_mtd_partitions(mtd, parts, nr_parts); - } - - return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts); + return 0; fail_free_irq: free_irq(irq, info); @@ -1255,8 +1230,8 @@ fail_free_mtd: static int pxa3xx_nand_remove(struct platform_device *pdev) { - struct mtd_info *mtd = platform_get_drvdata(pdev); - struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); + struct mtd_info *mtd = info->mtd; struct resource *r; int irq; @@ -1285,11 +1260,48 @@ static int pxa3xx_nand_remove(struct platform_device *pdev) return 0; } +static int __devinit pxa3xx_nand_probe(struct platform_device *pdev) +{ + struct pxa3xx_nand_platform_data *pdata; + struct pxa3xx_nand_info *info; + int ret; + + pdata = pdev->dev.platform_data; + if (!pdata) { + dev_err(&pdev->dev, "no platform data defined\n"); + return -ENODEV; + } + + ret = alloc_nand_resource(pdev); + if (ret) + return ret; + + info = platform_get_drvdata(pdev); + if (nand_scan(info->mtd, 1)) { + dev_err(&pdev->dev, "failed to scan nand\n"); + pxa3xx_nand_remove(pdev); + return -ENODEV; + } + + if (mtd_has_cmdlinepart()) { + static const char *probes[] = { "cmdlinepart", NULL }; + struct mtd_partition *parts; + int nr_parts; + + nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0); + + if (nr_parts) + return add_mtd_partitions(mtd, parts, nr_parts); + } + + return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts); +} + #ifdef CONFIG_PM static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) { - struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); - struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); + struct mtd_info *mtd = info->mtd; if (info->state != STATE_READY) { dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); @@ -1301,8 +1313,8 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) static int pxa3xx_nand_resume(struct platform_device *pdev) { - struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev); - struct pxa3xx_nand_info *info = mtd->priv; + struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); + struct mtd_info *mtd = info->mtd; nand_writel(info, NDTR0CS0, info->ndtr0cs0); nand_writel(info, NDTR1CS0, info->ndtr1cs0); -- 1.7.0.4 From leiwen at marvell.com Mon May 31 02:05:46 2010 From: leiwen at marvell.com (Lei Wen) Date: Mon, 31 May 2010 14:05:46 +0800 Subject: [PATCH 05/25] pxa3xx_nand: rework irq logic Message-ID: Enable all irq when we start the nand controller, and put all the transaction logic in the pxa3xx_nand_irq. By doing this way, we could dramatically increase the performance by avoid unnecessary delay. Signed-off-by: Lei Wen Signed-off-by: Haojian Zhuang --- drivers/mtd/nand/pxa3xx_nand.c | 382 +++++++++++++++------------------------- 1 files changed, 140 insertions(+), 242 deletions(-) diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c index 1f52701..753346f 100644 --- a/drivers/mtd/nand/pxa3xx_nand.c +++ b/drivers/mtd/nand/pxa3xx_nand.c @@ -27,6 +27,7 @@ #include #define CHIP_DELAY_TIMEOUT (2 * HZ/10) +#define NAND_STOP_DELAY (2 * HZ/50) /* registers and bit definitions */ #define NDCR (0x00) /* Control register */ @@ -49,6 +50,7 @@ #define NDCR_DWIDTH_M (0x1 << 26) #define NDCR_PAGE_SZ (0x1 << 24) #define NDCR_NCSX (0x1 << 23) +#define NDCR_STOP_ON_UNCOR (0x1 << 22) #define NDCR_ND_MODE (0x3 << 21) #define NDCR_NAND_MODE (0x0) #define NDCR_CLR_PG_CNT (0x1 << 20) @@ -59,9 +61,11 @@ #define NDCR_RA_START (0x1 << 15) #define NDCR_PG_PER_BLK (0x1 << 14) #define NDCR_ND_ARB_EN (0x1 << 12) +#define NDCR_INT_MASK (0xFFF) #define NDSR_MASK (0xfff) -#define NDSR_RDY (0x1 << 11) +#define NDSR_RDY (0x1 << 12) +#define NDSR_FLASH_RDY (0x1 << 11) #define NDSR_CS0_PAGED (0x1 << 10) #define NDSR_CS1_PAGED (0x1 << 9) #define NDSR_CS0_CMDD (0x1 << 8) @@ -104,13 +108,14 @@ enum { }; enum { - STATE_READY = 0, - STATE_CMD_HANDLE, - STATE_DMA_READING, - STATE_DMA_WRITING, - STATE_DMA_DONE, - STATE_PIO_READING, - STATE_PIO_WRITING, + STATE_CMD_WAIT_DONE = 1, + STATE_DATA_PROCESSING = (1 << 1), + STATE_DATA_DONE = (1 << 2), + STATE_PAGE_DONE = (1 << 3), + STATE_CMD_DONE = (1 << 4), + STATE_READY = (1 << 5), + STATE_CMD_PREPARED = (1 << 6), + STATE_IS_WRITE = (1 << 7), }; struct pxa3xx_nand_timing { @@ -305,25 +310,6 @@ static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info, nand_writel(info, NDTR1CS0, ndtr1); } -#define WAIT_EVENT_TIMEOUT 10 - -static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event) -{ - int timeout = WAIT_EVENT_TIMEOUT; - uint32_t ndsr; - - while (timeout--) { - ndsr = nand_readl(info, NDSR) & NDSR_MASK; - if (ndsr & event) { - nand_writel(info, NDSR, ndsr); - return 0; - } - udelay(10); - } - - return -ETIMEDOUT; -} - static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) { int oob_enable = info->reg_ndcr & NDCR_SPARE_EN; @@ -343,7 +329,47 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info) } } -static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, +/** + * NOTE: it is a must to set ND_RUN firstly, then write + * command buffer, otherwise, it does not work. + * We enable all the interrupt at the same time, and + * let pxa3xx_nand_irq to handle all logic. + */ +static void pxa3xx_nand_start(struct pxa3xx_nand_info *info) +{ + uint32_t ndcr; + + ndcr = info->reg_ndcr; + ndcr |= NDCR_ECC_EN; + ndcr |= info->use_dma ? NDCR_DMA_EN : NDCR_STOP_ON_UNCOR; + ndcr |= NDCR_ND_RUN; + + /* clear status bits and run */ + nand_writel(info, NDCR, 0); + nand_writel(info, NDSR, NDSR_MASK); + nand_writel(info, NDCR, ndcr); +} + +static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info) +{ + uint32_t ndcr; + int timeout = NAND_STOP_DELAY; + + /* wait RUN bit in NDCR become 0 */ + do { + /* clear status bits */ + nand_writel(info, NDSR, NDSR_MASK); + ndcr = nand_readl(info, NDCR); + udelay(1); + } while ((ndcr & NDCR_ND_RUN) && (timeout -- > 0)); + + if (timeout <= 0) { + ndcr &= ~(NDCR_ND_RUN); + nand_writel(info, NDCR, ndcr); + } +} + +static void prepare_read_prog_cmd(struct pxa3xx_nand_info *info, uint16_t cmd, int column, int page_addr) { pxa3xx_set_datasize(info); @@ -369,21 +395,18 @@ static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info, if (cmd == cmdset.program) info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS; - - return 0; } -static int prepare_erase_cmd(struct pxa3xx_nand_info *info, +static void prepare_erase_cmd(struct pxa3xx_nand_info *info, uint16_t cmd, int page_addr) { info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3); info->ndcb1 = page_addr; info->ndcb2 = 0; - return 0; } -static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) +static void prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) { info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0); info->ndcb1 = 0; @@ -398,10 +421,7 @@ static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd) } else if (cmd == cmdset.reset || cmd == cmdset.lock || cmd == cmdset.unlock) { info->ndcb0 |= NDCB0_CMD_TYPE(5); - } else - return -EINVAL; - - return 0; + } } static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) @@ -420,71 +440,23 @@ static void disable_int(struct pxa3xx_nand_info *info, uint32_t int_mask) nand_writel(info, NDCR, ndcr | int_mask); } -/* NOTE: it is a must to set ND_RUN firstly, then write command buffer - * otherwise, it does not work - */ -static int write_cmd(struct pxa3xx_nand_info *info) -{ - uint32_t ndcr; - - /* clear status bits and run */ - nand_writel(info, NDSR, NDSR_MASK); - - ndcr = info->reg_ndcr; - - ndcr |= info->use_ecc ? NDCR_ECC_EN : 0; - ndcr |= info->use_dma ? NDCR_DMA_EN : 0; - ndcr |= NDCR_ND_RUN; - - nand_writel(info, NDCR, ndcr); - - if (wait_for_event(info, NDSR_WRCMDREQ)) { - printk(KERN_ERR "timed out writing command\n"); - return -ETIMEDOUT; - } - - nand_writel(info, NDCB0, info->ndcb0); - nand_writel(info, NDCB0, info->ndcb1); - nand_writel(info, NDCB0, info->ndcb2); - return 0; -} - -static int handle_data_pio(struct pxa3xx_nand_info *info) +static void handle_data_pio(struct pxa3xx_nand_info *info) { - int ret, timeout = CHIP_DELAY_TIMEOUT; - - switch (info->state) { - case STATE_PIO_WRITING: + if (info->state & STATE_IS_WRITE) { __raw_writesl(info->mmio_base + NDDB, info->data_buff, DIV_ROUND_UP(info->data_size, 4)); if (info->oob_size > 0) __raw_writesl(info->mmio_base + NDDB, info->oob_buff, DIV_ROUND_UP(info->oob_size, 4)); - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - - ret = wait_for_completion_timeout(&info->cmd_complete, timeout); - if (!ret) { - printk(KERN_ERR "program command time out\n"); - return -1; - } - break; - case STATE_PIO_READING: + } + else { __raw_readsl(info->mmio_base + NDDB, info->data_buff, DIV_ROUND_UP(info->data_size, 4)); if (info->oob_size > 0) __raw_readsl(info->mmio_base + NDDB, info->oob_buff, DIV_ROUND_UP(info->oob_size, 4)); - - break; - default: - printk(KERN_ERR "%s: invalid state %d\n", __func__, - info->state); - return -EINVAL; } - - info->state = STATE_READY; - return 0; } static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out) @@ -520,93 +492,59 @@ static void pxa3xx_nand_data_dma_irq(int channel, void *data) if (dcsr & DCSR_BUSERR) { info->retcode = ERR_DMABUSERR; - complete(&info->cmd_complete); } - if (info->state == STATE_DMA_WRITING) { - info->state = STATE_DMA_DONE; - enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - } else { - info->state = STATE_READY; - complete(&info->cmd_complete); - } + enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); } static irqreturn_t pxa3xx_nand_irq(int irq, void *devid) { struct pxa3xx_nand_info *info = devid; - unsigned int status; + unsigned int status, is_completed = 0; status = nand_readl(info, NDSR); - if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) { - if (status & NDSR_DBERR) - info->retcode = ERR_DBERR; - else if (status & NDSR_SBERR) - info->retcode = ERR_SBERR; - - disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); + if (status & NDSR_DBERR) + info->retcode = ERR_DBERR; + if (status & NDSR_SBERR) + info->retcode = ERR_SBERR; + if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) { + info->state |= STATE_DATA_PROCESSING; + /* whether use dma to transfer data */ if (info->use_dma) { - info->state = STATE_DMA_READING; + disable_int(info, NDSR_WRDREQ); start_data_dma(info, 0); - } else { - info->state = STATE_PIO_READING; - complete(&info->cmd_complete); - } - } else if (status & NDSR_WRDREQ) { - disable_int(info, NDSR_WRDREQ); - if (info->use_dma) { - info->state = STATE_DMA_WRITING; - start_data_dma(info, 1); - } else { - info->state = STATE_PIO_WRITING; - complete(&info->cmd_complete); - } - } else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) { - if (status & NDSR_CS0_BBD) - info->retcode = ERR_BBERR; + goto NORMAL_IRQ_EXIT; + } else + handle_data_pio(info); - disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - info->state = STATE_READY; - complete(&info->cmd_complete); + info->state |= STATE_DATA_DONE; } - nand_writel(info, NDSR, status); - return IRQ_HANDLED; -} - -static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event) -{ - uint32_t ndcr; - int ret, timeout = CHIP_DELAY_TIMEOUT; - - if (write_cmd(info)) { - info->retcode = ERR_SENDCMD; - goto fail_stop; + if (status & NDSR_CS0_CMDD) { + info->state |= STATE_CMD_DONE; + is_completed = 1; } - - info->state = STATE_CMD_HANDLE; - - enable_int(info, event); - - ret = wait_for_completion_timeout(&info->cmd_complete, timeout); - if (!ret) { - printk(KERN_ERR "command execution timed out\n"); - info->retcode = ERR_SENDCMD; - goto fail_stop; + if (status & NDSR_FLASH_RDY) + info->state |= STATE_READY; + if (status & NDSR_CS0_PAGED) + info->state |= STATE_PAGE_DONE; + + if (status & NDSR_WRCMDREQ) { + nand_writel(info, NDSR, NDSR_WRCMDREQ); + status &= ~NDSR_WRCMDREQ; + info->state |= STATE_CMD_WAIT_DONE; + nand_writel(info, NDCB0, info->ndcb0); + nand_writel(info, NDCB0, info->ndcb1); + nand_writel(info, NDCB0, info->ndcb2); } - if (info->use_dma == 0 && info->data_size > 0) - if (handle_data_pio(info)) - goto fail_stop; - - return 0; - -fail_stop: - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - udelay(10); - return -ETIMEDOUT; + /* clear NDSR to let the controller exit the IRQ */ + nand_writel(info, NDSR, status); + if (is_completed) + complete(&info->cmd_complete); +NORMAL_IRQ_EXIT: + return IRQ_HANDLED; } static int pxa3xx_nand_dev_ready(struct mtd_info *mtd) @@ -627,14 +565,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, int column, int page_addr) { struct pxa3xx_nand_info *info = mtd->priv; - int ret; + int ret, exec_cmd = 0; info->use_dma = (use_dma) ? 1 : 0; info->use_ecc = 0; info->data_size = 0; - info->state = STATE_READY; - - init_completion(&info->cmd_complete); + info->state = 0; switch (command) { case NAND_CMD_READOOB: @@ -643,14 +579,13 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_start = mtd->writesize + column; memset(info->data_buff, 0xFF, info->buf_count); - if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); + prepare_read_prog_cmd(info, cmdset.read1, column, page_addr); /* We only are OOB, so if the data has error, does not matter */ if (info->retcode == ERR_DBERR) info->retcode = ERR_NONE; + + exec_cmd = 1; break; case NAND_CMD_READ0: @@ -660,11 +595,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_count = mtd->writesize + mtd->oobsize; memset(info->data_buff, 0xFF, info->buf_count); - if (prepare_read_prog_cmd(info, cmdset.read1, column, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR); - + prepare_read_prog_cmd(info, cmdset.read1, column, page_addr); if (info->retcode == ERR_DBERR) { /* for blank page (all 0xff), HW will calculate its ECC as * 0, which is different from the ECC information within @@ -673,6 +604,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, if (is_buf_blank(info->data_buff, mtd->writesize)) info->retcode = ERR_NONE; } + + exec_cmd = 1; break; case NAND_CMD_SEQIN: info->buf_start = column; @@ -686,18 +619,14 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, case NAND_CMD_PAGEPROG: info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1; - if (prepare_read_prog_cmd(info, cmdset.program, - info->seqin_column, info->seqin_page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_WRDREQ); + prepare_read_prog_cmd(info, cmdset.program, + info->seqin_column, info->seqin_page_addr); + info->state |= STATE_IS_WRITE; + exec_cmd = 1; break; case NAND_CMD_ERASE1: - if (prepare_erase_cmd(info, cmdset.erase, page_addr)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD); - break; + prepare_erase_cmd(info, cmdset.erase, page_addr); + exec_cmd = 1; case NAND_CMD_ERASE2: break; case NAND_CMD_READID: @@ -707,39 +636,37 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command, info->buf_count = (command == NAND_CMD_READID) ? info->read_id_bytes : 1; - if (prepare_other_cmd(info, (command == NAND_CMD_READID) ? - cmdset.read_id : cmdset.read_status)) - break; - - pxa3xx_nand_do_cmd(info, NDSR_RDDREQ); + prepare_other_cmd(info, (command == NAND_CMD_READID) ? + cmdset.read_id : cmdset.read_status); + exec_cmd = 1; break; case NAND_CMD_RESET: - if (prepare_other_cmd(info, cmdset.reset)) - break; - - ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD); - if (ret == 0) { - int timeout = 2; - uint32_t ndcr; - - while (timeout--) { - if (nand_readl(info, NDSR) & NDSR_RDY) - break; - msleep(10); - } - - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - } + prepare_other_cmd(info, cmdset.reset); + exec_cmd = 1; break; default: printk(KERN_ERR "non-supported command.\n"); break; } - if (info->retcode == ERR_DBERR) { - printk(KERN_ERR "double bit error @ page %08x\n", page_addr); - info->retcode = ERR_NONE; + if (exec_cmd) { + init_completion(&info->cmd_complete); + info->state |= STATE_CMD_PREPARED; + pxa3xx_nand_start(info); + + ret = wait_for_completion_timeout(&info->cmd_complete, + CHIP_DELAY_TIMEOUT); + if (!ret) { + printk(KERN_ERR "Wait time out!!!\n"); + } + /* Stop State Machine for next command cycle */ + pxa3xx_nand_stop(info); + disable_int(info, NDCR_INT_MASK); + info->state &= ~STATE_CMD_PREPARED; + if (info->retcode == ERR_DBERR) { + printk(KERN_ERR "double bit error @ page %08x\n", page_addr); + info->retcode = ERR_NONE; + } } } @@ -848,41 +775,12 @@ static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd, return 0; } -static int __readid(struct pxa3xx_nand_info *info, uint32_t *id) -{ - uint32_t ndcr; - uint8_t id_buff[8]; - - if (prepare_other_cmd(info, cmdset.read_id)) { - printk(KERN_ERR "failed to prepare command\n"); - return -EINVAL; - } - - /* Send command */ - if (write_cmd(info)) - goto fail_timeout; - - /* Wait for CMDDM(command done successfully) */ - if (wait_for_event(info, NDSR_RDDREQ)) - goto fail_timeout; - - __raw_readsl(info->mmio_base + NDDB, id_buff, 2); - *id = id_buff[0] | (id_buff[1] << 8); - return 0; - -fail_timeout: - ndcr = nand_readl(info, NDCR); - nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN); - udelay(10); - return -ETIMEDOUT; -} - static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info, const struct pxa3xx_nand_flash *f) { struct platform_device *pdev = info->pdev; struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data; - uint32_t ndcr = 0x00000FFF; /* disable all interrupts */ + uint32_t ndcr = 0; /* calculate flash information */ info->page_size = f->page_size; @@ -949,8 +847,9 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info) info->read_id_bytes = (default_flash.page_size == 2048) ? 4 : 2; info->reg_ndcr = ndcr; - if (__readid(info, &id)) - return -ENODEV; + + pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); /* Lookup the flash id */ id = (id >> 8) & 0xff; /* device id is byte 2 */ @@ -997,8 +896,8 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, f = &builtin_flash_types[0]; pxa3xx_nand_config_flash(info, f); - if (__readid(info, &id)) - goto fail_detect; + pxa3xx_nand_cmdfunc(info->mtd, NAND_CMD_READID, 0, 0); + id = *((uint16_t *)(info->data_buff)); for (i=0; inum_flash - 1; i++) { if (i < pdata->num_flash) @@ -1015,7 +914,6 @@ static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info, dev_warn(&info->pdev->dev, "failed to detect configured nand flash; found %04x instead of\n", id); -fail_detect: return -ENODEV; } @@ -1303,7 +1201,7 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state) struct pxa3xx_nand_info *info = platform_get_drvdata(pdev); struct mtd_info *mtd = info->mtd; - if (info->state != STATE_READY) { + if (info->state & STATE_CMD_PREPARED) { dev_err(&pdev->dev, "driver busy, state = %d\n", info->state); return -EAGAIN; } -- 1.7.0.4 From leiwen at marvell.com Mon May 31 02:57:49 2010 From: leiwen at marvell.com (Lei Wen) Date: Mon, 31 May 2010 14:57:49 +0800 Subject: [PATCH 08/25] mmp: add nand support to pxa168 Message-ID: Signed-off-by: Lei Wen --- arch/arm/configs/pxa168_defconfig | 9 ++++++++- drivers/mtd/nand/Kconfig | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig index 113511f..a01ea99 100644 --- a/arch/arm/configs/pxa168_defconfig +++ b/arch/arm/configs/pxa168_defconfig @@ -438,7 +438,14 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set +CONFIG_MTD=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_PXA3xx=y # CONFIG_PARPORT is not set # CONFIG_BLK_DEV is not set # CONFIG_MISC_DEVICES is not set diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 9a35d92..0d29b5d 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -394,7 +394,7 @@ endchoice config MTD_NAND_PXA3xx tristate "Support for NAND flash devices on PXA3xx" - depends on MTD_NAND && (PXA3xx || ARCH_MMP) + depends on MTD_NAND && PLAT_PXA help This enables the driver for the NAND flash device found on PXA3xx processors -- 1.7.0.4 From leiwen at marvell.com Mon May 31 02:57:49 2010 From: leiwen at marvell.com (Lei Wen) Date: Mon, 31 May 2010 14:57:49 +0800 Subject: [PATCH 11/29] mmp: add nand support to pxa168 Message-ID: Signed-off-by: Lei Wen --- arch/arm/configs/pxa168_defconfig | 9 ++++++++- 1 files changed, 8 insertions(+), 1 deletions(-) diff --git a/arch/arm/configs/pxa168_defconfig b/arch/arm/configs/pxa168_defconfig index 113511f..a01ea99 100644 --- a/arch/arm/configs/pxa168_defconfig +++ b/arch/arm/configs/pxa168_defconfig @@ -438,7 +438,14 @@ CONFIG_EXTRA_FIRMWARE="" # CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set # CONFIG_CONNECTOR is not set -# CONFIG_MTD is not set +CONFIG_MTD=y +CONFIG_MTD_PARTITIONS=y +CONFIG_MTD_CMDLINE_PARTS=y +CONFIG_MTD_CHAR=y +CONFIG_MTD_BLKDEVS=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_NAND=y +CONFIG_MTD_NAND_PXA3xx=y # CONFIG_PARPORT is not set # CONFIG_BLK_DEV is not set # CONFIG_MISC_DEVICES is not set -- 1.7.0.4 From dedekind1 at gmail.com Wed May 26 12:32:29 2010 From: dedekind1 at gmail.com (Artem Bityutskiy) Date: Wed, 26 May 2010 16:32:29 -0000 Subject: Can not mount UBIFS In-Reply-To: References: <531B6536C9F737458807DF75064873C8BE5EB0382D@mta-digimail.MTA.INT> <1270544458.6754.15.camel@localhost> <1272888512.27729.46.camel@localhost> <1273556690.2209.146.camel@localhost> Message-ID: <1273635024.8881.1.camel@localhost.localdomain> On Wed, 2010-05-12 at 09:18 +0800, ??? wrote: > Dear Sir, > > I am very confused. > If the driver has some problems, why images written by ubiformat can work well? > Images written by bootloader or ubiformat should have the same > problem, if the driver is wrong. I do not know. May be this is not a driver problem. May be you write twice to the same page? Just dig your driver, insert printks and find out where exactly it decides to return error. -- Best Regards, Artem Bityutskiy (????? ????????) From manonuevo at micron.com Mon May 24 17:54:00 2010 From: manonuevo at micron.com (Mona Anonuevo (manonuevo)) Date: Mon, 24 May 2010 21:54:00 -0000 Subject: [PATCH] MTD: Micron SPINAND Driver support Message-ID: This patch adds support for Micron SPINAND via MTD. Signed-off-by: Mona Anonuevo (manonuevo at micron.com) Signed-off-by: Tuan Nguyen (tqnguyen at micron.com) ---- drivers/mtd/Kconfig | 2 drivers/mtd/Makefile | 2 drivers/mtd/spinand/Kconfig | 25 + drivers/mtd/spinand/Makefile | 10 drivers/mtd/spinand/spinand_lld.c | 760 ++++++++++++++++++++++++++++++++++++++ drivers/mtd/spinand/spinand_mtd.c | 728 ++++++++++++++++++++++++++++++++++++ include/linux/mtd/spinand.h | 160 ++++++++ 7 files changed, 1687 insertions(+) PATCH FOLLOWS Kernel Version: Linux 2.6.33.20 diff -urN linux-2.6.33.20-orig/drivers/mtd/Kconfig linux-2.6.33.20/drivers/mtd/Kconfig --- linux-2.6.33.20-orig/drivers/mtd/Kconfig 2010-04-01 16:02:33.000000000 -0700 +++ linux-2.6.33.20/drivers/mtd/Kconfig 2010-05-19 04:28:06.000000000 -0700 @@ -325,6 +325,8 @@ source "drivers/mtd/onenand/Kconfig" +source "drivers/mtd/spinand/Kconfig" + source "drivers/mtd/lpddr/Kconfig" source "drivers/mtd/ubi/Kconfig" diff -urN linux-2.6.33.20-orig/drivers/mtd/Makefile linux-2.6.33.20/drivers/mtd/Makefile --- linux-2.6.33.20-orig/drivers/mtd/Makefile 2010-04-01 16:02:33.000000000 -0700 +++ linux-2.6.33.20/drivers/mtd/Makefile 2010-05-19 04:28:06.000000000 -0700 @@ -31,4 +31,6 @@ obj-y += chips/ lpddr/ maps/ devices/ nand/ onenand/ tests/ +obj-y += spinand/ + obj-$(CONFIG_MTD_UBI) += ubi/ diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/Kconfig linux-2.6.33.20/drivers/mtd/spinand/Kconfig --- linux-2.6.33.20-orig/drivers/mtd/spinand/Kconfig 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.33.20/drivers/mtd/spinand/Kconfig 2010-05-19 04:28:06.000000000 -0700 @@ -0,0 +1,25 @@ +# +# linux/drivers/mtd/spinand/Kconfig +# + +menuconfig MTD_SPINAND + tristate "SPINAND Device Support" + depends on MTD + help + This enables support for accessing Micron SPI NAND flash + devices. + +if MTD_SPINAND + +config MTD_SPINAND_ONDIEECC + bool "Use SPINAND internal ECC" + help + Internel ECC + +config MTD_SPINAND_SWECC + bool "Use software ECC" + depends on MTD_NAND + help + software ECC + +endif diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/Makefile linux-2.6.33.20/drivers/mtd/spinand/Makefile --- linux-2.6.33.20-orig/drivers/mtd/spinand/Makefile 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.33.20/drivers/mtd/spinand/Makefile 2010-05-19 04:28:07.000000000 -0700 @@ -0,0 +1,10 @@ +# +# Makefile for the SPI NAND MTD +# + +# Core functionality. +obj-$(CONFIG_MTD_SPINAND) += spinand.o + +spinand-objs := spinand_mtd.o spinand_lld.o + + diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_lld.c linux-2.6.33.20/drivers/mtd/spinand/spinand_lld.c --- linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_lld.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.33.20/drivers/mtd/spinand/spinand_lld.c 2010-05-19 03:56:51.000000000 -0700 @@ -0,0 +1,760 @@ +/* +spinand_lld.c + +Copyright (c) 2009-2010 Micron Technology, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +#define mu_spi_nand_driver_version "Beagle-MTD_01.00_Linux2.6.33_20100507" +#define SPI_NAND_MICRON_DRIVER_KEY 0x1233567 + +/********************************************************************** ******/ + +/** + OOB area specification layout: Total 32 available free bytes. +*/ +static struct nand_ecclayout spinand_oob_64 = { + .eccbytes = 24, + .eccpos = { + 1, 2, 3, 4, 5, 6, + 17, 18, 19, 20, 21, 22, + 33, 34, 35, 36, 37, 38, + 49, 50, 51, 52, 53, 54, }, + .oobavail = 32, + .oobfree = { + {.offset = 8, + .length = 8}, + {.offset = 24, + .length = 8}, + {.offset = 40, + .length = 8}, + {.offset = 56, + .length = 8}, } +}; +/** + * spinand_cmd - to process a command to send to the SPI Nand + * + * Description: + * Set up the command buffer to send to the SPI controller. + * The command buffer has to initized to 0 + */ +int spinand_cmd(struct spi_device *spi, struct spinand_cmd *cmd) +{ + int ret; + struct spi_message message; + struct spi_transfer x[4]; + u8 dummy = 0xff; + + + spi_message_init(&message); + memset(x, 0, sizeof x); + + x[0].len = 1; + x[0].tx_buf = &cmd->cmd; + spi_message_add_tail(&x[0], &message); + + if (cmd->n_addr) + { + x[1].len = cmd->n_addr; + x[1].tx_buf = cmd->addr; + spi_message_add_tail(&x[1], &message); + } + + if (cmd->n_dummy) + { + x[2].len = cmd->n_dummy; + x[2].tx_buf = &dummy; + spi_message_add_tail(&x[2], &message); + } + + if (cmd->n_tx) + { + x[3].len = cmd->n_tx; + x[3].tx_buf = cmd->tx_buf; + spi_message_add_tail(&x[3], &message); + } + + if (cmd->n_rx) + { + x[3].len = cmd->n_rx; + x[3].rx_buf = cmd->rx_buf; + spi_message_add_tail(&x[3], &message); + } + + ret = spi_sync(spi, &message); + + return ret; +} + +/** + * spinand_reset- send reset command "0xff" to the Nand device + * + * Description: + * Reset the SPI Nand with the reset command 0xff + */ +static int spinand_reset(struct spi_device *spi_nand) +{ + struct spinand_cmd cmd = {0}; + + cmd.cmd = CMD_RESET; + + return spinand_cmd(spi_nand, &cmd); +} +/** + * spinand_read_id- Read SPI Nand ID + * + * Description: + * Read ID: read two ID bytes from the SPI Nand device + */ +static int spinand_read_id(struct spi_device *spi_nand, u8 *id) +{ + struct spinand_cmd cmd = {0}; + ssize_t retval; + + + cmd.cmd = CMD_READ_ID; + cmd.n_dummy = 1; + cmd.n_rx = 2; + cmd.rx_buf = id; + + retval = spinand_cmd(spi_nand, &cmd); + + if (retval != 0) { + dev_err(&spi_nand->dev, "error %d reading id\n", + (int) retval); + return retval; + } + + return 0; +} + +/** + * spinand_lock_block- send write register 0x1f command to the Nand device + * + * Description: + * After power up, all the Nand blocks are locked. This function allows + * one to unlock the blocks, and so it can be wriiten or erased. + */ +static int spinand_lock_block(struct spi_device *spi_nand, struct spinand_info *info, u8 lock) +{ + struct spinand_cmd cmd = {0}; + ssize_t retval; + + cmd.cmd = CMD_WRITE_REG; + cmd.n_addr = 1; + cmd.addr[0] = REG_BLOCK_LOCK; + cmd.n_tx = 1; + cmd.tx_buf = &lock; + + retval = spinand_cmd(spi_nand, &cmd); + + if (retval != 0) { + dev_err(&spi_nand->dev, "error %d lock block\n", + (int) retval); + return retval; + } + + return 0; +} + +/** + * spinand_read_status- send command 0xf to the SPI Nand status register + * + * Description: + * After read, write, or erase, the Nand device is expected to set the busy status. + * This function is to allow reading the status of the command: read, write, and erase. + * Once the status turns to be ready, the other status bits also are valid status bits. + */ +static int spinand_read_status(struct spi_device *spi_nand, struct spinand_info *info, u8 *status) +{ + struct spinand_cmd cmd = {0}; + ssize_t retval; + + cmd.cmd = CMD_READ_REG; + cmd.n_addr = 1; + cmd.addr[0] = REG_STATUS; + cmd.n_rx = 1; + cmd.rx_buf = status; + + retval = spinand_cmd(spi_nand, &cmd); + + if (retval != 0) { + dev_err(&spi_nand->dev, "error %d reading status register\n", + (int) retval); + return retval; + } + + return 0; +} + +/** + * spinand_get_otp- send command 0xf to read the SPI Nand OTP register + * + * Description: + * There is one bit( bit 0x10 ) to set or to clear the internal ECC. + * Enable chip internal ECC, set the bit to 1 + * Disable chip internal ECC, clear the bit to 0 + */ +static int spinand_get_otp(struct spi_device *spi_nand, struct spinand_info *info, u8* otp) +{ + struct spinand_cmd cmd = {0}; + ssize_t retval; + + cmd.cmd = CMD_READ_REG; + cmd.n_addr = 1; + cmd.addr[0] = REG_OTP; + cmd.n_rx = 1; + cmd.rx_buf = otp; + + retval = spinand_cmd(spi_nand, &cmd); + + if (retval != 0) { + dev_err(&spi_nand->dev, "error %d get otp\n", + (int) retval); + return retval; + } + + return 0; +} + + +/** + * spinand_set_otp- send command 0x1f to write the SPI Nand OTP register + * + * Description: + * There is one bit( bit 0x10 ) to set or to clear the internal ECC. + * Enable chip internal ECC, set the bit to 1 + * Disable chip internal ECC, clear the bit to 0 + */ +static int spinand_set_otp(struct spi_device *spi_nand, struct spinand_info *info, u8* otp) +{ + struct spinand_cmd cmd = {0}; + ssize_t retval; + + cmd.cmd = CMD_WRITE_REG; + cmd.n_addr = 1; + cmd.addr[0] = REG_OTP; + cmd.n_tx = 1; + cmd.tx_buf = otp; + + retval = spinand_cmd(spi_nand, &cmd); + + if (retval != 0) { + dev_err(&spi_nand->dev, "error %d set otp\n", + (int) retval); + return retval; + } + + return 0; +} + +/** + * sspinand_enable_ecc- send command 0x1f to write the SPI Nand OTP register + * + * Description: + * There is one bit( bit 0x10 ) to set or to clear the internal ECC. + * Enable chip internal ECC, set the bit to 1 + * Disable chip internal ECC, clear the bit to 0 + */ +static int spinand_enable_ecc(struct spi_device *spi_nand, struct spinand_info *info) +{ + ssize_t retval; + u8 otp = 0; + + retval = spinand_get_otp(spi_nand, info, &otp); + + if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) + { + return 0; + } + else + { + otp |= OTP_ECC_MASK; + retval = spinand_set_otp(spi_nand, info, &otp); + retval = spinand_get_otp(spi_nand, info, &otp); + return retval; + } +} + +static int spinand_disable_ecc(struct spi_device *spi_nand, struct spinand_info *info) +{ + ssize_t retval; + u8 otp = 0; + + retval = spinand_get_otp(spi_nand, info, &otp); + + + if ((otp & OTP_ECC_MASK) == OTP_ECC_MASK) + { + otp &= ~OTP_ECC_MASK; + retval = spinand_set_otp(spi_nand, info, &otp); + retval = spinand_get_otp(spi_nand, info, &otp); + return retval; + } + else + { + return 0; + } +} + +/** + * sspinand_write_enable- send command 0x06 to enable write or erase the Nand cells + * + * Description: + * Before write and erase the Nand cells, the write enable has to be set. + * After the write or erase, the write enable bit is automatically cleared( status register bit 2 ) + * Set the bit 2 of the status register has the same effect + */ +static int spinand_write_enable(struct spi_device *spi_nand, struct spinand_info *info) +{ + struct spinand_cmd cmd = {0}; + + cmd.cmd = CMD_WR_ENABLE; + + return spinand_cmd(spi_nand, &cmd); +} + +static int spinand_read_page_to_cache(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id) +{ + struct spinand_cmd cmd = {0}; + u16 row; + + row = page_id; + + cmd.cmd = CMD_READ; + cmd.n_addr = 3; + cmd.addr[1] = (u8)((row&0xff00)>>8); + cmd.addr[2] = (u8)(row&0x00ff); + + return spinand_cmd(spi_nand, &cmd); +} + +/** + * spinand_read_from_cache- send command 0x03 to read out the data from the cache register( 2112 bytes max ) + * + * Description: + * The read can specify 1 to 2112 bytes of data read at the coresponded locations. + * No tRd delay. + */ +static int spinand_read_from_cache(struct spi_device *spi_nand, struct spinand_info *info, u16 byte_id, u16 len, u8* rbuf) +{ + struct spinand_cmd cmd = {0}; + u16 column; + + column = byte_id; + + cmd.cmd = CMD_READ_RDM; + cmd.n_addr = 2; + cmd.addr[0] = (u8)((column&0xff00)>>8); + cmd.addr[1] = (u8)(column&0x00ff); + cmd.n_dummy = 1; + cmd.n_rx = len; + cmd.rx_buf = rbuf; + + return spinand_cmd(spi_nand, &cmd); +} + +/** + * spinand_read_page-to read a page with: + * @page_id: the physical page number + * @offset: the location from 0 to 2111 + * @len: number of bytes to read + * @rbuf: read buffer to hold @len bytes + * + * Description: + * The read icludes two commands to the Nand: 0x13 and 0x03 commands + * Poll to read status to wait for tRD time. + */ +static int spinand_read_page(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* rbuf) +{ + ssize_t retval; + u8 status = 0; + + retval = spinand_read_page_to_cache(spi_nand, info, page_id); + + while (1) + { + retval = spinand_read_status(spi_nand, info, &status); + if (retval<0) { + dev_err(&spi_nand->dev, "error %d reading status register\n", + (int) retval); + return retval; + } + + if ((status & STATUS_OIP_MASK) == STATUS_READY) + { + if ((status & STATUS_ECC_MASK) == STATUS_ECC_ERROR) + { + dev_err(&spi_nand->dev, "ecc error, page=%d\n", page_id); + if (spi_nand == SPI_NAND_MICRON_DRIVER_KEY) + printk(KERN_INFO "Error: reformat or erase your device. \n"); + else + return -1; + } + break; + } + } + + retval = spinand_read_from_cache(spi_nand, info, offset, len, rbuf); + return 0; + +} + +/** + * spinand_program_data_to_cache--to write a page to cache with: + * @byte_id: the location to write to the cache + * @len: number of bytes to write + * @rbuf: read buffer to hold @len bytes + * + * Description: + * The write command used here is 0x84--indicating that the cache is not cleared first. + * Since it is writing the data to cache, there is no tPROG time. + */ +static int spinand_program_data_to_cache(struct spi_device *spi_nand, struct spinand_info *info, u16 byte_id, u16 len, u8* wbuf) +{ + struct spinand_cmd cmd = {0}; + u16 column; + + column = byte_id; + + cmd.cmd = CMD_PROG_PAGE_CLRCACHE; + cmd.n_addr = 2; + cmd.addr[0] = (u8)((column&0xff00)>>8); + cmd.addr[1] = (u8)(column&0x00ff); + cmd.n_tx = len; + cmd.tx_buf = wbuf; + + return spinand_cmd(spi_nand, &cmd); +} + +/** + * spinand_program_execute--to write a page from cache to the Nand array with: + * @page_id: the physical page location to write the page. + * + * Description: + * The write command used here is 0x10--indicating the cache is writing to the Nand array. + * Need to wait for tPROG time to finish the transaction. + */ +static int spinand_program_execute(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id) +{ + struct spinand_cmd cmd = {0}; + u16 row; + + row = page_id; + + cmd.cmd = CMD_PROG_PAGE_EXC; + cmd.n_addr = 3; + cmd.addr[1] = (u8)((row&0xff00)>>8); + cmd.addr[2] = (u8)(row&0x00ff); + + return spinand_cmd(spi_nand, &cmd); +} + +/** + * spinand_program_page--to write a page with: + * @page_id: the physical page location to write the page. + * @offset: the location from the cache starting from 0 to 2111 + * @len: the number of bytes to write + * @wbuf: the buffer to hold the number of bytes + * + * Description: + * The commands used here are 0x06, 0x84, and 0x10--indicating that the write enable is first + * sent, the write cache command, and the write execute command + * Poll to wait for the tPROG time to finish the transaction. + */ +static int spinand_program_page(struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* wbuf) +{ + ssize_t retval; + u8 status = 0; + + retval = spinand_write_enable(spi_nand, info); + + retval = spinand_program_data_to_cache(spi_nand, info, offset, len, wbuf); + + retval = spinand_program_execute(spi_nand, info, page_id); + + while (1) + { + retval = spinand_read_status(spi_nand, info, &status); + if (retval<0) { + dev_err(&spi_nand->dev, "error %d reading status register\n", + (int) retval); + return retval; + } + + if ((status & STATUS_OIP_MASK) == STATUS_READY) + { + + if ((status & STATUS_P_FAIL_MASK) == STATUS_P_FAIL) + { + dev_err(&spi_nand->dev, "program error, page=%d\n", page_id); + return -1; + } + else + break; + } + } + + return 0; +} + +/** + * spinand_erase_block_erase--to erase a page with: + * @block_id: the physical block location to erase. + * + * Description: + * The command used here is 0xd8--indicating an erase command to erase one block--64 pages + * Need to wait for tERS. + */ +static int spinand_erase_block_erase(struct spi_device *spi_nand, struct spinand_info *info, u16 block_id) +{ + struct spinand_cmd cmd = {0}; + u16 row; + + row = block_id << 6; + cmd.cmd = CMD_ERASE_BLK; + cmd.n_addr = 3; + cmd.addr[1] = (u8)((row&0xff00)>>8); + cmd.addr[2] = (u8)(row&0x00ff); + + return spinand_cmd(spi_nand, &cmd); +} + +/** + * spinand_erase_block--to erase a page with: + * @block_id: the physical block location to erase. + * + * Description: + * The commands used here are 0x06 and 0xd8--indicating an erase command to erase one block--64 pages + * It will first to enable the write enable bit ( 0x06 command ), and then send the 0xd8 erase command + * Poll to wait for the tERS time to complete the tranaction. + */ +static int spinand_erase_block(struct spi_device *spi_nand, struct spinand_info *info, u16 block_id) +{ + ssize_t retval; + u8 status= 0; + + retval = spinand_write_enable(spi_nand, info); + + retval = spinand_erase_block_erase(spi_nand, info, block_id); + + while (1) + { + retval = spinand_read_status(spi_nand, info, &status); + if (retval<0) { + dev_err(&spi_nand->dev, "error %d reading status register\n", + (int) retval); + return retval; + } + + if ((status & STATUS_OIP_MASK) == STATUS_READY) + { + if ((status & STATUS_E_FAIL_MASK) == STATUS_E_FAIL) + { + dev_err(&spi_nand->dev, "erase error, block=%d\n", block_id); + return -1; + } + else + break; + } + } + + return 0; +} + +/* +* spinand_get_info: get NAND info, from read id or const value + + * Description: + * To set up the device parameters. + */ +static int spinand_get_info(struct spi_device *spi_nand, struct spinand_info *info, u8* id) +{ + if (id[0]==0x2C && (id[1]==0x11 || id[1]==0x12 || id[1]==0x13)) + { + info->mid = id[0]; + info->did = id[1]; + info->name = "MT29F1G01ZAC"; + info->nand_size = (1024 * 64 * 2112); + info->usable_size = (1024 * 64 * 2048); + info->block_size = (2112*64); + info->block_main_size = (2048*64); + info->block_num_per_chip = 1024; + info->page_size = 2112; + info->page_main_size = 2048; + info->page_spare_size = 64; + info->page_num_per_block = 64; + + info->block_shift = 17; + info->block_mask = 0x1ffff; + + info->page_shift = 11; + info->page_mask = 0x7ff; + + info->ecclayout = &spinand_oob_64; + } + + return 0; +} + +/** + * spinand_probe - [spinand Interface] +* @spi_nand: registered device driver. + * + * Description: + * To set up the device driver parameters to make the device available. + */ +static int __devinit spinand_probe(struct spi_device *spi_nand) +{ + ssize_t retval; + struct mtd_info *mtd; + struct spinand_chip *chip; + struct spinand_info *info; + u8 id[2]= {0}; + + retval = spinand_reset(spi_nand); + retval = spinand_reset(spi_nand); + retval = spinand_read_id(spi_nand, (u8*)&id); + if (id[0]==0 && id[1]==0) + { + printk(KERN_INFO "SPINAND: read id error! 0x%02x, 0x%02x!\n", id[0], id[1]); + return 0; + } + + info = kzalloc(sizeof(struct spinand_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + retval = spinand_get_info(spi_nand, info, (u8*)&id); + printk(KERN_INFO "SPINAND: 0x%02x, 0x%02x, %s\n", id[0], id[1], info->name); + printk(KERN_INFO "%s\n", mu_spi_nand_driver_version); + retval = spinand_lock_block(spi_nand, info, BL_ALL_UNLOCKED); + +#ifdef CONFIG_MTD_SPINAND_ONDIEECC + retval = spinand_enable_ecc(spi_nand, info); +#else + retval = spinand_disable_ecc(spi_nand, info); +#endif + + chip = kzalloc(sizeof(struct spinand_chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->spi_nand = spi_nand; + chip->info = info; + chip->reset = spinand_reset; + chip->read_id = spinand_read_id; + chip->read_page = spinand_read_page; + chip->program_page = spinand_program_page; + chip->erase_block = spinand_erase_block; + + chip->buf = kzalloc(info->page_size, GFP_KERNEL); + if (!chip->buf) + return -ENOMEM; + + chip->oobbuf = kzalloc(info->ecclayout->oobavail, GFP_KERNEL); + if (!chip->oobbuf) + return -ENOMEM; + + mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL); + if (!mtd) + return -ENOMEM; + + dev_set_drvdata(&spi_nand->dev, mtd); + + mtd->priv = chip; + + retval = spinand_mtd(mtd); + + return retval; +} + +/** + * __devexit spinand_remove--Remove the device driver + * @spi: the spi device. + * + * Description: + * To remove the device driver parameters and free up allocated memories. + */ +static int __devexit spinand_remove(struct spi_device *spi) +{ + struct mtd_info *mtd; + struct spinand_chip *chip; + + DEBUG(MTD_DEBUG_LEVEL1, "%s: remove\n", dev_name(&spi->dev)); + + mtd = dev_get_drvdata(&spi->dev); + + spinand_mtd_release(mtd); + + chip = mtd->priv; + + kfree(chip->info); + kfree(chip->buf); + kfree(chip->oobbuf); + kfree(chip); + kfree(mtd); + + return 0; +} + +/** + * Device name structure description +*/ +static struct spi_driver spinand_driver = { + .driver = { + .name = "spi_nand", + .bus = &spi_bus_type, + .owner = THIS_MODULE, + }, + + .probe = spinand_probe, + .remove = __devexit_p(spinand_remove), +}; + +/** + * Device driver registration +*/ +static int __init spinand_init(void) +{ + return spi_register_driver(&spinand_driver); +} + +/** + * unregister Device driver. +*/ +static void __exit spinand_exit(void) +{ + spi_unregister_driver(&spinand_driver); +} + +module_init(spinand_init); +module_exit(spinand_exit); + + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Henry Pan "); +MODULE_DESCRIPTION("SPI NAND driver code"); diff -urN linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_mtd.c linux-2.6.33.20/drivers/mtd/spinand/spinand_mtd.c --- linux-2.6.33.20-orig/drivers/mtd/spinand/spinand_mtd.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.33.20/drivers/mtd/spinand/spinand_mtd.c 2010-05-19 04:28:07.000000000 -0700 @@ -0,0 +1,728 @@ +/* +spinand_mtd.c + +Copyright (c) 2009-2010 Micron Technology, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/** + * spinand_get_device - [GENERIC] Get chip for selected access + * @param mtd MTD device structure + * @param new_state the state which is requested + * + * Get the device and lock it for exclusive access + */ +#define mu_spi_nand_driver_version "Beagle-MTD_01.00_Linux2.6.33_20100507" +static int spinand_get_device(struct mtd_info *mtd, int new_state) +{ + struct spinand_chip *this = mtd->priv; + DECLARE_WAITQUEUE(wait, current); + + /* + * Grab the lock and see if the device is available + */ + while (1) { + spin_lock(&this->chip_lock); + if (this->state == FL_READY) { + this->state = new_state; + spin_unlock(&this->chip_lock); + break; + } + if (new_state == FL_PM_SUSPENDED) { + spin_unlock(&this->chip_lock); + return (this->state == FL_PM_SUSPENDED) ? 0 : -EAGAIN; + } + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&this->wq, &wait); + spin_unlock(&this->chip_lock); + schedule(); + remove_wait_queue(&this->wq, &wait); + } + return 0; +} + +/** + * spinand_release_device - [GENERIC] release chip + * @param mtd MTD device structure + * + * Deselect, release chip lock and wake up anyone waiting on the device + */ +static void spinand_release_device(struct mtd_info *mtd) +{ + struct spinand_chip *this = mtd->priv; + + /* Release the chip */ + spin_lock(&this->chip_lock); + this->state = FL_READY; + wake_up(&this->wq); + spin_unlock(&this->chip_lock); +} + +#ifdef CONFIG_MTD_SPINAND_SWECC +static void spinand_calculate_ecc(struct mtd_info *mtd) +{ + int i; + int eccsize = 512; + int eccbytes = 3; + int eccsteps = 4; + int ecctotal = 12; + struct spinand_chip *chip = mtd->priv; + struct spinand_info *info = chip->info; + unsigned char *p = chip->buf; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + __nand_calculate_ecc(p, eccsize, &chip->ecc_calc[i]); + + for (i = 0; i < ecctotal; i++) + chip->buf[info->page_main_size + info->ecclayout->eccpos[i]] = chip->ecc_calc[i]; +} + +static int spinand_correct_data(struct mtd_info *mtd) +{ + int i; + int eccsize = 512; + int eccbytes = 3; + int eccsteps = 4; + int ecctotal = 12; + struct spinand_chip *chip = mtd->priv; + struct spinand_info *info = chip->info; + unsigned char *p = chip->buf; + int errcode = 0; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + __nand_calculate_ecc(p, eccsize, &chip->ecc_calc[i]); + + for (i = 0; i < ecctotal; i++) + chip->ecc_code[i] = chip->buf[info->page_main_size + info->ecclayout->eccpos[i]]; + + for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) + { + int stat; + + stat = __nand_correct_data(p, &chip->ecc_code[i], &chip->ecc_calc[i], eccsize); + if (stat < 0) + { + errcode = -1; + } + else if (stat == 1) + { + errcode = 1; + } + } + + return errcode; +} +#endif + +static int spinand_read_ops(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) +{ + struct spinand_chip *chip = mtd->priv; + struct spi_device *spi_nand = chip->spi_nand; + struct spinand_info *info = chip->info; + int page_id, page_offset, page_num, oob_num; + + int count; + int main_ok, main_left, main_offset; + int oob_ok, oob_left; + + signed int retval; + signed int errcode=0; + + if (!chip->buf) + return -1; + + page_id = from >> info->page_shift; + + /* for main data */ + page_offset = from & info->page_mask; + page_num = (page_offset + ops->len + info->page_main_size -1 ) / info->page_main_size; + + /* for oob */ + oob_num = (ops->ooblen + info->ecclayout->oobavail -1) / info->ecclayout->oobavail; + + count = 0; + + main_left = ops->len; + main_ok = 0; + main_offset = page_offset; + + oob_left = ops->ooblen; + oob_ok = 0; + + while (1) + { + if (count < page_num || count < oob_num) + { + memset(chip->buf, 0, info->page_size); + retval = chip->read_page(spi_nand, info, page_id + count, 0, info->page_size, chip->buf); + if (retval != 0) + { + errcode = -1; + printk(KERN_INFO "spinand_read_ops: fail, page=%d!\n", page_id); + + return errcode; + } + } + else + { + break; + } + + if (count < page_num && ops->datbuf) + { + int size; + +#ifdef CONFIG_MTD_SPINAND_SWECC + retval = spinand_correct_data(mtd); + if (retval == -1) + printk(KERN_INFO "SWECC uncorrectable error! page=%x\n", page_id+count); + else if (retval == 1) + printk(KERN_INFO "SWECC 1 bit error, corrected! page=%x\n", page_id+count); + +#endif + + if ((main_offset + main_left) < info->page_main_size) + { + size = main_left; + } + else + { + size = info->page_main_size - main_offset; + } + + memcpy (ops->datbuf + main_ok, chip->buf, size); + + main_ok += size; + main_left -= size; + main_offset = 0; + + ops->retlen = main_ok; + } + + if (count < oob_num && ops->oobbuf && chip->oobbuf) + { + int size; + int offset, len, temp; + + /* repack spare to oob */ + memset(chip->oobbuf, 0, info->ecclayout->oobavail); + + temp = 0; + offset = info->ecclayout->oobfree[0].offset; + len = info->ecclayout->oobfree[0].length; + memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len); + + temp += len; + offset = info->ecclayout->oobfree[1].offset; + len = info->ecclayout->oobfree[1].length; + memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len); + + temp += len; + offset = info->ecclayout->oobfree[2].offset; + len = info->ecclayout->oobfree[2].length; + memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len); + + temp += len; + offset = info->ecclayout->oobfree[3].offset; + len = info->ecclayout->oobfree[3].length; + memcpy (chip->oobbuf + temp, chip->buf + info->page_main_size + offset, len); + + /* copy oobbuf to ops oobbuf */ + if (oob_left < info->ecclayout->oobavail) + { + size = oob_left; + } + else + { + size = info->ecclayout->oobavail; + } + + memcpy (ops->oobbuf + oob_ok, chip->oobbuf, size); + + oob_ok += size; + oob_left -= size; + + ops->oobretlen = oob_ok; + } + + count++; + } + return errcode; +} + +static int spinand_write_ops(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + struct spinand_chip *chip = mtd->priv; + struct spi_device *spi_nand = chip->spi_nand; + struct spinand_info *info = chip->info; + int page_id, page_offset, page_num, oob_num; + + int count; + + int main_ok, main_left, main_offset; + int oob_ok, oob_left; + + signed int retval; + signed int errcode=0; + + if (!chip->buf) + return -1; + + page_id = to >> info->page_shift; + + /* for main data */ + page_offset = to & info->page_mask; + page_num = (page_offset + ops->len + info->page_main_size -1 ) / info->page_main_size; + + /* for oob */ + oob_num = (ops->ooblen + info->ecclayout->oobavail -1) / info->ecclayout->oobavail; + + count = 0; + + main_left = ops->len; + main_ok = 0; + main_offset = page_offset; + + oob_left = ops->ooblen; + oob_ok = 0; + + while (1) + { + if (count < page_num || count < oob_num) + { + memset(chip->buf, 0xFF, info->page_size); + } + else + { + break; + } + + if (count < page_num && ops->datbuf) + { + int size; + + if ((main_offset + main_left) < info->page_main_size) + { + size = main_left; + } + else + { + size = info->page_main_size - main_offset; + } + + memcpy (chip->buf, ops->datbuf + main_ok, size); + + main_ok += size; + main_left -= size; + main_offset = 0; + +#ifdef CONFIG_MTD_SPINAND_SWECC + spinand_calculate_ecc(mtd); +#endif + } + + if (count < oob_num && ops->oobbuf && chip->oobbuf) + { + int size; + int offset, len, temp; + + memset(chip->oobbuf, 0xFF, info->ecclayout->oobavail); + + if (oob_left < info->ecclayout->oobavail) + { + size = oob_left; + } + else + { + size = info->ecclayout->oobavail; + } + + memcpy (chip->oobbuf, ops->oobbuf + oob_ok, size); + + oob_ok += size; + oob_left -= size; + + /* repack oob to spare */ + temp = 0; + offset = info->ecclayout->oobfree[0].offset; + len = info->ecclayout->oobfree[0].length; + memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len); + + temp += len; + offset = info->ecclayout->oobfree[1].offset; + len = info->ecclayout->oobfree[1].length; + memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len); + + temp += len; + offset = info->ecclayout->oobfree[2].offset; + len = info->ecclayout->oobfree[2].length; + memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len); + + temp += len; + offset = info->ecclayout->oobfree[3].offset; + len = info->ecclayout->oobfree[3].length; + memcpy (chip->buf + info->page_main_size + offset, chip->oobbuf + temp, len); + + } + + if (count < page_num || count < oob_num) + { + + retval = chip->program_page(spi_nand, info, page_id + count, 0, info->page_size, chip->buf); + if (retval != 0) + { + errcode = -1; + printk(KERN_INFO "spinand_write_ops: fail, page=%d!\n", page_id); + + return errcode; + } + } + + if (count < page_num && ops->datbuf) + { + ops->retlen = main_ok; + } + + if (count < oob_num && ops->oobbuf && chip->oobbuf) + { + ops->oobretlen = oob_ok; + } + + count++; + + } + + return errcode; +} + +static int spinand_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct mtd_oob_ops ops = {0}; + int ret; + + /* Do not allow reads past end of device */ + if ((from + len) > mtd->size) + return -EINVAL; + + if (!len) + return 0; + + spinand_get_device(mtd, FL_READING); + + ops.len = len; + ops.datbuf = buf; + + ret = spinand_read_ops(mtd, from, &ops); + + *retlen = ops.retlen; + + spinand_release_device(mtd); + + return ret; +} + +static int spinand_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct mtd_oob_ops ops = {0}; + int ret; + + /* Do not allow reads past end of device */ + if ((to + len) > mtd->size) + return -EINVAL; + if (!len) + return 0; + + spinand_get_device(mtd, FL_WRITING); + + ops.len = len; + ops.datbuf = (uint8_t *)buf; + + ret = spinand_write_ops(mtd, to, &ops); + + *retlen = ops.retlen; + + spinand_release_device(mtd); + + return ret; +} + +static int spinand_read_oob(struct mtd_info *mtd, loff_t from, + struct mtd_oob_ops *ops) +{ + int ret; + + spinand_get_device(mtd, FL_READING); + + ret = spinand_read_ops(mtd, from, ops); + + spinand_release_device(mtd); + + return ret; +} + +static int spinand_write_oob(struct mtd_info *mtd, loff_t to, + struct mtd_oob_ops *ops) +{ + int ret; + + spinand_get_device(mtd, FL_WRITING); + + ret = spinand_write_ops(mtd, to, ops); + + spinand_release_device(mtd); + + return ret; +} + +/** + * spinand_erase - [MTD Interface] erase block(s) + * @param mtd MTD device structure + * @param instr erase instruction + * + * Erase one ore more blocks + */ +static int spinand_erase(struct mtd_info *mtd, struct erase_info *instr) +{ + struct spinand_chip *chip = mtd->priv; + struct spi_device *spi_nand = chip->spi_nand; + struct spinand_info *info = chip->info; + u16 block_id, block_num, count; + signed int retval=0; + signed int errcode=0; + + DEBUG(MTD_DEBUG_LEVEL3, "spinand_erase: start = 0x%012llx, len = %llu\n", + (unsigned long long)instr->addr, (unsigned long long)instr->len); + + /* check address align on block boundary */ + if (instr->addr & (info->block_main_size - 1)) { + DEBUG(MTD_DEBUG_LEVEL0, "spinand_erase: Unaligned address\n"); + return -EINVAL; + } + + if (instr->len & (info->block_main_size - 1)) { + DEBUG(MTD_DEBUG_LEVEL0, "spinand_erase: " + "Length not block aligned\n"); + return -EINVAL; + } + + /* Do not allow erase past end of device */ + if ((instr->len + instr->addr) > info->usable_size) { + DEBUG(MTD_DEBUG_LEVEL0, "spinand_erase: " + "Erase past end of device\n"); + return -EINVAL; + } + + instr->fail_addr = MTD_FAIL_ADDR_UNKNOWN; + + + /* Grab the lock and see if the device is available */ + spinand_get_device(mtd, FL_ERASING); + + block_id = instr->addr >> info->block_shift; + block_num = instr->len >> info->block_shift; + count = 0; + + while (count < block_num ) + { + retval = chip->erase_block(spi_nand, info, block_id+count); + + if (retval!=0) + { + retval = chip->erase_block(spi_nand, info, block_id+count); + if (retval!=0) + { + printk(KERN_INFO "spinand_erase: fail, block=%d!\n", block_id+count); + errcode = -1; + } + } + count++; + } + + if (errcode == 0) + { + instr->state = MTD_ERASE_DONE; + } + + /* Deselect and wake up anyone waiting on the device */ + spinand_release_device(mtd); + + /* Do call back function */ + if(instr->callback) + instr->callback(instr); + + return errcode; +} + +/** + * spinand_sync - [MTD Interface] sync + * @param mtd MTD device structure + * + * Sync is actually a wait for chip ready function + */ +static void spinand_sync(struct mtd_info *mtd) +{ + DEBUG(MTD_DEBUG_LEVEL3, "spinand_sync: called\n"); + + /* Grab the lock and see if the device is available */ + spinand_get_device(mtd, FL_SYNCING); + + /* Release it and go back */ + spinand_release_device(mtd); +} + +static int spinand_block_isbad(struct mtd_info *mtd, loff_t ofs) +{ + struct spinand_chip *chip = mtd->priv; + struct spi_device *spi_nand = chip->spi_nand; + struct spinand_info *info = chip->info; + u16 block_id; + u8 is_bad = 0x00; + u8 ret = 0; + + spinand_get_device(mtd, FL_READING); + + block_id = ofs >> info->block_shift; + + chip->read_page(spi_nand, info, block_id*info->page_num_per_block, info->page_main_size, 1, &is_bad); + + if (is_bad != 0xFF) + { + ret = 1; + } + + spinand_release_device(mtd); + + return ret; +} + +/** + * spinand_block_markbad - [MTD Interface] Mark bad block + * @param mtd MTD device structure + * @param ofs Bad block number + */ +static int spinand_block_markbad(struct mtd_info *mtd, loff_t ofs) +{ + struct spinand_chip *chip = mtd->priv; + struct spi_device *spi_nand = chip->spi_nand; + struct spinand_info *info = chip->info; + u16 block_id; + u8 is_bad = 0x00; + u8 ret = 0; + + spinand_get_device(mtd, FL_WRITING); + + block_id = ofs >> info->block_shift; + + chip->program_page(spi_nand, info, block_id*info->page_num_per_block, info->page_main_size, 1, &is_bad); + + spinand_release_device(mtd); + + return ret; +} + + +/** + * spinand_suspend - [MTD Interface] Suspend the spinand flash + * @param mtd MTD device structure + */ +static int spinand_suspend(struct mtd_info *mtd) +{ + return spinand_get_device(mtd, FL_PM_SUSPENDED); +} + +/** + * spinand_resume - [MTD Interface] Resume the spinand flash + * @param mtd MTD device structure + */ +static void spinand_resume(struct mtd_info *mtd) +{ + struct spinand_chip *this = mtd->priv; + + if (this->state == FL_PM_SUSPENDED) + spinand_release_device(mtd); + else + printk(KERN_ERR "resume() called for the chip which is not" + "in suspended state\n"); +} + +/** + * spinand_mtd - add MTD device with parameters + * @param mtd MTD device structure + * + * Add MTD device with parameters. + */ +int spinand_mtd(struct mtd_info *mtd) +{ + struct spinand_chip *chip = mtd->priv; + struct spinand_info *info = chip->info; + + chip->state = FL_READY; + init_waitqueue_head(&chip->wq); + spin_lock_init(&chip->chip_lock); + + mtd->name = info->name; + mtd->size = info->usable_size; + mtd->erasesize = info->block_main_size; + mtd->writesize = info->page_main_size; + mtd->oobsize = info->ecclayout->oobavail; + mtd->owner = THIS_MODULE; + mtd->type = MTD_NANDFLASH; + mtd->flags = MTD_CAP_NANDFLASH; + + mtd->ecclayout = info->ecclayout; + + mtd->erase = spinand_erase; + mtd->point = NULL; + mtd->unpoint = NULL; + mtd->read = spinand_read; + mtd->write = spinand_write; + mtd->read_oob = spinand_read_oob; + mtd->write_oob = spinand_write_oob; + mtd->sync = spinand_sync; + mtd->lock = NULL; + mtd->unlock = NULL; + mtd->suspend = spinand_suspend; + mtd->resume = spinand_resume; + mtd->block_isbad = spinand_block_isbad; + mtd->block_markbad = spinand_block_markbad; + + return add_mtd_device(mtd) == 1 ? -ENODEV : 0; +} + +void spinand_mtd_release(struct mtd_info *mtd) +{ + del_mtd_device(mtd); +} + +EXPORT_SYMBOL_GPL(spinand_mtd); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Henry Pan "); +MODULE_DESCRIPTION("SPI NAND driver code"); diff -urN linux-2.6.33.20-orig/include/linux/mtd/spinand.h linux-2.6.33.20/include/linux/mtd/spinand.h --- linux-2.6.33.20-orig/include/linux/mtd/spinand.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.33.20/include/linux/mtd/spinand.h 2010-05-19 04:28:07.000000000 -0700 @@ -0,0 +1,160 @@ +/* + * linux/include/linux/mtd/spinand.h + * + Copyright (c) 2009-2010 Micron Technology, Inc. + +This software is licensed under the terms of the GNU General Public +License version 2, as published by the Free Software Foundation, and +may be copied, distributed, and modified under those terms. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + + * Henry Pan + * + * based on nand.h + */ +#ifndef __LINUX_MTD_SPI_NAND_H +#define __LINUX_MTD_SPI_NAND_H + +#include +#include +#include + +/* cmd */ +#define CMD_READ 0x13 +#define CMD_READ_RDM 0x03 +#define CMD_PROG_PAGE_CLRCACHE 0x02 +#define CMD_PROG_PAGE 0x84 +#define CMD_PROG_PAGE_EXC 0x10 +#define CMD_ERASE_BLK 0xd8 +#define CMD_WR_ENABLE 0x06 +#define CMD_WR_DISABLE 0x04 +#define CMD_READ_ID 0x9f +#define CMD_RESET 0xff +#define CMD_READ_REG 0x0f +#define CMD_WRITE_REG 0x1f + +/* feature/ status reg */ +#define REG_BLOCK_LOCK 0xa0 +#define REG_OTP 0xb0 +#define REG_STATUS 0xc0/* timing */ + +/* status */ +#define STATUS_OIP_MASK 0x01 +#define STATUS_READY 0 << 0 +#define STATUS_BUSY 1 << 0 + +#define STATUS_E_FAIL_MASK 0x04 +#define STATUS_E_FAIL 1 << 2 + +#define STATUS_P_FAIL_MASK 0x08 +#define STATUS_P_FAIL 1 << 3 + +#define STATUS_ECC_MASK 0x30 +#define STATUS_ECC_1BIT_CORRECTED 1 << 4 +#define STATUS_ECC_ERROR 2 << 4 +#define STATUS_ECC_RESERVED 3 << 4 + + +/*ECC enable defines*/ +#define OTP_ECC_MASK 0x10 +#define OTP_ECC_OFF 0 +#define OTP_ECC_ON 1 + +#define ECC_DISABLED +#define ECC_IN_NAND +#define ECC_SOFT + +/* block lock */ +#define BL_ALL_LOCKED 0x38 +#define BL_1_2_LOCKED 0x30 +#define BL_1_4_LOCKED 0x28 +#define BL_1_8_LOCKED 0x20 +#define BL_1_16_LOCKED 0x18 +#define BL_1_32_LOCKED 0x10 +#define BL_1_64_LOCKED 0x08 +#define BL_ALL_UNLOCKED 0 + +/********************************************************************** ******/ + +struct spinand_info { + u8 mid; + u8 did; + char *name; + u64 nand_size; + u64 usable_size; + + u32 block_size; + u32 block_main_size; + /*u32 block_spare_size; */ + u16 block_num_per_chip; + + u16 page_size; + u16 page_main_size; + u16 page_spare_size; + u16 page_num_per_block; + + u8 block_shift; + u32 block_mask; + + u8 page_shift; + u16 page_mask; + + struct nand_ecclayout *ecclayout; +}; + +typedef enum { + FL_READY, + FL_READING, + FL_WRITING, + FL_ERASING, + FL_SYNCING, + FL_LOCKING, + FL_RESETING, + FL_OTPING, + FL_PM_SUSPENDED, +} spinand_state_t; + +struct spinand_chip { /* used for multi chip */ + spinlock_t chip_lock; + wait_queue_head_t wq; + spinand_state_t state; + struct spi_device *spi_nand; + struct spinand_info *info; + /*struct mtd_info *mtd; */ + + int (*reset) (struct spi_device *spi_nand); + int (*read_id) (struct spi_device *spi_nand, u8* id); + int (*read_page) (struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* rbuf); + int (*program_page) (struct spi_device *spi_nand, struct spinand_info *info, u16 page_id, u16 offset, u16 len, u8* wbuf); + int (*erase_block) (struct spi_device *spi_nand, struct spinand_info *info, u16 block_id); + + u8 *buf; + u8 *oobbuf; /* temp buffer */ + + +#ifdef CONFIG_MTD_SPINAND_SWECC + u8 ecc_calc[12]; + u8 ecc_code[12]; +#endif +}; + +struct spinand_cmd { + u8 cmd; + unsigned n_addr; + u8 addr[3]; + unsigned n_dummy; + unsigned n_tx; + u8 *tx_buf; + unsigned n_rx; + u8 *rx_buf; +}; + +extern int spinand_mtd(struct mtd_info *mtd); +extern void spinand_mtd_release(struct mtd_info *mtd); + + +#endif /* __LINUX_MTD_SPI_NAND_H */ -------------- next part -------------- An HTML attachment was scrubbed... URL: