From dedekind1 at gmail.com  Wed Jun  1 03:42:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 10:42:46 +0300
Subject: [PATCH v6 1/8] MTD: Add integrator-flash feature to physmap
In-Reply-To: <BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
References: <1305637877-24436-1-git-send-email-marc.zyngier@arm.com>
	<1305637877-24436-2-git-send-email-marc.zyngier@arm.com>
	<4DE53D52.4040508@ru.mvista.com>
	<20110531224428.6636e283@taxman.wild-wind.fr.eu.org>
	<BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
Message-ID: <1306914166.4405.47.camel@localhost>

On Tue, 2011-05-31 at 22:20 -0400, Mike Frysinger wrote:
> On Tue, May 31, 2011 at 17:44, Marc Zyngier wrote:
> > On Tue, 31 May 2011 23:11:14 +0400 Sergei Shtylyov wrote:
> >> Marc Zyngier wrote:
> >> > In the process of moving platforms away from integrator-flash
> >> > (aka armflash), add to physmap the few features that make
> >> > armflash unique:
> >>
> >> > - optionnal probing for the AFS partition type
> >> > - init() and exit() methods, used by Integrator to control
> >> >   write access to the various onboard programmable components
> >>
> >> > Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> > Acked-by: Catalin Marinas <catalin.marinas at arm.com>
> >> > Cc: David Woodhouse <dwmw2 at infradead.org>
> >> [...]
> >>
> >> > diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
> >> > index bcfd9f7..d37cca0 100644
> >> > --- a/include/linux/mtd/physmap.h
> >> > +++ b/include/linux/mtd/physmap.h
> >> > @@ -22,6 +22,8 @@ struct map_info;
> >> >
> >> >  struct physmap_flash_data {
> >> >     unsigned int            width;
> >> > +   int                     (*init)(struct platform_device *);
> >> > +   void                    (*exit)(struct platform_device *);
> >>
> >>     How about a declaration for 'struct platform_device' beforehand? This breaks
> >> build on other platforms at least...
> >
> > Sure. Please send a patch.
> 
> uhh, what ?  you broke things, so you fix them.  i already pointed out
> this breakage to you over a week ago.
> -mike

The change went in via Russell's tree, I sent him a fix. It looks like
he did not merge it. Now I'm not sure who should merge this patch. I'll
ping dwmw2.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 03:45:54 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 10:45:54 +0300
Subject: [PATCH -next] mtd: fix physmap.h warnings
In-Reply-To: <1306222943.2785.55.camel@localhost>
References: <20110523154518.5e27cfb0.sfr@canb.auug.org.au>
	<20110523113709.4357b4ba.randy.dunlap@oracle.com>
	<1306216431.2785.46.camel@localhost>
	<1306216683.2785.47.camel@localhost>
	<20110524074020.GA9490@flint.arm.linux.org.uk>
	<1306222943.2785.55.camel@localhost>
Message-ID: <1306914354.4405.49.camel@localhost>

On Tue, 2011-05-24 at 10:42 +0300, Artem Bityutskiy wrote:
> From: Randy Dunlap <randy.dunlap at oracle.com>
> Subject: [PATCH] mtd: fix physmap.h warnings
> 
> Fix build warnings in physmap.h:
> 
> include/linux/mtd/physmap.h:25: warning: 'struct platform_device' declared inside parameter list
> include/linux/mtd/physmap.h:25: warning: its scope is only this definition or declaration, which is probably not what you want
> include/linux/mtd/physmap.h:26: warning: 'struct platform_device' declared inside parameter list
> include/linux/mtd/physmap.h:27: warning: 'struct platform_device' declared inside parameter list
> 
> Signed-off-by: Randy Dunlap <randy.dunlap at oracle.com>
> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

David, it looks like Russel did not merge this patch and people
complain. Could you please merge it?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 03:48:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 10:48:34 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
Message-ID: <1306914514.4405.51.camel@localhost>

On Fri, 2011-05-27 at 17:12 -0400, Matthew L. Creech wrote:
> Hi,
> 
> We encountered a device which has the following error:
> 
> UBIFS error (pid 428): ubifs_decompress: cannot decompress 1010 bytes,
> compressor lzo, error -22
> UBIFS error (pid 428): read_block: bad data node (block 388, inode 556196)
> UBIFS error (pid 428): do_readpage: cannot read page 388 of inode
> 556196, error -22
> UBIFS error (pid 428): ubifs_decompress: cannot decompress 1010 bytes,
> compressor lzo, error -22
> UBIFS error (pid 428): read_block: bad data node (block 388, inode 556196)
> UBIFS error (pid 428): do_readpage: cannot read page 388 of inode
> 556196, error -22
> 
> The device is still bootable (though not functional), so I can get
> more debug info if needed.  Any ideas on what could cause this?

Yes, you can enable mount and recovery debugging messages and send me
the log.

> - MPC8313 (using fsl_elbc_nand driver)
> - 1GB NAND flash (partitioned into 5MB for U-Boot, remainder for UBI/UBIFS)
> - 2.6.39 kernel
> 
> Thanks!
> 


-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 03:51:26 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 10:51:26 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
Message-ID: <1306914686.4405.53.camel@localhost>

On Tue, 2011-05-31 at 17:47 -0400, Matthew L. Creech wrote:
> Unfortunately it's not repeatable enough for us to capture adequate
> debug output - we've had several devices logging extensive debug
> output via netconsole for months now, but none have recreated this
> problem so far under those conditions.

How this happens? What do you do? Does this happen after mount when you
first read your data? Or this happens at some point while you stress
testing your system? Or this happens after a power cut?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From lh_post at yahoo.com  Wed Jun  1 03:57:07 2011
From: lh_post at yahoo.com (Lars Michael)
Date: Wed, 1 Jun 2011 00:57:07 -0700 (PDT)
Subject: U-Boot: using nand write to flash an ubi image, ubi part fails
Message-ID: <891190.21758.qm@web30201.mail.mud.yahoo.com>

Hello,

Using mkfs.ubifs and ubinize I have created an image with 5 volumes. In Linux I could flash it using "ubiformat /dev/mtd1 -f /root/ubi.img" and attach it using "ubiattach /dev/ubi_ctrl -m 1". It worked.

In production I would prefer to write the image from U-Boot. So in U-Boot I used "nand erase" then "nand write" to flash the image. Then I want to attach by "ubi part" command - but this fails: "UBI error: ubi_init: UBI error: cannot initialize UBI, error -17"

Then I booted Linux (via nfs) and tried to re-format+attach, but now it fails. Format complains about eraseblock contents and missing erase counters: 

ubiformat: warning!: 1099 of 2036 eraseblocks contain non-ubifs data
ubiformat: warning!: only 937 of 2036 eraseblocks have valid erase counter

The ubiattach now reports lots of:
...
UBI error: check_corruption: PEB 0 contains corrupted VID header, and the data does not contain all 0xFF, this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection

UBI warning: process_eb: valid VID header but corrupted EC header at PEB 4
...

I realize that the U-Boot 'nand erase' does not preserve the erase counters. So what would be the correct way to erase and write in U-Boot? And why is the ubiformat not able to correct the problems?

My kernel is 2.6.29 patched with 165 patched from the ubi back port tree.
U-Boot is 2009.08 with ubifs support, but I am not sure if there are relevant patches. The CPU is a v4 ColdFire and 256MB Micron NAND.

Any help is appreciated, thanks. Below are the detailed listing:


-> mtd

device nand0 <NAND>, # parts = 2
 #: name		size		offset		mask_flags
 0: u-boot              0x00100000	0x00000000	0
 1: ubi                 0x0ff00000	0x00100000	0

active partition: nand0,0 - (u-boot) 0x00100000 @ 0x00000000

defaults:
mtdids  : nand0=NAND
mtdparts: mtdparts=NAND:1m(u-boot),-(ubi)

-> nand erase ubi

NAND erase: device 0 offset 0x100000, size 0xff00000
Erasing at 0x100000 --   0% complete.
<cut>
Erasing at 0xfd60000 --  99% complete.
Skipping bad block at  0x0ff80000                                          

Skipping bad block at  0x0ffa0000                                          

Skipping bad block at  0x0ffc0000                                          

Skipping bad block at  0x0ffe0000                                          

OK

Using FEC0 device
TFTP from server 10.28.151.113; our IP address is 10.28.151.112
Filename '/twr5441x/ubi.img'.
Load address: 0x40010000
Loading: *#################################################################
	 #################################################################
<cut>
	 #################################################################
	 ########################################################
done
Bytes transferred = 58064896 (3760000 hex)
-> md 40010000 100

40010000: 55424923 01000000 00000000 00000000    UBI#............
40010010: 00000800 00001000 27162ae3 00000000    ........'.*.....
40010020: 00000000 00000000 00000000 00000000    ................
40010030: 00000000 00000000 00000000 7d780a89    ............}x..
40010040: ffffffff ffffffff ffffffff ffffffff    ................
<cut>
400113f0: 00000000 00000000 00000000 00000000    ................
-> nand write ${loadaddr} 100000 ${filesize}

NAND write: device 0 offset 0x100000, size 0x3760000
 58064896 bytes written: OK
-> ubi part ubi

Creating 1 MTD partitions on "nand0":
0x000000100000-0x000010000000 : "mtd=1"
UBI: attaching mtd1 to ubi0
UBI: physical eraseblock size:   131072 bytes (128 KiB)
UBI: logical eraseblock size:    126976 bytes
UBI: smallest flash I/O unit:    2048
UBI: VID header offset:          2048 (aligned 2048)
UBI: data offset:                4096
UBI warning: process_lvol: volume table copy #1 is corrupted
UBI: create volume table (copy #1)
UBI: volume table was restored
UBI: volume 5 ("datafs") re-sized from 133 to 1316 LEBs
UBI: attached mtd1 to ubi0
UBI: MTD device name:            "mtd=1"
UBI: MTD device size:            255 MiB
UBI: number of good PEBs:        2036
UBI: number of bad PEBs:         4
UBI: max. allowed volumes:       128
UBI: wear-leveling threshold:    4096
UBI: number of internal volumes: 1
UBI: number of user volumes:     5
UBI: available PEBs:             0
UBI: total number of reserved PEBs: 2036
UBI: number of PEBs reserved for bad PEB handling: 20
UBI: max/mean erase counter: 5/0
UBI error: ubi_init: cannot attach mtd1
UBI: mtd1 is detached from ubi0
UBI error: ubi_init: UBI error: cannot initialize UBI, error -17
UBI init error -17
exit not allowed from main input shell.

------------------

[root at M54418TWR root]# ubiformat /dev/mtd1 -f /root/ubi.img
ubiformat: mtd1 (NAND), size 267386880 bytes (255.0 MiB), 131072 eraseblocks of 131072 bytes (128.0 KiB), min. I/O size 2048 bytes

libscan: scanning eraseblock 0 --  0 % complete  
...
libscan: scanning eraseblock 2039 -- 100 % complete  
ubiformat: 303 eraseblocks have valid erase counter, mean value is 0
ubiformat: 643 eraseblocks are supposedly empty
ubiformat: bad eraseblocks: 2036, 2037, 2038, 2039
ubiformat: warning!: 1090 of 2036 eraseblocks contain non-ubifs data
ubiformat: continue? (yes/no)  yes
ubiformat: warning!: only 303 of 2036 eraseblocks have valid erase counter
ubiformat: erase counter 0 will be used for all eraseblocks
ubiformat: note, arbitrary erase counter value may be specified using -e option
ubiformat: continue? (yes/no)  yes
ubiformat: use erase counter 0 for all eraseblocks

ubiformat: flashing eraseblock 0 --  0 % complete  
...
ubiformat: flashing eraseblock 442 -- 100 % complete  

ubiformat: formatting eraseblock 443 --  0 % complete  
...
ubiformat: formatting eraseblock 2039 -- 100 % complete  

[root at M54418TWR root]# ubiattach /dev/ubi_ctrl -m 1
UBI: attaching mtd1 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    126976 bytes

UBI: smallest flash I/O unit:    2048

UBI: VID header offset:          2048 (aligned 2048)

UBI: data offset:                4096

UBI error: check_corruption: PEB 0 contains corrupted VID header, and the data does not contain all 0xFF, this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection

UBI warning: process_eb: valid VID header but corrupted EC header at PEB 4

UBI warning: process_eb: valid VID header but corrupted EC header at PEB 7

UBI warning: process_eb: valid VID header but corrupted EC header at PEB 8

UBI warning: process_eb: valid VID header but corrupted EC header at PEB 12

UBI error: check_corruption: PEB 16 contains corrupted VID header, and the data does not contain all 0xFF, this may be a non-UBI PEB or a severe VID header corruption which requires manual inspection

UBI warning: process_eb: valid VID header but corrupted EC header at PEB 22

...


Thanks,

- Lars



From dedekind1 at gmail.com  Wed Jun  1 03:54:54 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 10:54:54 +0300
Subject: -EBADMSG with free-space-fixup flag
In-Reply-To: <BANLkTimWafVH_bCJomN1uFW=t4+jRw1L9g@mail.gmail.com>
References: <BANLkTimWafVH_bCJomN1uFW=t4+jRw1L9g@mail.gmail.com>
Message-ID: <1306914894.4405.56.camel@localhost>

On Fri, 2011-05-27 at 17:47 -0400, Ben Gardiner wrote:
> Hi Matthew, Artem,
> 
> Following-up on my problems with the free-space-fixup no da850evm.
> 
> I have done lots of manual testing with u-boot and mtd-utils on-top-of
> 'c724452 UBIFS: switch to dynamic printks' to confirm that there isn't
> an 0xff ECC problem with davinci-nand.
> 
> I found that by the time the -74 is returned for PEB 18, the contents
> on NAND have been replaced.
> 
> I turned on lots of UBIFS debugging and saw that the PEB in question
> is in fact LEB 1; which is geting written to as part of the
> auto-resize of (master)

OK, so we missed the fact that we may have auto-resize before the
fix-up.

> NB: I have ubi attached with --vid-hdr-offset of 2048 because of the
> subpage writing limitations of davinci-nand.

Which means your driver may be incorrect - it should report that it does
not support sub-pages - does it do this? Then UBI will not even try to
use sub-pages and you won't need that option.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From rmk at arm.linux.org.uk  Wed Jun  1 04:05:13 2011
From: rmk at arm.linux.org.uk (Russell King)
Date: Wed, 1 Jun 2011 09:05:13 +0100
Subject: [PATCH -next] mtd: fix physmap.h warnings
In-Reply-To: <1306914354.4405.49.camel@localhost>
References: <20110523154518.5e27cfb0.sfr@canb.auug.org.au>
	<20110523113709.4357b4ba.randy.dunlap@oracle.com>
	<1306216431.2785.46.camel@localhost>
	<1306216683.2785.47.camel@localhost>
	<20110524074020.GA9490@flint.arm.linux.org.uk>
	<1306222943.2785.55.camel@localhost>
	<1306914354.4405.49.camel@localhost>
Message-ID: <20110601080513.GA21186@flint.arm.linux.org.uk>

On Wed, Jun 01, 2011 at 10:45:54AM +0300, Artem Bityutskiy wrote:
> On Tue, 2011-05-24 at 10:42 +0300, Artem Bityutskiy wrote:
> > From: Randy Dunlap <randy.dunlap at oracle.com>
> > Subject: [PATCH] mtd: fix physmap.h warnings
> > 
> > Fix build warnings in physmap.h:
> > 
> > include/linux/mtd/physmap.h:25: warning: 'struct platform_device' declared inside parameter list
> > include/linux/mtd/physmap.h:25: warning: its scope is only this definition or declaration, which is probably not what you want
> > include/linux/mtd/physmap.h:26: warning: 'struct platform_device' declared inside parameter list
> > include/linux/mtd/physmap.h:27: warning: 'struct platform_device' declared inside parameter list
> > 
> > Signed-off-by: Randy Dunlap <randy.dunlap at oracle.com>
> > Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> 
> David, it looks like Russel did not merge this patch and people
                            ^^
> complain. Could you please merge it?

Bah, it got lost in the depths of my mailboxes and forgotten...

-- 
Russell King
 Linux kernel    2.6 ARM Linux   - http://www.arm.linux.org.uk/
 maintainer of:


From dedekind1 at gmail.com  Wed Jun  1 04:02:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:02:08 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
Message-ID: <1306915328.4405.62.camel@localhost>

On Tue, 2011-05-31 at 11:47 -0400, Matthew L. Creech wrote:
> On Mon, May 30, 2011 at 8:29 AM, Ben Gardiner
> <bengardiner at nanometrics.ca> wrote:
> >
> > I don't see any debug statements in lzo1x_decompress_safe() that can
> > be enabled, so you might want to add some printing to
> > lzo1x_decompress_safe() or at least print the non-ok return code of
> > lzo1x_decompress_safe() in lzo_decompress() to get an idea of how the
> > decompressor is failing.
> >
> 
> Looks like it's returning LZO_E_LOOKBEHIND_OVERRUN.  I don't know what
> that indicates, but there is trailing 0xff data in the block to be
> decompressed if that matters:
> 
> XXXX: LZO_E_LOOKBEHIND_OVERRUN
> UBIFS error (pid 428): ubifs_decompress: cannot decompress 1010 bytes,
> compressor lzo, error -22
> 00000000: 00 0f 69 6e 3a 61 74 74 72 00 c2 38 1c 03 39 03  ..in:attr..8..9.
> 00000010: 2f 30 31 2f 6d 57 43 2f 2e 56 61 6c 75 65 4d 61  /01/mWC/.ValueMa
> 00000020: 78 3a 61 91 03 94 31 72 00 69 6e d0 03 00 01 37  x:a...1r.in....7
> 00000030: 1c 03 3d 01 2f 53 65 72 69 61 6c 4e 75 6d 62 65  ..=./SerialNumbe
> 00000040: 72 2f 98 07 98 03 00 0a 04 2f 03 63 01 2f 53 6f  r/......./.c./So
> 00000050: 66 74 77 61 72 65 2f 43 6f 6d 6d 61 6e 64 73 2f  ftware/Commands/
> 00000060: 6e 65 78 74 d2 01 49 44 29 bc 00 03 06 47 04 81  next..ID)....G..
> 00000070: 0d 03 28 c0 00 00 04 44 61 74 61 20 53 65 72 76  ..(....Data Serv
> 00000080: 65 72 73 2f 42 41 43 6e 65 74 2d 49 50 c4 01 0b  ers/BACnet-IP...
> 00000090: 44 65 76 69 63 65 49 6e 73 74 61 6e 63 65 29 14  DeviceInstance).
> 000000a0: 01 05 00 f7 28 41 04 81 03 02 20 0c 1f 01 4d 41  ....(A.... ...MA
> 000000b0: 43 29 08 01 03 02 19 42 04 81 05 20 0d 07 01 4e  C).....B... ...N
> 000000c0: 61 6d 2a 14 02 02 02 18 3c 03 7b 20 02 04 01 07  am*.....<.{ ....
> 000000d0: 42 4d 44 41 64 64 72 65 73 73 2a fc 01 02 1d 40  BMDAddress*....@
> 000000e0: 04 81 01 20 05 f4 00 06 54 69 6d 65 54 6f 4c 69  ... ....TimeToLi
> 000000f0: 76 2b f5 01 1e 20 05 f4 01 02 61 73 65 49 64 80  v+... ....aseId.
> 00000100: 36 2a f5 01 20 20 05 f4 03 07 44 65 66 61 75 6c  6*..  ....Defaul
> 00000110: 74 4e 65 74 2f e4 07 03 02 1a 46 04 81 0d 20 01  tNet/.....F... .
> 00000120: 00 03 00 02 45 6e 61 62 6c 65 42 61 73 65 46 6f  ....EnableBaseFo
> 00000130: 72 47 61 74 65 77 61 79 2a 24 02 02 1f 45 04 81  rGateway*$...E..
> 00000140: 0b 20 0e 18 01 03 52 6f 75 74 65 64 2a 14 01 02  . ....Routed*...
> 00000150: 21 50 04 81 21 20 01 14 01 c2 07 30 31 3e 84 09  !P..! .....01>..
> 00000160: 03 01 f4 4b 04 81 17 20 17 40 01 2d a8 09 02 24  ...K... . at .-...$
> 00000170: 4c 04 81 19 20 17 2c 01 2e d0 09 01 23 3a 03 77  L... .,.....#:.w
> 00000180: 20 07 2c 01 2d 1d 02 1c 20 05 d0 0c b0 24 33 cc   .,.-... ....$3.
> 00000190: 07 02 1b 00 00 00 11 6c 00 00 3f 6a 68 2e 73 ec  .......l..?jh.s.
> 000001a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000001b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000001c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000001d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000001e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000001f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000200: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000210: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000220: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000230: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000240: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000250: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000260: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000270: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000280: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000290: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000002a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000002b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000002c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000002d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000002e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000002f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000300: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000310: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000320: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000330: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000340: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000350: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000360: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000370: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000380: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 00000390: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000003a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000003b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000003c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000003d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000003e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff  ................
> 000003f0: ff ff
> UBIFS error (pid 428): read_block: bad data node (block 388, inode 556196)
> UBIFS error (pid 428): do_readpage: cannot read page 388 of inode
> 556196, error -22

I see the following possibilities:

1. The data has been written like this - then the bug is at writing
side. Check the data node - what is its length, is CRC correct? It would
be useful to dump the node which cannot be decompressed - I'd accept
such patch with great delight.

2. You had power cuts while this peace of data has been written and
recovery did not work correctly. Enabling mount and recovery messages
would help.

3. I merged several changes to 2.6.39 which could in theory break
recovery. Try to reproduce this with 2.6.38.

4. The fixup feature might have broke this - we might for some reason
read less data than there. Although I see FFs start at offset 416, which
is strange.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 04:07:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:07:36 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1306915328.4405.62.camel@localhost>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<1306915328.4405.62.camel@localhost>
Message-ID: <1306915656.4405.67.camel@localhost>

On Wed, 2011-06-01 at 11:02 +0300, Artem Bityutskiy wrote:
> I see the following possibilities:
> 
> 1. The data has been written like this - then the bug is at writing
> side. Check the data node - what is its length, is CRC correct? It would
> be useful to dump the node which cannot be decompressed - I'd accept
> such patch with great delight.
> 
> 2. You had power cuts while this peace of data has been written and
> recovery did not work correctly. Enabling mount and recovery messages
> would help.
> 
> 3. I merged several changes to 2.6.39 which could in theory break
> recovery. Try to reproduce this with 2.6.38.
> 
> 4. The fixup feature might have broke this - we might for some reason
> read less data than there. Although I see FFs start at offset 416, which
> is strange.

So Matthew, let's try to exclude some of these possibilities. Please,
send me some description about what you do to reproduce this. Is this
error persistent or it goes away after remount or reboot. And other
information relevant to the above points.

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 04:20:24 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:20:24 +0300
Subject: [TRIVIAL PATCH next 09/15] mtd: Convert vmalloc/memset to vzalloc
In-Reply-To: <adc50014679048de28c7d536f1686cd945fc40f6.1306603968.git.joe@perches.com>
References: <cover.1306603968.git.joe@perches.com>
	<adc50014679048de28c7d536f1686cd945fc40f6.1306603968.git.joe@perches.com>
Message-ID: <1306916424.4405.68.camel@localhost>

On Sat, 2011-05-28 at 10:36 -0700, Joe Perches wrote:
> Signed-off-by: Joe Perches <joe at perches.com>
> ---
>  drivers/mtd/mtdswap.c |    3 +--
>  1 files changed, 1 insertions(+), 2 deletions(-)

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 04:29:23 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:29:23 +0300
Subject: [Ubi] Wrong major:minor
In-Reply-To: <BANLkTimab0pKp68f_coPfsjm_6GdKAxSew@mail.gmail.com>
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<BANLkTimab0pKp68f_coPfsjm_6GdKAxSew@mail.gmail.com>
Message-ID: <1306916963.4405.72.camel@localhost>

On Sun, 2011-05-29 at 11:54 -0400, Mike Frysinger wrote:
> On Sun, May 29, 2011 at 06:39, Gilles wrote:
> > I'm no Linux expert, and was wondering how to find out what the
> > correct major:minor is for the Ubi device nodes?
> 
> they're most likely dynamic and there's no safe way you could create
> the nodes ahead of time with a device table.  simply run mdev to take
> care of /dev for you.
> 
> you can check /proc/devices to be sure ... anything over 250 is dynamic
> -mike

Right, UBI allocates device numbers dynamically, so pre-creating device
nodes is not a good idea.

Major/minor for every UBI device / UBI volume can be found at:

/sys/class/ubi/ubiX/dev
/sys/class/ubi/ubiX_Y/dev

Or the major number can be indeed found at /proc/devices, and then the
minor numbers follow the following fomula:

UBI Volume major number = UBI device major number.
UBI Volume minor number = UBI volume ID + 1.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 04:36:21 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:36:21 +0300
Subject: [Ubi] Wrong major:minor
In-Reply-To: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
Message-ID: <1306917381.4405.76.camel@localhost>

On Sun, 2011-05-29 at 12:39 +0200, Gilles wrote:
> Hello
> 
> I used the following data to compile Ubi(fs) into a uClinux kernel:
> 
> ========= device_table.txt
> #UBIFS nodes
> /dev/ubi_ctrl	c	644	0	0	10	63	0	0	-
> /dev/ubi0	c	644	0	0	253	0	0	0	-
> ========= 

But I guess you may add an UBI module parameter which will ask UBI to
use major numbers you want - should be easy to do. E.g., if you add a
'major_base=200' parameter then UBI will use 200:0 for ubi0, 201:0 for
ubi1, 200:1 for ubi0_0, 200:2 for ubi0_1, etc.

Then you could do:

modprobe ubi major_base=200

or add

ubi.major_base=200

to you kernel parameters if you have UBI compiled-in.
 
-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 04:37:35 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:37:35 +0300
Subject: [Ubi] Wrong major:minor
In-Reply-To: <1306917381.4405.76.camel@localhost>
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
Message-ID: <1306917455.4405.77.camel@localhost>

On Wed, 2011-06-01 at 11:36 +0300, Artem Bityutskiy wrote:
> On Sun, 2011-05-29 at 12:39 +0200, Gilles wrote:
> > Hello
> > 
> > I used the following data to compile Ubi(fs) into a uClinux kernel:
> > 
> > ========= device_table.txt
> > #UBIFS nodes
> > /dev/ubi_ctrl	c	644	0	0	10	63	0	0	-
> > /dev/ubi0	c	644	0	0	253	0	0	0	-
> > ========= 
> 
> But I guess you may add an UBI module parameter which will ask UBI to
> use major numbers you want - should be easy to do. E.g., if you add a
> 'major_base=200' parameter then UBI will use 200:0 for ubi0, 201:0 for
> ubi1, 200:1 for ubi0_0, 200:2 for ubi0_1, etc.

Although I'm not sure - dynamic numbers were introduced because fixed
numbers are PITA, so adding such a parameter would be a step backward.
Not sure...

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 04:39:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 11:39:36 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1306915328.4405.62.camel@localhost>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<1306915328.4405.62.camel@localhost>
Message-ID: <1306917576.4405.78.camel@localhost>

On Wed, 2011-06-01 at 11:02 +0300, Artem Bityutskiy wrote:
> 3. I merged several changes to 2.6.39 which could in theory break
> recovery. Try to reproduce this with 2.6.38.

Err, sorry, those went to 2.6.40, so disregard this point please.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Marc.Zyngier at arm.com  Wed Jun  1 03:49:06 2011
From: Marc.Zyngier at arm.com (Marc Zyngier)
Date: Wed, 01 Jun 2011 08:49:06 +0100
Subject: [PATCH v6 1/8] MTD: Add integrator-flash feature to physmap
In-Reply-To: <BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
References: <1305637877-24436-1-git-send-email-marc.zyngier@arm.com>
	<1305637877-24436-2-git-send-email-marc.zyngier@arm.com>
	<4DE53D52.4040508@ru.mvista.com>
	<20110531224428.6636e283@taxman.wild-wind.fr.eu.org>
	<BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
Message-ID: <1306914546.27474.349.camel@e102391-lin.cambridge.arm.com>

On Tue, 2011-05-31 at 22:20 -0400, Mike Frysinger wrote:
> On Tue, May 31, 2011 at 17:44, Marc Zyngier wrote:
> > On Tue, 31 May 2011 23:11:14 +0400 Sergei Shtylyov wrote:
> >> Marc Zyngier wrote:
> >> > In the process of moving platforms away from integrator-flash
> >> > (aka armflash), add to physmap the few features that make
> >> > armflash unique:
> >>
> >> > - optionnal probing for the AFS partition type
> >> > - init() and exit() methods, used by Integrator to control
> >> >   write access to the various onboard programmable components
> >>
> >> > Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> >> > Acked-by: Catalin Marinas <catalin.marinas at arm.com>
> >> > Cc: David Woodhouse <dwmw2 at infradead.org>
> >> [...]
> >>
> >> > diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
> >> > index bcfd9f7..d37cca0 100644
> >> > --- a/include/linux/mtd/physmap.h
> >> > +++ b/include/linux/mtd/physmap.h
> >> > @@ -22,6 +22,8 @@ struct map_info;
> >> >
> >> >  struct physmap_flash_data {
> >> >     unsigned int            width;
> >> > +   int                     (*init)(struct platform_device *);
> >> > +   void                    (*exit)(struct platform_device *);
> >>
> >>     How about a declaration for 'struct platform_device' beforehand? This breaks
> >> build on other platforms at least...
> >
> > Sure. Please send a patch.
> 
> uhh, what ?  you broke things, so you fix them.  i already pointed out
> this breakage to you over a week ago.

Mike,

Sorry I missed your earlier comment about this. My bad.

Now, about my reply to Sergei:
      * Sergei identified the problem, and proposed a valid fix. It's
        only fair he gets credited for his work (yes, you did it before
        he did, but I didn't know it). The SOB on a patch is the proper
        way of managing the attribution.
      * Posting a patch is the quickest way for the maintainer (in this
        case David) to be able to push a fix to mainline.
      * It also helps other folks reading the ML and facing the same
        issue. They can grab the patch, apply it locally and go on with
        their own stuff until the patch is merged.
      * The person reporting the problem probably has a configuration
        showing the problem. If any of my platforms had shown that
        error, I would have fixed it long before it hit the mailing
        list.

Now, to keep everyone happy, an untested patch. David, can you please
apply it?

Cheers,

	M.

>From 1440a857e119b90df68e87cf9da87fce870c86cf Mon Sep 17 00:00:00 2001
From: Marc Zyngier <marc.zyngier at arm.com>
Date: Wed, 1 Jun 2011 08:37:28 +0100
Subject: [PATCH] MTD: Fix physmap compilation error

Commit b7281ca2a4 (MTD: Add integrator-flash feature to physmap)
broke some platforms by using 'struct platform_device' without
declaring it.

Add a forward declaration to keep everyone happy.

Fix proposed by both Mike Frysinger and Sergei Shtylyov.

Reported-by: Mike Frysinger <vapier.adi at gmail.com>
Reported-by: Sergei Shtylyov <sshtylyov at mvista.com>
Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 include/linux/mtd/physmap.h |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index d40bfa1..e5f21d2 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -19,6 +19,7 @@
 #include <linux/mtd/partitions.h>
 
 struct map_info;
+struct platform_device;
 
 struct physmap_flash_data {
 	unsigned int		width;
-- 
1.7.0.4


-- 
Reality is an implementation detail.




From dedekind1 at gmail.com  Wed Jun  1 05:43:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 12:43:46 +0300
Subject: [PATCH v6 1/8] MTD: Add integrator-flash feature to physmap
In-Reply-To: <1306914546.27474.349.camel@e102391-lin.cambridge.arm.com>
References: <1305637877-24436-1-git-send-email-marc.zyngier@arm.com>
	<1305637877-24436-2-git-send-email-marc.zyngier@arm.com>
	<4DE53D52.4040508@ru.mvista.com>
	<20110531224428.6636e283@taxman.wild-wind.fr.eu.org>
	<BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
	<1306914546.27474.349.camel@e102391-lin.cambridge.arm.com>
Message-ID: <1306921426.4405.83.camel@localhost>

On Wed, 2011-06-01 at 08:49 +0100, Marc Zyngier wrote:
> On Tue, 2011-05-31 at 22:20 -0400, Mike Frysinger wrote:
> > On Tue, May 31, 2011 at 17:44, Marc Zyngier wrote:
> > > On Tue, 31 May 2011 23:11:14 +0400 Sergei Shtylyov wrote:
> > >> Marc Zyngier wrote:
> > >> > In the process of moving platforms away from integrator-flash
> > >> > (aka armflash), add to physmap the few features that make
> > >> > armflash unique:
> > >>
> > >> > - optionnal probing for the AFS partition type
> > >> > - init() and exit() methods, used by Integrator to control
> > >> >   write access to the various onboard programmable components
> > >>
> > >> > Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> > >> > Acked-by: Catalin Marinas <catalin.marinas at arm.com>
> > >> > Cc: David Woodhouse <dwmw2 at infradead.org>
> > >> [...]
> > >>
> > >> > diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
> > >> > index bcfd9f7..d37cca0 100644
> > >> > --- a/include/linux/mtd/physmap.h
> > >> > +++ b/include/linux/mtd/physmap.h
> > >> > @@ -22,6 +22,8 @@ struct map_info;
> > >> >
> > >> >  struct physmap_flash_data {
> > >> >     unsigned int            width;
> > >> > +   int                     (*init)(struct platform_device *);
> > >> > +   void                    (*exit)(struct platform_device *);
> > >>
> > >>     How about a declaration for 'struct platform_device' beforehand? This breaks
> > >> build on other platforms at least...
> > >
> > > Sure. Please send a patch.
> > 
> > uhh, what ?  you broke things, so you fix them.  i already pointed out
> > this breakage to you over a week ago.
> 
> Mike,
> 
> Sorry I missed your earlier comment about this. My bad.
> 
> Now, about my reply to Sergei:
>       * Sergei identified the problem, and proposed a valid fix. It's
>         only fair he gets credited for his work (yes, you did it before
>         he did, but I didn't know it). The SOB on a patch is the proper
>         way of managing the attribution.
>       * Posting a patch is the quickest way for the maintainer (in this
>         case David) to be able to push a fix to mainline.
>       * It also helps other folks reading the ML and facing the same
>         issue. They can grab the patch, apply it locally and go on with
>         their own stuff until the patch is merged.
>       * The person reporting the problem probably has a configuration
>         showing the problem. If any of my platforms had shown that
>         error, I would have fixed it long before it hit the mailing
>         list.
> 
> Now, to keep everyone happy, an untested patch. David, can you please
> apply it?
> 
> Cheers,
> 
> 	M.
> 
> >From 1440a857e119b90df68e87cf9da87fce870c86cf Mon Sep 17 00:00:00 2001
> From: Marc Zyngier <marc.zyngier at arm.com>
> Date: Wed, 1 Jun 2011 08:37:28 +0100
> Subject: [PATCH] MTD: Fix physmap compilation error
> 
> Commit b7281ca2a4 (MTD: Add integrator-flash feature to physmap)
> broke some platforms by using 'struct platform_device' without
> declaring it.
> 
> Add a forward declaration to keep everyone happy.
> 
> Fix proposed by both Mike Frysinger and Sergei Shtylyov.

The first person who sent a patch was Randy, so we already have the
patch, now it is only about merging it.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 06:03:29 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:03:29 +0300
Subject: [PATCH 1/3] UBIFS: assert no fixup when writing a node
In-Reply-To: <4a63933a3365daf8d1ec38d22c9029a949f3eccd.1306780983.git.bengardiner@nanometrics.ca>
References: <cover.1306780983.git.bengardiner@nanometrics.ca>
	<4a63933a3365daf8d1ec38d22c9029a949f3eccd.1306780983.git.bengardiner@nanometrics.ca>
Message-ID: <1306922609.4405.88.camel@localhost>

On Mon, 2011-05-30 at 14:56 -0400, Ben Gardiner wrote:
> The current free space fixup can result in some writing to the UBI volume
> when the space_fixup flag is set.
> 
> To catch instances where UBIFS is writing to the NAND while the space_fixup
> flag is set, add an assert to ubifs_write_node().
> 
> Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
> 
> ---
>  fs/ubifs/io.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
> index 166951e..db298de 100644
> --- a/fs/ubifs/io.c
> +++ b/fs/ubifs/io.c
> @@ -763,6 +763,8 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
>  	if (c->ro_error)
>  		return -EROFS;
>  
> +	ubifs_assert(!c->space_fixup);
> +

I've moved this assert upper to where all other assertions are placed.

I've also added this assertion to 'ubifs_wbuf_write_nolock()' because it
is the other often used write path.

And pushed to the UBIFS tree, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 06:06:50 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:06:50 +0300
Subject: [PATCH 2/3] UBIFS: intialize the LPT earlier
In-Reply-To: <e0fb2d40ab7314049654d85b86a4c27e9a1801ef.1306780983.git.bengardiner@nanometrics.ca>
References: <cover.1306780983.git.bengardiner@nanometrics.ca>
	<e0fb2d40ab7314049654d85b86a4c27e9a1801ef.1306780983.git.bengardiner@nanometrics.ca>
Message-ID: <1306922810.4405.91.camel@localhost>

Hi,

thanks for the patch, however

On Mon, 2011-05-30 at 14:56 -0400, Ben Gardiner wrote: 
> +	err = ubifs_lpt_init(c, 1, !c->ro_mount);
> +	if (err)
> +		goto out_lpt;

You cannot call ubifs_lpt_init()

> +
>  	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
>  		ubifs_msg("recovery needed");
>  		c->need_recovery = 1;
>  		if (!c->ro_mount) {
>  			err = ubifs_recover_inl_heads(c, c->sbuf);

Before ubifs_recover_inl_heads() is called in case of dirty FS.

I've massaged your patch and pushed the following analogous patch to the
ubifs tree, please check/test:




From vapier.adi at gmail.com  Wed Jun  1 06:11:49 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Wed, 1 Jun 2011 06:11:49 -0400
Subject: [Ubi] Wrong major:minor
In-Reply-To: <1306917455.4405.77.camel@localhost>
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
	<1306917455.4405.77.camel@localhost>
Message-ID: <BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com>

On Wed, Jun 1, 2011 at 04:37, Artem Bityutskiy wrote:
> On Wed, 2011-06-01 at 11:36 +0300, Artem Bityutskiy wrote:
>> On Sun, 2011-05-29 at 12:39 +0200, Gilles wrote:
>> > I used the following data to compile Ubi(fs) into a uClinux kernel:
>> >
>> > ========= device_table.txt
>> > #UBIFS nodes
>> > /dev/ubi_ctrl ? ? ? c ? ? ? 644 ? ? 0 ? ? ? 0 ? ? ? 10 ? ? ?63 ? ? ?0 ? ? ? 0 ? ? ? -
>> > /dev/ubi0 ? c ? ? ? 644 ? ? 0 ? ? ? 0 ? ? ? 253 ? ? 0 ? ? ? 0 ? ? ? 0 ? ? ? -
>> > =========
>>
>> But I guess you may add an UBI module parameter which will ask UBI to
>> use major numbers you want - should be easy to do. E.g., if you add a
>> 'major_base=200' parameter then UBI will use 200:0 for ubi0, 201:0 for
>> ubi1, 200:1 for ubi0_0, 200:2 for ubi0_1, etc.
>
> Although I'm not sure - dynamic numbers were introduced because fixed
> numbers are PITA, so adding such a parameter would be a step backward.
> Not sure...

yeah, i dont think there should be.  at least nothing specific to ubi.
 perhaps a general kernel thing where you could match the registered
name to a static #, but then that wouldnt be ubi's problem.  that'd be
in the core logic and work for all devices.
-mike


From dedekind1 at gmail.com  Wed Jun  1 06:14:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:14:14 +0300
Subject: [Ubi] Wrong major:minor
In-Reply-To: <BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com>
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
	<1306917455.4405.77.camel@localhost>
	<BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com>
Message-ID: <1306923254.4405.92.camel@localhost>

On Wed, 2011-06-01 at 06:11 -0400, Mike Frysinger wrote:
> On Wed, Jun 1, 2011 at 04:37, Artem Bityutskiy wrote:
> > On Wed, 2011-06-01 at 11:36 +0300, Artem Bityutskiy wrote:
> >> On Sun, 2011-05-29 at 12:39 +0200, Gilles wrote:
> >> > I used the following data to compile Ubi(fs) into a uClinux kernel:
> >> >
> >> > ========= device_table.txt
> >> > #UBIFS nodes
> >> > /dev/ubi_ctrl       c       644     0       0       10      63      0       0       -
> >> > /dev/ubi0   c       644     0       0       253     0       0       0       -
> >> > =========
> >>
> >> But I guess you may add an UBI module parameter which will ask UBI to
> >> use major numbers you want - should be easy to do. E.g., if you add a
> >> 'major_base=200' parameter then UBI will use 200:0 for ubi0, 201:0 for
> >> ubi1, 200:1 for ubi0_0, 200:2 for ubi0_1, etc.
> >
> > Although I'm not sure - dynamic numbers were introduced because fixed
> > numbers are PITA, so adding such a parameter would be a step backward.
> > Not sure...
> 
> yeah, i dont think there should be.  at least nothing specific to ubi.
>  perhaps a general kernel thing where you could match the registered
> name to a static #, but then that wouldnt be ubi's problem.  that'd be
> in the core logic and work for all devices.

Yes, I agree. Gilles, please, disregard my suggestion.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 06:16:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:16:47 +0300
Subject: [PATCH 3/3] UBIFS: fix-up free space earlier
In-Reply-To: <546eb16b8aedc7708774ae66bffd6c1175331b49.1306780983.git.bengardiner@nanometrics.ca>
References: <cover.1306780983.git.bengardiner@nanometrics.ca>
	<546eb16b8aedc7708774ae66bffd6c1175331b49.1306780983.git.bengardiner@nanometrics.ca>
Message-ID: <1306923407.4405.94.camel@localhost>

On Mon, 2011-05-30 at 14:56 -0400, Ben Gardiner wrote:
> The free space fixup is currently initiated during mount after the call to
> ubifs_write_master() which results in a write to PEBs; this has been observed
> with the patch 'assert no fixup when writing a node' applied:
> 
> Move the free space fixup on mount to before the calls to
> ubifs_recover_inl_heads() and ubifs_write_master(). This results in no
> assertions with the previously mentioned patch applied.
> 
> Signed-off-by: Ben Gardiner <bengardiner at nanometrics>
> CC: Matthew L. Creech <mlcreech at gmail.com>
> 
> ---
>  fs/ubifs/super.c |   12 ++++++------
>  1 files changed, 6 insertions(+), 6 deletions(-)
> 
> diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
> index 89c8d33..531b9b7 100644
> --- a/fs/ubifs/super.c
> +++ b/fs/ubifs/super.c
> @@ -1285,6 +1285,12 @@ static int mount_ubifs(struct ubifs_info *c)
>  	if (err)
>  		goto out_lpt;
>  
> +	if (!c->ro_mount && c->space_fixup) {
> +		err = ubifs_fixup_free_space(c);
> +		if (err)
> +			goto out_infos;
> +	}

Tweaked the patch a bit to make sure 'init_constants_master()' is called
before we start fixing-up - this does not matter now but it is less
error prone. And pushed to the UBIFS git tree, thank you.

But please, do review my tweaks and test them. When you confirm it
works, I'll send a pull request to Linus.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 06:19:25 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:19:25 +0300
Subject: [PATCH 0/3] fix-up free space earlier in mount_ubifs()
In-Reply-To: <cover.1306780983.git.bengardiner@nanometrics.ca>
References: <cover.1306780983.git.bengardiner@nanometrics.ca>
Message-ID: <1306923565.4405.96.camel@localhost>

On Mon, 2011-05-30 at 14:56 -0400, Ben Gardiner wrote:
> In testing Mattew Creech's free-space-fixup flag series I found that was unable
> to boot a da850evm which had flashed to it's NAND a ubinized image containing a
> UBIFS that has the free-space-fixup flag set.
> 
> The cause of the problem was found to be the call to ubifs_write_master() from
> mount_ubifs() as is evidenced the backtrace produced by the assertion
> introduced in the first patch of this series; where the assertion introduced is
> that c->space_fixup is false when ubifs_write_node() is called.

So the fixes are now in the ubifs tree. You can see them in the
linux-next banch's tip or in the master branch under a pile of other
changes. The point is that linux-next currently contains what I want to
merge to linux-3.0 and master branch contains the same plus a pile of
things for linux-3.1.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 06:20:28 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:20:28 +0300
Subject: [PATCH 0/3] fix-up free space earlier in mount_ubifs()
In-Reply-To: <BANLkTi=_8nSWYt=7+EgoORiYHqpRhOQurw@mail.gmail.com>
References: <cover.1306780983.git.bengardiner@nanometrics.ca>
	<BANLkTinu7dX5Tfhs0ak0BEfc212mpJKb+w@mail.gmail.com>
	<BANLkTikPqkDON4mzBEko46JdgACrbTOiiA@mail.gmail.com>
	<BANLkTi=_8nSWYt=7+EgoORiYHqpRhOQurw@mail.gmail.com>
Message-ID: <1306923628.4405.97.camel@localhost>

On Tue, 2011-05-31 at 11:22 -0400, Matthew L. Creech wrote:
> Reviewed-by: Matthew L. Creech <mlcreech at gmail.com>

OK, added.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 06:30:35 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 13:30:35 +0300
Subject: [PATCH 1/2] mtd: nand: generalized error messages with __func__
In-Reply-To: <BANLkTimsTWAcR4HgOoHguDMv9P-Eox=kbg@mail.gmail.com>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>
	<4DDDE19D.9010505@compulab.co.il> <1306387008.2785.138.camel@localhost>
	<BANLkTimsTWAcR4HgOoHguDMv9P-Eox=kbg@mail.gmail.com>
Message-ID: <1306924235.4405.102.camel@localhost>

Hi,

On Tue, 2011-05-31 at 11:52 -0700, Brian Norris wrote:
> > Brian, would you please instead just zap the prints?
> 
> Sure, can do. In general, then, is it best practice to simply 'return
> -ENOMEM' or similar (without any printing) in all MTD code?

Yes.

> > On Thu, 2011-05-26 at 08:14 +0300, Igor Grinberg wrote:
> >> On 05/26/11 00:59, Brian Norris wrote:
> >> pr_err() will save you from the need to define the log level each time.
> >> pr_fmt will save you the need to add %s: and __func__.
> 
> Also, it seems that the second statement is not necessarily true. In
> fact, in include/linux/printk.h, we default to the following
> declaration:
>      #define pr_fmt(fmt) fmt

To be more precise:

#ifndef pr_fmt
#define pr_fmt(fmt) fmt
#endif

> So it seems that, when we desire to print out the relevant function
> name, we should manually use __func__ instead of relying on
> pr_fmt...or should we define our own pr_fmt in include/linux/mtd.h?

Yes, before you include files.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From gilles.ganault at free.fr  Wed Jun  1 07:21:14 2011
From: gilles.ganault at free.fr (Gilles)
Date: Wed, 01 Jun 2011 13:21:14 +0200
Subject: [Ubi] Wrong major:minor
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
	<1306917455.4405.77.camel@localhost>
Message-ID: <g48cu69tgrhk8hd76lp172kiskuagqal3r@4ax.com>

On Wed, 01 Jun 2011 11:37:35 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>Although I'm not sure - dynamic numbers were introduced because fixed
>numbers are PITA, so adding such a parameter would be a step backward.

No problem. Mdev seems to work fine, so I'll stop using static dev
nodes. Thanks for the infos.



From gilles.ganault at free.fr  Wed Jun  1 07:22:50 2011
From: gilles.ganault at free.fr (Gilles)
Date: Wed, 01 Jun 2011 13:22:50 +0200
Subject: [Ubi] Wrong major:minor
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<BANLkTimab0pKp68f_coPfsjm_6GdKAxSew@mail.gmail.com>
	<i1q6u61tl5go0ou25i0dcupco020ea94a3@4ax.com>
	<BANLkTinmGVeysdwxGSRBsMVXPRnAtOWivg@mail.gmail.com>
Message-ID: <v58cu6p3r5civ2ae44r5ad9hc34rqaab6e@4ax.com>

On Mon, 30 May 2011 12:29:56 -0400, Mike Frysinger
<vapier.adi at gmail.com> wrote:

>On Mon, May 30, 2011 at 05:53, Gilles wrote:
>> ? ? ? ? ? ?#BAD echo /sbin/mdev > /proc/sys/kernel/hotplug;
>
>i dont know why you've disabled this.  if you want dynamic nodes after
>boot, you need it.

Because...
1. of that error:
====
Starting mdev...
sh: can't open '/proc/sys/kernel/hotplug': No such file or directory
====

2. and because I don't actually need hotplugging, since the appliance
is a closed-box, so users can't actually (un)plug devices anyway.

I just needed mdev so that Linux would create the right dev nodes for
Ubi.

Thank you.



From dedekind1 at gmail.com  Wed Jun  1 07:30:35 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 14:30:35 +0300
Subject: [PATCH] mtd: OneNAND: OMAP2: Return proper error if
	regulator_get fails
In-Reply-To: <1306848053.13412.1.camel@phoenix>
References: <1306848053.13412.1.camel@phoenix>
Message-ID: <1306927835.4405.107.camel@localhost>

On Tue, 2011-05-31 at 21:20 +0800, Axel Lin wrote:
> Signed-off-by: Axel Lin <axel.lin at gmail.com>
> ---
>  drivers/mtd/onenand/omap2.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)

Pushed to l2-mtd-2.6.git, thank you.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 07:43:43 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 14:43:43 +0300
Subject: [PATCH 0/8] clean-up NAND / BBT code, flags
In-Reply-To: <1306884687-1824-1-git-send-email-computersforpeace@gmail.com>
References: <1306884687-1824-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1306928623.4405.108.camel@localhost>

On Tue, 2011-05-31 at 16:31 -0700, Brian Norris wrote:
> Hello,
> 
> This patch series handles several issues with NAND chip flags and BBT
> flags, especially those related to the nand_chip.options and
> nand_bbt_descr.options fields. This topic was discussed and reviewed a
> bit on the linux-mtd thread found here:
>     http://lists.infradead.org/pipermail/linux-mtd/2011-April/035146.html
> 
> These changes have affected many drivers in relatively small ways, so
> I copied all the maintainers/contributors given by the
> scripts/getmaintainer.pl scripts. FYI, this patch set is based on the
> mtd-2.6.git repository from linux-mtd.
> 
> Also, the first patch:
>     mtd: nand: remove NAND_BBT_SCANBYTE1AND6 option
> solves the regression issues discussed here:
>     http://lists.infradead.org/pipermail/linux-mtd/2011-May/035696.html

Looks good to me, thank you. Pushed to l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From sharon_burns72 at gmail.com  Wed Jun  1 07:50:12 2011
From: sharon_burns72 at gmail.com (Sharon.Burns)
Date: Wed, 01 Jun 2011 06:50:12 -0500
Subject: Hello Would You Like To Earn
Message-ID: <E1QRjwC-002r4a-PO@host113.kvchosting.com>

Hello linux-mtd

Would you like to earn an extra $200 everyday?, for just 45 minutes work? You could quit your job and make double the money at home working for yourself.

visit->http:tinyurl.com/3brnlpx

Regards,

Sharon Burns

Survey Human Resources Dept.




From dedekind1 at gmail.com  Wed Jun  1 07:56:15 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 14:56:15 +0300
Subject: U-Boot: using nand write to flash an ubi image, ubi part fails
In-Reply-To: <891190.21758.qm@web30201.mail.mud.yahoo.com>
References: <891190.21758.qm@web30201.mail.mud.yahoo.com>
Message-ID: <1306929375.4405.116.camel@localhost>

On Wed, 2011-06-01 at 00:57 -0700, Lars Michael wrote:
> Hello,
> 
> Using mkfs.ubifs and ubinize I have created an image with 5 volumes.
> In Linux I could flash it using "ubiformat /dev/mtd1 -f /root/ubi.img"
> and attach it using "ubiattach /dev/ubi_ctrl -m 1". It worked.

OK.

> In production I would prefer to write the image from U-Boot. So in
> U-Boot I used "nand erase" then "nand write" to flash the image. Then
> I want to attach by "ubi part" command - but this fails: "UBI error:
> ubi_init: UBI error: cannot initialize UBI, error -17"

Sorry, I'm not familiar with U-boot, so probably cc-ing U-boot mailing
list would be a good idea.

> Then I booted Linux (via nfs) and tried to re-format+attach, but now
> it fails. Format complains about eraseblock contents and missing erase
> counters: 
> 
> ubiformat: warning!: 1099 of 2036 eraseblocks contain non-ubifs data
> ubiformat: warning!: only 937 of 2036 eraseblocks have valid erase
> counter

OK, this means that many eraseblocks in the flash contain some data
which does not look like UBI headers.

> 
> The ubiattach now reports lots of:
> ...
> UBI error: check_corruption: PEB 0 contains corrupted VID header, and
> the data does not contain all 0xFF, this may be a non-UBI PEB or a
> severe VID header corruption which requires manual inspection
> 
> UBI warning: process_eb: valid VID header but corrupted EC header at
> PEB 4
> ...

OK.

> I realize that the U-Boot 'nand erase' does not preserve the erase
> counters. So what would be the correct way to erase and write in
> U-Boot?

I do not know, you need to ask U-boot-aware people. I've CCed some.

>  And why is the ubiformat not able to correct the problems?

It should be able to format any flash. Probably this is a bug. Can you
reproduce this with nandsim please? Just insmod nandsim on your PC (see
http://www.linux-mtd.infradead.org/faq/nand.html#L_nand_nandsim or
modinfo nandsim), write some garbage there or your image, and try to
format it.

If you can describe how I can reproduce this in my PC, I might look at
this. Or you can just debug ubiformat yourself.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From nicolas.ferre at atmel.com  Wed Jun  1 09:31:59 2011
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Wed, 01 Jun 2011 15:31:59 +0200
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <4DE63F4F.60108@atmel.com>

Le 29/05/2011 15:49, Dmitry Eremin-Solenikov :
> Currently atmel_nand driver used by AT91 and AVR32 calls a special callback
> which return nand partition table and number of partitions. However in all
> boards this callback returns just static data. So drop this callback and
> make atmel_nand use partition table provided statically via platform_data.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Good. So, for the AT91 part of it:

Acked-by: Nicolas Ferre <nicolas.ferre at atmel.com>

Best regards,

> ---
>  arch/arm/mach-at91/board-afeb-9260v1.c      |    9 ++-------
>  arch/arm/mach-at91/board-cam60.c            |    9 ++-------
>  arch/arm/mach-at91/board-cap9adk.c          |    9 ++-------
>  arch/arm/mach-at91/board-kb9202.c           |    9 ++-------
>  arch/arm/mach-at91/board-neocore926.c       |    9 ++-------
>  arch/arm/mach-at91/board-qil-a9260.c        |    9 ++-------
>  arch/arm/mach-at91/board-rm9200dk.c         |    9 ++-------
>  arch/arm/mach-at91/board-sam9-l9260.c       |    9 ++-------
>  arch/arm/mach-at91/board-sam9260ek.c        |    9 ++-------
>  arch/arm/mach-at91/board-sam9261ek.c        |    9 ++-------
>  arch/arm/mach-at91/board-sam9263ek.c        |    9 ++-------
>  arch/arm/mach-at91/board-sam9g20ek.c        |    9 ++-------
>  arch/arm/mach-at91/board-sam9m10g45ek.c     |    9 ++-------
>  arch/arm/mach-at91/board-sam9rlek.c         |    9 ++-------
>  arch/arm/mach-at91/board-snapper9260.c      |   10 ++--------
>  arch/arm/mach-at91/board-usb-a9260.c        |    9 ++-------
>  arch/arm/mach-at91/board-usb-a9263.c        |    9 ++-------
>  arch/arm/mach-at91/board-yl-9200.c          |    9 ++-------
>  arch/arm/mach-at91/include/mach/board.h     |    3 ++-
>  arch/avr32/boards/atngw100/setup.c          |    8 ++------
>  arch/avr32/boards/atstk1000/atstk1002.c     |    9 ++-------
>  arch/avr32/mach-at32ap/include/mach/board.h |    3 ++-
>  drivers/mtd/nand/atmel_nand.c               |    7 ++++---
>  23 files changed, 48 insertions(+), 145 deletions(-)
> 
> diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
> index a4924de..78c77fc 100644
> --- a/arch/arm/mach-at91/board-afeb-9260v1.c
> +++ b/arch/arm/mach-at91/board-afeb-9260v1.c
> @@ -136,19 +136,14 @@ static struct mtd_partition __initdata afeb9260_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(afeb9260_nand_partition);
> -	return afeb9260_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata afeb9260_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  	.rdy_pin	= AT91_PIN_PC13,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
>  	.bus_width_16	= 0,
> +	.parts		= afeb9260_nand_partition,
> +	.num_parts	= ARRAY_SIZE(afeb9260_nand_partition),
>  };
>  
>  
> diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
> index 148fccb..eefae5b 100644
> --- a/arch/arm/mach-at91/board-cam60.c
> +++ b/arch/arm/mach-at91/board-cam60.c
> @@ -138,19 +138,14 @@ static struct mtd_partition __initdata cam60_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(cam60_nand_partition);
> -	return cam60_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata cam60_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  	// .det_pin	= ... not there
>  	.rdy_pin	= AT91_PIN_PA9,
>  	.enable_pin	= AT91_PIN_PA7,
> -	.partition_info	= nand_partitions,
> +	.parts		= cam60_nand_partition,
> +	.num_parts	= ARRAY_SIZE(cam60_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata cam60_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-cap9adk.c b/arch/arm/mach-at91/board-cap9adk.c
> index 1904fdf..8aaa6e6 100644
> --- a/arch/arm/mach-at91/board-cap9adk.c
> +++ b/arch/arm/mach-at91/board-cap9adk.c
> @@ -175,19 +175,14 @@ static struct mtd_partition __initdata cap9adk_nand_partitions[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(cap9adk_nand_partitions);
> -	return cap9adk_nand_partitions;
> -}
> -
>  static struct atmel_nand_data __initdata cap9adk_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  //	.rdy_pin	= ... not connected
>  	.enable_pin	= AT91_PIN_PD15,
> -	.partition_info	= nand_partitions,
> +	.parts		= cap9adk_nand_partitions,
> +	.num_parts	= ARRAY_SIZE(cap9adk_nand_partitions),
>  };
>  
>  static struct sam9_smc_config __initdata cap9adk_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
> index a813a74..0cac9d3 100644
> --- a/arch/arm/mach-at91/board-kb9202.c
> +++ b/arch/arm/mach-at91/board-kb9202.c
> @@ -102,19 +102,14 @@ static struct mtd_partition __initdata kb9202_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(kb9202_nand_partition);
> -	return kb9202_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata kb9202_nand_data = {
>  	.ale		= 22,
>  	.cle		= 21,
>  	// .det_pin	= ... not there
>  	.rdy_pin	= AT91_PIN_PC29,
>  	.enable_pin	= AT91_PIN_PC28,
> -	.partition_info	= nand_partitions,
> +	.parts		= kb9202_nand_partition,
> +	.num_parts	= ARRAY_SIZE(kb9202_nand_partition),
>  };
>  
>  static void __init kb9202_board_init(void)
> diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
> index 961e805..a63a4c9 100644
> --- a/arch/arm/mach-at91/board-neocore926.c
> +++ b/arch/arm/mach-at91/board-neocore926.c
> @@ -188,19 +188,14 @@ static struct mtd_partition __initdata neocore926_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(neocore926_nand_partition);
> -	return neocore926_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata neocore926_nand_data = {
>  	.ale			= 21,
>  	.cle			= 22,
>  	.rdy_pin		= AT91_PIN_PB19,
>  	.rdy_pin_active_low	= 1,
>  	.enable_pin		= AT91_PIN_PD15,
> -	.partition_info		= nand_partitions,
> +	.parts			= neocore926_nand_partition,
> +	.num_parts		= ARRAY_SIZE(neocore926_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata neocore926_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
> index d1a6001..86c163f 100644
> --- a/arch/arm/mach-at91/board-qil-a9260.c
> +++ b/arch/arm/mach-at91/board-qil-a9260.c
> @@ -136,19 +136,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PC13,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
> index aef9627..7c9af30 100644
> --- a/arch/arm/mach-at91/board-rm9200dk.c
> +++ b/arch/arm/mach-at91/board-rm9200dk.c
> @@ -143,19 +143,14 @@ static struct mtd_partition __initdata dk_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(dk_nand_partition);
> -	return dk_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata dk_nand_data = {
>  	.ale		= 22,
>  	.cle		= 21,
>  	.det_pin	= AT91_PIN_PB1,
>  	.rdy_pin	= AT91_PIN_PC2,
>  	// .enable_pin	= ... not there
> -	.partition_info	= nand_partitions,
> +	.parts		= dk_nand_partition,
> +	.num_parts	= ARRAY_SIZE(dk_nand_partition),
>  };
>  
>  #define DK_FLASH_BASE	AT91_CHIPSELECT_0
> diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
> index aaf1bf0..3646c2b 100644
> --- a/arch/arm/mach-at91/board-sam9-l9260.c
> +++ b/arch/arm/mach-at91/board-sam9-l9260.c
> @@ -137,19 +137,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PC13,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
> index d600dc1..d6d9b21 100644
> --- a/arch/arm/mach-at91/board-sam9260ek.c
> +++ b/arch/arm/mach-at91/board-sam9260ek.c
> @@ -179,19 +179,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PC13,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
> index f897f84..b4a3e18 100644
> --- a/arch/arm/mach-at91/board-sam9261ek.c
> +++ b/arch/arm/mach-at91/board-sam9261ek.c
> @@ -185,19 +185,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 22,
>  	.cle		= 21,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PC15,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
> index 605b26f..4e6d586 100644
> --- a/arch/arm/mach-at91/board-sam9263ek.c
> +++ b/arch/arm/mach-at91/board-sam9263ek.c
> @@ -186,19 +186,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PA22,
>  	.enable_pin	= AT91_PIN_PD15,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
> index 7624cf0..b0488b1 100644
> --- a/arch/arm/mach-at91/board-sam9g20ek.c
> +++ b/arch/arm/mach-at91/board-sam9g20ek.c
> @@ -163,19 +163,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  /* det_pin is not connected */
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  	.rdy_pin	= AT91_PIN_PC13,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
> index 063c95d..0bb3468 100644
> --- a/arch/arm/mach-at91/board-sam9m10g45ek.c
> +++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
> @@ -143,19 +143,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  /* det_pin is not connected */
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  	.rdy_pin	= AT91_PIN_PC8,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
> index effb399..7aee8ab 100644
> --- a/arch/arm/mach-at91/board-sam9rlek.c
> +++ b/arch/arm/mach-at91/board-sam9rlek.c
> @@ -94,19 +94,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PD17,
>  	.enable_pin	= AT91_PIN_PB6,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
> index 3eb0a11..a481451 100644
> --- a/arch/arm/mach-at91/board-snapper9260.c
> +++ b/arch/arm/mach-at91/board-snapper9260.c
> @@ -102,18 +102,12 @@ static struct mtd_partition __initdata snapper9260_nand_partitions[] = {
>  	},
>  };
>  
> -static struct mtd_partition * __init
> -snapper9260_nand_partition_info(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(snapper9260_nand_partitions);
> -	return snapper9260_nand_partitions;
> -}
> -
>  static struct atmel_nand_data __initdata snapper9260_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  	.rdy_pin	= AT91_PIN_PC13,
> -	.partition_info	= snapper9260_nand_partition_info,
> +	.parts		= snapper9260_nand_partitions,
> +	.num_parts	= ARRAY_SIZE(snapper9260_nand_partitions),
>  	.bus_width_16	= 0,
>  };
>  
> diff --git a/arch/arm/mach-at91/board-usb-a9260.c b/arch/arm/mach-at91/board-usb-a9260.c
> index 0e784e6..43f40ef 100644
> --- a/arch/arm/mach-at91/board-usb-a9260.c
> +++ b/arch/arm/mach-at91/board-usb-a9260.c
> @@ -110,19 +110,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	}
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PC13,
>  	.enable_pin	= AT91_PIN_PC14,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-usb-a9263.c b/arch/arm/mach-at91/board-usb-a9263.c
> index cf626dd..288d764 100644
> --- a/arch/arm/mach-at91/board-usb-a9263.c
> +++ b/arch/arm/mach-at91/board-usb-a9263.c
> @@ -123,19 +123,14 @@ static struct mtd_partition __initdata ek_nand_partition[] = {
>  	}
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(ek_nand_partition);
> -	return ek_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata ek_nand_data = {
>  	.ale		= 21,
>  	.cle		= 22,
>  //	.det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PA22,
>  	.enable_pin	= AT91_PIN_PD15,
> -	.partition_info	= nand_partitions,
> +	.parts		= ek_nand_partition,
> +	.num_parts	= ARRAY_SIZE(ek_nand_partition),
>  };
>  
>  static struct sam9_smc_config __initdata ek_nand_smc_config = {
> diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
> index c208cc3..9ebc1ed 100644
> --- a/arch/arm/mach-at91/board-yl-9200.c
> +++ b/arch/arm/mach-at91/board-yl-9200.c
> @@ -178,19 +178,14 @@ static struct mtd_partition __initdata yl9200_nand_partition[] = {
>  	}
>  };
>  
> -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(yl9200_nand_partition);
> -	return yl9200_nand_partition;
> -}
> -
>  static struct atmel_nand_data __initdata yl9200_nand_data = {
>  	.ale		= 6,
>  	.cle		= 7,
>  	// .det_pin	= ... not connected
>  	.rdy_pin	= AT91_PIN_PC14,	/* R/!B (Sheet10) */
>  	.enable_pin	= AT91_PIN_PC15,	/* !CE  (Sheet10) */
> -	.partition_info	= nand_partitions,
> +	.parts		= yl9200_nand_partition,
> +	.num_parts	= ARRAY_SIZE(yl9200_nand_partition),
>  };
>  
>  /*
> diff --git a/arch/arm/mach-at91/include/mach/board.h b/arch/arm/mach-at91/include/mach/board.h
> index ed544a0..6643531 100644
> --- a/arch/arm/mach-at91/include/mach/board.h
> +++ b/arch/arm/mach-at91/include/mach/board.h
> @@ -112,7 +112,8 @@ struct atmel_nand_data {
>  	u8		ale;		/* address line number connected to ALE */
>  	u8		cle;		/* address line number connected to CLE */
>  	u8		bus_width_16;	/* buswidth is 16 bit */
> -	struct mtd_partition* (*partition_info)(int, int*);
> +	struct mtd_partition *parts;
> +	unsigned int	num_parts;
>  };
>  extern void __init at91_add_device_nand(struct atmel_nand_data *data);
>  
> diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c
> index fafed4c..1f17bde 100644
> --- a/arch/avr32/boards/atngw100/setup.c
> +++ b/arch/avr32/boards/atngw100/setup.c
> @@ -90,11 +90,6 @@ static struct mtd_partition nand_partitions[] = {
>  	},
>  };
>  
> -static struct mtd_partition *nand_part_info(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(nand_partitions);
> -	return nand_partitions;
> -}
>  
>  static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
>  	.cle		= 21,
> @@ -102,7 +97,8 @@ static struct atmel_nand_data atngw100mkii_nand_data __initdata = {
>  	.rdy_pin	= GPIO_PIN_PB(28),
>  	.enable_pin	= GPIO_PIN_PE(23),
>  	.bus_width_16	= true,
> -	.partition_info	= nand_part_info,
> +	.parts		= nand_partitions,
> +	.num_parts	= ARRAY_SIZE(nand_partitions),
>  };
>  #endif
>  
> diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c
> index 6ce30fb..4643ff5 100644
> --- a/arch/avr32/boards/atstk1000/atstk1002.c
> +++ b/arch/avr32/boards/atstk1000/atstk1002.c
> @@ -90,18 +90,13 @@ static struct mtd_partition nand_partitions[] = {
>  	},
>  };
>  
> -static struct mtd_partition *nand_part_info(int size, int *num_partitions)
> -{
> -	*num_partitions = ARRAY_SIZE(nand_partitions);
> -	return nand_partitions;
> -}
> -
>  static struct atmel_nand_data atstk1006_nand_data __initdata = {
>  	.cle		= 21,
>  	.ale		= 22,
>  	.rdy_pin	= GPIO_PIN_PB(30),
>  	.enable_pin	= GPIO_PIN_PB(29),
> -	.partition_info	= nand_part_info,
> +	.parts		= nand_partitions,
> +	.num_parts	= ARRAY_SIZE(num_partitions),
>  };
>  #endif
>  
> diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h
> index 679458d..5d7ffca 100644
> --- a/arch/avr32/mach-at32ap/include/mach/board.h
> +++ b/arch/avr32/mach-at32ap/include/mach/board.h
> @@ -128,7 +128,8 @@ struct atmel_nand_data {
>  	u8	ale;		/* address line number connected to ALE */
>  	u8	cle;		/* address line number connected to CLE */
>  	u8	bus_width_16;	/* buswidth is 16 bit */
> -	struct mtd_partition *(*partition_info)(int size, int *num_partitions);
> +	struct mtd_partition *parts;
> +	unsigned int	num_parts;
>  };
>  struct platform_device *
>  at32_add_device_nand(unsigned int id, struct atmel_nand_data *data);
> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
> index b300705..10605ed 100644
> --- a/drivers/mtd/nand/atmel_nand.c
> +++ b/drivers/mtd/nand/atmel_nand.c
> @@ -659,9 +659,10 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
>  	num_partitions = parse_mtd_partitions(mtd, part_probes,
>  					      &partitions, 0);
>  #endif
> -	if (num_partitions <= 0 && host->board->partition_info)
> -		partitions = host->board->partition_info(mtd->size,
> -							 &num_partitions);
> +	if (num_partitions <= 0 && host->board->parts) {
> +		partitions = host->board->parts;
> +		num_partitions = host->board->num_parts;
> +	}
>  
>  	if ((!partitions) || (num_partitions == 0)) {
>  		printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");


-- 
Nicolas Ferre



From hans-christian.egtvedt at atmel.com  Wed Jun  1 09:32:09 2011
From: hans-christian.egtvedt at atmel.com (Hans-Christian Egtvedt)
Date: Wed, 01 Jun 2011 15:32:09 +0200
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>

On Sun, 2011-05-29 at 17:49 +0400, Dmitry Eremin-Solenikov wrote:
> Currently atmel_nand driver used by AT91 and AVR32 calls a special callback
> which return nand partition table and number of partitions. However in all
> boards this callback returns just static data. So drop this callback and
> make atmel_nand use partition table provided statically via platform_data.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Thanks for this update, always nice seeing code being optimized. I
really can't recall why it was made like this in the first place...

For the AVR32 related parts:

Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>

<snipp diff>

Will this go through the linux-mtd tree (since it spans two archs) or
should it go through an arch tree?

-- 
Hans-Christian Egtvedt



From bengardiner at nanometrics.ca  Wed Jun  1 09:41:19 2011
From: bengardiner at nanometrics.ca (Ben Gardiner)
Date: Wed, 1 Jun 2011 09:41:19 -0400
Subject: U-Boot: using nand write to flash an ubi image, ubi part fails
In-Reply-To: <1306929375.4405.116.camel@localhost>
References: <891190.21758.qm@web30201.mail.mud.yahoo.com>
	<1306929375.4405.116.camel@localhost>
Message-ID: <BANLkTimKSzpAqZ2e7TFgFwp3Cx=v==wq-Q@mail.gmail.com>

Hi Lars

On Wed, Jun 1, 2011 at 3:57 AM, Lars Michael <lh_post at yahoo.com> wrote:
> Hello,
>
> Using mkfs.ubifs and ubinize I have created an image with 5 volumes. In Linux I could flash it using "ubiformat /dev/mtd1 -f /root/ubi.img" and attach it using "ubiattach /dev/ubi_ctrl -m 1". It worked.
>
> In production I would prefer to write the image from U-Boot. So in U-Boot I used "nand erase" then "nand write" to flash the image. Then I want to attach by "ubi part" command - but this fails: "UBI error: ubi_init: UBI error: cannot initialize UBI, error -17"
> [...]
> I realize that the U-Boot 'nand erase' does not preserve the erase counters. So what would be the correct way to erase and write in U-Boot? And why is the ubiformat not able to correct the problems?

It's true that the ECs are not preserved. But it's also true that
trailing pages of 0xff are not trimmed either. You definitely need to
drop trailing 0xff pages when writing ubinized images containing UBIFS
volumes. To do this you can use either the new 'nand write' variant,
.trimffs [1] which is currently patches that have been Acked. Or you
can use the free-space-fixup feature which is available in the
ubifs-2.6 tree and requires that you use a mkfs.ubifs built from the
the mtd-utils tree.

I've never seen the particular error "ubi_init: UBI error: cannot
initialize UBI, error -17" when I have erroneously written a ubinized
image with nand write. But maybe that is due to the paritculars of my
platform drivers or it may be due to the version of u-boot you are
running there -- see below.

I reccomend giving both the 'nand write.trimffs' patches and the
free-space-fixup feature a try (indivually) and reporting back with
your success. After you update u-boot, see below:

> My kernel is 2.6.29 patched with 165 patched from the ubi back port tree.
> U-Boot is 2009.08 with ubifs support, but I am not sure if there are relevant patches. The CPU is a v4 ColdFire and 256MB Micron NAND.

2009.08 is maybe too old. There have been several fixes to both ubi
and ubis in u-boot since then:

$git log --oneline v2009.08..u-boot/master  -- fs/ubifs/ drivers/mtd/ubi/
c7b7d45 UBIFS: Fix dereferencing type-punned pointer compiler warning
64b6817 ubifs.c: BUG: Error following links
b1a14f8 UBIFS: Change ubifsload to not read beyond the requested size
cb9c09d UBIFS: Add ubifsumount command to unmount an active volume
6d8962e Switch from archive libraries to partial linking
2e5167c Replace CONFIG_RELOC_FIXUP_WORKS by CONFIG_NEEDS_MANUAL_RELOC
86af10c Fix "ubi part" cmd re-entrancy
ceeba00 UBI: initialise update marker
1b1f9a9 UBI: Ensure that "background thread" operations are really executed
6865168 ubifsmount fails due to not initialized list
87d93a1 move prototypes for gunzip() and zunzip() to common.h
4b142fe common: delete CONFIG_SYS_64BIT_VSPRINTF and CONFIG_SYS_64BIT_STRTOUL
521af04 Conditionally perform common relocation fixups
ef37c68 ubifs: Correct dereferencing of files-after-symlinks
9d7952e ubifs: Add support for looking up directory and relative symlinks
02f9990 Move __set/clear_bit from ubifs.h to bitops.h


Best Regards,
Ben Gardiner

---
Nanometrics Inc.
http://www.nanometrics.ca


From bengardiner at nanometrics.ca  Wed Jun  1 09:49:36 2011
From: bengardiner at nanometrics.ca (Ben Gardiner)
Date: Wed,  1 Jun 2011 09:49:36 -0400
Subject: [PATCH] mkfs.ubifs: trivial: 2.6.40 -> 3.0
Message-ID: <1306936176-24533-1-git-send-email-bengardiner@nanometrics.ca>

In commit 04665066ebedb0a31335b525fb5f19df32cb8cfe it was noted that the free
space fixup feature would be available in kernels 2.6.40 or greater. Since
then it has been decided that the release following 2.6.39 will be 3.0.

Replace the instances of 2.6.40 with 3.0.

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
---
 mkfs.ubifs/mkfs.ubifs.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index e3ccb32..ac3c8d3 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -185,7 +185,7 @@ static const char *helptext =
 "                         mkfs.ubifs use zlib instead of LZO (default 20%)\n"
 "-f, --fanout=NUM         fanout NUM (default: 8)\n"
 "-F, --space-fixup        file-system free space has to be fixed up on first mount\n"
-"                         (requires kernel version 2.6.40 or greater)\n"
+"                         (requires kernel version 3.0 or greater)\n"
 "-k, --keyhash=TYPE       key hash type - \"r5\" or \"test\" (default: \"r5\")\n"
 "-p, --orph-lebs=COUNT    count of erase blocks for orphans (default: 1)\n"
 "-D, --devtable=FILE      use device table FILE\n"
@@ -233,7 +233,7 @@ static const char *helptext =
 "when flashing the image and the second time when UBIFS is mounted and writes useful\n"
 "data there. A proper UBI-aware flasher should skip such NAND pages, though. Note, this\n"
 "flag may make the first mount very slow, because the \"free space fixup\" procedure\n"
-"takes time. This feature is supported by the Linux kernel starting from version 2.6.40.\n";
+"takes time. This feature is supported by the Linux kernel starting from version 3.0.\n";
 
 /**
  * make_path - make a path name from a directory and a name.
-- 
1.7.4.1



From bengardiner at nanometrics.ca  Wed Jun  1 09:52:22 2011
From: bengardiner at nanometrics.ca (Ben Gardiner)
Date: Wed, 1 Jun 2011 09:52:22 -0400
Subject: -EBADMSG with free-space-fixup flag
In-Reply-To: <1306914894.4405.56.camel@localhost>
References: <BANLkTimWafVH_bCJomN1uFW=t4+jRw1L9g@mail.gmail.com>
	<1306914894.4405.56.camel@localhost>
Message-ID: <BANLkTikv7hTLqjyMhe17KEwXForx4S7t4Q@mail.gmail.com>

Hi Artem,

On Wed, Jun 1, 2011 at 3:54 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> NB: I have ubi attached with --vid-hdr-offset of 2048 because of the
>> subpage writing limitations of davinci-nand.
>
> Which means your driver may be incorrect - it should report that it does
> not support sub-pages - does it do this? Then UBI will not even try to
> use sub-pages and you won't need that option.

Right. This is a known issue with davinci_nand driver; the last time I
investigated this there was only a way for the NAND chip to report
support for subpages and no way for the driver to do so analogously.

Best Regards,
Ben Gardiner

---
Nanometrics Inc.
http://www.nanometrics.ca


From jiri.pinkava at vscht.cz  Wed Jun  1 09:56:40 2011
From: jiri.pinkava at vscht.cz (jiri.pinkava at vscht.cz)
Date: Wed, 1 Jun 2011 15:56:40 +0200
Subject: [PATCH] nand: Remove meaningless delay from nand_unlock
Message-ID: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>

From: Jiri Pinkava <jiri.pinkava at vscht.cz>

This delay is meaningless. If delay is needed it is device specific
and must be reimplemented by specific driver, otherwise no delay is
needed.

This function is not used by any current kernel code, affects only
external code (like main).

Signed-off-by: Jiri Pinkava <jiri.pinkava at vscht.cz>
---
 drivers/mtd/nand/nand_base.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a46e9bb..290a1db 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -919,7 +919,6 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 
 	/* Call wait ready function */
 	status = chip->waitfunc(mtd, chip);
-	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
@@ -1028,7 +1027,6 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 	/* Call wait ready function */
 	status = chip->waitfunc(mtd, chip);
-	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
 		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
-- 
1.7.5.2



From bengardiner at nanometrics.ca  Wed Jun  1 10:53:28 2011
From: bengardiner at nanometrics.ca (Ben Gardiner)
Date: Wed,  1 Jun 2011 10:53:28 -0400
Subject: [PATCH] UBIFS: fixup merged 'UBIFS: fix-up free space earlier'
In-Reply-To: <1306923407.4405.94.camel@localhost>
References: <1306923407.4405.94.camel@localhost>
Message-ID: <1306940008-28454-1-git-send-email-bengardiner@nanometrics.ca>

When the patch 'UBIFS: intialize LPT earlier' was massaged before being applied
the context of the next patch 'UBIFS: fix-up free space earlier' was muddled
sufficiently for the order of allocate-lpt then free-space-fixup was reversed --
I think.

Put the free-space-fixup after allocate-lpt.

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>

---
With this fixup applied on-top-of the ubifs-2.6 master I am able to mount a
ubinized image containing a UBIFS volume which has the free-space-fixup flag
set. No assertions are displayed.

---
 fs/ubifs/super.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 4722f31..70e8c92 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1284,12 +1284,6 @@ static int mount_ubifs(struct ubifs_info *c)
 
 	init_constants_master(c);
 
-	if (!c->ro_mount && c->space_fixup) {
-		err = ubifs_fixup_free_space(c);
-		if (err)
-			goto out_infos;
-	}
-
 	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
 		ubifs_msg("recovery needed");
 		c->need_recovery = 1;
@@ -1305,6 +1299,12 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		goto out_master;
 
+	if (!c->ro_mount && c->space_fixup) {
+		err = ubifs_fixup_free_space(c);
+		if (err)
+			goto out_master;
+	}
+
 	if (!c->ro_mount) {
 		/*
 		 * Set the "dirty" flag so that if we reboot uncleanly we
-- 
1.7.4.1



From dbaryshkov at gmail.com  Wed Jun  1 10:54:30 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 1 Jun 2011 18:54:30 +0400
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
	<1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>
Message-ID: <BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>

On 6/1/11, Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com> wrote:
> On Sun, 2011-05-29 at 17:49 +0400, Dmitry Eremin-Solenikov wrote:
>> Currently atmel_nand driver used by AT91 and AVR32 calls a special
>> callback
>> which return nand partition table and number of partitions. However in all
>> boards this callback returns just static data. So drop this callback and
>> make atmel_nand use partition table provided statically via platform_data.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>
> Thanks for this update, always nice seeing code being optimized. I
> really can't recall why it was made like this in the first place...
>
> For the AVR32 related parts:
>
> Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>
>
> <snipp diff>
>
> Will this go through the linux-mtd tree (since it spans two archs) or
> should it go through an arch tree?

On one hand, I'd prefer for this to go through the linux-mtd, if noone objects,
as I'd also like to submit several (a pile) patches cleaning up mtd
partitioning, which would depend on this.

OTOH, I think there will be a cleanup of AT91 platform, which would bring
lot's of conflicts with this patch, if it goes through linux-mtd.

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Wed Jun  1 11:01:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 18:01:49 +0300
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
	<1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>
	<BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
Message-ID: <1306940509.4405.121.camel@localhost>

On Wed, 2011-06-01 at 18:54 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/1/11, Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com> wrote:
> > On Sun, 2011-05-29 at 17:49 +0400, Dmitry Eremin-Solenikov wrote:
> >> Currently atmel_nand driver used by AT91 and AVR32 calls a special
> >> callback
> >> which return nand partition table and number of partitions. However in all
> >> boards this callback returns just static data. So drop this callback and
> >> make atmel_nand use partition table provided statically via platform_data.
> >>
> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >
> > Thanks for this update, always nice seeing code being optimized. I
> > really can't recall why it was made like this in the first place...
> >
> > For the AVR32 related parts:
> >
> > Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>
> >
> > <snipp diff>
> >
> > Will this go through the linux-mtd tree (since it spans two archs) or
> > should it go through an arch tree?
> 
> On one hand, I'd prefer for this to go through the linux-mtd, if noone objects,
> as I'd also like to submit several (a pile) patches cleaning up mtd
> partitioning, which would depend on this.
> 
> OTOH, I think there will be a cleanup of AT91 platform, which would bring
> lot's of conflicts with this patch, if it goes through linux-mtd.

Meanwhile, while you are thinking, I've put this patch to the l2-mtd-2.6
tree. Please, let me know if you decide to take a non-mtd path - then
I'll drop it.

And if you want to see this in linux-next - ping dwmw2.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 11:03:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 18:03:51 +0300
Subject: [PATCH] UBIFS: fixup merged 'UBIFS: fix-up free space earlier'
In-Reply-To: <1306940008-28454-1-git-send-email-bengardiner@nanometrics.ca>
References: <1306923407.4405.94.camel@localhost>
	<1306940008-28454-1-git-send-email-bengardiner@nanometrics.ca>
Message-ID: <1306940631.4405.122.camel@localhost>

On Wed, 2011-06-01 at 10:53 -0400, Ben Gardiner wrote:
> When the patch 'UBIFS: intialize LPT earlier' was massaged before being applied
> the context of the next patch 'UBIFS: fix-up free space earlier' was muddled
> sufficiently for the order of allocate-lpt then free-space-fixup was reversed --
> I think.
> 
> Put the free-space-fixup after allocate-lpt.
> 
> Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>

I'll take a look at this and fold this change in a bit later, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  1 11:14:16 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 01 Jun 2011 18:14:16 +0300
Subject: [PATCH] UBIFS: fixup merged 'UBIFS: fix-up free space earlier'
In-Reply-To: <1306940008-28454-1-git-send-email-bengardiner@nanometrics.ca>
References: <1306923407.4405.94.camel@localhost>
	<1306940008-28454-1-git-send-email-bengardiner@nanometrics.ca>
Message-ID: <1306941256.4405.123.camel@localhost>

On Wed, 2011-06-01 at 10:53 -0400, Ben Gardiner wrote:
> When the patch 'UBIFS: intialize LPT earlier' was massaged before being applied
> the context of the next patch 'UBIFS: fix-up free space earlier' was muddled
> sufficiently for the order of allocate-lpt then free-space-fixup was reversed --
> I think.
> 
> Put the free-space-fixup after allocate-lpt.
> 
> Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
> 
> ---
> With this fixup applied on-top-of the ubifs-2.6 master I am able to mount a
> ubinized image containing a UBIFS volume which has the free-space-fixup flag
> set. No assertions are displayed.

Thanks. Merged this patch to the 3rd one and pushed out.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From bengardiner at nanometrics.ca  Wed Jun  1 11:28:41 2011
From: bengardiner at nanometrics.ca (Ben Gardiner)
Date: Wed, 1 Jun 2011 11:28:41 -0400
Subject: [PATCH] UBIFS: fixup merged 'UBIFS: fix-up free space earlier'
In-Reply-To: <1306941256.4405.123.camel@localhost>
References: <1306923407.4405.94.camel@localhost>
	<1306940008-28454-1-git-send-email-bengardiner@nanometrics.ca>
	<1306941256.4405.123.camel@localhost>
Message-ID: <BANLkTimzuZ5URhDj2BxPj3g_YaHmZufWsg@mail.gmail.com>

Hi Artem,

On Wed, Jun 1, 2011 at 11:14 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-01 at 10:53 -0400, Ben Gardiner wrote:
>> When the patch 'UBIFS: intialize LPT earlier' was massaged before being applied
>> the context of the next patch 'UBIFS: fix-up free space earlier' was muddled
>> sufficiently for the order of allocate-lpt then free-space-fixup was reversed --
>> I think.
>>
>> Put the free-space-fixup after allocate-lpt.
>>
>> Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
>>
>> ---
>> With this fixup applied on-top-of the ubifs-2.6 master I am able to mount a
>> ubinized image containing a UBIFS volume which has the free-space-fixup flag
>> set. No assertions are displayed.
>
> Thanks. Merged this patch to the 3rd one and pushed out.

You're most welcome.

Both branches master and linux-next are working as expected.

Best Regards,
Ben Gardiner

---
Nanometrics Inc.
http://www.nanometrics.ca


From sshtylyov at mvista.com  Wed Jun  1 12:28:59 2011
From: sshtylyov at mvista.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2011 20:28:59 +0400
Subject: [PATCH v6 1/8] MTD: Add integrator-flash feature to physmap
In-Reply-To: <1306914546.27474.349.camel@e102391-lin.cambridge.arm.com>
References: <1305637877-24436-1-git-send-email-marc.zyngier@arm.com>	
	<1305637877-24436-2-git-send-email-marc.zyngier@arm.com>	
	<4DE53D52.4040508@ru.mvista.com>	
	<20110531224428.6636e283@taxman.wild-wind.fr.eu.org>	
	<BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
	<1306914546.27474.349.camel@e102391-lin.cambridge.arm.com>
Message-ID: <4DE668CB.9040408@ru.mvista.com>

Marc Zyngier wrote:

>>>>> In the process of moving platforms away from integrator-flash
>>>>> (aka armflash), add to physmap the few features that make
>>>>> armflash unique:
>>>>> - optionnal probing for the AFS partition type
>>>>> - init() and exit() methods, used by Integrator to control
>>>>>   write access to the various onboard programmable components
>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>>> Acked-by: Catalin Marinas <catalin.marinas at arm.com>
>>>>> Cc: David Woodhouse <dwmw2 at infradead.org>
>>>> [...]

>>>>> diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
>>>>> index bcfd9f7..d37cca0 100644
>>>>> --- a/include/linux/mtd/physmap.h
>>>>> +++ b/include/linux/mtd/physmap.h
>>>>> @@ -22,6 +22,8 @@ struct map_info;
>>>>>
>>>>>  struct physmap_flash_data {
>>>>>     unsigned int            width;
>>>>> +   int                     (*init)(struct platform_device *);
>>>>> +   void                    (*exit)(struct platform_device *);

>>>>     How about a declaration for 'struct platform_device' beforehand? This breaks
>>>> build on other platforms at least...

>>> Sure. Please send a patch.

>> uhh, what ?  you broke things, so you fix them.  i already pointed out
>> this breakage to you over a week ago.

> Mike,

> Sorry I missed your earlier comment about this. My bad.

> Now, about my reply to Sergei:
>       * Sergei identified the problem, and proposed a valid fix. It's
>         only fair he gets credited for his work (yes, you did it before
>         he did, but I didn't know it). The SOB on a patch is the proper
>         way of managing the attribution.
>       * Posting a patch is the quickest way for the maintainer (in this
>         case David) to be able to push a fix to mainline.
>       * It also helps other folks reading the ML and facing the same
>         issue. They can grab the patch, apply it locally and go on with
>         their own stuff until the patch is merged.
>       * The person reporting the problem probably has a configuration
>         showing the problem. If any of my platforms had shown that
>         error, I would have fixed it long before it hit the mailing
>         list.

    Actually, I'm not a primary reporter. The issue came up on the #mipslinux 
IRC channel, I then just remembered that I saw the patch set touching this file, 
and it was easy enough to complain to you after finding the corresponding mails.
    This happens to break MIPS platforms because they use warnings-as-errors 
option of gcc.

WBR, Sergei


From sshtylyov at mvista.com  Wed Jun  1 12:32:23 2011
From: sshtylyov at mvista.com (Sergei Shtylyov)
Date: Wed, 01 Jun 2011 20:32:23 +0400
Subject: [PATCH v6 1/8] MTD: Add integrator-flash feature to physmap
In-Reply-To: <1306914166.4405.47.camel@localhost>
References: <1305637877-24436-1-git-send-email-marc.zyngier@arm.com>	
	<1305637877-24436-2-git-send-email-marc.zyngier@arm.com>	
	<4DE53D52.4040508@ru.mvista.com>	
	<20110531224428.6636e283@taxman.wild-wind.fr.eu.org>	
	<BANLkTim0xrx+33BeoSbXbQcu2Ab6Oin=Wg@mail.gmail.com>
	<1306914166.4405.47.camel@localhost>
Message-ID: <4DE66997.1060808@ru.mvista.com>

Hello.

Artem Bityutskiy wrote:

>>>>> In the process of moving platforms away from integrator-flash
>>>>> (aka armflash), add to physmap the few features that make
>>>>> armflash unique:
>>>>> - optionnal probing for the AFS partition type
>>>>> - init() and exit() methods, used by Integrator to control
>>>>>   write access to the various onboard programmable components
>>>>> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>>>> Acked-by: Catalin Marinas <catalin.marinas at arm.com>
>>>>> Cc: David Woodhouse <dwmw2 at infradead.org>
>>>> [...]

>>>>> diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
>>>>> index bcfd9f7..d37cca0 100644
>>>>> --- a/include/linux/mtd/physmap.h
>>>>> +++ b/include/linux/mtd/physmap.h
>>>>> @@ -22,6 +22,8 @@ struct map_info;
>>>>>
>>>>>  struct physmap_flash_data {
>>>>>     unsigned int            width;
>>>>> +   int                     (*init)(struct platform_device *);
>>>>> +   void                    (*exit)(struct platform_device *);
>>>>     How about a declaration for 'struct platform_device' beforehand? This breaks
>>>> build on other platforms at least...

>>> Sure. Please send a patch.

>> uhh, what ?  you broke things, so you fix them.  i already pointed out
>> this breakage to you over a week ago.
>> -mike

> The change went in via Russell's tree, I sent him a fix. It looks like
> he did not merge it.

    Russell doesn't merge patches sent to him AFAIK, they need to be put into 
his patch system first.

WBR, Sergei



From Woodrow.Douglass at QinetiQ-NA.com  Wed Jun  1 13:52:16 2011
From: Woodrow.Douglass at QinetiQ-NA.com (Douglass, Woody)
Date: Wed, 1 Jun 2011 13:52:16 -0400
Subject: ubi image only mounts once
Message-ID: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>

To whom it may concern;

I am trying to build a linux image to run on a custom omap3530 board. I
have reached a point where my build system builds a UBI image that can
be mounted exactly once; subsequent mounts fail. Here is the related
dmesg output:

When it works:

[  131.461883] omap2-nand driver initializing
[  131.466796] OMAP NAND: use WAIT0 as R/B# pin
[  131.504669] NAND device: Manufacturer ID: 0xad, Chip ID: 0xba (Hynix
NAND 256MiB 1,8V 16-bit)
[  131.524658] omap_ident_nand_chip:1352 ad ba
[  131.528869] Creating 5 MTD partitions on "omap2-nand":
[  131.534057] 0x000000000000-0x000000080000 : "X-Loader"
[  131.544036] 0x000000080000-0x000000260000 : "U-Boot"
[  131.552947] 0x000000260000-0x000000280000 : "U-Boot Env"
[  131.561065] 0x000000280000-0x000000680000 : "Kernel"
[  131.570281] 0x000000680000-0x000010000000 : "File System"
[  131.668182] OneNAND driver initializing
[  131.677215] UBI: attaching mtd4 to ubi0
[  131.681091] UBI: physical eraseblock size:   131072 bytes (128 KiB)
[  131.687744] UBI: logical eraseblock size:    129024 bytes
[  131.693176] UBI: smallest flash I/O unit:    2048
[  131.697998] UBI: sub-page size:              512
[  131.702636] UBI: VID header offset:          512 (aligned 512)
[  131.708923] UBI: data offset:                2048
[  132.483612] UBI: volume 0 ("rootfs") re-sized from 1041 to 1970 LEBs
[  132.495361] UBI: attached mtd4 to ubi0
[  132.499145] UBI: MTD device name:            "File System"
[  132.504852] UBI: MTD device size:            249 MiB
[  132.509857] UBI: number of good PEBs:        1993
[  132.514678] UBI: number of bad PEBs:         3
[  132.519165] UBI: max. allowed volumes:       128
[  132.523803] UBI: wear-leveling threshold:    4096
[  132.528594] UBI: number of internal volumes: 1
[  132.533081] UBI: number of user volumes:     1
[  132.537628] UBI: available PEBs:             0
[  132.542114] UBI: total number of reserved PEBs: 1993
[  132.547180] UBI: number of PEBs reserved for bad PEB handling: 19
[  132.553314] UBI: max/mean erase counter: 4/2
[  132.557678] UBI: image sequence number: 859895637
[  132.563018] UBI: background thread "ubi_bgt0d" started, PID 425

When it doesn't:

[  196.955749] omap2-nand driver initializing
[  196.960693] OMAP NAND: use WAIT0 as R/B# pin
[  196.998199] NAND device: Manufacturer ID: 0xad, Chip ID: 0xba (Hynix
NAND 256MiB 1,8V 16-bit)
[  197.018188] omap_ident_nand_chip:1352 ad ba
[  197.022399] Creating 5 MTD partitions on "omap2-nand":
[  197.027587] 0x000000000000-0x000000080000 : "X-Loader"
[  197.037536] 0x000000080000-0x000000260000 : "U-Boot"
[  197.046417] 0x000000260000-0x000000280000 : "U-Boot Env"
[  197.054565] 0x000000280000-0x000000680000 : "Kernel"
[  197.063781] 0x000000680000-0x000010000000 : "File System"
[  197.161712] OneNAND driver initializing
[  197.170745] UBI: attaching mtd4 to ubi0
[  197.174621] UBI: physical eraseblock size:   131072 bytes (128 KiB)
[  197.181274] UBI: logical eraseblock size:    129024 bytes
[  197.186706] UBI: smallest flash I/O unit:    2048
[  197.191528] UBI: sub-page size:              512
[  197.196166] UBI: VID header offset:          512 (aligned 512)
[  197.202453] UBI: data offset:                2048
[  197.311676] UBI error: ubi_io_read: error -74 while reading 64 bytes
from PEB 277:0, read 64 bytes
[  197.321197] UBI error: ubi_io_read: error -74 while reading 64 bytes
from PEB 278:0, read 64 bytes
[  197.330718] UBI error: ubi_io_read: error -74 while reading 64 bytes
from PEB 279:0, read 64 bytes
[  197.341644] UBI error: ubi_io_read: error -74 while reading 64 bytes
from PEB 284:0, read 64 bytes
[  197.983612] UBI error: ubi_read_volume_table: the layout volume was
not found
[  197.994171] UBI error: ubi_init: cannot attach mtd4
[  198.001983] UBI error: ubi_init: UBI error: cannot initialize UBI,
error -22

Note that I've run Angstrom linux on this board before, with the same
kernel; it worked fine.

I am using these commands to create the image:
mkfs.ubifs -r /mnt/storage/hc-build/output/fs -o
/mnt/storage/hc-build/build/fs/root.ubifs -m 2048 -e 129024 -c 2047 -U 
ubinize -o /mnt/storage/hc-build/output/boot/root.ubi -m 2048 -p 131072
-s 512 /mnt/storage/hc-build/build/fs/ubinize.conf

and my ubinize.conf is:
[ubifs]
mode=ubi
image=/mnt/storage/hc-build/build/fs/root.ubifs
vol_id=0
vol_size=128MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

Thank you very much for any insight you can provide.

-Woodrow Douglass


From computersforpeace at gmail.com  Wed Jun  1 14:37:32 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 1 Jun 2011 11:37:32 -0700
Subject: [PATCH 1/2] mtd: nand: generalized error messages with __func__
In-Reply-To: <1306924235.4405.102.camel@localhost>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>
	<4DDDE19D.9010505@compulab.co.il>
	<1306387008.2785.138.camel@localhost>
	<BANLkTimsTWAcR4HgOoHguDMv9P-Eox=kbg@mail.gmail.com>
	<1306924235.4405.102.camel@localhost>
Message-ID: <BANLkTi=BYeQ+cBMpRodDDY_KapjEoHVA+A@mail.gmail.com>

On Wed, Jun 1, 2011 at 3:30 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> or should we define our own pr_fmt in include/linux/mtd.h?
>
> Yes, before you include files.

Well, I've tried this, and as I suspected, I can't just include it in
mtd.h at the top, since we can't guarantee that <linux/mtd/mtd.h> is
going to be the first included header in other files. Specifically, in
include/linux/mtd/nand.h, we include other headers before mtd.h and so
printk.h has already defined pr_fmt() for us, so this doesn't work.
I'm not sure if there's a nice place to define pr_fmt() right now...

Brian


From mlcreech at gmail.com  Thu Jun  2 00:03:39 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Thu, 2 Jun 2011 00:03:39 -0400
Subject: ubi image only mounts once
In-Reply-To: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
Message-ID: <BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>

On Wed, Jun 1, 2011 at 1:52 PM, Douglass, Woody
<Woodrow.Douglass at qinetiq-na.com> wrote:
>
> I am trying to build a linux image to run on a custom omap3530 board. I
> have reached a point where my build system builds a UBI image that can
> be mounted exactly once; subsequent mounts fail. Here is the related
> dmesg output:
>
<snip>

Hi,

How are you flashing the image on to NAND - using "ubiformat", or a
direct flashing utility like "nandwrite"?  I ask because it sounds
like the problem described here:

http://linux-mtd.infradead.org/faq/ubifs.html#L_why_ubiformat

Using "ubiformat" or generating the UBIFS image with the
free-space-fixup (-F) flag will fix the problem, if that's what it is.
If you use the mkfs.ubifs fixup flag, you'll need a very recent kernel
(3.0-rc1), and possibly also Ben Gardiner's patches from a couple days
ago:

http://lists.infradead.org/pipermail/linux-mtd/2011-May/035737.html

-- 
Matthew L. Creech


From mlcreech at gmail.com  Thu Jun  2 00:30:15 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Thu, 2 Jun 2011 00:30:15 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1306914686.4405.53.camel@localhost>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
	<1306914686.4405.53.camel@localhost>
Message-ID: <BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>

On Wed, Jun 1, 2011 at 3:51 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> How this happens? What do you do? Does this happen after mount when you
> first read your data? Or this happens at some point while you stress
> testing your system? Or this happens after a power cut?
>

So far there's no discernable pattern.  Most of the failed units are
returns from the field, so we don't know what kind of conditions
they've been placed in.  Some are from our test department, but we
haven't found anything that might "trigger" the problem in any way.

The device works fine for some period of time (usually weeks /
months), then we get complaints about various problems.  The reported
symptoms eventually come down to one of these UBIFS errors.  Depending
on the region which happens to go bad, it can result in breakage of a
minor feature (because a file we try to read/write after mount
triggers the error), all the way up to a completely non-functional
device.  I'm not sure if we've ever seen it fail to mount altogether
(I'll check into that), but we've had several cases in which U-Boot
couldn't read the kernel image from UBIFS, so the device wouldn't boot
Linux at all.

Power cuts are probably not common, though.  We have to expect them in
the product of course, but practically speaking, our service guy
assures me that a couple of the bad units he shipped me had stable
power and were rarely/never rebooted.  But I can't rule it out with
certainty.

Aside from that, it's just normal operation.  If the usage pattern
matters, the only files ever written to in the persistent (UBIFS)
filesystem are SQLite databases.  It's generally light usage, logging
a variety of measurements once every 5 minutes.  I've tried
stress-testing by running non-stop SQLite operations, recreating the
normal usage pattern but with a _much_ higher frequency of writes than
normal.  It didn't seem to help reproduce the error - we've yet to
succeed in making this problem happen under controlled conditions.

As for this specific error (ubifs_decompress): tomorrow I'll try to
gather & post additional log data for this device.  Thanks!

-- 
Matthew L. Creech


From mlcreech at gmail.com  Thu Jun  2 00:34:50 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Thu, 2 Jun 2011 00:34:50 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1306915328.4405.62.camel@localhost>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<1306915328.4405.62.camel@localhost>
Message-ID: <BANLkTinFZqjt5cp8u_Oqmd9B9ycec16Lhg@mail.gmail.com>

On Wed, Jun 1, 2011 at 4:02 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> 4. The fixup feature might have broke this - we might for some reason
> read less data than there. Although I see FFs start at offset 416, which
> is strange.
>

Also, I can rule this possibility out - although the device is now
running a recent kernel with the fix-up code present, it was upgraded
last week from an older version.  So the UBIFS image it was originally
programmed with (and is still using) didn't have the fixup flag set.

-- 
Matthew L. Creech


From mlcreech at gmail.com  Thu Jun  2 00:59:00 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Thu,  2 Jun 2011 00:59:00 -0400
Subject: [PATCH] UBIFS FAQ: kernel version 2.6.40 -> 3.0
Message-ID: <1306990740-7741-1-git-send-email-mlcreech@gmail.com>

---
 faq/ubifs.xml |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/faq/ubifs.xml b/faq/ubifs.xml
index 06ae05b..3348da4 100644
--- a/faq/ubifs.xml
+++ b/faq/ubifs.xml
@@ -629,7 +629,7 @@ time. But this happens only once, and the "free space fixup" procedure then
 unsets the "fixup" UBIFS superblock flag.</p>
 
 <p>This option is supported if you are running a kernel version
-<code>2.6.40</code> or higher, or if you have pulled the changes from a UBIFS
+<code>3.0</code> or higher, or if you have pulled the changes from a UBIFS
 <a href="../doc/ubifs.html#L_source">back-port tree</a>.  Note that
 <code>ubiformat</code> is still the preferred flashing method if the image is
 not being flashed for the first time, since it preserves existing erase
-- 
1.7.4.1



From sharon_burns72 at gmail.com  Thu Jun  2 01:22:01 2011
From: sharon_burns72 at gmail.com (Sharon.Burns)
Date: Thu, 02 Jun 2011 00:22:01 -0500
Subject: Hello Would You Like To Earn
Message-ID: <E1QS0M5-000Uc4-VG@host113.kvchosting.com>

Hello linux-mtd

Would you like to earn an extra $200 everyday?, for just 45 minutes work? You could quit your job and make double the money at home working for yourself.

visit->http:tinyurl.com/3brnlpx

Regards,

Sharon Burns

Survey Human Resources Dept.




From kmpark at infradead.org  Thu Jun  2 02:48:32 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Thu, 02 Jun 2011 15:48:32 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
Message-ID: <20110602064832.GA7319@july>

From: Kyungmin Park <kyungmin.park at samsung.com>

There's no case to use the subpage for 4KiB pagesize.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ac9e959..337be7c 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -4047,13 +4047,11 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 	 */
 	switch (mtd->oobsize) {
 	case 128:
-		if (FLEXONENAND(this)) {
+		if (FLEXONENAND(this))
 			this->ecclayout = &flexonenand_oob_128;
-			mtd->subpage_sft = 0;
-		} else {
+		else
 			this->ecclayout = &onenand_oob_128;
-			mtd->subpage_sft = 2;
-		}
+		mtd->subpage_sft = 0;
 		break;
 	case 64:
 		this->ecclayout = &onenand_oob_64;


From sharon_burns72 at gmail.com  Thu Jun  2 04:59:35 2011
From: sharon_burns72 at gmail.com (Sharon.Burns)
Date: Thu, 02 Jun 2011 03:59:35 -0500
Subject: Hello Would You Like To Earn
Message-ID: <E1QS3kd-001gbO-Dn@host113.kvchosting.com>

Hello linux-mtd

Would you like to earn an extra $200 everyday?, for just 45 minutes work? You could quit your job and make double the money at home working for yourself.

visit->http:tinyurl.com/3brnlpx

Regards,

Sharon Burns

Survey Human Resources Dept.




From sharon_burns72 at gmail.com  Thu Jun  2 05:41:00 2011
From: sharon_burns72 at gmail.com (Sharon.Burns)
Date: Thu, 02 Jun 2011 04:41:00 -0500
Subject: Hello Would You Like To Earn
Message-ID: <E1QS4Oi-001xh2-SO@host113.kvchosting.com>

Hello linux-mtd

Would you like to earn an extra $200 everyday?, for just 45 minutes work? You could quit your job and make double the money at home working for yourself.

visit->http:tinyurl.com/3brnlpx

Regards,

Sharon Burns

Survey Human Resources Dept.




From dbaryshkov at gmail.com  Thu Jun  2 07:54:07 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 15:54:07 +0400
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
Message-ID: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>

Port ceiva machine to use physmap flash instead of custom mapping driver
(which even can't compile cleanly with current kernels). All info
is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 arch/arm/mach-clps711x/ceiva.c |   60 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-clps711x/ceiva.c b/arch/arm/mach-clps711x/ceiva.c
index 16481cf..00e3c45 100644
--- a/arch/arm/mach-clps711x/ceiva.c
+++ b/arch/arm/mach-clps711x/ceiva.c
@@ -26,6 +26,9 @@
 #include <asm/mach/arch.h>
 
 #include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
 
 #include <mach/hardware.h>
 #include <asm/page.h>
@@ -46,6 +49,56 @@ static struct map_desc ceiva_io_desc[] __initdata = {
 	}
 };
 
+/* Flash / Partition sizing */
+/* For the 28F8003, we use the block mapping to calcuate the sizes */
+#define MAX_SIZE_KiB                  (16 + 8 + 8 + 96 + (7*128))
+#define BOOT_PARTITION_SIZE_KiB       (16)
+#define PARAMS_PARTITION_SIZE_KiB     (8)
+#define KERNEL_PARTITION_SIZE_KiB     (4*128)
+/* Use both remaining portion of first flash, and all of second flash */
+#define ROOT_PARTITION_SIZE_KiB       ((3*128) + (8*128))
+
+static struct mtd_partition ceiva_partitions[] = {
+	{
+		.name = "Ceiva BOOT partition",
+		.size   = BOOT_PARTITION_SIZE_KiB*1024,
+		.offset = 0,
+
+	}, {
+		.name = "Ceiva parameters partition",
+		.size   = PARAMS_PARTITION_SIZE_KiB*1024,
+		.offset = (16 + 8) * 1024,
+	}, {
+		.name = "Ceiva kernel partition",
+		.size = (KERNEL_PARTITION_SIZE_KiB)*1024,
+		.offset = 0x20000,
+
+	}, {
+		.name = "Ceiva root filesystem partition",
+		.offset = MTDPART_OFS_APPEND,
+		.size = (ROOT_PARTITION_SIZE_KiB)*1024,
+	}
+};
+
+static struct physmap_flash_data __initdata ceiva_flash_data = {
+	.width		= CEIVA_FLASH_WIDTH,
+	.parts		= ceiva_partitions,
+	.nr_parts	= ARRAY_SIZE(ceiva_partitions),
+	.probe_type	= "jedec_probe",
+};
+
+static struct resource __initdata ceiva_flash_resouces[] = {
+	{
+		.start	= CS0_PHYS_BASE,
+		.end	= CS0_PHYS_BASE + SZ_32M,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= CS1_PHYS_BASE,
+		.end	= CS1_PHYS_BASE + SZ_32M,
+		.flags	= IORESOURCE_MEM,
+	}
+};
 
 static void __init ceiva_map_io(void)
 {
@@ -53,11 +106,18 @@ static void __init ceiva_map_io(void)
         iotable_init(ceiva_io_desc, ARRAY_SIZE(ceiva_io_desc));
 }
 
+static void __init ceiva_init(void)
+{
+	platform_device_register_resndata(NULL, "physmap-flash", -1,
+			ceiva_flash_resouces, ARRAY_SIZE(ceiva_flash_resouces),
+			&ceiva_flash_data, sizeof(ceiva_flash_data));
+}
 
 MACHINE_START(CEIVA, "CEIVA/Polaroid Photo MAX Digital Picture Frame")
 	/* Maintainer: Rob Scott */
 	.boot_params	= 0xc0000100,
 	.map_io		= ceiva_map_io,
 	.init_irq	= clps711x_init_irq,
+	.init_machine	= ceiva_init,
 	.timer		= &clps711x_timer,
 MACHINE_END
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 07:54:08 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 15:54:08 +0400
Subject: [PATCH 2/2] mtd: drop ceiva map driver
In-Reply-To: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307015648-17505-2-git-send-email-dbaryshkov@gmail.com>

The same functionality is provided by physmap flash driver,
drivers/mtd/maps/ceiva.c didn't receive any functional changes since
the start of current git history, so drop it.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/Kconfig  |    8 -
 drivers/mtd/maps/Makefile |    1 -
 drivers/mtd/maps/ceiva.c  |  341 ---------------------------------------------
 3 files changed, 0 insertions(+), 350 deletions(-)
 delete mode 100644 drivers/mtd/maps/ceiva.c

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 1831063..46eca3b 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -406,14 +406,6 @@ config MTD_IMPA7
 	  This enables access to the NOR Flash on the impA7 board of
 	  implementa GmbH. If you have such a board, say 'Y' here.
 
-config MTD_CEIVA
-	tristate "JEDEC Flash device mapped on Ceiva/Polaroid PhotoMax Digital Picture Frame"
-	depends on MTD_JEDECPROBE && ARCH_CEIVA
-	help
-	  This enables access to the flash chips on the Ceiva/Polaroid
-	  PhotoMax Digital Picture Frame.
-	  If you have such a device, say 'Y'.
-
 config MTD_H720X
 	tristate "Hynix evaluation board mappings"
 	depends on MTD_CFI && ( ARCH_H7201 || ARCH_H7202 )
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index cb48b11..d6379fe 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -19,7 +19,6 @@ obj-$(CONFIG_MTD_CK804XROM)	+= ck804xrom.o
 obj-$(CONFIG_MTD_TSUNAMI)	+= tsunami_flash.o
 obj-$(CONFIG_MTD_PXA2XX)	+= pxa2xx-flash.o
 obj-$(CONFIG_MTD_MBX860)	+= mbx860.o
-obj-$(CONFIG_MTD_CEIVA)		+= ceiva.o
 obj-$(CONFIG_MTD_OCTAGON)	+= octagon-5066.o
 obj-$(CONFIG_MTD_PHYSMAP)	+= physmap.o
 obj-$(CONFIG_MTD_PHYSMAP_OF)	+= physmap_of.o
diff --git a/drivers/mtd/maps/ceiva.c b/drivers/mtd/maps/ceiva.c
deleted file mode 100644
index 06f9c98..0000000
--- a/drivers/mtd/maps/ceiva.c
+++ /dev/null
@@ -1,341 +0,0 @@
-/*
- * Ceiva flash memory driver.
- * Copyright (C) 2002 Rob Scott <rscott at mtrob.fdns.net>
- *
- * Note: this driver supports jedec compatible devices. Modification
- * for CFI compatible devices should be straight forward: change
- * jedec_probe to cfi_probe.
- *
- * Based on: sa1100-flash.c, which has the following copyright:
- * Flash memory access on SA11x0 based devices
- *
- * (C) 2000 Nicolas Pitre <nico at fluxnic.net>
- *
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/ioport.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-#include <linux/mtd/concat.h>
-
-#include <mach/hardware.h>
-#include <asm/mach-types.h>
-#include <asm/io.h>
-#include <asm/sizes.h>
-
-/*
- * This isn't complete yet, so...
- */
-#define CONFIG_MTD_CEIVA_STATICMAP
-
-#ifdef CONFIG_MTD_CEIVA_STATICMAP
-/*
- * See include/linux/mtd/partitions.h for definition of the mtd_partition
- * structure.
- *
- * Please note:
- *  1. The flash size given should be the largest flash size that can
- *     be accommodated.
- *
- *  2. The bus width must defined in clps_setup_flash.
- *
- * The MTD layer will detect flash chip aliasing and reduce the size of
- * the map accordingly.
- *
- */
-
-#ifdef CONFIG_ARCH_CEIVA
-/* Flash / Partition sizing */
-/* For the 28F8003, we use the block mapping to calcuate the sizes */
-#define MAX_SIZE_KiB                  (16 + 8 + 8 + 96 + (7*128))
-#define BOOT_PARTITION_SIZE_KiB       (16)
-#define PARAMS_PARTITION_SIZE_KiB     (8)
-#define KERNEL_PARTITION_SIZE_KiB     (4*128)
-/* Use both remaining portion of first flash, and all of second flash */
-#define ROOT_PARTITION_SIZE_KiB       (3*128) + (8*128)
-
-static struct mtd_partition ceiva_partitions[] = {
-	{
-		.name = "Ceiva BOOT partition",
-		.size   = BOOT_PARTITION_SIZE_KiB*1024,
-		.offset = 0,
-
-	},{
-		.name = "Ceiva parameters partition",
-		.size   = PARAMS_PARTITION_SIZE_KiB*1024,
-		.offset = (16 + 8) * 1024,
-	},{
-		.name = "Ceiva kernel partition",
-		.size = (KERNEL_PARTITION_SIZE_KiB)*1024,
-		.offset = 0x20000,
-
-	},{
-		.name = "Ceiva root filesystem partition",
-		.offset = MTDPART_OFS_APPEND,
-		.size = (ROOT_PARTITION_SIZE_KiB)*1024,
-	}
-};
-#endif
-
-static int __init clps_static_partitions(struct mtd_partition **parts)
-{
-	int nb_parts = 0;
-
-#ifdef CONFIG_ARCH_CEIVA
-	if (machine_is_ceiva()) {
-		*parts       = ceiva_partitions;
-		nb_parts     = ARRAY_SIZE(ceiva_partitions);
-	}
-#endif
-	return nb_parts;
-}
-#endif
-
-struct clps_info {
-	unsigned long base;
-	unsigned long size;
-	int width;
-	void *vbase;
-	struct map_info *map;
-	struct mtd_info *mtd;
-	struct resource *res;
-};
-
-#define NR_SUBMTD 4
-
-static struct clps_info info[NR_SUBMTD];
-
-static int __init clps_setup_mtd(struct clps_info *clps, int nr, struct mtd_info **rmtd)
-{
-	struct mtd_info *subdev[nr];
-	struct map_info *maps;
-	int i, found = 0, ret = 0;
-
-	/*
-	 * Allocate the map_info structs in one go.
-	 */
-	maps = kzalloc(sizeof(struct map_info) * nr, GFP_KERNEL);
-	if (!maps)
-		return -ENOMEM;
-	/*
-	 * Claim and then map the memory regions.
-	 */
-	for (i = 0; i < nr; i++) {
-		if (clps[i].base == (unsigned long)-1)
-			break;
-
-		clps[i].res = request_mem_region(clps[i].base, clps[i].size, "clps flash");
-		if (!clps[i].res) {
-			ret = -EBUSY;
-			break;
-		}
-
-		clps[i].map = maps + i;
-
-		clps[i].map->name = "clps flash";
-		clps[i].map->phys = clps[i].base;
-
-		clps[i].vbase = ioremap(clps[i].base, clps[i].size);
-		if (!clps[i].vbase) {
-			ret = -ENOMEM;
-			break;
-		}
-
-		clps[i].map->virt = (void __iomem *)clps[i].vbase;
-		clps[i].map->bankwidth = clps[i].width;
-		clps[i].map->size = clps[i].size;
-
-		simple_map_init(&clps[i].map);
-
-		clps[i].mtd = do_map_probe("jedec_probe", clps[i].map);
-		if (clps[i].mtd == NULL) {
-			ret = -ENXIO;
-			break;
-		}
-		clps[i].mtd->owner = THIS_MODULE;
-		subdev[i] = clps[i].mtd;
-
-		printk(KERN_INFO "clps flash: JEDEC device at 0x%08lx, %dMiB, "
-			"%d-bit\n", clps[i].base, clps[i].mtd->size >> 20,
-			clps[i].width * 8);
-		found += 1;
-	}
-
-	/*
-	 * ENXIO is special.  It means we didn't find a chip when
-	 * we probed.  We need to tear down the mapping, free the
-	 * resource and mark it as such.
-	 */
-	if (ret == -ENXIO) {
-		iounmap(clps[i].vbase);
-		clps[i].vbase = NULL;
-		release_resource(clps[i].res);
-		clps[i].res = NULL;
-	}
-
-	/*
-	 * If we found one device, don't bother with concat support.
-	 * If we found multiple devices, use concat if we have it
-	 * available, otherwise fail.
-	 */
-	if (ret == 0 || ret == -ENXIO) {
-		if (found == 1) {
-			*rmtd = subdev[0];
-			ret = 0;
-		} else if (found > 1) {
-			/*
-			 * We detected multiple devices.  Concatenate
-			 * them together.
-			 */
-			*rmtd = mtd_concat_create(subdev, found,
-						  "clps flash");
-			if (*rmtd == NULL)
-				ret = -ENXIO;
-		}
-	}
-
-	/*
-	 * If we failed, clean up.
-	 */
-	if (ret) {
-		do {
-			if (clps[i].mtd)
-				map_destroy(clps[i].mtd);
-			if (clps[i].vbase)
-				iounmap(clps[i].vbase);
-			if (clps[i].res)
-				release_resource(clps[i].res);
-		} while (i--);
-
-		kfree(maps);
-	}
-
-	return ret;
-}
-
-static void __exit clps_destroy_mtd(struct clps_info *clps, struct mtd_info *mtd)
-{
-	int i;
-
-	mtd_device_unregister(mtd);
-
-	if (mtd != clps[0].mtd)
-		mtd_concat_destroy(mtd);
-
-	for (i = NR_SUBMTD; i >= 0; i--) {
-		if (clps[i].mtd)
-			map_destroy(clps[i].mtd);
-		if (clps[i].vbase)
-			iounmap(clps[i].vbase);
-		if (clps[i].res)
-			release_resource(clps[i].res);
-	}
-	kfree(clps[0].map);
-}
-
-/*
- * We define the memory space, size, and width for the flash memory
- * space here.
- */
-
-static int __init clps_setup_flash(void)
-{
-	int nr = 0;
-
-#ifdef CONFIG_ARCH_CEIVA
-	if (machine_is_ceiva()) {
-		info[0].base = CS0_PHYS_BASE;
-		info[0].size = SZ_32M;
-		info[0].width = CEIVA_FLASH_WIDTH;
-		info[1].base = CS1_PHYS_BASE;
-		info[1].size = SZ_32M;
-		info[1].width = CEIVA_FLASH_WIDTH;
-		nr = 2;
-	}
-#endif
-	return nr;
-}
-
-static struct mtd_partition *parsed_parts;
-static const char *probes[] = { "cmdlinepart", "RedBoot", NULL };
-
-static void __init clps_locate_partitions(struct mtd_info *mtd)
-{
-	const char *part_type = NULL;
-	int nr_parts = 0;
-	do {
-		/*
-		 * Partition selection stuff.
-		 */
-		nr_parts = parse_mtd_partitions(mtd, probes, &parsed_parts, 0);
-		if (nr_parts > 0) {
-			part_type = "command line";
-			break;
-		}
-#ifdef CONFIG_MTD_CEIVA_STATICMAP
-		nr_parts = clps_static_partitions(&parsed_parts);
-		if (nr_parts > 0) {
-			part_type = "static";
-			break;
-		}
-		printk("found: %d partitions\n", nr_parts);
-#endif
-	} while (0);
-
-	if (nr_parts == 0) {
-		printk(KERN_NOTICE "clps flash: no partition info "
-			"available, registering whole flash\n");
-		mtd_device_register(mtd, NULL, 0);
-	} else {
-		printk(KERN_NOTICE "clps flash: using %s partition "
-			"definition\n", part_type);
-		mtd_device_register(mtd, parsed_parts, nr_parts);
-	}
-
-	/* Always succeeds. */
-}
-
-static void __exit clps_destroy_partitions(void)
-{
-	kfree(parsed_parts);
-}
-
-static struct mtd_info *mymtd;
-
-static int __init clps_mtd_init(void)
-{
-	int ret;
-	int nr;
-
-	nr = clps_setup_flash();
-	if (nr < 0)
-		return nr;
-
-	ret = clps_setup_mtd(info, nr, &mymtd);
-	if (ret)
-		return ret;
-
-	clps_locate_partitions(mymtd);
-
-	return 0;
-}
-
-static void __exit clps_mtd_cleanup(void)
-{
-	clps_destroy_mtd(info, mymtd);
-	clps_destroy_partitions();
-}
-
-module_init(clps_mtd_init);
-module_exit(clps_mtd_cleanup);
-
-MODULE_AUTHOR("Rob Scott");
-MODULE_DESCRIPTION("Cirrus Logic JEDEC map driver");
-MODULE_LICENSE("GPL");
-- 
1.7.4.4



From zohar at linux.vnet.ibm.com  Thu Jun  2 08:23:36 2011
From: zohar at linux.vnet.ibm.com (Mimi Zohar)
Date: Thu,  2 Jun 2011 08:23:36 -0400
Subject: [PATCH v6 13/20] evm: add evm_inode_post_init call in jffs2
In-Reply-To: <1307017423-15093-1-git-send-email-zohar@linux.vnet.ibm.com>
References: <1307017423-15093-1-git-send-email-zohar@linux.vnet.ibm.com>
Message-ID: <1307017423-15093-14-git-send-email-zohar@linux.vnet.ibm.com>

After creating the initial LSM security extended attribute, call
evm_inode_post_init_security() to create the 'security.evm'
extended attribute.

Signed-off-by: Mimi Zohar <zohar at us.ibm.com>
---
 fs/jffs2/security.c |   26 +++++++++++++++++++-------
 1 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index cfeb716..6847769 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -20,6 +20,7 @@
 #include <linux/xattr.h>
 #include <linux/mtd/mtd.h>
 #include <linux/security.h>
+#include <linux/evm.h>
 #include "nodelist.h"
 
 /* ---- Initial Security Label Attachment -------------- */
@@ -28,19 +29,30 @@ int jffs2_init_security(struct inode *inode, struct inode *dir,
 {
 	int rc;
 	size_t len;
-	void *value;
-	char *name;
+	struct xattr lsm_xattr;
+	struct xattr evm_xattr;
 
-	rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
+	rc = security_inode_init_security(inode, dir, qstr, &lsm_xattr.name,
+					  &lsm_xattr.value,
+					  &lsm_xattr.value_len);
 	if (rc) {
 		if (rc == -EOPNOTSUPP)
 			return 0;
 		return rc;
 	}
-	rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
-
-	kfree(name);
-	kfree(value);
+	rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, lsm_xattr.name,
+			       lsm_xattr.value, lsm_xattr.value_len, 0);
+	if (rc)
+		goto out;
+	rc = evm_inode_post_init_security(inode, &lsm_xattr, &evm_xattr);
+	if (err)
+		goto out;
+	rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, evm_xattr.name,
+			       evm_xattr.value, evm_xattr.value_len, 0);
+	kfree(evm_xattr.value);
+out:
+	kfree(lsm_xattr.name);
+	kfree(lsm_xattr.value);
 	return rc;
 }
 
-- 
1.7.3.4



From salesfour at chinagoldshine.com  Thu Jun  2 10:07:00 2011
From: salesfour at chinagoldshine.com (GOLDSHINE-Judy)
Date: Thu, 2 Jun 2011 22:07:00 +0800 (CST)
Subject: www.goldshinechina.com
Message-ID: <358cd249.1ca1e.13050a94233.Coremail.salesfour@chinagoldshine.com>

Dear Sir or Madam:

We have the pleasure to introduce ourselves as one of the leading manufactures and exporters of the load cell products, load cell block, weighing scale etc.

We take this opportunity to approach you with a view to establishing close and cordial business relationship for the following commodity, and could establish business relations of OEM terms with any parter.

 We shall be pleased to receive your interesting and hope this may be the start of mutually successful businese relationship.  we will send some our product for your referance. at the same time we can produce according to customer's requirement. Please don't hesitate to tell us if you have special requirement we will do our best to support you!

Ref. to our products please visit our website:      www.sensorloadcell.com   OR    www.goldshinechina.com   

Ref. to our crane scale visit our website:http://www.sensorloadcell.com/crane-system/

At the same time we can produce according to customer's requirement, please don't hesitate to tell us if you have any questions or special requirement we will do our best to support you




--


BEST REGARDS

JUDYZHU

GOLDSHINE

NINGBOGOLDSHINE ELECTRONIC CO.,LTD

Add:  No.3 Building Xiapu Industry ZoneNingbo,ChinaZIP: 315807

(:+86-574-86902659      7:+86-574-86902656 

 Contact: Ms Judy Skype:goldshinecn  MSN:goldshinecn at hotmail.com
Web:http://www.sensorloadcell.com    OR www.goldshinechina.com
http://goldshinechina.preview.alibaba.com      *:sales at goldshinechina.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110602/04b064ee/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: GOLDSHINE-Lifting Crane.pdf
Type: application/pdf
Size: 738130 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110602/04b064ee/attachment-0001.pdf>

From dbaryshkov at gmail.com  Thu Jun  2 10:51:14 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:14 +0400
Subject: [PATCH 004/104] mtd: drop physmap_configure
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-2-git-send-email-dbaryshkov@gmail.com>

physmap_configure() and physmap_set_partitions() have no users in kernel.
Out of kernel users should have been converted to regular platform device
long ago. Drop support for this obsolete API.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/Kconfig    |    6 ------
 drivers/mtd/maps/physmap.c  |   15 ---------------
 include/linux/mtd/physmap.h |   17 -----------------
 3 files changed, 0 insertions(+), 38 deletions(-)

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 11cc230..46eca3b 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -41,8 +41,6 @@ config MTD_PHYSMAP_START
 	  are mapped on your particular target board. Refer to the
 	  memory map which should hopefully be in the documentation for
 	  your board.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_LEN
 	hex "Physical length of flash mapping"
@@ -55,8 +53,6 @@ config MTD_PHYSMAP_LEN
 	  than the total amount of flash present. Refer to the memory
 	  map which should hopefully be in the documentation for your
 	  board.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_BANKWIDTH
 	int "Bank width in octets"
@@ -67,8 +63,6 @@ config MTD_PHYSMAP_BANKWIDTH
 	  in octets. For example, if you have a data bus width of 32
 	  bits, you would set the bus width octet value to 4. This is
 	  used internally by the CFI drivers.
-	  Ignore this option if you use run-time physmap configuration
-	  (i.e., run-time calling physmap_configure()).
 
 config MTD_PHYSMAP_OF
 	tristate "Flash device in physical memory map based on OF description"
diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index f64cee4..2174d10 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -245,21 +245,6 @@ static struct platform_device physmap_flash = {
 	.num_resources	= 1,
 	.resource	= &physmap_flash_resource,
 };
-
-void physmap_configure(unsigned long addr, unsigned long size,
-		int bankwidth, void (*set_vpp)(struct map_info *, int))
-{
-	physmap_flash_resource.start = addr;
-	physmap_flash_resource.end = addr + size - 1;
-	physmap_flash_data.width = bankwidth;
-	physmap_flash_data.set_vpp = set_vpp;
-}
-
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts)
-{
-	physmap_flash_data.nr_parts = num_parts;
-	physmap_flash_data.parts = parts;
-}
 #endif
 
 static int __init physmap_init(void)
diff --git a/include/linux/mtd/physmap.h b/include/linux/mtd/physmap.h
index d40bfa1..be4ed0d 100644
--- a/include/linux/mtd/physmap.h
+++ b/include/linux/mtd/physmap.h
@@ -31,21 +31,4 @@ struct physmap_flash_data {
 	struct mtd_partition	*parts;
 };
 
-/*
- * Board needs to specify the exact mapping during their setup time.
- */
-void physmap_configure(unsigned long addr, unsigned long size,
-		int bankwidth, void (*set_vpp)(struct map_info *, int) );
-
-/*
- * Machines that wish to do flash partition may want to call this function in
- * their setup routine.
- *
- *	physmap_set_partitions(mypartitions, num_parts);
- *
- * Note that one can always override this hard-coded partition with
- * command line partition (you need to enable CONFIG_MTD_CMDLINE_PARTS).
- */
-void physmap_set_partitions(struct mtd_partition *parts, int num_parts);
-
 #endif /* __LINUX_MTD_PHYSMAP__ */
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:13 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:13 +0400
Subject: [RFC PATCH 000/104] mtd: cleanup partition parsing interface
Message-ID: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>

Hello,

This is an RFC for a huge serie of patches converting most mtd drivers to use
single instance of code for managing mtd partitions parsing and handling.

Currently each driver responsible for partitions implements this part of code
on it's own, resulting in memory leaks, possible frees of non-allocated memory,
etc. As the patch serie is huge, I'm posting only patches I consider
"interesting", i. e. from the subserie doing the same cleanup for different
drivers I post only first patch. Rest are available through the gitweb.

Only one driver still uses parse_mtd_partitions after this serie (edb7312),
as it registers both parsed partitions and the whole mtd device and I ain't
sure how to behave at this case.

If the idea seems find to be commited, I'll post the whole serie for full
review.

The following changes since commit 55922c9d1b84b89cb946c777fddccb3247e7df2c:

  Linux 3.0-rc1 (2011-05-29 17:43:36 -0700)

are available in the git repository at:
  ssh://master.kernel.org/pub/scm/linux/kernel/git/lumag/mtd-cleanup.git mtd-cleanup

Dmitry Eremin-Solenikov (104):
      ATMEL, AVR32: inline nand partition table access
      clps711x/ceiva: port to use physmap flash
      mtd: drop ceiva map driver
      mtd: drop physmap_configure
      mtd: cafe_nand: drop reference to CONFIG_MTD_CMDLINE_PARTS
      mtdpart: default to cmdlinepart, NULL partitions probing
      mtd: m25p80 don't specify default parsing options
      mtd: mtd_dataflash don't specify default parsing options
      mtd: sst25l don't specify default parsing options
      mtd: h720x-flash don't specify default parsing options
      mtd: impa7 don't specify default parsing options
      mtd: intel_vr_nor don't specify default parsing options
      mtd: rbtx4939-flash don't specify default parsing options
      mtd: atmel_nand don't specify default parsing options
      mtd: bcm_umi_nand don't specify default parsing options
      mtd: cmx270_nand don't specify default parsing options
      mtd: cs553x_nand don't specify default parsing options
      mtd: davinci_nand don't specify default parsing options
      mtd: edb7312 don't specify default parsing options
      mtd: fsl_upm don't specify default parsing options
      mtd: fsmc_nand don't specify default parsing options
      mtd: h1910 don't specify default parsing options
      mtd: jz4740_nand don't specify default parsing options
      mtd: lantiq-flash don't specify default parsing options
      mtd: latch-addr-flash don't specify default parsing options
      mtd: mpc5121_nfc don't specify default parsing options
      mtd: ndfc don't specify default parsing options
      mtd: omap2 don't specify default parsing options
      mtd: orion_nand don't specify default parsing options
      mtd: ppchameleonevb don't specify default parsing options
      mtd: pxa3xx_nand don't specify default parsing options
      mtd: s3c2410 don't specify default parsing options
      mtd: sharpsl don't specify default parsing options
      mtd: socrates_nand don't specify default parsing options
      mtd: tmio_nand don't specify default parsing options
      mtd: txx9ndfmc don't specify default parsing options
      mtd: onenand/generic don't specify default parsing options
      mtd: onenand/omap2 don't specify default parsing options
      mtd: samsung/onenand don't specify default parsing options
      mtd: drop mtd_has_cmdlinepart()
      mtd: prepare to convert of_mtd_parse_partitions to partition parser
      mtd: m25p80: use ofpart through generic parsing
      mtd: physmap_of: use ofpart through generic parsing
      mtd: fsl_elbc_nand: use ofpart through generic parsing
      mtd: fsl_upm: use ofpart through generic parsing
      mtd: mpc5121_nfc: use ofpart through generic parsing
      mtd: ndfc: use ofpart through generic parsing
      mtd: socrates_nand: use ofpart through generic parsing
      mtd: drop of_mtd_parse_partitions()
      physmap_of: separate parse_obsolete_partitions to separate parser
      mtd: add a flags for partitions which should just leave smth. after them
      ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
      mtd: plat-nand: drop unused fields from platform_nand_data
      mtd: add new API for handling MTD registration
      mtd: lart.c: use mtd_device_parse_register
      mtd: m25p80.c: use mtd_device_parse_register
      mtd: mtd_dataflash.c: use mtd_device_parse_register
      mtd: sst25l.c: use mtd_device_parse_register
      mtd: bfin-async-flash.c: use mtd_device_parse_register
      mtd: dc21285.c: use mtd_device_parse_register
      mtd: gpio-addr-flash.c: use mtd_device_parse_register
      mtd: h720x-flash.c: use mtd_device_parse_register
      mtd: impa7.c: use mtd_device_parse_register
      mtd: intel_vr_nor.c: use mtd_device_parse_register
      mtd: ixp2000.c: use mtd_device_parse_register
      mtd: ixp4xx.c: use mtd_device_parse_register
      mtd: lantiq-flash.c: use mtd_device_parse_register
      mtd: latch-addr-flash.c: use mtd_device_parse_register
      mtd: physmap.c: use mtd_device_parse_register
      mtd: physmap_of.c: use mtd_device_parse_register
      mtd: plat-ram.c: use mtd_device_parse_register
      mtd: pxa2xx-flash.c: use mtd_device_parse_register
      mtd: rbtx4939-flash.c: use mtd_device_parse_register
      mtd: sa1100-flash.c: use mtd_device_parse_register
      mtd: solutionengine.c: use mtd_device_parse_register
      mtd: wr_sbc82xx_flash.c: use mtd_device_parse_register
      mtd: atmel_nand.c: use mtd_device_parse_register
      mtd: bcm_umi_nand.c: use mtd_device_parse_register
      mtd: cafe_nand.c: use mtd_device_parse_register
      mtd: cmx270_nand.c: use mtd_device_parse_register
      mtd: cs553x_nand.c: use mtd_device_parse_register
      mtd: davinci_nand.c: use mtd_device_parse_register
      mtd: edb7312.c: use mtd_device_parse_register
      mtd: fsl_elbc_nand.c: use mtd_device_parse_register
      mtd: fsl_upm.c: use mtd_device_parse_register
      mtd: fsmc_nand.c: use mtd_device_parse_register
      mtd: h1910.c: use mtd_device_parse_register
      mtd: jz4740_nand.c: use mtd_device_parse_register
      mtd: mpc5121_nfc.c: use mtd_device_parse_register
      mtd: mxc_nand.c: use mtd_device_parse_register
      mtd: ndfc.c: use mtd_device_parse_register
      mtd: omap2.c: use mtd_device_parse_register
      mtd: orion_nand.c: use mtd_device_parse_register
      mtd: plat_nand.c: use mtd_device_parse_register
      mtd: ppchameleonevb.c: use mtd_device_parse_register
      mtd: pxa3xx_nand.c: use mtd_device_parse_register
      mtd: s3c2410.c: use mtd_device_parse_register
      mtd: sharpsl.c: use mtd_device_parse_register
      mtd: socrates_nand.c: use mtd_device_parse_register
      mtd: tmio_nand.c: use mtd_device_parse_register
      mtd: txx9ndfmc.c: use mtd_device_parse_register
      mtd: onenand/generic.c: use mtd_device_parse_register
      mtd: onenand/omap2.c: use mtd_device_parse_register
      mtd: onenand/samsung.c: use mtd_device_parse_register

 arch/arm/mach-at91/board-afeb-9260v1.c      |    9 +-
 arch/arm/mach-at91/board-cam60.c            |    9 +-
 arch/arm/mach-at91/board-cap9adk.c          |    9 +-
 arch/arm/mach-at91/board-kb9202.c           |    9 +-
 arch/arm/mach-at91/board-neocore926.c       |    9 +-
 arch/arm/mach-at91/board-qil-a9260.c        |    9 +-
 arch/arm/mach-at91/board-rm9200dk.c         |    9 +-
 arch/arm/mach-at91/board-sam9-l9260.c       |    9 +-
 arch/arm/mach-at91/board-sam9260ek.c        |    9 +-
 arch/arm/mach-at91/board-sam9261ek.c        |    9 +-
 arch/arm/mach-at91/board-sam9263ek.c        |    9 +-
 arch/arm/mach-at91/board-sam9g20ek.c        |    9 +-
 arch/arm/mach-at91/board-sam9m10g45ek.c     |    9 +-
 arch/arm/mach-at91/board-sam9rlek.c         |    9 +-
 arch/arm/mach-at91/board-snapper9260.c      |   10 +-
 arch/arm/mach-at91/board-usb-a9260.c        |    9 +-
 arch/arm/mach-at91/board-usb-a9263.c        |    9 +-
 arch/arm/mach-at91/board-yl-9200.c          |    9 +-
 arch/arm/mach-at91/include/mach/board.h     |    3 +-
 arch/arm/mach-clps711x/ceiva.c              |   60 +++++
 arch/arm/mach-ep93xx/ts72xx.c               |   22 +--
 arch/avr32/boards/atngw100/setup.c          |    8 +-
 arch/avr32/boards/atstk1000/atstk1002.c     |    9 +-
 arch/avr32/mach-at32ap/include/mach/board.h |    3 +-
 drivers/mtd/Kconfig                         |   10 +
 drivers/mtd/Makefile                        |    1 +
 drivers/mtd/devices/lart.c                  |   12 +-
 drivers/mtd/devices/m25p80.c                |   42 +---
 drivers/mtd/devices/mtd_dataflash.c         |   26 +--
 drivers/mtd/devices/sst25l.c                |   38 +---
 drivers/mtd/maps/Kconfig                    |   14 -
 drivers/mtd/maps/Makefile                   |    1 -
 drivers/mtd/maps/bfin-async-flash.c         |   16 +-
 drivers/mtd/maps/ceiva.c                    |  341 ---------------------------
 drivers/mtd/maps/dc21285.c                  |    9 +-
 drivers/mtd/maps/gpio-addr-flash.c          |   16 +-
 drivers/mtd/maps/h720x-flash.c              |   23 +--
 drivers/mtd/maps/impa7.c                    |   26 +--
 drivers/mtd/maps/intel_vr_nor.c             |    7 +-
 drivers/mtd/maps/ixp2000.c                  |   11 +-
 drivers/mtd/maps/ixp4xx.c                   |   29 +--
 drivers/mtd/maps/lantiq-flash.c             |   17 +--
 drivers/mtd/maps/latch-addr-flash.c         |   24 +--
 drivers/mtd/maps/physmap.c                  |   38 +---
 drivers/mtd/maps/physmap_of.c               |   79 +------
 drivers/mtd/maps/plat-ram.c                 |   23 +--
 drivers/mtd/maps/pxa2xx-flash.c             |   20 +--
 drivers/mtd/maps/rbtx4939-flash.c           |   21 +--
 drivers/mtd/maps/sa1100-flash.c             |   30 +--
 drivers/mtd/maps/solutionengine.c           |   30 +--
 drivers/mtd/maps/wr_sbc82xx_flash.c         |   30 +--
 drivers/mtd/mtdcore.c                       |   49 ++++
 drivers/mtd/mtdpart.c                       |   16 ++
 drivers/mtd/nand/atmel_nand.c               |   25 +--
 drivers/mtd/nand/bcm_umi_nand.c             |   22 +--
 drivers/mtd/nand/cafe_nand.c                |   13 +-
 drivers/mtd/nand/cmx270_nand.c              |   23 +--
 drivers/mtd/nand/cs553x_nand.c              |   10 +-
 drivers/mtd/nand/davinci_nand.c             |   32 +---
 drivers/mtd/nand/edb7312.c                  |   19 +--
 drivers/mtd/nand/fsl_elbc_nand.c            |   16 +-
 drivers/mtd/nand/fsl_upm.c                  |   13 +-
 drivers/mtd/nand/fsmc_nand.c                |   75 +-----
 drivers/mtd/nand/h1910.c                    |   19 +--
 drivers/mtd/nand/jz4740_nand.c              |   18 +--
 drivers/mtd/nand/mpc5121_nfc.c              |   18 +--
 drivers/mtd/nand/mxc_nand.c                 |   15 +-
 drivers/mtd/nand/ndfc.c                     |   20 +--
 drivers/mtd/nand/omap2.c                    |   12 +-
 drivers/mtd/nand/orion_nand.c               |   16 +-
 drivers/mtd/nand/plat_nand.c                |   24 +--
 drivers/mtd/nand/ppchameleonevb.c           |   47 +---
 drivers/mtd/nand/pxa3xx_nand.c              |   14 +-
 drivers/mtd/nand/s3c2410.c                  |   19 +--
 drivers/mtd/nand/sharpsl.c                  |   13 +-
 drivers/mtd/nand/socrates_nand.c            |   27 +--
 drivers/mtd/nand/tmio_nand.c                |   17 +-
 drivers/mtd/nand/txx9ndfmc.c                |    8 +-
 drivers/mtd/ofoldpart.c                     |   89 +++++++
 drivers/mtd/ofpart.c                        |   28 ++-
 drivers/mtd/onenand/generic.c               |   13 +-
 drivers/mtd/onenand/omap2.c                 |   15 +-
 drivers/mtd/onenand/samsung.c               |   13 +-
 include/linux/mtd/mtd.h                     |    8 +
 include/linux/mtd/nand.h                    |    2 -
 include/linux/mtd/partitions.h              |   27 +--
 include/linux/mtd/physmap.h                 |   17 --
 87 files changed, 457 insertions(+), 1557 deletions(-)
 delete mode 100644 drivers/mtd/maps/ceiva.c
 create mode 100644 drivers/mtd/ofoldpart.c



From dbaryshkov at gmail.com  Thu Jun  2 10:51:15 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:15 +0400
Subject: [PATCH 005/104] mtd: cafe_nand: drop reference to
	CONFIG_MTD_CMDLINE_PARTS
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-3-git-send-email-dbaryshkov@gmail.com>

There is no need to guard mtd->name with CONFIG_MTD_CMDLINE_PARTS
as name can be used by other parts.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cafe_nand.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 87ebb4e..2cb3141 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -802,9 +802,7 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	/* We register the whole device first, separate from the partitions */
 	mtd_device_register(mtd, NULL, 0);
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "cafe_nand";
-#endif
 	nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
 	if (nr_parts > 0) {
 		cafe->parts = parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:16 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:16 +0400
Subject: [PATCH 006/104] mtdpart: default to cmdlinepart,
	NULL partitions probing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-4-git-send-email-dbaryshkov@gmail.com>

Lots of MTD devices default to cmdlinepart, NULL as partition parsing
order. Make it a default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdpart.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 630be3e..3477e16 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -712,12 +712,17 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
+static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
+
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
 			 struct mtd_partition **pparts, unsigned long origin)
 {
 	struct mtd_part_parser *parser;
 	int ret = 0;
 
+	if (!types)
+		types = default_mtd_part_types;
+
 	for ( ; ret <= 0 && *types; types++) {
 		parser = get_partition_parser(*types);
 		if (!parser && !request_module("%s", *types))
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:17 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:17 +0400
Subject: [PATCH 007/104] mtd: m25p80 don't specify default parsing options
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-5-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 35180e4..70d5fca 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -968,13 +968,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[]
-			= { "cmdlinepart", NULL, };
-
-		nr_parts = parse_mtd_partitions(&flash->mtd,
-						part_probes, &parts, 0);
-	}
+	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
 
 	if (nr_parts <= 0 && data && data->parts) {
 		parts = data->parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:18 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:18 +0400
Subject: [PATCH 040/104] mtd: drop mtd_has_cmdlinepart()
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-6-git-send-email-dbaryshkov@gmail.com>

This function is unused now. Drop it.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 include/linux/mtd/partitions.h |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 3a6f037..08c9c7b 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -83,12 +83,6 @@ static inline int of_mtd_parse_partitions(struct device *dev,
 }
 #endif
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static inline int mtd_has_cmdlinepart(void) { return 1; }
-#else
-static inline int mtd_has_cmdlinepart(void) { return 0; }
-#endif
-
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
 		      long long offset, long long length);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:19 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:19 +0400
Subject: [PATCH 041/104] mtd: prepare to convert of_mtd_parse_partitions to
	partition parser
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>

Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
1) Register ofpart parser
2) Internally don't use passed device for error printing
3) Add device_node to mtd_info struct
4) Move of_mtd_parse_partitions from __devinit to common text section
5) add ofpart to the default list of partition parsers

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c          |    9 +++++++++
 drivers/mtd/mtdpart.c          |    2 +-
 drivers/mtd/ofpart.c           |   30 ++++++++++++++++++++++++++++--
 include/linux/mtd/mtd.h        |    3 +++
 include/linux/mtd/partitions.h |    2 +-
 5 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c510aff..bfd5a65 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -36,6 +36,7 @@
 #include <linux/idr.h>
 #include <linux/backing-dev.h>
 #include <linux/gfp.h>
+#include <linux/of.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
 			const struct mtd_partition *parts,
 			int nr_parts)
 {
+#ifdef CONFIG_OF
+	if (master->node)
+		of_node_get(master->node);
+#endif
 	return parts ? add_mtd_partitions(master, parts, nr_parts) :
 		add_mtd_device(master);
 }
@@ -461,6 +466,10 @@ int mtd_device_unregister(struct mtd_info *master)
 {
 	int err;
 
+#ifdef CONFIG_OF
+	if (master->node)
+		of_node_put(master->node);
+#endif
 	err = del_mtd_partitions(master);
 	if (err)
 		return err;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 3477e16..0b473ec 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -712,7 +712,7 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
-static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
+static const char *default_mtd_part_types[] = {"cmdlinepart", "ofpart", NULL};
 
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
 			 struct mtd_partition **pparts, unsigned long origin)
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index a996718..ff11b85 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -20,7 +20,20 @@
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
-int __devinit of_mtd_parse_partitions(struct device *dev,
+static int parse_ofpart_partitions(struct mtd_info *master,
+                             struct mtd_partition **pparts,
+                             unsigned long origin)
+{
+	struct device_node *node;
+
+	node = master->node;
+	if (!node)
+		return 0;
+
+	return of_mtd_parse_partitions(NULL, node, pparts);
+}
+
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts)
 {
@@ -69,7 +82,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 
 	if (!i) {
 		of_node_put(pp);
-		dev_err(dev, "No valid partition found on %s\n", node->full_name);
+		pr_err("No valid partition found on %s\n", node->full_name);
 		kfree(*pparts);
 		*pparts = NULL;
 		return -EINVAL;
@@ -79,4 +92,17 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 }
 EXPORT_SYMBOL(of_mtd_parse_partitions);
 
+static struct mtd_part_parser ofpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofpart_partitions,
+	.name = "ofpart",
+};
+
+static int __init ofpart_parser_init(void)
+{
+	return register_mtd_parser(&ofpart_parser);
+}
+
+module_init(ofpart_parser_init);
+
 MODULE_LICENSE("GPL");
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 2541fb8..14305d0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -171,6 +171,9 @@ struct mtd_info {
 	// Kernel-only stuff starts here.
 	const char *name;
 	int index;
+#ifdef CONFIG_OF
+	struct device_node *node;
+#endif
 
 	/* ecc layout structure pointer - read only ! */
 	struct nand_ecclayout *ecclayout;
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 08c9c7b..5fde0d8 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -71,7 +71,7 @@ struct device;
 struct device_node;
 
 #ifdef CONFIG_MTD_OF_PARTS
-int __devinit of_mtd_parse_partitions(struct device *dev,
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts);
 #else
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:20 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:20 +0400
Subject: [PATCH 042/104] mtd: m25p80: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-8-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 70d5fca..a1cdb52 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -928,6 +928,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 
+	flash->mtd.node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
 
@@ -975,13 +976,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 		nr_parts = data->nr_parts;
 	}
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (nr_parts <= 0 && spi->dev.of_node) {
-		nr_parts = of_mtd_parse_partitions(&spi->dev,
-						   spi->dev.of_node, &parts);
-	}
-#endif
-
 	if (nr_parts > 0) {
 		for (i = 0; i < nr_parts; i++) {
 			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:21 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:21 +0400
Subject: [PATCH 043/104] mtd: physmap_of: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-9-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   10 +++-------
 1 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index d251d1d..312eb17 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -165,7 +165,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
+static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+					"ofpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -331,6 +332,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	if (err)
 		goto err_out;
 
+	info->cmtd->node = dp;
 	part_probe_types = of_get_probes(dp);
 	err = parse_mtd_partitions(info->cmtd, part_probe_types,
 				   &info->parts, 0);
@@ -341,12 +343,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	of_free_probes(part_probe_types);
 
 	if (err == 0) {
-		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
-		if (err < 0)
-			goto err_out;
-	}
-
-	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
 		if (err < 0)
 			goto err_out;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:22 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:22 +0400
Subject: [PATCH 044/104] mtd: fsl_elbc_nand: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-10-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 0bb254c..b818264 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -842,7 +842,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct resource res;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
-		= { "cmdlinepart", "RedBoot", NULL };
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
 	struct mtd_partition *parts;
 	int ret;
 	int bank;
@@ -910,6 +910,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	priv->mtd.node = pdev->dev.of_node;
 	priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
 	if (!priv->mtd.name) {
 		ret = -ENOMEM;
@@ -938,12 +939,6 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(priv->dev, node, &parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	mtd_device_register(&priv->mtd, parts, ret);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:23 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:23 +0400
Subject: [PATCH 045/104] mtd: fsl_upm: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-11-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 7c782eb..253b8ff 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -175,6 +175,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 
 	fun->mtd.priv = &fun->chip;
 	fun->mtd.owner = THIS_MODULE;
+	fun->mtd.node = flash_np;
 
 	flash_np = of_get_next_child(upm_np, NULL);
 	if (!flash_np)
@@ -193,13 +194,6 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 
 	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, 0);
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
-		if (ret < 0)
-			goto err;
-	}
-#endif
 	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
 err:
 	of_node_put(flash_np);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:24 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:24 +0400
Subject: [PATCH 046/104] mtd: mpc5121_nfc: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-12-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index de3625b..390d1a0 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -725,6 +725,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	}
 
 	mtd->name = "MPC5121 NAND";
+	mtd->node = dn;
 	chip->dev_ready = mpc5121_nfc_dev_ready;
 	chip->cmdfunc = mpc5121_nfc_command;
 	chip->read_byte = mpc5121_nfc_read_byte;
@@ -836,10 +837,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 
 	/* Register device in MTD */
 	retval = parse_mtd_partitions(mtd, NULL, &parts, 0);
-#ifdef CONFIG_MTD_OF_PARTS
-	if (retval == 0)
-		retval = of_mtd_parse_partitions(dev, dn, &parts);
-#endif
 	if (retval < 0) {
 		dev_err(dev, "Error parsing MTD partitions!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:26 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:26 +0400
Subject: [PATCH 048/104] mtd: socrates_nand: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-14-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 6ed53e1..43b02b1 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -191,6 +191,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	mtd->name = "socrates_nand";
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &ofdev->dev;
+	mtd->node = ofdev->dev.of_node;
 
 	/*should never be accessed directly */
 	nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
@@ -230,16 +231,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto release;
 	}
 
-	if (num_partitions == 0) {
-		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-							 ofdev->dev.of_node,
-							 &partitions);
-		if (num_partitions < 0) {
-			res = num_partitions;
-			goto release;
-		}
-	}
-
 	res = mtd_device_register(mtd, partitions, num_partitions);
 	if (!res)
 		return res;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:27 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:27 +0400
Subject: [PATCH 049/104] mtd: drop of_mtd_parse_partitions()
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-15-git-send-email-dbaryshkov@gmail.com>

All users have been converted to call of_mtd_parse_partitions through
parse_mtd_partitions() multiplexer. Drop obsolete API.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/ofpart.c           |   16 ++++------------
 include/linux/mtd/partitions.h |   16 ----------------
 2 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index ff11b85..89a91ae 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -25,22 +25,15 @@ static int parse_ofpart_partitions(struct mtd_info *master,
                              unsigned long origin)
 {
 	struct device_node *node;
+	const char *partname;
+	struct device_node *pp;
+	int nr_parts, i;
+
 
 	node = master->node;
 	if (!node)
 		return 0;
 
-	return of_mtd_parse_partitions(NULL, node, pparts);
-}
-
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts)
-{
-	const char *partname;
-	struct device_node *pp;
-	int nr_parts, i;
-
 	/* First count the subnodes */
 	pp = NULL;
 	nr_parts = 0;
@@ -90,7 +83,6 @@ int of_mtd_parse_partitions(struct device *dev,
 
 	return nr_parts;
 }
-EXPORT_SYMBOL(of_mtd_parse_partitions);
 
 static struct mtd_part_parser ofpart_parser = {
 	.owner = THIS_MODULE,
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 5fde0d8..746fc97 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -67,22 +67,6 @@ extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-struct device;
-struct device_node;
-
-#ifdef CONFIG_MTD_OF_PARTS
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts);
-#else
-static inline int of_mtd_parse_partitions(struct device *dev,
-					  struct device_node *node,
-					  struct mtd_partition **pparts)
-{
-	return 0;
-}
-#endif
-
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
 		      long long offset, long long length);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:25 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:25 +0400
Subject: [PATCH 047/104] mtd: ndfc: use ofpart through generic parsing
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-13-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index cb66fd7..a041978 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -188,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (!flash_np)
 		return -ENODEV;
 
+	ndfc->mtd.node = flash_np;
 	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
 			dev_name(&ndfc->ofdev->dev), flash_np->name);
 	if (!ndfc->mtd.name) {
@@ -203,13 +204,6 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
-					      &ndfc->parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
 
 err:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:28 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:28 +0400
Subject: =?UTF-8?q?=5BPATCH=20050/104=5D=20physmap=5Fof=3A=20separate=20parse=5Fobsolete=5Fpartitions=20to=20separate=20parser?=
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>

Separate parse_obsolete_partitions() to external ofoldpart partitions parser.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/Kconfig           |   10 +++++
 drivers/mtd/Makefile          |    1 +
 drivers/mtd/maps/physmap_of.c |   53 +------------------------
 drivers/mtd/ofoldpart.c       |   89 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 101 insertions(+), 52 deletions(-)
 create mode 100644 drivers/mtd/ofoldpart.c

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 4be8373..2aa8afb 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -144,6 +144,16 @@ config MTD_OF_PARTS
 	  the partition map from the children of the flash node,
 	  as described in Documentation/powerpc/booting-without-of.txt.
 
+config MTD_OF_OLD_PARTS
+	bool "Obsolete OF tree partition info"
+	depends on OF
+	help
+	  This provides a partition parsing function which derives
+	  the partition map from the the flash node, being an obsolete
+	  way to describe physmap_of partitioning info.
+
+	  If you aren't sure you need this, you can say N.
+
 config MTD_AR7_PARTS
 	tristate "TI AR7 partitioning support"
 	---help---
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 39664c4..1de83b9 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -6,6 +6,7 @@
 obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
 mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
+mtd-$(CONFIG_MTD_OF_OLD_PARTS)	+= ofoldpart.o
 
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 312eb17..c953db3 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -40,51 +40,6 @@ struct of_flash {
 };
 
 #define OF_FLASH_PARTS(info)	((info)->parts)
-static int parse_obsolete_partitions(struct platform_device *dev,
-				     struct of_flash *info,
-				     struct device_node *dp)
-{
-	int i, plen, nr_parts;
-	const struct {
-		__be32 offset, len;
-	} *part;
-	const char *names;
-
-	part = of_get_property(dp, "partitions", &plen);
-	if (!part)
-		return 0; /* No partitions found */
-
-	dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
-
-	nr_parts = plen / sizeof(part[0]);
-
-	info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
-	if (!info->parts)
-		return -ENOMEM;
-
-	names = of_get_property(dp, "partition-names", &plen);
-
-	for (i = 0; i < nr_parts; i++) {
-		info->parts[i].offset = be32_to_cpu(part->offset);
-		info->parts[i].size   = be32_to_cpu(part->len) & ~1;
-		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
-			info->parts[i].mask_flags = MTD_WRITEABLE;
-
-		if (names && (plen > 0)) {
-			int len = strlen(names) + 1;
-
-			info->parts[i].name = (char *)names;
-			plen -= len;
-			names += len;
-		} else {
-			info->parts[i].name = "unnamed";
-		}
-
-		part++;
-	}
-
-	return nr_parts;
-}
 
 static int of_flash_remove(struct platform_device *dev)
 {
@@ -166,7 +121,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    default is use. These take precedence over other device tree
    information. */
 static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
-					"ofpart", NULL };
+					"ofpart", "ofoldpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -342,12 +297,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	}
 	of_free_probes(part_probe_types);
 
-	if (err == 0) {
-		err = parse_obsolete_partitions(dev, info, dp);
-		if (err < 0)
-			goto err_out;
-	}
-
 	mtd_device_register(info->cmtd, info->parts, err);
 
 	kfree(mtd_list);
diff --git a/drivers/mtd/ofoldpart.c b/drivers/mtd/ofoldpart.c
new file mode 100644
index 0000000..a2c143b
--- /dev/null
+++ b/drivers/mtd/ofoldpart.c
@@ -0,0 +1,89 @@
+/*
+ * Flash partitions described by the OF (or flattened) device tree
+ *
+ * Copyright ? 2006 MontaVista Software Inc.
+ * Author: Vitaly Wool <vwool at ru.mvista.com>
+ *
+ * Revised to handle newer style flash binding by:
+ *   Copyright ? 2007 David Gibson, IBM Corporation.
+ *
+ * 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.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/mtd/mtd.h>
+#include <linux/slab.h>
+#include <linux/mtd/partitions.h>
+
+static int parse_ofoldpart_partitions(struct mtd_info *master,
+                             struct mtd_partition **pparts,
+                             unsigned long origin)
+{
+	struct device_node *dp;
+	int i, plen, nr_parts;
+	const struct {
+		__be32 offset, len;
+	} *part;
+	const char *names;
+
+	dp = master->node;
+	if (!dp)
+		return 0;
+
+	part = of_get_property(dp, "partitions", &plen);
+	if (!part)
+		return 0; /* No partitions found */
+
+	pr_warning("Device tree uses obsolete partition map binding: %s\n",
+			dp->full_name);
+
+	nr_parts = plen / sizeof(part[0]);
+
+	*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
+	if (!pparts)
+		return -ENOMEM;
+
+	names = of_get_property(dp, "partition-names", &plen);
+
+	for (i = 0; i < nr_parts; i++) {
+		(*pparts)[i].offset = be32_to_cpu(part->offset);
+		(*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
+		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
+			(*pparts)[i].mask_flags = MTD_WRITEABLE;
+
+		if (names && (plen > 0)) {
+			int len = strlen(names) + 1;
+
+			(*pparts)[i].name = (char *)names;
+			plen -= len;
+			names += len;
+		} else {
+			(*pparts)[i].name = "unnamed";
+		}
+
+		part++;
+	}
+
+	return nr_parts;
+}
+
+static struct mtd_part_parser ofoldpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofoldpart_partitions,
+	.name = "ofoldpart",
+};
+
+static int __init ofoldpart_parser_init(void)
+{
+	return register_mtd_parser(&ofoldpart_parser);
+}
+
+module_init(ofoldpart_parser_init);
+
+MODULE_LICENSE("GPL");
+
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:29 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:29 +0400
Subject: [PATCH 051/104] mtd: add a flags for partitions which should just
	leave smth. after them
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-17-git-send-email-dbaryshkov@gmail.com>

Add support for MTDPART_OFS_RETAIN: such partitions start at the current
offset, take as much space as possible, but rain part->size bytes after
the end of the partitions for other parts. Primarily this is intended
for ts72xx arm platforms cleanup.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdpart.c          |   11 +++++++++++
 include/linux/mtd/partitions.h |    5 ++++-
 2 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 0b473ec..76244a7 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -479,6 +479,17 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
 			       (unsigned long long)cur_offset, (unsigned long long)slave->offset);
 		}
 	}
+	if (slave->offset == MTDPART_OFS_RETAIN) {
+		slave->offset = cur_offset;
+		if (master->size - slave->offset >= slave->mtd.size) {
+			slave->mtd.size = master->size - slave->offset - slave->mtd.size;
+		} else {
+			printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
+					part->name, master->size - slave->offset, slave->mtd.size);
+			/* register to preserve ordering */
+			goto out_register;
+		}
+	}
 	if (slave->mtd.size == MTDPART_SIZ_FULL)
 		slave->mtd.size = master->size - slave->offset;
 
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 746fc97..8601090 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -24,7 +24,9 @@
  * 	will extend to the end of the master MTD device.
  * offset: absolute starting position within the master MTD device; if
  * 	defined as MTDPART_OFS_APPEND, the partition will start where the
- * 	previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
+ * 	previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block;
+ * 	if MTDPART_OFS_RETAIN, consume as much as possible, leaving size
+ * 	after the end of partition.
  * mask_flags: contains flags that have to be masked (removed) from the
  * 	master MTD flag set for the corresponding MTD partition.
  * 	For example, to force a read-only partition, simply adding
@@ -42,6 +44,7 @@ struct mtd_partition {
 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only) */
 };
 
+#define MTDPART_OFS_RETAIN	(-3)
 #define MTDPART_OFS_NXTBLK	(-2)
 #define MTDPART_OFS_APPEND	(-1)
 #define MTDPART_SIZ_FULL	(0)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:30 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:30 +0400
Subject: [PATCH 052/104] ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-18-git-send-email-dbaryshkov@gmail.com>

Instead of specifying a callback for dynamic partitioning, use
MTDPART_OFS_RETAIN for reserving a place near the end of flash for
RedBoot.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Cc: Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ryan Mallon <ryan at bluewatersys.com>
---
 arch/arm/mach-ep93xx/ts72xx.c |   22 ++++------------------
 1 files changed, 4 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index c2d2cf4..68e2849 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -116,8 +116,8 @@ static struct mtd_partition ts72xx_nand_parts[] = {
 		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
 	}, {
 		.name		= "Linux",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 0,			/* filled in later */
+		.offset		= MTDPART_OFS_RETAIN,
+		.size		= TS72XX_REDBOOT_PART_SIZE, /* leave so much for last partition */
 	}, {
 		.name		= "RedBoot",
 		.offset		= MTDPART_OFS_APPEND,
@@ -126,28 +126,14 @@ static struct mtd_partition ts72xx_nand_parts[] = {
 	},
 };
 
-static void ts72xx_nand_set_parts(uint64_t size,
-				  struct platform_nand_chip *chip)
-{
-	/* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
-	if (size == SZ_32M || size == SZ_128M) {
-		/* Set the "Linux" partition size */
-		ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
-
-		chip->partitions = ts72xx_nand_parts;
-		chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
-	} else {
-		pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
-	}
-}
-
 static struct platform_nand_data ts72xx_nand_data = {
 	.chip = {
 		.nr_chips	= 1,
 		.chip_offset	= 0,
 		.chip_delay	= 15,
 		.part_probe_types = ts72xx_nand_part_probes,
-		.set_parts	= ts72xx_nand_set_parts,
+		.partitions	= ts72xx_nand_parts,
+		.nr_partitions	= ARRAY_SIZE(ts72xx_nand_parts),
 	},
 	.ctrl = {
 		.cmd_ctrl	= ts72xx_nand_hwcontrol,
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:31 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:31 +0400
Subject: [PATCH 053/104] mtd: plat-nand: drop unused fields from
	platform_nand_data
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-19-git-send-email-dbaryshkov@gmail.com>

Drop now unused set_parts from struct platform_nand_data. Also, while we are
at it, drop long unused priv field from platform_nand_data.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/plat_nand.c |    2 --
 include/linux/mtd/nand.h     |    2 --
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 633c04b..1339fa8 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -108,8 +108,6 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
 			return 0;
 		}
 	}
-	if (pdata->chip.set_parts)
-		pdata->chip.set_parts(data->mtd.size, &pdata->chip);
 	if (pdata->chip.partitions) {
 		data->parts = pdata->chip.partitions;
 		err = mtd_device_register(&data->mtd, data->parts,
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c2b9ac4..0b185ff 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -625,8 +625,6 @@ struct platform_nand_chip {
 	int chip_delay;
 	unsigned int options;
 	const char **part_probe_types;
-	void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
-	void *priv;
 };
 
 /* Keep gcc happy */
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:32 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:32 +0400
Subject: [PATCH 054/104] mtd: add new API for handling MTD registration
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-20-git-send-email-dbaryshkov@gmail.com>

Lots (nearly all) mtd drivers contain nearly the similar code that
calls parse_mtd_partitions, provides some platform-default values, if
parsing fails, and registers  mtd device.

This is an aim to provide single implementation of this scenario:
mtd_device_parse_register() which will handle all this parsing and
defaults.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c   |   40 ++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/mtd.h |    5 +++++
 2 files changed, 45 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index bfd5a65..fdbfb0c 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -456,6 +456,46 @@ int mtd_device_register(struct mtd_info *master,
 }
 EXPORT_SYMBOL_GPL(mtd_device_register);
 
+int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts)
+{
+	int err;
+	struct mtd_partition *parts;
+
+	err = parse_mtd_partitions(mtd, part_probe_types, &parts, origin);
+	if (err <= 0 && defnr_parts) {
+		unsigned long size = sizeof(*parts) * defnr_parts;
+		err = defnr_parts;
+		parts = kzalloc(size, GFP_KERNEL);
+		memcpy(parts, defparts, size);
+	}
+
+#ifdef CONFIG_OF
+	if (mtd->node)
+		of_node_get(mtd->node);
+#endif
+
+	if (err > 0) {
+		err = add_mtd_partitions(mtd, parts, err);
+		kfree(parts);
+	} else {
+		err = add_mtd_device(mtd);
+		if (err == 1)
+			err = -ENODEV;
+	}
+
+#ifdef CONFIG_OF
+	if (err < 0 && mtd->node)
+		of_node_put(mtd->node);
+#endif
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(mtd_device_parse_register);
+
 /**
  * mtd_device_unregister - unregister an existing MTD device.
  *
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 14305d0..d8f5efe 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -330,6 +330,11 @@ struct mtd_partition;
 extern int mtd_device_register(struct mtd_info *master,
 			       const struct mtd_partition *parts,
 			       int nr_parts);
+extern int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts);
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Thu Jun  2 10:51:33 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  2 Jun 2011 18:51:33 +0400
Subject: [PATCH 055/104] mtd: lart.c: use mtd_device_parse_register
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307026293-8535-21-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/lart.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 772a0ff..48b513f 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -619,6 +619,10 @@ static struct mtd_partition lart_partitions[] = {
 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
 	}
 };
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
+#else
+#define lart_partitions NULL
+#define NUM_PARTITIONS 0
 #endif
 
 static int __init lart_flash_init (void)
@@ -683,23 +687,15 @@ static int __init lart_flash_init (void)
 #endif
 #endif
 
-#ifndef HAVE_PARTITIONS
-   result = mtd_device_register(&mtd, NULL, 0);
-#else
    result = mtd_device_register(&mtd, lart_partitions,
                                 ARRAY_SIZE(lart_partitions));
-#endif
 
    return (result);
 }
 
 static void __exit lart_flash_exit (void)
 {
-#ifndef HAVE_PARTITIONS
    mtd_device_unregister(&mtd);
-#else
-   mtd_device_unregister(&mtd);
-#endif
 }
 
 module_init (lart_flash_init);
-- 
1.7.4.4



From computersforpeace at gmail.com  Thu Jun  2 12:23:56 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 2 Jun 2011 09:23:56 -0700
Subject: [PATCH] nand: Remove meaningless delay from nand_unlock
In-Reply-To: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>
References: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>
Message-ID: <BANLkTin0ki3brkxP02pxuZ2m6QBe=9bNhA@mail.gmail.com>

On Wed, Jun 1, 2011 at 6:56 AM,  <jiri.pinkava at vscht.cz> wrote:
> From: Jiri Pinkava <jiri.pinkava at vscht.cz>
>
> This delay is meaningless. If delay is needed it is device specific
> and must be reimplemented by specific driver, otherwise no delay is
> needed.
>
> This function is not used by any current kernel code, affects only
> external code (like main).

Looks ok to me, but I don't have hardware to test this with.

CC'ing Vimal who added this code originally.

Brian


From computersforpeace at gmail.com  Thu Jun  2 12:26:55 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 2 Jun 2011 09:26:55 -0700
Subject: [PATCH] nand: Remove meaningless delay from nand_unlock
In-Reply-To: <BANLkTin0ki3brkxP02pxuZ2m6QBe=9bNhA@mail.gmail.com>
References: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>
	<BANLkTin0ki3brkxP02pxuZ2m6QBe=9bNhA@mail.gmail.com>
Message-ID: <BANLkTi=3h1zgyMrjBhPOrB_cbbOnZhBa3w@mail.gmail.com>

On Thu, Jun 2, 2011 at 9:23 AM, Brian Norris
<computersforpeace at gmail.com> wrote:
> CC'ing Vimal who added this code originally.

Apparently I had the wrong address for Vimal...I think he has used
this one more recently.

Brian


From computersforpeace at gmail.com  Thu Jun  2 14:15:11 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 2 Jun 2011 11:15:11 -0700
Subject: [RFC] nanddump: skip bad blocks, print full length with
 --omitbad
Message-ID: <1307038511-5968-1-git-send-email-computersforpeace@gmail.com>

I'm not sure the original intended use of nanddump's '--omitbad' option,
but as described below, it doesn't seem to make the most sense to me.
I'm curiouse whether this change should be implemented as yet another
new nanddump option (perhaps a '--skipbad' vs. '--omitbad'? this starts
getting confusing) or if we can simply modify the old behavior of
'--omitbad'.

Brian

----

If, for example, the following is executed on a device with a bad block
at block 0, we get an empty file:
    $ nanddump --length=131072 --omitbad --file=/tmp/foo /dev/mtd0

This does not make intuitive sense. Instead, nanddump should skip the
bad block and continue to dump good data from the next good block.

This patch adds an informative warning to let the user know that a bad
block was skipped to aid with those who may be used to the old method,
where we omit the bad block and simply dump nothing in its place.

---
 nanddump.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 214fb12..e19e16a 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -403,8 +403,15 @@ int main(int argc, char * const argv[])
 		}
 
 		if (badblock) {
-			if (omitbad)
+			if (omitbad) {
+				/* skip bad block, increase end_addr */
+				fprintf(stderr, "Skipping bad block at 0x%08llx\n", ofs);
+				end_addr += mtd.eb_size;
+				ofs += mtd.eb_size - bs;
+				if (end_addr > mtd.size)
+					end_addr = mtd.size;
 				continue;
+			}
 			memset(readbuf, 0xff, bs);
 		} else {
 			/* Read page data and exit on failure */
-- 
1.7.0.4




From vimal.newwork at gmail.com  Thu Jun  2 14:24:01 2011
From: vimal.newwork at gmail.com (Vimal Singh)
Date: Thu, 2 Jun 2011 23:54:01 +0530
Subject: [PATCH] nand: Remove meaningless delay from nand_unlock
In-Reply-To: <BANLkTin0ki3brkxP02pxuZ2m6QBe=9bNhA@mail.gmail.com>
References: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>
	<BANLkTin0ki3brkxP02pxuZ2m6QBe=9bNhA@mail.gmail.com>
Message-ID: <BANLkTi=aex1zmOS+V1FiWVgoY+LySMfZFw@mail.gmail.com>

On Thu, Jun 2, 2011 at 9:53 PM, Brian Norris
<computersforpeace at gmail.com> wrote:
> On Wed, Jun 1, 2011 at 6:56 AM, ?<jiri.pinkava at vscht.cz> wrote:
>> From: Jiri Pinkava <jiri.pinkava at vscht.cz>
>>
>> This delay is meaningless. If delay is needed it is device specific
>> and must be reimplemented by specific driver, otherwise no delay is
>> needed.
Indeed, these delays are not required. I guess it was left out code
before posting the patch.
Here is my ack:

Acked-by: Vimal Singh <vimal.newwork at gmail.com>

-- 
Regards,
Vimal Singh

>>
>> This function is not used by any current kernel code, affects only
>> external code (like main).
>
> Looks ok to me, but I don't have hardware to test this with.
>
> CC'ing Vimal who added this code originally.
>
> Brian
>


From computersforpeace at gmail.com  Thu Jun  2 14:38:26 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 2 Jun 2011 11:38:26 -0700
Subject: [PATCH] mtd: nand: remove unnecessary TODO
Message-ID: <1307039906-6462-1-git-send-email-computersforpeace@gmail.com>

I believe this TODO was unnecessary back when it was introduced:
	commit d1e1f4e42b5df063712ca2926e50c07b95c96b96
	mtd: nand: add support for reading ONFI parameters...

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_base.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a46e9bb..7781988 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3151,7 +3151,6 @@ ident_done:
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
-	/* TODO onfi flash name */
 	printk(KERN_INFO "NAND device: Manufacturer ID:"
 		" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
 		nand_manuf_ids[maf_idx].name,
-- 
1.7.0.4




From vapier.adi at gmail.com  Thu Jun  2 14:51:45 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 2 Jun 2011 14:51:45 -0400
Subject: [RFC] nanddump: skip bad blocks, print full length with --omitbad
In-Reply-To: <1307038511-5968-1-git-send-email-computersforpeace@gmail.com>
References: <1307038511-5968-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTim3uCTqGav2PkJ6D2DfZBjKRg2gcw@mail.gmail.com>

On Thu, Jun 2, 2011 at 14:15, Brian Norris wrote:
> I'm not sure the original intended use of nanddump's '--omitbad' option,
> but as described below, it doesn't seem to make the most sense to me.
> I'm curiouse whether this change should be implemented as yet another
> new nanddump option (perhaps a '--skipbad' vs. '--omitbad'? this starts
> getting confusing) or if we can simply modify the old behavior of
> '--omitbad'.

pretty sure the opt operates as i intended.  sounds like you want to
add --skipbad.
-mike


From mlcreech at gmail.com  Thu Jun  2 14:59:34 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Thu, 2 Jun 2011 14:59:34 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
	<1306914686.4405.53.camel@localhost>
	<BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
Message-ID: <BANLkTimsanbjqD8ZqJ26wcp42iQWt+vFdw@mail.gmail.com>

On Thu, Jun 2, 2011 at 12:30 AM, Matthew L. Creech <mlcreech at gmail.com> wrote:
>
> As for this specific error (ubifs_decompress): tomorrow I'll try to
> gather & post additional log data for this device. ?Thanks!
>

Here is a console dump with more information enabled:

http://mcreech.com/work/ubifs-decompress-err.txt

I turned on mount & recovery debug messages, although it seems to
mount & recover correctly, so presumably any info from past recovery
actions is long gone.  The error actually occurs later on, when our
main application accesses SQLite databases.

I dumped out the corrupted node data in 3 places:

1. In ubifs_decompress(), I dumped the data buffer, prefixed with
"compressed node" (redundant with #3, really)

2. In read_block(), I page-align the starting offset & size, re-fetch
the pertinent pages from flash, and dump those with corresponding OOB
info, prefixed with "data" and "oob" respectively

3. There's already a dbg_dump_node() call in read_block(), so I
enabled that as well

-- 
Matthew L. Creech


From computersforpeace at gmail.com  Thu Jun  2 18:40:56 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 2 Jun 2011 15:40:56 -0700
Subject: [RFC] nanddump: skip bad blocks, print full length with --omitbad
In-Reply-To: <BANLkTim3uCTqGav2PkJ6D2DfZBjKRg2gcw@mail.gmail.com>
References: <1307038511-5968-1-git-send-email-computersforpeace@gmail.com>
	<BANLkTim3uCTqGav2PkJ6D2DfZBjKRg2gcw@mail.gmail.com>
Message-ID: <BANLkTinzWH1XFzW-q+gWK0A0XC_DppE9eQ@mail.gmail.com>

On Thu, Jun 2, 2011 at 11:51 AM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> pretty sure the opt operates as i intended. ?sounds like you want to
> add --skipbad.

OK, thanks for the info. I might add a new "skipbad" option and try to
clarify the differences between the various "omit" and "skip" options.

BTW, is there good history for mtd-utils pre-April 2006? Git doesn't
have history for this option, as it was part of the "initial commit."

Thanks,
Brian


From axel.lin at gmail.com  Thu Jun  2 21:12:15 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 09:12:15 +0800
Subject: [PATCH] mtd: denali: remove calling mtd_device_unregister() after
	nand_release()
Message-ID: <1307063535.10001.1.camel@phoenix>

The implementation of nand_release() already call mtd_device_unregister(),
no need to call it again.

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/denali.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index d527621..e119748 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1676,7 +1676,6 @@ static void denali_pci_remove(struct pci_dev *dev)
 	struct denali_nand_info *denali = pci_get_drvdata(dev);
 
 	nand_release(&denali->mtd);
-	mtd_device_unregister(&denali->mtd);
 
 	denali_irq_cleanup(dev->irq, denali);
 
-- 
1.7.4.1





From axel.lin at gmail.com  Thu Jun  2 21:51:53 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 09:51:53 +0800
Subject: [PATCH 1/2] mtd: nuc900_nand: add missing nand_release in
	nuc900_nand_remove
Message-ID: <1307065913.10001.2.camel@phoenix>

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/nuc900_nand.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
index 9c30a0b..fa8faed 100644
--- a/drivers/mtd/nand/nuc900_nand.c
+++ b/drivers/mtd/nand/nuc900_nand.c
@@ -339,6 +339,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev)
 	struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
 	struct resource *res;
 
+	nand_release(&nuc900_nand->mtd);
 	iounmap(nuc900_nand->reg);
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-- 
1.7.4.1





From axel.lin at gmail.com  Thu Jun  2 21:53:26 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 09:53:26 +0800
Subject: [PATCH 2/2] mtd: nomadik_nand: add missing nand_release in
	nomadik_nand_remove
In-Reply-To: <1307065913.10001.2.camel@phoenix>
References: <1307065913.10001.2.camel@phoenix>
Message-ID: <1307066006.10001.4.camel@phoenix>

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/nomadik_nand.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/nomadik_nand.c b/drivers/mtd/nand/nomadik_nand.c
index b6a5c86..b463ecf 100644
--- a/drivers/mtd/nand/nomadik_nand.c
+++ b/drivers/mtd/nand/nomadik_nand.c
@@ -187,6 +187,7 @@ static int nomadik_nand_remove(struct platform_device *pdev)
 		pdata->exit();
 
 	if (host) {
+		nand_release(&host->mtd);
 		iounmap(host->cmd_va);
 		iounmap(host->data_va);
 		iounmap(host->addr_va);
-- 
1.7.4.1





From mcuos.com at gmail.com  Thu Jun  2 22:25:52 2011
From: mcuos.com at gmail.com (Wan ZongShun)
Date: Fri, 3 Jun 2011 10:25:52 +0800
Subject: [PATCH 1/2] mtd: nuc900_nand: add missing nand_release in
	nuc900_nand_remove
In-Reply-To: <1307065913.10001.2.camel@phoenix>
References: <1307065913.10001.2.camel@phoenix>
Message-ID: <BANLkTikeK=bPMSrWEmjk6x=KwREJyajzvg@mail.gmail.com>

2011/6/3 Axel Lin <axel.lin at gmail.com>:
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Acked-by: Wan ZongShun <mcuos.com at gmail.com>

Thanks!

> ---
> ?drivers/mtd/nand/nuc900_nand.c | ? ?1 +
> ?1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/nand/nuc900_nand.c b/drivers/mtd/nand/nuc900_nand.c
> index 9c30a0b..fa8faed 100644
> --- a/drivers/mtd/nand/nuc900_nand.c
> +++ b/drivers/mtd/nand/nuc900_nand.c
> @@ -339,6 +339,7 @@ static int __devexit nuc900_nand_remove(struct platform_device *pdev)
> ? ? ? ?struct nuc900_nand *nuc900_nand = platform_get_drvdata(pdev);
> ? ? ? ?struct resource *res;
>
> + ? ? ? nand_release(&nuc900_nand->mtd);
> ? ? ? ?iounmap(nuc900_nand->reg);
>
> ? ? ? ?res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> --
> 1.7.4.1
>
>
>
>



-- 
Wan ZongShun.
www.mcuos.com


From dedekind1 at gmail.com  Fri Jun  3 00:32:20 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 07:32:20 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
	<1306914686.4405.53.camel@localhost>
	<BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
Message-ID: <1307075540.4405.128.camel@localhost>

On Thu, 2011-06-02 at 00:30 -0400, Matthew L. Creech wrote:
> On Wed, Jun 1, 2011 at 3:51 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >
> > How this happens? What do you do? Does this happen after mount when you
> > first read your data? Or this happens at some point while you stress
> > testing your system? Or this happens after a power cut?
> >
> 
> So far there's no discernable pattern.  Most of the failed units are
> returns from the field, so we don't know what kind of conditions
> they've been placed in.  Some are from our test department, but we
> haven't found anything that might "trigger" the problem in any way.
> 
> The device works fine for some period of time (usually weeks /
> months), then we get complaints about various problems.  The reported
> symptoms eventually come down to one of these UBIFS errors.  Depending
> on the region which happens to go bad, it can result in breakage of a
> minor feature (because a file we try to read/write after mount
> triggers the error), all the way up to a completely non-functional
> device.  I'm not sure if we've ever seen it fail to mount altogether
> (I'll check into that), but we've had several cases in which U-Boot
> couldn't read the kernel image from UBIFS, so the device wouldn't boot
> Linux at all.
> 
> Power cuts are probably not common, though.  We have to expect them in
> the product of course, but practically speaking, our service guy
> assures me that a couple of the bad units he shipped me had stable
> power and were rarely/never rebooted.  But I can't rule it out with
> certainty.
> 
> Aside from that, it's just normal operation.  If the usage pattern
> matters, the only files ever written to in the persistent (UBIFS)
> filesystem are SQLite databases.  It's generally light usage, logging
> a variety of measurements once every 5 minutes.  I've tried
> stress-testing by running non-stop SQLite operations, recreating the
> normal usage pattern but with a _much_ higher frequency of writes than
> normal.  It didn't seem to help reproduce the error - we've yet to
> succeed in making this problem happen under controlled conditions.
> 
> As for this specific error (ubifs_decompress): tomorrow I'll try to
> gather & post additional log data for this device.  Thanks!

OK, then this is not about power cuts and unstable bits. First thing
coming to my mind is that your kernel may have some non-UBIFS bugs which
end up in memory corruptions, so UBIFS writes corrupted data to the
flash.

But the hexdump you sent shows that you have some non-0xFFs and then
many 0xFFs. Are those trailing 0xFFs part of the node data or not? If
yes, then it does not look like memory corruption, but more like some
driver/flash issues.

BTW, have you run mtd tests? Would you mind to set up torture test on
one of your boards and let it run fore several weeks. I remember we
found a rare DMA bug in our board by running the torture test for long
time. Also, it might be interesting how your HW and SW behave when you
continuously wear out few eraseblocks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Fri Jun  3 00:38:25 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 07:38:25 +0300
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307075905.4405.130.camel@localhost>

On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
> Port ceiva machine to use physmap flash instead of custom mapping driver
> (which even can't compile cleanly with current kernels). All info
> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  arch/arm/mach-clps711x/ceiva.c |   60 ++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 60 insertions(+), 0 deletions(-)

Is ceiva used and not dead? May be we could kill it completely?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Fri Jun  3 01:02:47 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Fri, 3 Jun 2011 09:02:47 +0400
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <1307075905.4405.130.camel@localhost>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
Message-ID: <BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>

On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
>> Port ceiva machine to use physmap flash instead of custom mapping driver
>> (which even can't compile cleanly with current kernels). All info
>> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>> ---
>>  arch/arm/mach-clps711x/ceiva.c |   60
>> ++++++++++++++++++++++++++++++++++++++++
>>  1 files changed, 60 insertions(+), 0 deletions(-)
>
> Is ceiva used and not dead? May be we could kill it completely?

No functional changes to board file since start of git history. Also
I don't know how useful can be contemporary Linux on 4 MiB of RAM


-- 
With best wishes
Dmitry


From axel.lin at gmail.com  Fri Jun  3 01:14:10 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 13:14:10 +0800
Subject: [PATCH 1/2] mtd: pxa3xx_nand: fix a memory leak
Message-ID: <1307078050.4167.1.camel@phoenix>

In pxa3xx_nand_remove, we should call nand_release instead of
mtd_device_unregister to properly free bad block table memory
and bad block descriptor memory.

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 1fb3b3a..f7040ea 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1119,7 +1119,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	clk_put(info->clk);
 
 	if (mtd) {
-		mtd_device_unregister(mtd);
+		nand_release(mtd);
 		kfree(mtd);
 	}
 	return 0;
-- 
1.7.4.1





From Artem.Bityutskiy at nokia.com  Fri Jun  3 01:10:42 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 08:10:42 +0300
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
Message-ID: <1307077842.4405.133.camel@localhost>

On Fri, 2011-06-03 at 09:02 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> > On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
> >> Port ceiva machine to use physmap flash instead of custom mapping driver
> >> (which even can't compile cleanly with current kernels). All info
> >> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
> >>
> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >> ---
> >>  arch/arm/mach-clps711x/ceiva.c |   60
> >> ++++++++++++++++++++++++++++++++++++++++
> >>  1 files changed, 60 insertions(+), 0 deletions(-)
> >
> > Is ceiva used and not dead? May be we could kill it completely?
> 
> No functional changes to board file since start of git history. Also
> I don't know how useful can be contemporary Linux on 4 MiB of RAM

I also noticed that no one is interested in this board for long time. So
I suggest to remove ceiva support altogether via some arm tree.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From axel.lin at gmail.com  Fri Jun  3 01:15:30 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 13:15:30 +0800
Subject: [PATCH 2/2] mtd: fsmc_nand: fix a memory leak
In-Reply-To: <1307078050.4167.1.camel@phoenix>
References: <1307078050.4167.1.camel@phoenix>
Message-ID: <1307078130.4167.3.camel@phoenix>

In fsmc_nand_remove, we should call nand_release instead of
mtd_device_unregister to properly free bad block table memory
and bad block descriptor memory.

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/fsmc_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e9b275a..8a5f1aa 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -822,7 +822,7 @@ static int fsmc_nand_remove(struct platform_device *pdev)
 	platform_set_drvdata(pdev, NULL);
 
 	if (host) {
-		mtd_device_unregister(&host->mtd);
+		nand_release(&host->mtd);
 		clk_disable(host->clk);
 		clk_put(host->clk);
 
-- 
1.7.4.1





From dbaryshkov at gmail.com  Fri Jun  3 01:17:31 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Fri, 3 Jun 2011 09:17:31 +0400
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <1307077842.4405.133.camel@localhost>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
	<1307077842.4405.133.camel@localhost>
Message-ID: <BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>

On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> On Fri, 2011-06-03 at 09:02 +0400, Dmitry Eremin-Solenikov wrote:
>> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
>> > On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
>> >> Port ceiva machine to use physmap flash instead of custom mapping
>> >> driver
>> >> (which even can't compile cleanly with current kernels). All info
>> >> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
>> >>
>> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>> >> ---
>> >>  arch/arm/mach-clps711x/ceiva.c |   60
>> >> ++++++++++++++++++++++++++++++++++++++++
>> >>  1 files changed, 60 insertions(+), 0 deletions(-)
>> >
>> > Is ceiva used and not dead? May be we could kill it completely?
>>
>> No functional changes to board file since start of git history. Also
>> I don't know how useful can be contemporary Linux on 4 MiB of RAM
>
> I also noticed that no one is interested in this board for long time. So
> I suggest to remove ceiva support altogether via some arm tree.

Anyway the patch removing mtd support can be pushed via mtd tree
(there is really no point on mtd/maps/ceiva.c), and removing ceiva
depends on Russell's decision.

-- 
With best wishes
Dmitry


From Artem.Bityutskiy at nokia.com  Fri Jun  3 01:21:28 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 08:21:28 +0300
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
	<1307077842.4405.133.camel@localhost>
	<BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
Message-ID: <1307078488.4405.139.camel@localhost>

On Fri, 2011-06-03 at 09:17 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> > On Fri, 2011-06-03 at 09:02 +0400, Dmitry Eremin-Solenikov wrote:
> >> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> >> > On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
> >> >> Port ceiva machine to use physmap flash instead of custom mapping
> >> >> driver
> >> >> (which even can't compile cleanly with current kernels). All info
> >> >> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
> >> >>
> >> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >> >> ---
> >> >>  arch/arm/mach-clps711x/ceiva.c |   60
> >> >> ++++++++++++++++++++++++++++++++++++++++
> >> >>  1 files changed, 60 insertions(+), 0 deletions(-)
> >> >
> >> > Is ceiva used and not dead? May be we could kill it completely?
> >>
> >> No functional changes to board file since start of git history. Also
> >> I don't know how useful can be contemporary Linux on 4 MiB of RAM
> >
> > I also noticed that no one is interested in this board for long time. So
> > I suggest to remove ceiva support altogether via some arm tree.
> 
> Anyway the patch removing mtd support can be pushed via mtd tree
> (there is really no point on mtd/maps/ceiva.c), and removing ceiva
> depends on Russell's decision.

There is as well little point in changing ceiva code if we can just kill
it instead. So let's first try to ask Russell if he is fine with killing
ceiva or not. Could you please do this in a separate thread with an
appropriate subject.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Fri Jun  3 01:31:09 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 08:31:09 +0300
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
	<1307077842.4405.133.camel@localhost>
	<BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
Message-ID: <1307079069.4405.142.camel@localhost>

On Fri, 2011-06-03 at 09:17 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> > On Fri, 2011-06-03 at 09:02 +0400, Dmitry Eremin-Solenikov wrote:
> >> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> >> > On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
> >> >> Port ceiva machine to use physmap flash instead of custom mapping
> >> >> driver
> >> >> (which even can't compile cleanly with current kernels). All info
> >> >> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
> >> >>
> >> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >> >> ---
> >> >>  arch/arm/mach-clps711x/ceiva.c |   60
> >> >> ++++++++++++++++++++++++++++++++++++++++
> >> >>  1 files changed, 60 insertions(+), 0 deletions(-)
> >> >
> >> > Is ceiva used and not dead? May be we could kill it completely?
> >>
> >> No functional changes to board file since start of git history. Also
> >> I don't know how useful can be contemporary Linux on 4 MiB of RAM
> >
> > I also noticed that no one is interested in this board for long time. So
> > I suggest to remove ceiva support altogether via some arm tree.
> 
> Anyway the patch removing mtd support can be pushed via mtd tree
> (there is really no point on mtd/maps/ceiva.c), and removing ceiva
> depends on Russell's decision.

If you care about conflicts and how to merge all that - you can remove
ceiva via the arm tree, and at the same time modify the driver in the
mtd tree, and we'll just put a not to the commit message that during the
merge this change has to be discarded. Linus did a similar thing this
merge window for one board which mtd modified and arm tree removed.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From sharon_burns72 at gmail.com  Fri Jun  3 02:00:03 2011
From: sharon_burns72 at gmail.com (Sharon.Burns)
Date: Fri, 03 Jun 2011 01:00:03 -0500
Subject: Hello Would You Like To Earn
Message-ID: <E1QSNQR-003JuI-D8@host113.kvchosting.com>

Hello linux-mtd

Would you like to earn an extra $200 everyday?, for just 45 minutes work? You could quit your job and make double the money at home working for yourself.

visit->http:tinyurl.com/3brnlpx

Regards,

Sharon Burns

Survey Human Resources Dept.




From dbaryshkov at gmail.com  Fri Jun  3 02:07:07 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Fri, 3 Jun 2011 10:07:07 +0400
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <1307079069.4405.142.camel@localhost>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
	<1307077842.4405.133.camel@localhost>
	<BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
	<1307079069.4405.142.camel@localhost>
Message-ID: <BANLkTikDbi4YAXUy9TqOkXFDd6oVZ-Gybg@mail.gmail.com>

On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> On Fri, 2011-06-03 at 09:17 +0400, Dmitry Eremin-Solenikov wrote:
>> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
>> > On Fri, 2011-06-03 at 09:02 +0400, Dmitry Eremin-Solenikov wrote:
>> >> On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
>> >> > On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
>> >> >> Port ceiva machine to use physmap flash instead of custom mapping
>> >> >> driver
>> >> >> (which even can't compile cleanly with current kernels). All info
>> >> >> is gathered from drivers/mtd/maps/ceiva.c. Compile tested only.
>> >> >>
>> >> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>> >> >> ---
>> >> >>  arch/arm/mach-clps711x/ceiva.c |   60
>> >> >> ++++++++++++++++++++++++++++++++++++++++
>> >> >>  1 files changed, 60 insertions(+), 0 deletions(-)
>> >> >
>> >> > Is ceiva used and not dead? May be we could kill it completely?
>> >>
>> >> No functional changes to board file since start of git history. Also
>> >> I don't know how useful can be contemporary Linux on 4 MiB of RAM
>> >
>> > I also noticed that no one is interested in this board for long time. So
>> > I suggest to remove ceiva support altogether via some arm tree.
>>
>> Anyway the patch removing mtd support can be pushed via mtd tree
>> (there is really no point on mtd/maps/ceiva.c), and removing ceiva
>> depends on Russell's decision.
>
> If you care about conflicts and how to merge all that - you can remove
> ceiva via the arm tree, and at the same time modify the driver in the
> mtd tree, and we'll just put a not to the commit message that during the
> merge this change has to be discarded. Linus did a similar thing this
> merge window for one board which mtd modified and arm tree removed.

In fact second patch from this serie (drop of drivers/mtd/maps/ceiva.c)
should be commited through the mtd tree and will bring no conflicts in
either case. And either the first patch (port of ceiva to physmap) or complete
dropout of ceiva should come through the ARM tree, again bringing
no conflicts. So with these patches we are safe :)

-- 
With best wishes
Dmitry


From axel.lin at gmail.com  Fri Jun  3 02:10:22 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 14:10:22 +0800
Subject: [PATCH] mtd: mtdblock: Use DEFINE_MUTEX() for mtdblks_lock
Message-ID: <1307081422.6450.2.camel@phoenix>

mtdblks_lock can be initialized automatically with
DEFINE_MUTEX() rather than explicitly calling mutex_init().

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/mtdblock.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/mtdblock.c b/drivers/mtd/mtdblock.c
index 3326615..1976b6c 100644
--- a/drivers/mtd/mtdblock.c
+++ b/drivers/mtd/mtdblock.c
@@ -44,7 +44,7 @@ struct mtdblk_dev {
 	enum { STATE_EMPTY, STATE_CLEAN, STATE_DIRTY } cache_state;
 };
 
-static struct mutex mtdblks_lock;
+static DEFINE_MUTEX(mtdblks_lock);
 
 /*
  * Cache stuff...
@@ -389,8 +389,6 @@ static struct mtd_blktrans_ops mtdblock_tr = {
 
 static int __init init_mtdblock(void)
 {
-	mutex_init(&mtdblks_lock);
-
 	return register_mtd_blktrans(&mtdblock_tr);
 }
 
-- 
1.7.4.1





From axel.lin at gmail.com  Fri Jun  3 03:34:33 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 03 Jun 2011 15:34:33 +0800
Subject: [PATCH] mtd: pxa3xx_nand: remove unused variable 'mtd'
Message-ID: <1307086473.7474.1.camel@phoenix>

Remove unused variable 'mtd' to eliminate below warning.

  CC      drivers/mtd/nand/pxa3xx_nand.o
drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_suspend':
drivers/mtd/nand/pxa3xx_nand.c:1167: warning: unused variable 'mtd'
drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_resume':
drivers/mtd/nand/pxa3xx_nand.c:1180: warning: unused variable 'mtd'

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 1fb3b3a..5cae8ae 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1164,7 +1164,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 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) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
@@ -1177,7 +1176,6 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
 	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.4.1





From zonque at gmail.com  Fri Jun  3 03:44:36 2011
From: zonque at gmail.com (Daniel Mack)
Date: Fri, 3 Jun 2011 09:44:36 +0200
Subject: [PATCH] mtd: pxa3xx_nand: remove unused variable 'mtd'
In-Reply-To: <1307086473.7474.1.camel@phoenix>
References: <1307086473.7474.1.camel@phoenix>
Message-ID: <BANLkTikt4y3ZKJD2Ld_hxAAzjOpevEqFfA@mail.gmail.com>

Hi Alex,

On Fri, Jun 3, 2011 at 9:34 AM, Axel Lin <axel.lin at gmail.com> wrote:
> Remove unused variable 'mtd' to eliminate below warning.
>
> ?CC ? ? ?drivers/mtd/nand/pxa3xx_nand.o
> drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_suspend':
> drivers/mtd/nand/pxa3xx_nand.c:1167: warning: unused variable 'mtd'
> drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_resume':
> drivers/mtd/nand/pxa3xx_nand.c:1180: warning: unused variable 'mtd'

Do you actually use this driver? I'm asking because there's some sort
of nasty regression in the changes between 2.6.38 and 2.6.39 which
makes the driver fail to work on my PXA300 based board. Lei and me
tried to nail these issues down, but we didn't succeed yet.


Daniel


From linux at arm.linux.org.uk  Fri Jun  3 03:54:51 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Fri, 3 Jun 2011 08:54:51 +0100
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
	<1307077842.4405.133.camel@localhost>
	<BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
Message-ID: <20110603075451.GF10532@n2100.arm.linux.org.uk>

On Fri, Jun 03, 2011 at 09:17:31AM +0400, Dmitry Eremin-Solenikov wrote:
> Anyway the patch removing mtd support can be pushed via mtd tree
> (there is really no point on mtd/maps/ceiva.c), and removing ceiva
> depends on Russell's decision.

If it's not getting any attention and no one's interested in it then
it can be removed.


From axel.lin at gmail.com  Fri Jun  3 03:58:07 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 3 Jun 2011 15:58:07 +0800
Subject: [PATCH] mtd: pxa3xx_nand: remove unused variable 'mtd'
In-Reply-To: <BANLkTikt4y3ZKJD2Ld_hxAAzjOpevEqFfA@mail.gmail.com>
References: <1307086473.7474.1.camel@phoenix>
	<BANLkTikt4y3ZKJD2Ld_hxAAzjOpevEqFfA@mail.gmail.com>
Message-ID: <BANLkTikEEMGwsACR0404r54jpFKZxX5S=w@mail.gmail.com>

> Do you actually use this driver? I'm asking because there's some sort
> of nasty regression in the changes between 2.6.38 and 2.6.39 which
> makes the driver fail to work on my PXA300 based board. Lei and me
> tried to nail these issues down, but we didn't succeed yet.

hi Daniel,

I no longer have the device handy.
Last time I use this driver on a pxa310 device is running on 2.6.37 kernel.

Regards,
Axel


From jamie at jamieiles.com  Fri Jun  3 05:20:57 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri, 3 Jun 2011 10:20:57 +0100
Subject: [PATCH] mtd: denali: remove calling mtd_device_unregister()
	after nand_release()
In-Reply-To: <1307063535.10001.1.camel@phoenix>
References: <1307063535.10001.1.camel@phoenix>
Message-ID: <20110603092057.GC2637@pulham.picochip.com>

On Fri, Jun 03, 2011 at 09:12:15AM +0800, Axel Lin wrote:
> The implementation of nand_release() already call mtd_device_unregister(),
> no need to call it again.

Good catch!

> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Acked-by: Jamie Iles <jamie at jamieiles.com>


From dbaryshkov at gmail.com  Fri Jun  3 05:21:07 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Fri, 3 Jun 2011 13:21:07 +0400
Subject: [PATCH 1/2] clps711x/ceiva: port to use physmap flash
In-Reply-To: <20110603075451.GF10532@n2100.arm.linux.org.uk>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307075905.4405.130.camel@localhost>
	<BANLkTi=TQfMec9Kuq4-P9Rokp44g67Tx6A@mail.gmail.com>
	<1307077842.4405.133.camel@localhost>
	<BANLkTimG86aN5hUBy=GgpMAxhiQSPbetPg@mail.gmail.com>
	<20110603075451.GF10532@n2100.arm.linux.org.uk>
Message-ID: <BANLkTinfbi+fMq5nbWfYyUSVTXx-263jQw@mail.gmail.com>

On 6/3/11, Russell King - ARM Linux <linux at arm.linux.org.uk> wrote:
> On Fri, Jun 03, 2011 at 09:17:31AM +0400, Dmitry Eremin-Solenikov wrote:
>> Anyway the patch removing mtd support can be pushed via mtd tree
>> (there is really no point on mtd/maps/ceiva.c), and removing ceiva
>> depends on Russell's decision.
>
> If it's not getting any attention and no one's interested in it then
> it can be removed.

I've sent a separate e-mail to ARM ML to see if anybody is interested.


-- 
With best wishes
Dmitry


From jamie at jamieiles.com  Fri Jun  3 06:17:12 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:12 +0100
Subject: [PATCH 0/6] Further Denali NAND enhancements
Message-ID: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>

This series performs a couple of minor cleanups to the Denali NAND
controller driver and then introduces support for newer versions of the
IP where ECC fixup is supported in hardware.

Finally add support for partitioning through platform data and cmdline
partitioning.

Jamie Iles (6):
  nand/denali: convert to dev_() printk helpers
  nand/denali: annotate pci init/exit functions with correct section
  nand/denali: allow the number of ECC bits to be set by pdata
  nand/denali: support hardware with internal ECC fixup
  nand/denali: support MTD partitioning
  mtd/denali: support for cmdline partitioning

 drivers/mtd/nand/denali.c            |  195 ++++++++++++++++++----------------
 drivers/mtd/nand/denali.h            |   10 ++
 include/linux/platform_data/denali.h |   26 +++++
 3 files changed, 140 insertions(+), 91 deletions(-)
 create mode 100644 include/linux/platform_data/denali.h

-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:17:14 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:14 +0100
Subject: [PATCH 2/6] nand/denali: annotate pci init/exit functions with
	correct section
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307096238-25751-3-git-send-email-jamie@jamieiles.com>

The module init exit functions should be annotated with __init and
__exit.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index a4b4a29..491458a 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1686,14 +1686,14 @@ static struct pci_driver denali_pci_driver = {
 	.remove = denali_pci_remove,
 };
 
-static int __devinit denali_init(void)
+static int __init denali_init(void)
 {
 	pr_info(KERN_INFO "Spectra MTD driver\n");
 	return pci_register_driver(&denali_pci_driver);
 }
 
 /* Free memory */
-static void __devexit denali_exit(void)
+static void __exit denali_exit(void)
 {
 	pci_unregister_driver(&denali_pci_driver);
 }
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:17:13 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:13 +0100
Subject: [PATCH 1/6] nand/denali: convert to dev_() printk helpers
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307096238-25751-2-git-send-email-jamie@jamieiles.com>

Use the dev_() printk helpers rather than printk so the name of the
device is include.  Also remove a duplicate definition of BANK().

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c |  133 ++++++++++++++++++++-------------------------
 1 files changed, 60 insertions(+), 73 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index d527621..a4b4a29 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -175,8 +175,7 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 {
 	uint32_t i;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "resetting\n");
 
 	for (i = 0 ; i < denali->max_banks; i++)
 		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
@@ -191,7 +190,8 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 		if (ioread32(denali->flash_reg + INTR_STATUS(i)) &
 			INTR_STATUS__TIME_OUT)
 			dev_dbg(denali->dev,
-			"NAND Reset operation timed out on bank %d\n", i);
+				"NAND Reset operation timed out on bank %d\n",
+				i);
 	}
 
 	for (i = 0; i < denali->max_banks; i++)
@@ -228,8 +228,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 	uint16_t acc_clks;
 	uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "init timing\n");
 
 	en_lo = CEIL_DIV(Trp[mode], CLK_X);
 	en_hi = CEIL_DIV(Treh[mode], CLK_X);
@@ -265,8 +264,8 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 		acc_clks++;
 
 	if ((data_invalid - acc_clks * CLK_X) < 2)
-		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
-			__FILE__, __LINE__);
+		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
+			 __LINE__);
 
 	addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
 	re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
@@ -394,9 +393,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 		break;
 	default:
 		dev_warn(denali->dev,
-			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
-			"Will use default parameter values instead.\n",
-			device_id);
+			 "unknown Hynix NAND (Device ID: 0x%x). Will use default parameter values instead.\n",
+			 device_id);
 	}
 }
 
@@ -415,8 +413,8 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		index_addr_read_data(denali,
 				(uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
 
-		dev_dbg(denali->dev,
-			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
+		dev_dbg(denali->dev, "Return 1st ID for bank[%d]: %x\n", i,
+			id[i]);
 
 		if (i == 0) {
 			if (!(id[i] & 0x0ff))
@@ -436,13 +434,12 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		 */
 		if (denali->total_used_banks != 1) {
 			dev_err(denali->dev,
-					"Sorry, Intel CE4100 only supports "
-					"a single NAND device.\n");
+				"Sorry, Intel CE4100 only supports a single NAND device.\n");
 			BUG();
 		}
 	}
-	dev_dbg(denali->dev,
-		"denali->total_used_banks: %d\n", denali->total_used_banks);
+	dev_dbg(denali->dev, "denali->total_used_banks: %d\n",
+		denali->total_used_banks);
 }
 
 /*
@@ -486,9 +483,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	uint32_t id_bytes[5], addr;
 	uint8_t i, maf_id, device_id;
 
-	dev_dbg(denali->dev,
-			"%s, Line %d, Function: %s\n",
-			__FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "set the timing\n");
 
 	/* Use read id method to get device ID and other
 	 * params. For some NAND chips, controller can't
@@ -516,18 +511,17 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	}
 
 	dev_info(denali->dev,
-			"Dump timing register values:"
-			"acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
-			"we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
-			"rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
-			ioread32(denali->flash_reg + ACC_CLKS),
-			ioread32(denali->flash_reg + RE_2_WE),
-			ioread32(denali->flash_reg + RE_2_RE),
-			ioread32(denali->flash_reg + WE_2_RE),
-			ioread32(denali->flash_reg + ADDR_2_DATA),
-			ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
-			ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
-			ioread32(denali->flash_reg + CS_SETUP_CNT));
+		 "Dump timing register values: acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
+		 "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
+		 "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
+		 ioread32(denali->flash_reg + ACC_CLKS),
+		 ioread32(denali->flash_reg + RE_2_WE),
+		 ioread32(denali->flash_reg + RE_2_RE),
+		 ioread32(denali->flash_reg + WE_2_RE),
+		 ioread32(denali->flash_reg + ADDR_2_DATA),
+		 ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
+		 ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
+		 ioread32(denali->flash_reg + CS_SETUP_CNT));
 
 	find_valid_banks(denali);
 
@@ -545,8 +539,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "set interrupt modes\n");
 
 	if (INT_ENABLE)
 		iowrite32(1, denali->flash_reg + GLOBAL_INT_ENABLE);
@@ -669,7 +662,6 @@ static irqreturn_t denali_isr(int irq, void *dev_id)
 	spin_unlock(&denali->irq_lock);
 	return result;
 }
-#define BANK(x) ((x) << 24)
 
 static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 {
@@ -699,8 +691,9 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 
 	if (comp_res == 0) {
 		/* timeout */
-		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
-				intr_status, irq_mask);
+		dev_err(&denali->mtd.dev,
+			"timeout occurred, status = 0x%x, mask = 0x%x\n",
+			intr_status, irq_mask);
 
 		intr_status = 0;
 	}
@@ -785,9 +778,8 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
 
 			if (irq_status == 0) {
 				dev_err(denali->dev,
-						"cmd, page, addr on timeout "
-						"(0x%x, 0x%x, 0x%x)\n",
-						cmd, denali->page, addr);
+					"cmd, page, addr on timeout (0x%x, 0x%x, 0x%x)\n",
+					cmd, denali->page, addr);
 				status = FAIL;
 			} else {
 				cmd = MODE_01 | addr;
@@ -889,7 +881,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 
 		if (irq_status == 0)
 			dev_err(denali->dev, "page on OOB timeout %d\n",
-					denali->page);
+				denali->page);
 
 		/* We set the device back to MAIN_ACCESS here as I observed
 		 * instability with the controller if you do a block erase
@@ -1065,9 +1057,8 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	irq_status = wait_for_irq(denali, irq_mask);
 
 	if (irq_status == 0) {
-		dev_err(denali->dev,
-				"timeout on write_page (type = %d)\n",
-				raw_xfer);
+		dev_err(denali->dev, "timeout on write_page (type = %d)\n",
+			raw_xfer);
 		denali->status =
 			(irq_status & INTR_STATUS__PROGRAM_FAIL) ?
 			NAND_STATUS_FAIL : PASS;
@@ -1132,9 +1123,9 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
-		dev_err(denali->dev, "IN %s: page %d is not"
-				" equal to denali->page %d, investigate!!",
-				__func__, page, denali->page);
+		dev_err(denali->dev,
+			"IN %s: page %d is not equal to denali->page %d, investigate!!",
+			__func__, page, denali->page);
 		BUG();
 	}
 
@@ -1182,9 +1173,8 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
 
 	if (page != denali->page) {
-		dev_err(denali->dev, "IN %s: page %d is not"
-				" equal to denali->page %d, investigate!!",
-				__func__, page, denali->page);
+		dev_err(denali->dev, "IN %s: page %d is not equal to denali->page %d, investigate!!",
+			__func__, page, denali->page);
 		BUG();
 	}
 
@@ -1300,8 +1290,8 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 		/* TODO: Read OOB data */
 		break;
 	default:
-		printk(KERN_ERR ": unsupported command"
-				" received 0x%x\n", cmd);
+		dev_err(&denali->mtd.dev, "unsupported command received 0x%x\n",
+			cmd);
 		break;
 	}
 }
@@ -1311,8 +1301,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
 				uint8_t *ecc_code)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_calculate called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_calculate called unexpectedly\n");
 	BUG();
 	return -EIO;
 }
@@ -1321,8 +1310,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_correct called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_correct called unexpectedly\n");
 	BUG();
 	return -EIO;
 }
@@ -1330,8 +1318,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_hwctl called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_hwctl called unexpectedly\n");
 	BUG();
 }
 /* end NAND core entry points */
@@ -1432,9 +1419,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (!denali)
 		return -ENOMEM;
 
+	denali->dev = &dev->dev;
+
 	ret = pci_enable_device(dev);
 	if (ret) {
-		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
+		dev_err(denali->dev, "Spectra: pci_enable_device failed.\n");
 		goto failed_alloc_memery;
 	}
 
@@ -1443,8 +1432,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		 * ONFI timing mode 1 and below.
 		 */
 		if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
-			printk(KERN_ERR "Intel CE4100 only supports"
-					" ONFI timing mode 1 or below\n");
+			dev_err(denali->dev, "Intel CE4100 only supports ONFI timing mode 1 or below\n");
 			ret = -EINVAL;
 			goto failed_enable_dev;
 		}
@@ -1468,38 +1456,37 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	/* Is 32-bit DMA supported? */
 	ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
 	if (ret) {
-		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
+		dev_err(denali->dev, "Spectra: no usable DMA configuration\n");
 		goto failed_enable_dev;
 	}
 	denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
 					     DENALI_BUF_SIZE,
 					     DMA_BIDIRECTIONAL);
 
-	if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
+	if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
 		dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
 		goto failed_enable_dev;
 	}
 
 	pci_set_master(dev);
-	denali->dev = &dev->dev;
 	denali->mtd.dev.parent = &dev->dev;
 
 	ret = pci_request_regions(dev, DENALI_NAND_NAME);
 	if (ret) {
-		printk(KERN_ERR "Spectra: Unable to request memory regions\n");
+		dev_err(denali->dev, "Spectra: Unable to request memory regions\n");
 		goto failed_dma_map;
 	}
 
 	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
 	if (!denali->flash_reg) {
-		printk(KERN_ERR "Spectra: Unable to remap memory region\n");
+		dev_err(denali->dev, "Spectra: Unable to remap memory region\n");
 		ret = -ENOMEM;
 		goto failed_req_regions;
 	}
 
 	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
 	if (!denali->flash_mem) {
-		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
+		dev_err(denali->dev, "Spectra: ioremap_nocache failed!");
 		ret = -ENOMEM;
 		goto failed_remap_reg;
 	}
@@ -1511,7 +1498,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	 * initilization is finished*/
 	if (request_irq(dev->irq, denali_isr, IRQF_SHARED,
 			DENALI_NAND_NAME, denali)) {
-		printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
+		dev_err(denali->dev, "Spectra: Unable to allocate IRQ\n");
 		ret = -ENODEV;
 		goto failed_remap_mem;
 	}
@@ -1544,8 +1531,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	 */
 	if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
 		ret = -ENODEV;
-		printk(KERN_ERR "Spectra: device size not supported by this "
-			"version of MTD.");
+		dev_err(denali->dev,
+			"device size not supported by this version of MTD.");
 		goto failed_req_irq;
 	}
 
@@ -1595,8 +1582,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
 			ECC_8BITS * (denali->mtd.writesize /
 			ECC_SECTOR_SIZE))) {
-		printk(KERN_ERR "Your NAND chip OOB is not large enough to"
-				" contain 8bit ECC correction codes");
+		dev_err(&denali->mtd.dev,
+			"Your NAND chip OOB is not large enough to contain 8bit ECC correction codes");
 		goto failed_req_irq;
 	} else {
 		denali->nand.ecc.layout = &nand_8bit_oob;
@@ -1646,7 +1633,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	ret = mtd_device_register(&denali->mtd, NULL, 0);
 	if (ret) {
-		dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
+		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
 		goto failed_req_irq;
 	}
@@ -1701,7 +1688,7 @@ static struct pci_driver denali_pci_driver = {
 
 static int __devinit denali_init(void)
 {
-	printk(KERN_INFO "Spectra MTD driver\n");
+	pr_info(KERN_INFO "Spectra MTD driver\n");
 	return pci_register_driver(&denali_pci_driver);
 }
 
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:17:15 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:15 +0100
Subject: =?UTF-8?q?=5BPATCH=203/6=5D=20nand/denali=3A=20allow=20the=20number=20of=20ECC=20bits=20to=20be=20set=20by=20pdata?=
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307096238-25751-4-git-send-email-jamie@jamieiles.com>

Rather than having the number of ECC bits to be used set by a
preprocessor definition, allow it to be set by platform_data.  If there
is no platform_data then default to 8 bit ECC.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c            |   25 +++++++++++++------------
 drivers/mtd/nand/denali.h            |    1 +
 include/linux/platform_data/denali.h |   21 +++++++++++++++++++++
 3 files changed, 35 insertions(+), 12 deletions(-)
 create mode 100644 include/linux/platform_data/denali.h

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 491458a..f6bbafb 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
+#include <linux/platform_data/denali.h>
 
 #include "denali.h"
 
@@ -60,8 +61,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
  * valid or not */
 #define CHIP_SELECT_INVALID	-1
 
-#define SUPPORT_8BITECC		1
-
 /* This macro divides two integers and rounds fractional values up
  * to the nearest integer value. */
 #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
@@ -357,11 +356,8 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali)
 			ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 		iowrite32(tmp,
 				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
-#if SUPPORT_15BITECC
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
+		iowrite32(denali->nr_ecc_bits,
+			  denali->flash_reg + ECC_CORRECTION);
 	}
 }
 
@@ -385,11 +381,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 		iowrite32(spare_size,
 				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
 		iowrite32(0, denali->flash_reg + DEVICE_WIDTH);
-#if SUPPORT_15BITECC
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
+		iowrite32(denali->nr_ecc_bits,
+			  denali->flash_reg + ECC_CORRECTION);
 		break;
 	default:
 		dev_warn(denali->dev,
@@ -1414,6 +1407,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	resource_size_t csr_base, mem_base;
 	unsigned long csr_len, mem_len;
 	struct denali_nand_info *denali;
+	int ret;
+	struct denali_nand_pdata *pdata;
 
 	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
 	if (!denali)
@@ -1421,6 +1416,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	denali->dev = &dev->dev;
 
+	pdata = dev_get_platdata(denali->dev);
+	if (pdata && pdata->nr_ecc_bits > 8)
+		denali->nr_ecc_bits = pdata->nr_ecc_bits;
+	else
+		denali->nr_ecc_bits = 8;
+
 	ret = pci_enable_device(dev);
 	if (ret) {
 		dev_err(denali->dev, "Spectra: pci_enable_device failed.\n");
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index fabb9d5..b428ce3 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -494,6 +494,7 @@ struct denali_nand_info {
 	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
+	int nr_ecc_bits;
 };
 
 #endif /*_LLD_NAND_*/
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
new file mode 100644
index 0000000..cfdb775
--- /dev/null
+++ b/include/linux/platform_data/denali.h
@@ -0,0 +1,21 @@
+/*
+ * NAND flash controller device driver platform data.
+ * Copyright ? 2011, Picochip
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#ifndef __DENALI_PDATA_H__
+#define __DENALI_PDATA_H__
+
+struct denali_nand_pdata {
+	int	nr_ecc_bits;
+};
+
+#endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:17:16 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:16 +0100
Subject: [PATCH 4/6] nand/denali: support hardware with internal ECC fixup
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307096238-25751-5-git-send-email-jamie@jamieiles.com>

Some versions of the IP have the ECC fixup handled in hardware.  For
these devices we have a new interrupt status/enable mapping that tells
us when we have an uncorrectable error.  Unfortunately this replaces
existing interrupt bits and there is no way to probe for this capability
so we have to do it through platform data.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c            |   18 +++++++++++++++---
 drivers/mtd/nand/denali.h            |    9 +++++++++
 include/linux/platform_data/denali.h |    1 +
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index f6bbafb..fb8e49e 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -55,7 +55,8 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
 			INTR_STATUS__TIME_OUT | \
 			INTR_STATUS__ERASE_FAIL | \
 			INTR_STATUS__RST_COMP | \
-			INTR_STATUS__ERASE_COMP)
+			INTR_STATUS__ERASE_COMP | \
+			INTR_STATUS__ECC_UNCOR_ERR)
 
 /* indicates whether or not the internal value for the flash bank is
  * valid or not */
@@ -913,6 +914,14 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
 {
 	bool check_erased_page = false;
 
+	if (denali->have_hw_ecc_fixup &&
+	    (irq_status & INTR_STATUS__ECC_UNCOR_ERR)) {
+		clear_interrupts(denali);
+		denali_set_intr_modes(denali, true);
+
+		return true;
+	}
+
 	if (irq_status & INTR_STATUS__ECC_ERR) {
 		/* read the ECC errors. we'll ignore them for now */
 		uint32_t err_address = 0, err_correction_info = 0;
@@ -1111,8 +1120,9 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE |
-			    INTR_STATUS__ECC_ERR;
+	uint32_t irq_mask = denali->have_hw_ecc_fixup ?
+		(INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR) :
+		(INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__ECC_UNCOR_ERR);
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
@@ -1428,6 +1438,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_alloc_memery;
 	}
 
+	denali->have_hw_ecc_fixup = pdata ? pdata->have_hw_ecc_fixup : false;
+
 	if (id->driver_data == INTEL_CE4100) {
 		/* Due to a silicon limitation, we can only support
 		 * ONFI timing mode 1 and below.
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index b428ce3..f0b5e91 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -231,6 +231,14 @@
 #define     INTR_STATUS__PIPE_CMD_ERR			0x4000
 #define     INTR_STATUS__PAGE_XFER_INC			0x8000
 
+/*
+ * Some versions of the IP have the ECC fixup handled in hardware.  In this
+ * configuration we only get interrupted when the error is uncorrectable.
+ * Unfortunately this bit replaces INTR_STATUS__ECC_TRANSACTION_DONE from the
+ * old IP.
+ */
+#define     INTR_STATUS__ECC_UNCOR_ERR			0x0001
+
 #define     INTR_EN__ECC_TRANSACTION_DONE		0x0001
 #define     INTR_EN__ECC_ERR				0x0002
 #define     INTR_EN__DMA_CMD_COMP			0x0004
@@ -495,6 +503,7 @@ struct denali_nand_info {
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
 	int nr_ecc_bits;
+	bool have_hw_ecc_fixup;
 };
 
 #endif /*_LLD_NAND_*/
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
index cfdb775..3767333 100644
--- a/include/linux/platform_data/denali.h
+++ b/include/linux/platform_data/denali.h
@@ -16,6 +16,7 @@
 
 struct denali_nand_pdata {
 	int	nr_ecc_bits;
+	bool	have_hw_ecc_fixup;
 };
 
 #endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:17:17 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:17 +0100
Subject: [PATCH 5/6] nand/denali: support MTD partitioning
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307096238-25751-6-git-send-email-jamie@jamieiles.com>

Allow the platform to specify partitions through platform data.  If
there are no partitions specified then the whole device will be
registered.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c            |    8 +++++++-
 include/linux/platform_data/denali.h |    8 ++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index fb8e49e..19998ed 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 #include <linux/module.h>
 #include <linux/platform_data/denali.h>
 
@@ -1644,7 +1645,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_req_irq;
 	}
 
-	ret = mtd_device_register(&denali->mtd, NULL, 0);
+	if (pdata && pdata->parts)
+		ret = mtd_device_register(&denali->mtd, pdata->parts,
+					 pdata->nr_parts);
+	else
+		ret = mtd_device_register(&denali->mtd, NULL, 0);
+
 	if (ret) {
 		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
index 3767333..141da35 100644
--- a/include/linux/platform_data/denali.h
+++ b/include/linux/platform_data/denali.h
@@ -14,9 +14,13 @@
 #ifndef __DENALI_PDATA_H__
 #define __DENALI_PDATA_H__
 
+struct mtd_partition;
+
 struct denali_nand_pdata {
-	int	nr_ecc_bits;
-	bool	have_hw_ecc_fixup;
+	int				nr_ecc_bits;
+	bool				have_hw_ecc_fixup;
+	const struct mtd_partition	*parts;
+	unsigned int			nr_parts;
 };
 
 #endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:17:18 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:17:18 +0100
Subject: [PATCH 6/6] mtd/denali: support for cmdline partitioning
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307096238-25751-7-git-send-email-jamie@jamieiles.com>

Add support for command line partitioning.  This is favoured over
platform data based partitions.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 19998ed..4e440d6 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1420,6 +1420,9 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	struct denali_nand_info *denali;
 	int ret;
 	struct denali_nand_pdata *pdata;
+	struct mtd_partition *partitions = NULL;
+	int nr_parts = 0;
+	const char *part_probes[] = { "cmdlinepart", NULL };
 
 	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
 	if (!denali)
@@ -1645,7 +1648,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_req_irq;
 	}
 
-	if (pdata && pdata->parts)
+	nr_parts = parse_mtd_partitions(&denali->mtd, part_probes,
+					&partitions, 0);
+	if (partitions && nr_parts > 0)
+		ret = mtd_device_register(&denali->mtd, partitions, nr_parts);
+	else if (pdata && pdata->parts)
 		ret = mtd_device_register(&denali->mtd, pdata->parts,
 					 pdata->nr_parts);
 	else
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:31:49 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri, 3 Jun 2011 11:31:49 +0100
Subject: [PATCH 0/6] Further Denali NAND enhancements
In-Reply-To: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
References: <1307096238-25751-1-git-send-email-jamie@jamieiles.com>
Message-ID: <20110603103149.GI2637@pulham.picochip.com>

On Fri, Jun 03, 2011 at 11:17:12AM +0100, Jamie Iles wrote:
> This series performs a couple of minor cleanups to the Denali NAND
> controller driver and then introduces support for newer versions of the
> IP where ECC fixup is supported in hardware.
> 
> Finally add support for partitioning through platform data and cmdline
> partitioning.
> 
> Jamie Iles (6):
>   nand/denali: convert to dev_() printk helpers
>   nand/denali: annotate pci init/exit functions with correct section
>   nand/denali: allow the number of ECC bits to be set by pdata
>   nand/denali: support hardware with internal ECC fixup
>   nand/denali: support MTD partitioning
>   mtd/denali: support for cmdline partitioning

Please disregard this series; I was too trigger happy with git 
send-email after a rebase.  A respin follows with apologies.

Jamie


From jamie at jamieiles.com  Fri Jun  3 06:32:43 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:43 +0100
Subject: [PATCHv2 0/6] Further Denali NAND enhancements
Message-ID: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>

This series performs a couple of minor cleanups to the Denali NAND                                                                                                                                                                                                                                                             
controller driver and then introduces support for newer versions of the                                                                                                                                                                                                                                                        
IP where ECC fixup is supported in hardware.                                                                                                                                                                                                                                                                                   
                                                                                                                                                                                                                                                                                                                               
Finally add support for partitioning through platform data and cmdline                                                                                                                                                                                                                                                         
partitioning.

Jamie Iles (6):
  nand/denali: convert to dev_() printk helpers
  nand/denali: annotate pci init/exit functions with correct section
  nand/denali: allow the number of ECC bits to be set by pdata
  nand/denali: support hardware with internal ECC fixup
  nand/denali: support MTD partitioning
  mtd/denali: support for cmdline partitioning

 drivers/mtd/nand/denali.c            |  194 ++++++++++++++++++----------------
 drivers/mtd/nand/denali.h            |   10 ++
 include/linux/platform_data/denali.h |   26 +++++
 3 files changed, 139 insertions(+), 91 deletions(-)
 create mode 100644 include/linux/platform_data/denali.h

-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:32:44 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:44 +0100
Subject: [PATCHv2 1/6] nand/denali: convert to dev_() printk helpers
In-Reply-To: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307097169-11744-2-git-send-email-jamie@jamieiles.com>

Use the dev_() printk helpers rather than printk so the name of the
device is include.  Also remove a duplicate definition of BANK().

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c |  133 ++++++++++++++++++++-------------------------
 1 files changed, 60 insertions(+), 73 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index d527621..a4b4a29 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -175,8 +175,7 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 {
 	uint32_t i;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "resetting\n");
 
 	for (i = 0 ; i < denali->max_banks; i++)
 		iowrite32(INTR_STATUS__RST_COMP | INTR_STATUS__TIME_OUT,
@@ -191,7 +190,8 @@ static uint16_t denali_nand_reset(struct denali_nand_info *denali)
 		if (ioread32(denali->flash_reg + INTR_STATUS(i)) &
 			INTR_STATUS__TIME_OUT)
 			dev_dbg(denali->dev,
-			"NAND Reset operation timed out on bank %d\n", i);
+				"NAND Reset operation timed out on bank %d\n",
+				i);
 	}
 
 	for (i = 0; i < denali->max_banks; i++)
@@ -228,8 +228,7 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 	uint16_t acc_clks;
 	uint16_t addr_2_data, re_2_we, re_2_re, we_2_re, cs_cnt;
 
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "init timing\n");
 
 	en_lo = CEIL_DIV(Trp[mode], CLK_X);
 	en_hi = CEIL_DIV(Treh[mode], CLK_X);
@@ -265,8 +264,8 @@ static void nand_onfi_timing_set(struct denali_nand_info *denali,
 		acc_clks++;
 
 	if ((data_invalid - acc_clks * CLK_X) < 2)
-		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
-			__FILE__, __LINE__);
+		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
+			 __LINE__);
 
 	addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
 	re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
@@ -394,9 +393,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 		break;
 	default:
 		dev_warn(denali->dev,
-			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
-			"Will use default parameter values instead.\n",
-			device_id);
+			 "unknown Hynix NAND (Device ID: 0x%x). Will use default parameter values instead.\n",
+			 device_id);
 	}
 }
 
@@ -415,8 +413,8 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		index_addr_read_data(denali,
 				(uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
 
-		dev_dbg(denali->dev,
-			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
+		dev_dbg(denali->dev, "Return 1st ID for bank[%d]: %x\n", i,
+			id[i]);
 
 		if (i == 0) {
 			if (!(id[i] & 0x0ff))
@@ -436,13 +434,12 @@ static void find_valid_banks(struct denali_nand_info *denali)
 		 */
 		if (denali->total_used_banks != 1) {
 			dev_err(denali->dev,
-					"Sorry, Intel CE4100 only supports "
-					"a single NAND device.\n");
+				"Sorry, Intel CE4100 only supports a single NAND device.\n");
 			BUG();
 		}
 	}
-	dev_dbg(denali->dev,
-		"denali->total_used_banks: %d\n", denali->total_used_banks);
+	dev_dbg(denali->dev, "denali->total_used_banks: %d\n",
+		denali->total_used_banks);
 }
 
 /*
@@ -486,9 +483,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	uint32_t id_bytes[5], addr;
 	uint8_t i, maf_id, device_id;
 
-	dev_dbg(denali->dev,
-			"%s, Line %d, Function: %s\n",
-			__FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "set the timing\n");
 
 	/* Use read id method to get device ID and other
 	 * params. For some NAND chips, controller can't
@@ -516,18 +511,17 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 	}
 
 	dev_info(denali->dev,
-			"Dump timing register values:"
-			"acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
-			"we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
-			"rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
-			ioread32(denali->flash_reg + ACC_CLKS),
-			ioread32(denali->flash_reg + RE_2_WE),
-			ioread32(denali->flash_reg + RE_2_RE),
-			ioread32(denali->flash_reg + WE_2_RE),
-			ioread32(denali->flash_reg + ADDR_2_DATA),
-			ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
-			ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
-			ioread32(denali->flash_reg + CS_SETUP_CNT));
+		 "Dump timing register values: acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
+		 "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
+		 "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
+		 ioread32(denali->flash_reg + ACC_CLKS),
+		 ioread32(denali->flash_reg + RE_2_WE),
+		 ioread32(denali->flash_reg + RE_2_RE),
+		 ioread32(denali->flash_reg + WE_2_RE),
+		 ioread32(denali->flash_reg + ADDR_2_DATA),
+		 ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
+		 ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
+		 ioread32(denali->flash_reg + CS_SETUP_CNT));
 
 	find_valid_banks(denali);
 
@@ -545,8 +539,7 @@ static uint16_t denali_nand_timing_set(struct denali_nand_info *denali)
 static void denali_set_intr_modes(struct denali_nand_info *denali,
 					uint16_t INT_ENABLE)
 {
-	dev_dbg(denali->dev, "%s, Line %d, Function: %s\n",
-		       __FILE__, __LINE__, __func__);
+	dev_dbg(denali->dev, "set interrupt modes\n");
 
 	if (INT_ENABLE)
 		iowrite32(1, denali->flash_reg + GLOBAL_INT_ENABLE);
@@ -669,7 +662,6 @@ static irqreturn_t denali_isr(int irq, void *dev_id)
 	spin_unlock(&denali->irq_lock);
 	return result;
 }
-#define BANK(x) ((x) << 24)
 
 static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 {
@@ -699,8 +691,9 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
 
 	if (comp_res == 0) {
 		/* timeout */
-		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
-				intr_status, irq_mask);
+		dev_err(&denali->mtd.dev,
+			"timeout occurred, status = 0x%x, mask = 0x%x\n",
+			intr_status, irq_mask);
 
 		intr_status = 0;
 	}
@@ -785,9 +778,8 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
 
 			if (irq_status == 0) {
 				dev_err(denali->dev,
-						"cmd, page, addr on timeout "
-						"(0x%x, 0x%x, 0x%x)\n",
-						cmd, denali->page, addr);
+					"cmd, page, addr on timeout (0x%x, 0x%x, 0x%x)\n",
+					cmd, denali->page, addr);
 				status = FAIL;
 			} else {
 				cmd = MODE_01 | addr;
@@ -889,7 +881,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
 
 		if (irq_status == 0)
 			dev_err(denali->dev, "page on OOB timeout %d\n",
-					denali->page);
+				denali->page);
 
 		/* We set the device back to MAIN_ACCESS here as I observed
 		 * instability with the controller if you do a block erase
@@ -1065,9 +1057,8 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
 	irq_status = wait_for_irq(denali, irq_mask);
 
 	if (irq_status == 0) {
-		dev_err(denali->dev,
-				"timeout on write_page (type = %d)\n",
-				raw_xfer);
+		dev_err(denali->dev, "timeout on write_page (type = %d)\n",
+			raw_xfer);
 		denali->status =
 			(irq_status & INTR_STATUS__PROGRAM_FAIL) ?
 			NAND_STATUS_FAIL : PASS;
@@ -1132,9 +1123,9 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
-		dev_err(denali->dev, "IN %s: page %d is not"
-				" equal to denali->page %d, investigate!!",
-				__func__, page, denali->page);
+		dev_err(denali->dev,
+			"IN %s: page %d is not equal to denali->page %d, investigate!!",
+			__func__, page, denali->page);
 		BUG();
 	}
 
@@ -1182,9 +1173,8 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
 
 	if (page != denali->page) {
-		dev_err(denali->dev, "IN %s: page %d is not"
-				" equal to denali->page %d, investigate!!",
-				__func__, page, denali->page);
+		dev_err(denali->dev, "IN %s: page %d is not equal to denali->page %d, investigate!!",
+			__func__, page, denali->page);
 		BUG();
 	}
 
@@ -1300,8 +1290,8 @@ static void denali_cmdfunc(struct mtd_info *mtd, unsigned int cmd, int col,
 		/* TODO: Read OOB data */
 		break;
 	default:
-		printk(KERN_ERR ": unsupported command"
-				" received 0x%x\n", cmd);
+		dev_err(&denali->mtd.dev, "unsupported command received 0x%x\n",
+			cmd);
 		break;
 	}
 }
@@ -1311,8 +1301,7 @@ static int denali_ecc_calculate(struct mtd_info *mtd, const uint8_t *data,
 				uint8_t *ecc_code)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_calculate called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_calculate called unexpectedly\n");
 	BUG();
 	return -EIO;
 }
@@ -1321,8 +1310,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 				uint8_t *read_ecc, uint8_t *calc_ecc)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_correct called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_correct called unexpectedly\n");
 	BUG();
 	return -EIO;
 }
@@ -1330,8 +1318,7 @@ static int denali_ecc_correct(struct mtd_info *mtd, uint8_t *data,
 static void denali_ecc_hwctl(struct mtd_info *mtd, int mode)
 {
 	struct denali_nand_info *denali = mtd_to_denali(mtd);
-	dev_err(denali->dev,
-			"denali_ecc_hwctl called unexpectedly\n");
+	dev_err(denali->dev, "denali_ecc_hwctl called unexpectedly\n");
 	BUG();
 }
 /* end NAND core entry points */
@@ -1432,9 +1419,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	if (!denali)
 		return -ENOMEM;
 
+	denali->dev = &dev->dev;
+
 	ret = pci_enable_device(dev);
 	if (ret) {
-		printk(KERN_ERR "Spectra: pci_enable_device failed.\n");
+		dev_err(denali->dev, "Spectra: pci_enable_device failed.\n");
 		goto failed_alloc_memery;
 	}
 
@@ -1443,8 +1432,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		 * ONFI timing mode 1 and below.
 		 */
 		if (onfi_timing_mode < -1 || onfi_timing_mode > 1) {
-			printk(KERN_ERR "Intel CE4100 only supports"
-					" ONFI timing mode 1 or below\n");
+			dev_err(denali->dev, "Intel CE4100 only supports ONFI timing mode 1 or below\n");
 			ret = -EINVAL;
 			goto failed_enable_dev;
 		}
@@ -1468,38 +1456,37 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	/* Is 32-bit DMA supported? */
 	ret = dma_set_mask(&dev->dev, DMA_BIT_MASK(32));
 	if (ret) {
-		printk(KERN_ERR "Spectra: no usable DMA configuration\n");
+		dev_err(denali->dev, "Spectra: no usable DMA configuration\n");
 		goto failed_enable_dev;
 	}
 	denali->buf.dma_buf = dma_map_single(&dev->dev, denali->buf.buf,
 					     DENALI_BUF_SIZE,
 					     DMA_BIDIRECTIONAL);
 
-	if (dma_mapping_error(&dev->dev, denali->buf.dma_buf)) {
+	if (dma_mapping_error(denali->dev, denali->buf.dma_buf)) {
 		dev_err(&dev->dev, "Spectra: failed to map DMA buffer\n");
 		goto failed_enable_dev;
 	}
 
 	pci_set_master(dev);
-	denali->dev = &dev->dev;
 	denali->mtd.dev.parent = &dev->dev;
 
 	ret = pci_request_regions(dev, DENALI_NAND_NAME);
 	if (ret) {
-		printk(KERN_ERR "Spectra: Unable to request memory regions\n");
+		dev_err(denali->dev, "Spectra: Unable to request memory regions\n");
 		goto failed_dma_map;
 	}
 
 	denali->flash_reg = ioremap_nocache(csr_base, csr_len);
 	if (!denali->flash_reg) {
-		printk(KERN_ERR "Spectra: Unable to remap memory region\n");
+		dev_err(denali->dev, "Spectra: Unable to remap memory region\n");
 		ret = -ENOMEM;
 		goto failed_req_regions;
 	}
 
 	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
 	if (!denali->flash_mem) {
-		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
+		dev_err(denali->dev, "Spectra: ioremap_nocache failed!");
 		ret = -ENOMEM;
 		goto failed_remap_reg;
 	}
@@ -1511,7 +1498,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	 * initilization is finished*/
 	if (request_irq(dev->irq, denali_isr, IRQF_SHARED,
 			DENALI_NAND_NAME, denali)) {
-		printk(KERN_ERR "Spectra: Unable to allocate IRQ\n");
+		dev_err(denali->dev, "Spectra: Unable to allocate IRQ\n");
 		ret = -ENODEV;
 		goto failed_remap_mem;
 	}
@@ -1544,8 +1531,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	 */
 	if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
 		ret = -ENODEV;
-		printk(KERN_ERR "Spectra: device size not supported by this "
-			"version of MTD.");
+		dev_err(denali->dev,
+			"device size not supported by this version of MTD.");
 		goto failed_req_irq;
 	}
 
@@ -1595,8 +1582,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	} else if (denali->mtd.oobsize < (denali->bbtskipbytes +
 			ECC_8BITS * (denali->mtd.writesize /
 			ECC_SECTOR_SIZE))) {
-		printk(KERN_ERR "Your NAND chip OOB is not large enough to"
-				" contain 8bit ECC correction codes");
+		dev_err(&denali->mtd.dev,
+			"Your NAND chip OOB is not large enough to contain 8bit ECC correction codes");
 		goto failed_req_irq;
 	} else {
 		denali->nand.ecc.layout = &nand_8bit_oob;
@@ -1646,7 +1633,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	ret = mtd_device_register(&denali->mtd, NULL, 0);
 	if (ret) {
-		dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
+		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
 		goto failed_req_irq;
 	}
@@ -1701,7 +1688,7 @@ static struct pci_driver denali_pci_driver = {
 
 static int __devinit denali_init(void)
 {
-	printk(KERN_INFO "Spectra MTD driver\n");
+	pr_info(KERN_INFO "Spectra MTD driver\n");
 	return pci_register_driver(&denali_pci_driver);
 }
 
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:32:45 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:45 +0100
Subject: [PATCHv2 2/6] nand/denali: annotate pci init/exit functions with
	correct section
In-Reply-To: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307097169-11744-3-git-send-email-jamie@jamieiles.com>

The module init exit functions should be annotated with __init and
__exit.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index a4b4a29..491458a 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1686,14 +1686,14 @@ static struct pci_driver denali_pci_driver = {
 	.remove = denali_pci_remove,
 };
 
-static int __devinit denali_init(void)
+static int __init denali_init(void)
 {
 	pr_info(KERN_INFO "Spectra MTD driver\n");
 	return pci_register_driver(&denali_pci_driver);
 }
 
 /* Free memory */
-static void __devexit denali_exit(void)
+static void __exit denali_exit(void)
 {
 	pci_unregister_driver(&denali_pci_driver);
 }
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:32:46 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:46 +0100
Subject: =?UTF-8?q?=5BPATCHv2=203/6=5D=20nand/denali=3A=20allow=20the=20number=20of=20ECC=20bits=20to=20be=20set=20by=20pdata?=
In-Reply-To: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307097169-11744-4-git-send-email-jamie@jamieiles.com>

Rather than having the number of ECC bits to be used set by a
preprocessor definition, allow it to be set by platform_data.  If there
is no platform_data then default to 8 bit ECC.

Changes since v1: fixup compile error introduced from a bad rebase.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c            |   24 ++++++++++++------------
 drivers/mtd/nand/denali.h            |    1 +
 include/linux/platform_data/denali.h |   21 +++++++++++++++++++++
 3 files changed, 34 insertions(+), 12 deletions(-)
 create mode 100644 include/linux/platform_data/denali.h

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 491458a..5557d7b 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -26,6 +26,7 @@
 #include <linux/pci.h>
 #include <linux/mtd/mtd.h>
 #include <linux/module.h>
+#include <linux/platform_data/denali.h>
 
 #include "denali.h"
 
@@ -60,8 +61,6 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
  * valid or not */
 #define CHIP_SELECT_INVALID	-1
 
-#define SUPPORT_8BITECC		1
-
 /* This macro divides two integers and rounds fractional values up
  * to the nearest integer value. */
 #define CEIL_DIV(X, Y) (((X)%(Y)) ? ((X)/(Y)+1) : ((X)/(Y)))
@@ -357,11 +356,8 @@ static void get_toshiba_nand_para(struct denali_nand_info *denali)
 			ioread32(denali->flash_reg + DEVICE_SPARE_AREA_SIZE);
 		iowrite32(tmp,
 				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
-#if SUPPORT_15BITECC
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
+		iowrite32(denali->nr_ecc_bits,
+			  denali->flash_reg + ECC_CORRECTION);
 	}
 }
 
@@ -385,11 +381,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
 		iowrite32(spare_size,
 				denali->flash_reg + LOGICAL_PAGE_SPARE_SIZE);
 		iowrite32(0, denali->flash_reg + DEVICE_WIDTH);
-#if SUPPORT_15BITECC
-		iowrite32(15, denali->flash_reg + ECC_CORRECTION);
-#elif SUPPORT_8BITECC
-		iowrite32(8, denali->flash_reg + ECC_CORRECTION);
-#endif
+		iowrite32(denali->nr_ecc_bits,
+			  denali->flash_reg + ECC_CORRECTION);
 		break;
 	default:
 		dev_warn(denali->dev,
@@ -1414,6 +1407,7 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	resource_size_t csr_base, mem_base;
 	unsigned long csr_len, mem_len;
 	struct denali_nand_info *denali;
+	struct denali_nand_pdata *pdata;
 
 	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
 	if (!denali)
@@ -1421,6 +1415,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 
 	denali->dev = &dev->dev;
 
+	pdata = dev_get_platdata(denali->dev);
+	if (pdata && pdata->nr_ecc_bits > 8)
+		denali->nr_ecc_bits = pdata->nr_ecc_bits;
+	else
+		denali->nr_ecc_bits = 8;
+
 	ret = pci_enable_device(dev);
 	if (ret) {
 		dev_err(denali->dev, "Spectra: pci_enable_device failed.\n");
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index fabb9d5..b428ce3 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -494,6 +494,7 @@ struct denali_nand_info {
 	uint32_t blksperchip;
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
+	int nr_ecc_bits;
 };
 
 #endif /*_LLD_NAND_*/
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
new file mode 100644
index 0000000..cfdb775
--- /dev/null
+++ b/include/linux/platform_data/denali.h
@@ -0,0 +1,21 @@
+/*
+ * NAND flash controller device driver platform data.
+ * Copyright ? 2011, Picochip
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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.
+ */
+#ifndef __DENALI_PDATA_H__
+#define __DENALI_PDATA_H__
+
+struct denali_nand_pdata {
+	int	nr_ecc_bits;
+};
+
+#endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:32:47 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:47 +0100
Subject: [PATCHv2 4/6] nand/denali: support hardware with internal ECC fixup
In-Reply-To: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307097169-11744-5-git-send-email-jamie@jamieiles.com>

Some versions of the IP have the ECC fixup handled in hardware.  For
these devices we have a new interrupt status/enable mapping that tells
us when we have an uncorrectable error.  Unfortunately this replaces
existing interrupt bits and there is no way to probe for this capability
so we have to do it through platform data.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c            |   18 +++++++++++++++---
 drivers/mtd/nand/denali.h            |    9 +++++++++
 include/linux/platform_data/denali.h |    1 +
 3 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 5557d7b..229696b 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -55,7 +55,8 @@ MODULE_PARM_DESC(onfi_timing_mode, "Overrides default ONFI setting."
 			INTR_STATUS__TIME_OUT | \
 			INTR_STATUS__ERASE_FAIL | \
 			INTR_STATUS__RST_COMP | \
-			INTR_STATUS__ERASE_COMP)
+			INTR_STATUS__ERASE_COMP | \
+			INTR_STATUS__ECC_UNCOR_ERR)
 
 /* indicates whether or not the internal value for the flash bank is
  * valid or not */
@@ -913,6 +914,14 @@ static bool handle_ecc(struct denali_nand_info *denali, uint8_t *buf,
 {
 	bool check_erased_page = false;
 
+	if (denali->have_hw_ecc_fixup &&
+	    (irq_status & INTR_STATUS__ECC_UNCOR_ERR)) {
+		clear_interrupts(denali);
+		denali_set_intr_modes(denali, true);
+
+		return true;
+	}
+
 	if (irq_status & INTR_STATUS__ECC_ERR) {
 		/* read the ECC errors. we'll ignore them for now */
 		uint32_t err_address = 0, err_correction_info = 0;
@@ -1111,8 +1120,9 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
 	size_t size = denali->mtd.writesize + denali->mtd.oobsize;
 
 	uint32_t irq_status = 0;
-	uint32_t irq_mask = INTR_STATUS__ECC_TRANSACTION_DONE |
-			    INTR_STATUS__ECC_ERR;
+	uint32_t irq_mask = denali->have_hw_ecc_fixup ?
+		(INTR_STATUS__ECC_TRANSACTION_DONE | INTR_STATUS__ECC_ERR) :
+		(INTR_STATUS__DMA_CMD_COMP | INTR_STATUS__ECC_UNCOR_ERR);
 	bool check_erased_page = false;
 
 	if (page != denali->page) {
@@ -1427,6 +1437,8 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_alloc_memery;
 	}
 
+	denali->have_hw_ecc_fixup = pdata ? pdata->have_hw_ecc_fixup : false;
+
 	if (id->driver_data == INTEL_CE4100) {
 		/* Due to a silicon limitation, we can only support
 		 * ONFI timing mode 1 and below.
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index b428ce3..f0b5e91 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -231,6 +231,14 @@
 #define     INTR_STATUS__PIPE_CMD_ERR			0x4000
 #define     INTR_STATUS__PAGE_XFER_INC			0x8000
 
+/*
+ * Some versions of the IP have the ECC fixup handled in hardware.  In this
+ * configuration we only get interrupted when the error is uncorrectable.
+ * Unfortunately this bit replaces INTR_STATUS__ECC_TRANSACTION_DONE from the
+ * old IP.
+ */
+#define     INTR_STATUS__ECC_UNCOR_ERR			0x0001
+
 #define     INTR_EN__ECC_TRANSACTION_DONE		0x0001
 #define     INTR_EN__ECC_ERR				0x0002
 #define     INTR_EN__DMA_CMD_COMP			0x0004
@@ -495,6 +503,7 @@ struct denali_nand_info {
 	uint32_t bbtskipbytes;
 	uint32_t max_banks;
 	int nr_ecc_bits;
+	bool have_hw_ecc_fixup;
 };
 
 #endif /*_LLD_NAND_*/
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
index cfdb775..3767333 100644
--- a/include/linux/platform_data/denali.h
+++ b/include/linux/platform_data/denali.h
@@ -16,6 +16,7 @@
 
 struct denali_nand_pdata {
 	int	nr_ecc_bits;
+	bool	have_hw_ecc_fixup;
 };
 
 #endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:32:48 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:48 +0100
Subject: [PATCHv2 5/6] nand/denali: support MTD partitioning
In-Reply-To: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307097169-11744-6-git-send-email-jamie@jamieiles.com>

Allow the platform to specify partitions through platform data.  If
there are no partitions specified then the whole device will be
registered.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c            |    8 +++++++-
 include/linux/platform_data/denali.h |    8 ++++++--
 2 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 229696b..e24e214 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
 #include <linux/module.h>
 #include <linux/platform_data/denali.h>
 
@@ -1643,7 +1644,12 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_req_irq;
 	}
 
-	ret = mtd_device_register(&denali->mtd, NULL, 0);
+	if (pdata && pdata->parts)
+		ret = mtd_device_register(&denali->mtd, pdata->parts,
+					 pdata->nr_parts);
+	else
+		ret = mtd_device_register(&denali->mtd, NULL, 0);
+
 	if (ret) {
 		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
 				ret);
diff --git a/include/linux/platform_data/denali.h b/include/linux/platform_data/denali.h
index 3767333..141da35 100644
--- a/include/linux/platform_data/denali.h
+++ b/include/linux/platform_data/denali.h
@@ -14,9 +14,13 @@
 #ifndef __DENALI_PDATA_H__
 #define __DENALI_PDATA_H__
 
+struct mtd_partition;
+
 struct denali_nand_pdata {
-	int	nr_ecc_bits;
-	bool	have_hw_ecc_fixup;
+	int				nr_ecc_bits;
+	bool				have_hw_ecc_fixup;
+	const struct mtd_partition	*parts;
+	unsigned int			nr_parts;
 };
 
 #endif /* __DENALI_PDATA_H__ */
-- 
1.7.4.1



From jamie at jamieiles.com  Fri Jun  3 06:32:49 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Fri,  3 Jun 2011 11:32:49 +0100
Subject: [PATCHv2 6/6] mtd/denali: support for cmdline partitioning
In-Reply-To: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307097169-11744-7-git-send-email-jamie@jamieiles.com>

Add support for command line partitioning.  This is favoured over
platform data based partitions.

Cc: David Woodhouse <dwmw2 at infradead.org>
Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
Cc: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---
 drivers/mtd/nand/denali.c |    9 ++++++++-
 1 files changed, 8 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index e24e214..c48f5dd 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1419,6 +1419,9 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 	unsigned long csr_len, mem_len;
 	struct denali_nand_info *denali;
 	struct denali_nand_pdata *pdata;
+	struct mtd_partition *partitions = NULL;
+	int nr_parts = 0;
+	const char *part_probes[] = { "cmdlinepart", NULL };
 
 	denali = kzalloc(sizeof(*denali), GFP_KERNEL);
 	if (!denali)
@@ -1644,7 +1647,11 @@ static int denali_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
 		goto failed_req_irq;
 	}
 
-	if (pdata && pdata->parts)
+	nr_parts = parse_mtd_partitions(&denali->mtd, part_probes,
+					&partitions, 0);
+	if (partitions && nr_parts > 0)
+		ret = mtd_device_register(&denali->mtd, partitions, nr_parts);
+	else if (pdata && pdata->parts)
 		ret = mtd_device_register(&denali->mtd, pdata->parts,
 					 pdata->nr_parts);
 	else
-- 
1.7.4.1



From zonque at gmail.com  Fri Jun  3 09:00:18 2011
From: zonque at gmail.com (Daniel Mack)
Date: Fri, 3 Jun 2011 15:00:18 +0200
Subject: [PATCH] mtd: pxa3xx_nand: remove unused variable 'mtd'
In-Reply-To: <1307086473.7474.1.camel@phoenix>
References: <1307086473.7474.1.camel@phoenix>
Message-ID: <BANLkTinfOmA1cW6Ktuka1NS+7D0RhFqMvw@mail.gmail.com>

(cc Lei Wen)

On Fri, Jun 3, 2011 at 9:34 AM, Axel Lin <axel.lin at gmail.com> wrote:
> Remove unused variable 'mtd' to eliminate below warning.
>
> ?CC ? ? ?drivers/mtd/nand/pxa3xx_nand.o
> drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_suspend':
> drivers/mtd/nand/pxa3xx_nand.c:1167: warning: unused variable 'mtd'
> drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_resume':
> drivers/mtd/nand/pxa3xx_nand.c:1180: warning: unused variable 'mtd'
>
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Lei, I had the same patch queued up on my side and dropped it now. Can
you apply this one?

Thanks,
Daniel



> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ? ?2 --
> ?1 files changed, 0 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 1fb3b3a..5cae8ae 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -1164,7 +1164,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
> ?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) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
> @@ -1177,7 +1176,6 @@ static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
> ?static int pxa3xx_nand_resume(struct platform_device *pdev)
> ?{
> ? ? ? ?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.4.1
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at ?http://www.tux.org/lkml/
>


From zonque at gmail.com  Fri Jun  3 09:02:07 2011
From: zonque at gmail.com (Daniel Mack)
Date: Fri, 3 Jun 2011 15:02:07 +0200
Subject: [PATCH 1/2] mtd: pxa3xx_nand: fix a memory leak
In-Reply-To: <1307078050.4167.1.camel@phoenix>
References: <1307078050.4167.1.camel@phoenix>
Message-ID: <BANLkTikNC8F2TPY2TFHuHtU=-xhwef2ikw@mail.gmail.com>

(Cc Lei Wen)

On Fri, Jun 3, 2011 at 7:14 AM, Axel Lin <axel.lin at gmail.com> wrote:
> In pxa3xx_nand_remove, we should call nand_release instead of
> mtd_device_unregister to properly free bad block table memory
> and bad block descriptor memory.
>
> Signed-off-by: Axel Lin <axel.lin at gmail.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ? ?2 +-
> ?1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 1fb3b3a..f7040ea 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -1119,7 +1119,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
> ? ? ? ?clk_put(info->clk);
>
> ? ? ? ?if (mtd) {
> - ? ? ? ? ? ? ? mtd_device_unregister(mtd);
> + ? ? ? ? ? ? ? nand_release(mtd);
> ? ? ? ? ? ? ? ?kfree(mtd);
> ? ? ? ?}
> ? ? ? ?return 0;
> --
> 1.7.4.1
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at ?http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at ?http://www.tux.org/lkml/
>


From dedekind1 at gmail.com  Fri Jun  3 09:49:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:51 +0300
Subject: [PATCH 00/10] UBIFS: for Linux 3.0
Message-ID: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>

Hi,

I'm going to send these patches to Linus later today.

Artem.


From dedekind1 at gmail.com  Fri Jun  3 09:49:56 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:56 +0300
Subject: [PATCH 05/10] UBIFS: fix shrinker object count reports
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-6-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Sometimes VM asks the shrinker to return amount of objects it can shrink,
and we return the ubifs_clean_zn_cnt in that case. However, it is possible
that this counter is negative for a short period of time, due to the way
UBIFS TNC code updates it. And I can observe the following warnings sometimes:

shrink_slab: ubifs_shrinker+0x0/0x2b7 [ubifs] negative objects to delete nr=-8541616642706119788

This patch makes sure UBIFS never returns negative count of objects.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Cc: stable at kernel.org
---
 fs/ubifs/shrinker.c |    6 +++++-
 1 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/fs/ubifs/shrinker.c b/fs/ubifs/shrinker.c
index ca953a9..dfc105a 100644
--- a/fs/ubifs/shrinker.c
+++ b/fs/ubifs/shrinker.c
@@ -284,7 +284,11 @@ int ubifs_shrinker(struct shrinker *shrink, struct shrink_control *sc)
 	long clean_zn_cnt = atomic_long_read(&ubifs_clean_zn_cnt);
 
 	if (nr == 0)
-		return clean_zn_cnt;
+		/*
+		 * Due to the way UBIFS updates the clean znode counter it may
+		 * temporarily be negative.
+		 */
+		return clean_zn_cnt > 0 ?: 1;
 
 	if (!clean_zn_cnt) {
 		/*
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:57 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:57 +0300
Subject: [PATCH 06/10] UBIFS: fix memory leak on error path
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-7-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

UBIFS leaks memory on error path in 'ubifs_jnl_update()' in case of write
failure because it forgets to free the 'struct ubifs_dent_node *dent' object.
Although the object is small, the alignment can make it large - e.g., 2KiB
if the min. I/O unit is 2KiB.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Cc: stable at kernel.org
---
 fs/ubifs/journal.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 34b1679..cef0460 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -669,6 +669,7 @@ out_free:
 
 out_release:
 	release_head(c, BASEHD);
+	kfree(dent);
 out_ro:
 	ubifs_ro_mode(c, err);
 	if (last_reference)
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:59 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:59 +0300
Subject: [PATCH 08/10] UBIFS: assert no fixup when writing a node
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-9-git-send-email-dedekind1@gmail.com>

From: Ben Gardiner <bengardiner at nanometrics.ca>

The current free space fixup can result in some writing to the UBI volume
when the space_fixup flag is set.

To catch instances where UBIFS is writing to the NAND while the space_fixup
flag is set, add an assert to ubifs_write_node().

Artem: tweaked the patch, added similar assertion to the write buffer
       write path.

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
Reviewed-by: Matthew L. Creech <mlcreech at gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/io.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 166951e..3be645e 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -581,6 +581,7 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 	ubifs_assert(wbuf->size % c->min_io_size == 0);
 	ubifs_assert(mutex_is_locked(&wbuf->io_mutex));
 	ubifs_assert(!c->ro_media && !c->ro_mount);
+	ubifs_assert(!c->space_fixup);
 	if (c->leb_size - wbuf->offs >= c->max_write_size)
 		ubifs_assert(!((wbuf->offs + wbuf->size) % c->max_write_size));
 
@@ -759,6 +760,7 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
 	ubifs_assert(lnum >= 0 && lnum < c->leb_cnt && offs >= 0);
 	ubifs_assert(offs % c->min_io_size == 0 && offs < c->leb_size);
 	ubifs_assert(!c->ro_media && !c->ro_mount);
+	ubifs_assert(!c->space_fixup);
 
 	if (c->ro_error)
 		return -EROFS;
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:58 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:58 +0300
Subject: [PATCH 07/10] UBIFS: fix clean znode counter corruption in error cases
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-8-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

UBIFS maintains per-filesystem and global clean znode counters
('c->clean_zn_cnt' and 'ubifs_clean_zn_cnt'). It is important to maintain
correct values there since the shrinker relies on 'ubifs_clean_zn_cnt'.

However, in case of failures during commit the counters were corrupted. E.g.,
if a failure happens in the middle of 'write_index()', then some nodes in the
commit list ('c->cnext') are marked as clean, and some are marked as dirty. And
the 'ubifs_destroy_tnc_subtree()' frees does not retrun correct count, and we
end up with non-zero 'c->clean_zn_cnt' when unmounting. This means that if we
have 2 file-sytem and one of them fails, and we unmount it,
'ubifs_clean_zn_cnt' stays incorrect and confuses the shrinker.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/tnc.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 8119b1f..91b4213 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -2876,12 +2876,13 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
  */
 void ubifs_tnc_close(struct ubifs_info *c)
 {
-	long clean_freed;
-
 	tnc_destroy_cnext(c);
 	if (c->zroot.znode) {
-		clean_freed = ubifs_destroy_tnc_subtree(c->zroot.znode);
-		atomic_long_sub(clean_freed, &ubifs_clean_zn_cnt);
+		long n;
+
+		ubifs_destroy_tnc_subtree(c->zroot.znode);
+		n = atomic_long_read(&c->clean_zn_cnt);
+		atomic_long_sub(n, &ubifs_clean_zn_cnt);
 	}
 	kfree(c->gap_lebs);
 	kfree(c->ilebs);
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:54 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:54 +0300
Subject: [PATCH 03/10] UBIFS: amend ubifs_recover_leb interface
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-4-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Instead of passing "grouped" parameter to 'ubifs_recover_leb()' which tells
whether the nodes are grouped in the LEB to recover, pass the journal head
number and let 'ubifs_recover_leb()' look at the journal head's 'grouped' flag.

This patch is a preparation to a further fix where we'll need to know the
journal head number for other purposes.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/orphan.c   |    2 +-
 fs/ubifs/recovery.c |   10 ++++++----
 fs/ubifs/replay.c   |    3 +--
 fs/ubifs/ubifs.h    |    2 +-
 4 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index bd644bf..a5422ff 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -674,7 +674,7 @@ static int kill_orphans(struct ubifs_info *c)
 		if (IS_ERR(sleb)) {
 			if (PTR_ERR(sleb) == -EUCLEAN)
 				sleb = ubifs_recover_leb(c, lnum, 0,
-							 c->sbuf, 0);
+							 c->sbuf, -1);
 			if (IS_ERR(sleb)) {
 				err = PTR_ERR(sleb);
 				break;
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 95e2418..6adb532 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -604,7 +604,8 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)
  * @lnum: LEB number
  * @offs: offset
  * @sbuf: LEB-sized buffer to use
- * @grouped: nodes may be grouped for recovery
+ * @jhead: journal head number this LEB belongs to (%-1 if the LEB does not
+ *         belong to any journal head)
  *
  * This function does a scan of a LEB, but caters for errors that might have
  * been caused by the unclean unmount from which we are attempting to recover.
@@ -612,13 +613,14 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)
  * found, and a negative error code in case of failure.
  */
 struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
-					 int offs, void *sbuf, int grouped)
+					 int offs, void *sbuf, int jhead)
 {
 	int ret = 0, err, len = c->leb_size - offs, start = offs, min_io_unit;
+	int grouped = jhead == -1 ? 0 : c->jheads[jhead].grouped;
 	struct ubifs_scan_leb *sleb;
 	void *buf = sbuf + offs;
 
-	dbg_rcvry("%d:%d", lnum, offs);
+	dbg_rcvry("%d:%d, jhead %d, grouped %d", lnum, offs, jhead, grouped);
 
 	sleb = ubifs_start_scan(c, lnum, offs, sbuf);
 	if (IS_ERR(sleb))
@@ -881,7 +883,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 		}
 		ubifs_scan_destroy(sleb);
 	}
-	return ubifs_recover_leb(c, lnum, offs, sbuf, 0);
+	return ubifs_recover_leb(c, lnum, offs, sbuf, -1);
 }
 
 /**
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 6617280..5e97161 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -557,8 +557,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)
 		 * these LEBs could possibly be written to at the power cut
 		 * time.
 		 */
-		sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf,
-					 b->bud->jhead != GCHD);
+		sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, b->bud->jhead);
 	else
 		sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);
 	if (IS_ERR(sleb))
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index adeca14..f79983d 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1744,7 +1744,7 @@ struct inode *ubifs_iget(struct super_block *sb, unsigned long inum);
 int ubifs_recover_master_node(struct ubifs_info *c);
 int ubifs_write_rcvrd_mst_node(struct ubifs_info *c);
 struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
-					 int offs, void *sbuf, int grouped);
+					 int offs, void *sbuf, int jhead);
 struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 					     int offs, void *sbuf);
 int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf);
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:53 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:53 +0300
Subject: [PATCH 02/10] UBIFS: introduce a "grouped" journal head flag
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-3-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Journal heads are different in a way how UBIFS writes nodes there. All normal
journal heads receive grouped nodes, while the GC journal heads receives
ungrouped nodes. This patch adds a 'grouped' flag to 'struct ubifs_jhead' which
describes this property.

This patch is a preparation to a further recovery fix.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/super.c |    5 ++++-
 fs/ubifs/ubifs.h |    2 ++
 2 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 1ab0d22..1e40db7 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -811,15 +811,18 @@ static int alloc_wbufs(struct ubifs_info *c)
 
 		c->jheads[i].wbuf.sync_callback = &bud_wbuf_callback;
 		c->jheads[i].wbuf.jhead = i;
+		c->jheads[i].grouped = 1;
 	}
 
 	c->jheads[BASEHD].wbuf.dtype = UBI_SHORTTERM;
 	/*
 	 * Garbage Collector head likely contains long-term data and
-	 * does not need to be synchronized by timer.
+	 * does not need to be synchronized by timer. Also GC head nodes are
+	 * not grouped.
 	 */
 	c->jheads[GCHD].wbuf.dtype = UBI_LONGTERM;
 	c->jheads[GCHD].wbuf.no_timer = 1;
+	c->jheads[GCHD].grouped = 0;
 
 	return 0;
 }
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index a70d7b4..adeca14 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -722,12 +722,14 @@ struct ubifs_bud {
  * struct ubifs_jhead - journal head.
  * @wbuf: head's write-buffer
  * @buds_list: list of bud LEBs belonging to this journal head
+ * @grouped: non-zero if UBIFS groups nodes when writing to this journal head
  *
  * Note, the @buds list is protected by the @c->buds_lock.
  */
 struct ubifs_jhead {
 	struct ubifs_wbuf wbuf;
 	struct list_head buds_list;
+	unsigned int grouped:1;
 };
 
 /**
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:52 +0300
Subject: [PATCH 01/10] UBIFS: supress false error messages
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-2-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Commit ab51afe05273741f72383529ef488aa1ea598ec6 was a good clean-up, but
it introduced a regression - now UBIFS prints scary error messages during
recovery on all corrupted nodes, even though the corruptions are expected
(due to a power cut). This patch fixes the issue.

Additionally fix a typo in a commentary introduced by the same commit.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/recovery.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 731d9e2..95e2418 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -635,7 +635,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 		 * Scan quietly until there is an error from which we cannot
 		 * recover
 		 */
-		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 0);
+		ret = ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
 		if (ret == SCANNED_A_NODE) {
 			/* A valid node, and not a padding node */
 			struct ubifs_ch *ch = buf;
@@ -701,7 +701,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 	 * While we are in the middle of the same min. I/O unit keep dropping
 	 * nodes. So basically, what we want is to make sure that the last min.
 	 * I/O unit where we saw the corruption is dropped completely with all
-	 * the uncorrupted node which may possibly sit there.
+	 * the uncorrupted nodes which may possibly sit there.
 	 *
 	 * In other words, let's name the min. I/O unit where the corruption
 	 * starts B, and the previous min. I/O unit A. The below code tries to
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:50:00 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:50:00 +0300
Subject: [PATCH 09/10] UBIFS: intialize LPT earlier
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-10-git-send-email-dedekind1@gmail.com>

From: Ben Gardiner <bengardiner at nanometrics.ca>

The current 'mount_ubifs()' implementation does not initialize the LPT until the
the master node is marked dirty. Move the LPT initialization to before marking
the master node dirty. This is a preparation for the next patch which will move
the free-space-fixup check to before marking the master node dirty, because we
have to fix-up the free space before doing any writes.

Artem: massaged the patch and commit message.

Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>
Reviewed-by: Matthew L. Creech <mlcreech at gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/super.c |   29 ++++++++++++++++-------------
 1 files changed, 16 insertions(+), 13 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 1e40db7..6d357fd 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1282,17 +1282,24 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		goto out_master;
 
-	init_constants_master(c);
-
 	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
 		ubifs_msg("recovery needed");
 		c->need_recovery = 1;
-		if (!c->ro_mount) {
-			err = ubifs_recover_inl_heads(c, c->sbuf);
-			if (err)
-				goto out_master;
-		}
-	} else if (!c->ro_mount) {
+	}
+
+	init_constants_master(c);
+
+	if (c->need_recovery && !c->ro_mount) {
+		err = ubifs_recover_inl_heads(c, c->sbuf);
+		if (err)
+			goto out_master;
+	}
+
+	err = ubifs_lpt_init(c, 1, !c->ro_mount);
+	if (err)
+		goto out_master;
+
+	if (!c->ro_mount) {
 		/*
 		 * Set the "dirty" flag so that if we reboot uncleanly we
 		 * will notice this immediately on the next mount.
@@ -1300,13 +1307,9 @@ static int mount_ubifs(struct ubifs_info *c)
 		c->mst_node->flags |= cpu_to_le32(UBIFS_MST_DIRTY);
 		err = ubifs_write_master(c);
 		if (err)
-			goto out_master;
+			goto out_lpt;
 	}
 
-	err = ubifs_lpt_init(c, 1, !c->ro_mount);
-	if (err)
-		goto out_lpt;
-
 	err = dbg_check_idx_size(c, c->bi.old_idx_sz);
 	if (err)
 		goto out_lpt;
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:49:55 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:49:55 +0300
Subject: [PATCH 04/10] UBIFS: fix recovery broken by the previous recovery fix
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-5-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Unfortunately, the recovery fix d1606a59b6be4ea392eabd40d1250aa1eeb19efb
(UBIFS: fix extremely rare mount failure) broke recovery. This commit make
UBIFS drop the last min. I/O unit in all journal heads, but this is needed only
for the GC head. And this does not work for non-GC heads. For example, if
suppose we have min. I/O units A and B, and A contains a valid node X, which
was fsynced, and then a group of nodes Y which spans the rest of A and B. In
this case we'll drop not only Y, but also X, which is obviously incorrect.

This patch fixes the issue and additionally makes recovery to drop last min.
I/O unit only for the GC head, and leave things as they have been for ages for
the other heads - this is safer.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/recovery.c |  152 +++++++++++++++++++++++++++++----------------------
 1 files changed, 87 insertions(+), 65 deletions(-)

diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 6adb532..783d8e0 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -564,19 +564,15 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 }
 
 /**
- * drop_last_node - drop the last node or group of nodes.
+ * drop_last_group - drop the last group of nodes.
  * @sleb: scanned LEB information
  * @offs: offset of dropped nodes is returned here
- * @grouped: non-zero if whole group of nodes have to be dropped
  *
  * This is a helper function for 'ubifs_recover_leb()' which drops the last
- * node of the scanned LEB or the last group of nodes if @grouped is not zero.
- * This function returns %1 if a node was dropped and %0 otherwise.
+ * group of nodes of the scanned LEB.
  */
-static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)
+static void drop_last_group(struct ubifs_scan_leb *sleb, int *offs)
 {
-	int dropped = 0;
-
 	while (!list_empty(&sleb->nodes)) {
 		struct ubifs_scan_node *snod;
 		struct ubifs_ch *ch;
@@ -585,17 +581,40 @@ static int drop_last_node(struct ubifs_scan_leb *sleb, int *offs, int grouped)
 				  list);
 		ch = snod->node;
 		if (ch->group_type != UBIFS_IN_NODE_GROUP)
-			return dropped;
-		dbg_rcvry("dropping node at %d:%d", sleb->lnum, snod->offs);
+			break;
+
+		dbg_rcvry("dropping grouped node at %d:%d",
+			  sleb->lnum, snod->offs);
+		*offs = snod->offs;
+		list_del(&snod->list);
+		kfree(snod);
+		sleb->nodes_cnt -= 1;
+	}
+}
+
+/**
+ * drop_last_node - drop the last node.
+ * @sleb: scanned LEB information
+ * @offs: offset of dropped nodes is returned here
+ * @grouped: non-zero if whole group of nodes have to be dropped
+ *
+ * This is a helper function for 'ubifs_recover_leb()' which drops the last
+ * node of the scanned LEB.
+ */
+static void drop_last_node(struct ubifs_scan_leb *sleb, int *offs)
+{
+	struct ubifs_scan_node *snod;
+
+	if (!list_empty(&sleb->nodes)) {
+		snod = list_entry(sleb->nodes.prev, struct ubifs_scan_node,
+				  list);
+
+		dbg_rcvry("dropping last node at %d:%d", sleb->lnum, snod->offs);
 		*offs = snod->offs;
 		list_del(&snod->list);
 		kfree(snod);
 		sleb->nodes_cnt -= 1;
-		dropped = 1;
-		if (!grouped)
-			break;
 	}
-	return dropped;
 }
 
 /**
@@ -697,59 +716,62 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 		 * If nodes are grouped, always drop the incomplete group at
 		 * the end.
 		 */
-		drop_last_node(sleb, &offs, 1);
+		drop_last_group(sleb, &offs);
 
-	/*
-	 * While we are in the middle of the same min. I/O unit keep dropping
-	 * nodes. So basically, what we want is to make sure that the last min.
-	 * I/O unit where we saw the corruption is dropped completely with all
-	 * the uncorrupted nodes which may possibly sit there.
-	 *
-	 * In other words, let's name the min. I/O unit where the corruption
-	 * starts B, and the previous min. I/O unit A. The below code tries to
-	 * deal with a situation when half of B contains valid nodes or the end
-	 * of a valid node, and the second half of B contains corrupted data or
-	 * garbage. This means that UBIFS had been writing to B just before the
-	 * power cut happened. I do not know how realistic is this scenario
-	 * that half of the min. I/O unit had been written successfully and the
-	 * other half not, but this is possible in our 'failure mode emulation'
-	 * infrastructure at least.
-	 *
-	 * So what is the problem, why we need to drop those nodes? Whey can't
-	 * we just clean-up the second half of B by putting a padding node
-	 * there? We can, and this works fine with one exception which was
-	 * reproduced with power cut emulation testing and happens extremely
-	 * rarely. The description follows, but it is worth noting that that is
-	 * only about the GC head, so we could do this trick only if the bud
-	 * belongs to the GC head, but it does not seem to be worth an
-	 * additional "if" statement.
-	 *
-	 * So, imagine the file-system is full, we run GC which is moving valid
-	 * nodes from LEB X to LEB Y (obviously, LEB Y is the current GC head
-	 * LEB). The @c->gc_lnum is -1, which means that GC will retain LEB X
-	 * and will try to continue. Imagine that LEB X is currently the
-	 * dirtiest LEB, and the amount of used space in LEB Y is exactly the
-	 * same as amount of free space in LEB X.
-	 *
-	 * And a power cut happens when nodes are moved from LEB X to LEB Y. We
-	 * are here trying to recover LEB Y which is the GC head LEB. We find
-	 * the min. I/O unit B as described above. Then we clean-up LEB Y by
-	 * padding min. I/O unit. And later 'ubifs_rcvry_gc_commit()' function
-	 * fails, because it cannot find a dirty LEB which could be GC'd into
-	 * LEB Y! Even LEB X does not match because the amount of valid nodes
-	 * there does not fit the free space in LEB Y any more! And this is
-	 * because of the padding node which we added to LEB Y. The
-	 * user-visible effect of this which I once observed and analysed is
-	 * that we cannot mount the file-system with -ENOSPC error.
-	 *
-	 * So obviously, to make sure that situation does not happen we should
-	 * free min. I/O unit B in LEB Y completely and the last used min. I/O
-	 * unit in LEB Y should be A. This is basically what the below code
-	 * tries to do.
-	 */
-	while (min_io_unit == round_down(offs, c->min_io_size) &&
-	       min_io_unit != offs &&
-	       drop_last_node(sleb, &offs, grouped));
+	if (jhead == GCHD) {
+		/*
+		 * If this LEB belongs to the GC head then while we are in the
+		 * middle of the same min. I/O unit keep dropping nodes. So
+		 * basically, what we want is to make sure that the last min.
+		 * I/O unit where we saw the corruption is dropped completely
+		 * with all the uncorrupted nodes which may possibly sit there.
+		 *
+		 * In other words, let's name the min. I/O unit where the
+		 * corruption starts B, and the previous min. I/O unit A. The
+		 * below code tries to deal with a situation when half of B
+		 * contains valid nodes or the end of a valid node, and the
+		 * second half of B contains corrupted data or garbage. This
+		 * means that UBIFS had been writing to B just before the power
+		 * cut happened. I do not know how realistic is this scenario
+		 * that half of the min. I/O unit had been written successfully
+		 * and the other half not, but this is possible in our 'failure
+		 * mode emulation' infrastructure at least.
+		 *
+		 * So what is the problem, why we need to drop those nodes? Why
+		 * can't we just clean-up the second half of B by putting a
+		 * padding node there? We can, and this works fine with one
+		 * exception which was reproduced with power cut emulation
+		 * testing and happens extremely rarely.
+		 *
+		 * Imagine the file-system is full, we run GC which starts
+		 * moving valid nodes from LEB X to LEB Y (obviously, LEB Y is
+		 * the current GC head LEB). The @c->gc_lnum is -1, which means
+		 * that GC will retain LEB X and will try to continue. Imagine
+		 * that LEB X is currently the dirtiest LEB, and the amount of
+		 * used space in LEB Y is exactly the same as amount of free
+		 * space in LEB X.
+		 *
+		 * And a power cut happens when nodes are moved from LEB X to
+		 * LEB Y. We are here trying to recover LEB Y which is the GC
+		 * head LEB. We find the min. I/O unit B as described above.
+		 * Then we clean-up LEB Y by padding min. I/O unit. And later
+		 * 'ubifs_rcvry_gc_commit()' function fails, because it cannot
+		 * find a dirty LEB which could be GC'd into LEB Y! Even LEB X
+		 * does not match because the amount of valid nodes there does
+		 * not fit the free space in LEB Y any more! And this is
+		 * because of the padding node which we added to LEB Y. The
+		 * user-visible effect of this which I once observed and
+		 * analysed is that we cannot mount the file-system with
+		 * -ENOSPC error.
+		 *
+		 * So obviously, to make sure that situation does not happen we
+		 * should free min. I/O unit B in LEB Y completely and the last
+		 * used min. I/O unit in LEB Y should be A. This is basically
+		 * what the below code tries to do.
+		 */
+		while (offs > min_io_unit)
+			drop_last_node(sleb, &offs);
+	}
 
 	buf = sbuf + offs;
 	len = c->leb_size - offs;
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:50:01 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri,  3 Jun 2011 16:50:01 +0300
Subject: [PATCH 10/10] UBIFS: fix-up free space earlier
In-Reply-To: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307109001-19761-11-git-send-email-dedekind1@gmail.com>

From: Ben Gardiner <bengardiner at nanometrics.ca>

The free space fixup is currently initiated during mount after the call to
ubifs_write_master() which results in a write to PEBs; this has been observed
with the patch 'assert no fixup when writing a node' applied:

Move the free space fixup on mount to before the calls to
ubifs_recover_inl_heads() and ubifs_write_master(). This results in no
assertions with the previously mentioned patch applied.

Artem: tweaked the patch a bit

Signed-off-by: Ben Gardiner <bengardiner at nanometrics>
Reviewed-by: Matthew L. Creech <mlcreech at gmail.com>
Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/super.c |   16 ++++++++--------
 1 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 6d357fd..b5aeb5a 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1282,13 +1282,13 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		goto out_master;
 
+	init_constants_master(c);
+
 	if ((c->mst_node->flags & cpu_to_le32(UBIFS_MST_DIRTY)) != 0) {
 		ubifs_msg("recovery needed");
 		c->need_recovery = 1;
 	}
 
-	init_constants_master(c);
-
 	if (c->need_recovery && !c->ro_mount) {
 		err = ubifs_recover_inl_heads(c, c->sbuf);
 		if (err)
@@ -1299,6 +1299,12 @@ static int mount_ubifs(struct ubifs_info *c)
 	if (err)
 		goto out_master;
 
+	if (!c->ro_mount && c->space_fixup) {
+		err = ubifs_fixup_free_space(c);
+		if (err)
+			goto out_master;
+	}
+
 	if (!c->ro_mount) {
 		/*
 		 * Set the "dirty" flag so that if we reboot uncleanly we
@@ -1402,12 +1408,6 @@ static int mount_ubifs(struct ubifs_info *c)
 	} else
 		ubifs_assert(c->lst.taken_empty_lebs > 0);
 
-	if (!c->ro_mount && c->space_fixup) {
-		err = ubifs_fixup_free_space(c);
-		if (err)
-			goto out_infos;
-	}
-
 	err = dbg_check_filesystem(c);
 	if (err)
 		goto out_infos;
-- 
1.7.2.3



From dedekind1 at gmail.com  Fri Jun  3 09:48:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 16:48:46 +0300
Subject: [PATCH 05/10] UBIFS: fix shrinker object count reports
In-Reply-To: <1307109001-19761-6-git-send-email-dedekind1@gmail.com>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
	<1307109001-19761-6-git-send-email-dedekind1@gmail.com>
Message-ID: <1307108926.3069.0.camel@localhost>

On Fri, 2011-06-03 at 16:49 +0300, Artem Bityutskiy wrote:
> +		/*
> +		 * Due to the way UBIFS updates the clean znode counter it may
> +		 * temporarily be negative.
> +		 */
> +		return clean_zn_cnt > 0 ?: 1;

Oh, this should be  clean_zn_cnt >= 0 ?: 1;

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 10:30:13 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 17:30:13 +0300
Subject: [PATCH 05/10] UBIFS: fix shrinker object count reports
In-Reply-To: <1307108926.3069.0.camel@localhost>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
	<1307109001-19761-6-git-send-email-dedekind1@gmail.com>
	<1307108926.3069.0.camel@localhost>
Message-ID: <1307111413.3069.5.camel@localhost>

On Fri, 2011-06-03 at 16:48 +0300, Artem Bityutskiy wrote:
> On Fri, 2011-06-03 at 16:49 +0300, Artem Bityutskiy wrote:
> > +		/*
> > +		 * Due to the way UBIFS updates the clean znode counter it may
> > +		 * temporarily be negative.
> > +		 */
> > +		return clean_zn_cnt > 0 ?: 1;
> 
> Oh, this should be  clean_zn_cnt >= 0 ?: 1;

Crap, sorry, stupid me :-)

return clean_zn_cnt < 0 ?: clean_zn_cnt;

But yeah, it is saner to not use "?:" at all:

return clean_zn_cnt >= 0 ? clean_zn_cnt: 1;

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 11:06:59 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:06:59 +0300
Subject: [PATCH 05/10] UBIFS: fix shrinker object count reports
In-Reply-To: <1307111413.3069.5.camel@localhost>
References: <1307109001-19761-1-git-send-email-dedekind1@gmail.com>
	<1307109001-19761-6-git-send-email-dedekind1@gmail.com>
	<1307108926.3069.0.camel@localhost> <1307111413.3069.5.camel@localhost>
Message-ID: <1307113619.3069.14.camel@localhost>

So,


From adrian.wenl at gmail.com  Fri Jun  3 11:11:54 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 3 Jun 2011 23:11:54 +0800
Subject: [PATCH] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <1305865207-7869-1-git-send-email-leiwen@marvell.com>
References: <BANLkTimos3-Ds4Y8FDfDZegqAhH7nSS4PA@mail.gmail.com>
	<1305865207-7869-1-git-send-email-leiwen@marvell.com>
Message-ID: <BANLkTinuqQmp43K4H0iPDbb-H-rDA_nL9w@mail.gmail.com>

Tested-by: Daniel Mack <zonque at gmail.com>

Also cc to MTD maillist and stable kernel.

On Fri, May 20, 2011 at 12:20 PM, Lei Wen <leiwen at marvell.com> wrote:
> When keep_config is set, the detection would goes different routine.
> That the driver would read out the setting which is set previously
> by bootloader. While most bootloader keep the irq mask as off, and
> current driver need all irq default open, keep_config behavior would
> lead to no irq at all.
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
> ?drivers/mtd/nand/pxa3xx_nand.c | ? 12 +++++++-----
> ?1 files changed, 7 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index ff07012..9896aef 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -813,7 +813,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ? ? ? ?info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
> ? ? ? ?/* set info fields needed to read id */
> ? ? ? ?info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
> - ? ? ? info->reg_ndcr = ndcr;
> + ? ? ? info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
> ? ? ? ?info->cmdset = &default_cmdset;
>
> ? ? ? ?info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> @@ -882,7 +882,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> ? ? ? ?struct platform_device *pdev = info->pdev;
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> - ? ? ? struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} };
> + ? ? ? struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
> ? ? ? ?const struct pxa3xx_nand_flash *f = NULL;
> ? ? ? ?struct nand_chip *chip = mtd->priv;
> ? ? ? ?uint32_t id = -1;
> @@ -942,8 +942,10 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
> ? ? ? ?if (f->flash_width == 16)
> ? ? ? ? ? ? ? ?pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
> + ? ? ? pxa3xx_flash_ids[1].name = NULL;
> + ? ? ? def = pxa3xx_flash_ids;
> ?KEEP_CONFIG:
> - ? ? ? if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
> + ? ? ? if (nand_scan_ident(mtd, 1, def))
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?/* calculate addressing information */
> ? ? ? ?info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
> @@ -954,9 +956,9 @@ KEEP_CONFIG:
> ? ? ? ? ? ? ? ?info->row_addr_cycles = 2;
> ? ? ? ?mtd->name = mtd_names[0];
> ? ? ? ?chip->ecc.mode = NAND_ECC_HW;
> - ? ? ? chip->ecc.size = f->page_size;
> + ? ? ? chip->ecc.size = info->page_size;
>
> - ? ? ? chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
> + ? ? ? chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
> ? ? ? ?chip->options |= NAND_NO_AUTOINCR;
> ? ? ? ?chip->options |= NAND_NO_READRDY;
>
> --
> 1.7.0.4
>
>
> _______________________________________________
> 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  Fri Jun  3 11:31:06 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 3 Jun 2011 23:31:06 +0800
Subject: [PATCH] MTD: pxa3xx_nand: Fix blank page ECC mismatch
In-Reply-To: <BANLkTimpLKkfSJbeuM6kc7bUE+JybTmVrA@mail.gmail.com>
References: <1307106198-11965-1-git-send-email-zonque@gmail.com>
	<BANLkTimpLKkfSJbeuM6kc7bUE+JybTmVrA@mail.gmail.com>
Message-ID: <BANLkTik1_cuo5UH995agoNYa2FdQ8Qasiw@mail.gmail.com>

Also cc to MTD mailist
Cc: linux-mtd at lists.infradead.org

On Fri, Jun 3, 2011 at 11:04 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
> On Fri, Jun 3, 2011 at 9:03 PM, Daniel Mack <zonque at gmail.com> wrote:
>> This bug was introduced in f8155a40 ("mtd: pxa3xx_nand: rework irq
>> logic") and causes the PXA3xx NAND controller fail to operate with NAND
>> flash that has empty pages. According to the comment in this block, the
>> hardware controller will report a double-bit error for empty pages,
>> which can and must be ignored.
>>
>> This patch restores the original behaviour of the driver.
>>
>> Signed-off-by: Daniel Mack <zonque at gmail.com>
>> Cc: Lei Wen <leiwen at marvell.com>
>> Cc: Haojian Zhuang <haojian.zhuang at marvell.com>
>> Cc: David Woodhouse <David.Woodhouse at intel.com>
>> Cc: stable at kernel.org
>> ---
>> ?drivers/mtd/nand/pxa3xx_nand.c | ? ?2 ++
>> ?1 files changed, 2 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index 0c6ed72..60167d1 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -687,6 +687,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>> ? ? ? ? ? ? ? ? * OOB, ignore such double bit errors
>> ? ? ? ? ? ? ? ? */
>> ? ? ? ? ? ? ? ?if (is_buf_blank(buf, mtd->writesize))
>> + ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
>> + ? ? ? ? ? ? ? else
>> ? ? ? ? ? ? ? ? ? ? ? ?mtd->ecc_stats.failed++;
>> ? ? ? ?}
>>
>> --
>> 1.7.5.1
>>
>
> Acked-by: Lei Wen <leiwen at marvell.com>
>


From dedekind1 at gmail.com  Fri Jun  3 11:30:01 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:30:01 +0300
Subject: [PATCH] mkfs.ubifs: trivial: 2.6.40 -> 3.0
In-Reply-To: <1306936176-24533-1-git-send-email-bengardiner@nanometrics.ca>
References: <1306936176-24533-1-git-send-email-bengardiner@nanometrics.ca>
Message-ID: <1307115001.3069.15.camel@localhost>

On Wed, 2011-06-01 at 09:49 -0400, Ben Gardiner wrote:
> In commit 04665066ebedb0a31335b525fb5f19df32cb8cfe it was noted that the free
> space fixup feature would be available in kernels 2.6.40 or greater. Since
> then it has been decided that the release following 2.6.39 will be 3.0.
> 
> Replace the instances of 2.6.40 with 3.0.
> 
> Signed-off-by: Ben Gardiner <bengardiner at nanometrics.ca>

Pushed to mtd-utils.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 11:32:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:32:36 +0300
Subject: [PATCH] nand: Remove meaningless delay from nand_unlock
In-Reply-To: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>
References: <1306936600-28870-1-git-send-email-jiri.pinkava@vscht.cz>
Message-ID: <1307115156.3069.16.camel@localhost>

On Wed, 2011-06-01 at 15:56 +0200, jiri.pinkava at vscht.cz wrote:
> From: Jiri Pinkava <jiri.pinkava at vscht.cz>
> 
> This delay is meaningless. If delay is needed it is device specific
> and must be reimplemented by specific driver, otherwise no delay is
> needed.
> 
> This function is not used by any current kernel code, affects only
> external code (like main).
> 
> Signed-off-by: Jiri Pinkava <jiri.pinkava at vscht.cz>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 11:35:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:35:17 +0300
Subject: [PATCH 1/2] mtd: nand: generalized error messages with __func__
In-Reply-To: <BANLkTi=BYeQ+cBMpRodDDY_KapjEoHVA+A@mail.gmail.com>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>
	<4DDDE19D.9010505@compulab.co.il> <1306387008.2785.138.camel@localhost>
	<BANLkTimsTWAcR4HgOoHguDMv9P-Eox=kbg@mail.gmail.com>
	<1306924235.4405.102.camel@localhost>
	<BANLkTi=BYeQ+cBMpRodDDY_KapjEoHVA+A@mail.gmail.com>
Message-ID: <1307115317.3069.18.camel@localhost>

On Wed, 2011-06-01 at 11:37 -0700, Brian Norris wrote:
> On Wed, Jun 1, 2011 at 3:30 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >> or should we define our own pr_fmt in include/linux/mtd.h?
> >
> > Yes, before you include files.
> 
> Well, I've tried this, and as I suspected, I can't just include it in
> mtd.h at the top, since we can't guarantee that <linux/mtd/mtd.h> is
> going to be the first included header in other files.

In any case we do not want to blow the kernel binary size by too many
__func__ strings. They should be used only when needed.

>  Specifically, in
> include/linux/mtd/nand.h, we include other headers before mtd.h and so
> printk.h has already defined pr_fmt() for us, so this doesn't work.
> I'm not sure if there's a nice place to define pr_fmt() right now...

.c files, AFAIU.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 11:41:07 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:41:07 +0300
Subject: [PATCH] UBIFS FAQ: kernel version 2.6.40 -> 3.0
In-Reply-To: <1306990740-7741-1-git-send-email-mlcreech@gmail.com>
References: <1306990740-7741-1-git-send-email-mlcreech@gmail.com>
Message-ID: <1307115667.3069.19.camel@localhost>

On Thu, 2011-06-02 at 00:59 -0400, Matthew L. Creech wrote:
> ---
>  faq/ubifs.xml |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 11:41:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:41:41 +0300
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <20110602064832.GA7319@july>
References: <20110602064832.GA7319@july>
Message-ID: <1307115701.3069.20.camel@localhost>

On Thu, 2011-06-02 at 15:48 +0900, Kyungmin Park wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> There's no case to use the subpage for 4KiB pagesize.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
> diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
> index ac9e959..337be7c 100644
> --- a/drivers/mtd/onenand/onenand_base.c
> +++ b/drivers/mtd/onenand/onenand_base.c
> @@ -4047,13 +4047,11 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
>  	 */
>  	switch (mtd->oobsize) {
>  	case 128:
> -		if (FLEXONENAND(this)) {
> +		if (FLEXONENAND(this))
>  			this->ecclayout = &flexonenand_oob_128;
> -			mtd->subpage_sft = 0;
> -		} else {
> +		else
>  			this->ecclayout = &onenand_oob_128;
> -			mtd->subpage_sft = 2;
> -		}
> +		mtd->subpage_sft = 0;
>  		break;
>  	case 64:
>  		this->ecclayout = &onenand_oob_64;

Roman, are you happy with this change?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Fri Jun  3 11:49:19 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:49:19 +0300
Subject: [PATCH 2/2] mtd: drop ceiva map driver
In-Reply-To: <1307015648-17505-2-git-send-email-dbaryshkov@gmail.com>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307015648-17505-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307116159.3069.22.camel@localhost>

On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
> The same functionality is provided by physmap flash driver,
> drivers/mtd/maps/ceiva.c didn't receive any functional changes since
> the start of current git history, so drop it.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

How about this: I take this patch to l2-mtd-2.6, but not taking the
first patch. If someone complains that he needs ceiva, we'll add you
first patch. Otherwise, you should kill all the other ceiva bits. Is
this OK?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From adrian.wenl at gmail.com  Fri Jun  3 11:58:03 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Fri, 3 Jun 2011 23:58:03 +0800
Subject: [PATCH 1/2] mtd: pxa3xx_nand: fix a memory leak
In-Reply-To: <BANLkTikNC8F2TPY2TFHuHtU=-xhwef2ikw@mail.gmail.com>
References: <1307078050.4167.1.camel@phoenix>
	<BANLkTikNC8F2TPY2TFHuHtU=-xhwef2ikw@mail.gmail.com>
Message-ID: <BANLkTin5oTOEq_t+NDHGOdtG5e0Mam9BLg@mail.gmail.com>

On Fri, Jun 3, 2011 at 9:02 PM, Daniel Mack <zonque at gmail.com> wrote:
> (Cc Lei Wen)
>
> On Fri, Jun 3, 2011 at 7:14 AM, Axel Lin <axel.lin at gmail.com> wrote:
>> In pxa3xx_nand_remove, we should call nand_release instead of
>> mtd_device_unregister to properly free bad block table memory
>> and bad block descriptor memory.
>>
>> Signed-off-by: Axel Lin <axel.lin at gmail.com>
>> ---
>> ?drivers/mtd/nand/pxa3xx_nand.c | ? ?2 +-
>> ?1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index 1fb3b3a..f7040ea 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -1119,7 +1119,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
>> ? ? ? ?clk_put(info->clk);
>>
>> ? ? ? ?if (mtd) {
>> - ? ? ? ? ? ? ? mtd_device_unregister(mtd);
>> + ? ? ? ? ? ? ? nand_release(mtd);
>> ? ? ? ? ? ? ? ?kfree(mtd);
>> ? ? ? ?}
>> ? ? ? ?return 0;
>> --
>> 1.7.4.1
>>

Acked-by: Lei Wen <leiwen at marvell.com>


From dedekind1 at gmail.com  Fri Jun  3 11:55:15 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:55:15 +0300
Subject: [RFC PATCH 000/104] mtd: cleanup partition parsing interface
In-Reply-To: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307116515.3069.24.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> Hello,
> 
> This is an RFC for a huge serie of patches converting most mtd drivers to use
> single instance of code for managing mtd partitions parsing and handling.
> 
> Currently each driver responsible for partitions implements this part of code
> on it's own, resulting in memory leaks, possible frees of non-allocated memory,
> etc. As the patch serie is huge, I'm posting only patches I consider
> "interesting", i. e. from the subserie doing the same cleanup for different
> drivers I post only first patch. Rest are available through the gitweb.
> 
> Only one driver still uses parse_mtd_partitions after this serie (edb7312),
> as it registers both parsed partitions and the whole mtd device and I ain't
> sure how to behave at this case.
> 
> If the idea seems find to be commited, I'll post the whole serie for full
> review.

Hi, sure this is interesting. I'll try to find time and go through this
and push to l2 tree. But then please, ping dwmw2 to look at this,
because otherwise it will not get to linux-next till the end of the next
merge window.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Fri Jun  3 11:58:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 03 Jun 2011 18:58:52 +0300
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <20110602064832.GA7319@july>
References: <20110602064832.GA7319@july>
Message-ID: <1307116732.3069.26.camel@localhost>

On Thu, 2011-06-02 at 15:48 +0900, Kyungmin Park wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> There's no case to use the subpage for 4KiB pagesize.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>

I think Roman was testing subpage support with 4KiB pages and it worked,
but I'm not sure and I did not read the specs. Let's ask Roman.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From computersforpeace at gmail.com  Fri Jun  3 14:25:01 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 3 Jun 2011 11:25:01 -0700
Subject: [PATCH 2/2] nanddump: sort options in help message
	alphabetically by shortname
In-Reply-To: <1307125501-32558-1-git-send-email-computersforpeace@gmail.com>
References: <1307125501-32558-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307125501-32558-2-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 78ea22e..c9d7e8b 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -48,6 +48,7 @@ static void display_help(void)
 "           --help               Display this help and exit\n"
 "           --version            Output version information and exit\n"
 "-a         --forcebinary        Force printing of binary data to tty\n"
+"-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
 "-k         --skipbad            Skip over bad blocks (see below)\n"
@@ -55,7 +56,6 @@ static void display_help(void)
 "-n         --noecc              Read without error correction\n"
 "-N         --noskipbad          Read without bad block skipping\n"
 "-o         --omitoob            Omit oob data\n"
-"-b         --omitbad            Omit bad blocks from the dump\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun  3 14:25:00 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 3 Jun 2011 11:25:00 -0700
Subject: [PATCH 1/2] nanddump: add --skipbad option for bad blocks
Message-ID: <1307125501-32558-1-git-send-email-computersforpeace@gmail.com>

This patch adds a new option "--skipbad" to nanddump. It is subtly
different than "--omitbad". The following description was included in
the help message to attempt to clarify the differences.

 Notes on --omitbad and --skipbad:
   With either option, we stop dumping data when we encounter a bad block
   and resume dumping at the next good block. However, with --omitbad, we
   count the bad block as part of the total dump length, whereas with
   --skipbad, the bad block is 'skipped,' that is, not counted toward the
   total dump length.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   38 ++++++++++++++++++++++++++++++++++++--
 1 files changed, 36 insertions(+), 2 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 214fb12..78ea22e 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -50,6 +50,7 @@ static void display_help(void)
 "-a         --forcebinary        Force printing of binary data to tty\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
+"-k         --skipbad            Skip over bad blocks (see below)\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
 "-N         --noskipbad          Read without bad block skipping\n"
@@ -57,7 +58,14 @@ static void display_help(void)
 "-b         --omitbad            Omit bad blocks from the dump\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
-"-s addr    --startaddress=addr  Start address\n",
+"-s addr    --startaddress=addr  Start address\n"
+"\n"
+"Notes on --omitbad and --skipbad:\n"
+"  With either option, we stop dumping data when we encounter a bad block\n"
+"  and resume dumping at the next good block. However, with --omitbad, we\n"
+"  count the bad block as part of the total dump length, whereas with\n"
+"  --skipbad, the bad block is 'skipped,' that is, not counted toward the\n"
+"  total dump length.\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
 }
@@ -90,6 +98,7 @@ static bool			omitbad = false;
 static bool			quiet = false;		// suppress diagnostic output
 static bool			canonical = false;	// print nice + ascii
 static bool			forcebinary = false;	// force printing binary to tty
+static bool			skipbad = false;	// skip over bad blocks
 
 static void process_options(int argc, char * const argv[])
 {
@@ -97,7 +106,7 @@ static void process_options(int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "bs:f:l:opqnNca";
+		static const char *short_options = "bs:f:l:opqnNcak";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
@@ -111,6 +120,7 @@ static void process_options(int argc, char * const argv[])
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
 			{"noskipbad", no_argument, 0, 'N'},
+			{"skipbad", no_argument, 0, 'k'},
 			{"quiet", no_argument, 0, 'q'},
 			{0, 0, 0, 0},
 		};
@@ -167,6 +177,9 @@ static void process_options(int argc, char * const argv[])
 			case 'N':
 				noskipbad = true;
 				break;
+			case 'k':
+				skipbad = true;
+				break;
 			case '?':
 				error++;
 				break;
@@ -193,6 +206,19 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (noskipbad && skipbad) {
+		fprintf(stderr, "The noskipbad and skipbad options are "
+				"mutually-exclusive.\n"
+				"Choose one or the other.\n");
+		exit(EXIT_FAILURE);
+	}
+
+	if (omitbad && skipbad) {
+		fprintf(stderr, "The omitbad and skipbad options are mutually-"
+				"exclusive.\nChoose one or the other.\n");
+		exit(EXIT_FAILURE);
+	}
+
 	if ((argc - optind) != 1 || error)
 		display_help();
 
@@ -403,6 +429,14 @@ int main(int argc, char * const argv[])
 		}
 
 		if (badblock) {
+			/* skip bad block, increase end_addr */
+			if (skipbad) {
+				end_addr += mtd.eb_size;
+				ofs += mtd.eb_size - bs;
+				if (end_addr > mtd.size)
+					end_addr = mtd.size;
+				continue;
+			}
 			if (omitbad)
 				continue;
 			memset(readbuf, 0xff, bs);
-- 
1.7.0.4




From greg at kroah.com  Fri Jun  3 18:32:26 2011
From: greg at kroah.com (Greg KH)
Date: Sat, 4 Jun 2011 07:32:26 +0900
Subject: [stable] [PATCH] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <BANLkTinuqQmp43K4H0iPDbb-H-rDA_nL9w@mail.gmail.com>
References: <BANLkTimos3-Ds4Y8FDfDZegqAhH7nSS4PA@mail.gmail.com>
	<1305865207-7869-1-git-send-email-leiwen@marvell.com>
	<BANLkTinuqQmp43K4H0iPDbb-H-rDA_nL9w@mail.gmail.com>
Message-ID: <20110603223226.GC9161@kroah.com>

On Fri, Jun 03, 2011 at 11:11:54PM +0800, Lei Wen wrote:
> Tested-by: Daniel Mack <zonque at gmail.com>
> 
> Also cc to MTD maillist and stable kernel.


<formletter>

This is not the correct way to submit patches for inclusion in the
stable kernel tree.  Please read Documentation/stable_kernel_rules.txt
for how to do this properly.

</formletter>


From zonque at gmail.com  Sat Jun  4 03:45:25 2011
From: zonque at gmail.com (Daniel Mack)
Date: Sat, 4 Jun 2011 09:45:25 +0200
Subject: [stable] [PATCH] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <20110603223226.GC9161@kroah.com>
References: <BANLkTimos3-Ds4Y8FDfDZegqAhH7nSS4PA@mail.gmail.com>
	<1305865207-7869-1-git-send-email-leiwen@marvell.com>
	<BANLkTinuqQmp43K4H0iPDbb-H-rDA_nL9w@mail.gmail.com>
	<20110603223226.GC9161@kroah.com>
Message-ID: <BANLkTi=GEV3xfAZ+UphPPSG2hZavchiwPQ@mail.gmail.com>

On Sat, Jun 4, 2011 at 12:32 AM, Greg KH <greg at kroah.com> wrote:
> On Fri, Jun 03, 2011 at 11:11:54PM +0800, Lei Wen wrote:
>> Tested-by: Daniel Mack <zonque at gmail.com>
>>
>> Also cc to MTD maillist and stable kernel.
>
> <formletter>
>
> This is not the correct way to submit patches for inclusion in the
> stable kernel tree. ?Please read Documentation/stable_kernel_rules.txt
> for how to do this properly.
>
> </formletter>

Jup.

Lei - when you collect the patches for this driver to send them out,
make sure every one gets a "Cc: stable at kernel.org" line under the
S-o-b, so it can be picked automatically later on.

Just to be sure, I count four patches now:

 - 1 from you regarding keep_config chip detection and DMA support
(which is *not* the one this thread refers to, you sent an amended
version to me privately, and it might make sense to split this patch
again)
 - 1 from me for the blank page ECC issue
 - 2 from Alex Lin (one for removal of unused variable, one plugs a memory leak)


Thanks,
Daniel


From dbaryshkov at gmail.com  Sat Jun  4 04:23:13 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sat, 4 Jun 2011 12:23:13 +0400
Subject: [PATCH 2/2] mtd: drop ceiva map driver
In-Reply-To: <1307116159.3069.22.camel@localhost>
References: <1307015648-17505-1-git-send-email-dbaryshkov@gmail.com>
	<1307015648-17505-2-git-send-email-dbaryshkov@gmail.com>
	<1307116159.3069.22.camel@localhost>
Message-ID: <BANLkTim0e4OYbSvwq1nENWkcUFynjV3ksg@mail.gmail.com>

Hello,

On 6/3/11, Artem Bityutskiy <Artem.Bityutskiy at nokia.com> wrote:
> On Thu, 2011-06-02 at 15:54 +0400, Dmitry Eremin-Solenikov wrote:
>> The same functionality is provided by physmap flash driver,
>> drivers/mtd/maps/ceiva.c didn't receive any functional changes since
>> the start of current git history, so drop it.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>
> How about this: I take this patch to l2-mtd-2.6, but not taking the
> first patch. If someone complains that he needs ceiva, we'll add you
> first patch. Otherwise, you should kill all the other ceiva bits. Is
> this OK?

Yes, this is perfectly fine with me. Anyway, I'm still waiting for a response
from Russell/linux-arm-kernel regarding ceiva & whole clps sub-arch.

-- 
With best wishes
Dmitry


From dbaryshkov at gmail.com  Sat Jun  4 04:25:45 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sat, 4 Jun 2011 12:25:45 +0400
Subject: [RFC PATCH 000/104] mtd: cleanup partition parsing interface
In-Reply-To: <1307116515.3069.24.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307116515.3069.24.camel@localhost>
Message-ID: <BANLkTi==kBwqeJLMRzA_VXJ58sky7FE_gg@mail.gmail.com>

On 6/3/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
>> Hello,
>>
>> This is an RFC for a huge serie of patches converting most mtd drivers to
>> use
>> single instance of code for managing mtd partitions parsing and handling.
>>
>> Currently each driver responsible for partitions implements this part of
>> code
>> on it's own, resulting in memory leaks, possible frees of non-allocated
>> memory,
>> etc. As the patch serie is huge, I'm posting only patches I consider
>> "interesting", i. e. from the subserie doing the same cleanup for
>> different
>> drivers I post only first patch. Rest are available through the gitweb.
>>
>> Only one driver still uses parse_mtd_partitions after this serie
>> (edb7312),
>> as it registers both parsed partitions and the whole mtd device and I
>> ain't
>> sure how to behave at this case.
>>
>> If the idea seems find to be commited, I'll post the whole serie for full
>> review.
>
> Hi, sure this is interesting. I'll try to find time and go through this
> and push to l2 tree. But then please, ping dwmw2 to look at this,
> because otherwise it will not get to linux-next till the end of the next
> merge window.

I'll then rebase this on top of l2 tree and post a formal pull request
with both you and dwmw2 in cc. Is this fine from your point of view?

-- 
With best wishes
Dmitry


From pewi at gw-instruments.de  Sun Jun  5 12:40:03 2011
From: pewi at gw-instruments.de (Peter Wippich)
Date: Sun, 5 Jun 2011 18:40:03 +0200 (CEST)
Subject: nandwrite with raw oob data 
Message-ID: <alpine.LSU.2.00.1106051821580.26001@redbean.intranet.gw-instruments.de>


Dear all,

I run into the same problem as outlined here before:
http://lists.infradead.org/pipermail/linux-mtd/2011-March/034516.html

Going a little bit deeper it looks to me that writing any nand flash data 
with raw (precomputed ECC) OOB data is not possible at all with a recent 
Kernel and nandwrite version.

What happens here is that nandwrite will set MTD_MODE_RAW when noecc is 
specified. Doing so will force the kernel driver to write OOB data only on 
a normal write. Obviously this will fail when someone is trying to write 
normal data to flash in MODE_RAW.

Question: is this realy the intended behaviour ???

It may be easy to fix this on kernel level, but may be there is some good 
reason I don't know to do it as it is. And I don't want to break things.

Any comments welcome.

Thank you and Cheers,

Peter





From vapier at gentoo.org  Mon Jun  6 00:09:13 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 00:09:13 -0400
Subject: [PATCH 4/5] flash_{lock,unlock}: convert to common code
In-Reply-To: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307333354-26583-4-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_unlock.c |   75 ++++++++++++++++++++++++++++++-------------------------
 1 files changed, 41 insertions(+), 34 deletions(-)

diff --git a/flash_unlock.c b/flash_unlock.c
index 759a5bc..3d7dd53 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -22,48 +22,57 @@
 #include <sys/mount.h>
 #include <string.h>
 
+#include "common.h"
 #include <mtd/mtd-user.h>
 
+static void usage(int status)
+{
+	fprintf(status ? stderr : stdout,
+		"Usage: %s <mtd device> [offset] [block count]\n\n"
+		"If offset is not specified, it defaults to 0.\n"
+		"If block count is not specified, it defaults to all blocks.\n",
+		PROGRAM_NAME);
+	exit(status);
+}
+
 int main(int argc, char *argv[])
 {
 	int fd, request;
 	struct mtd_info_user mtdInfo;
 	struct erase_info_user mtdLockInfo;
 	int count;
+	const char *dev;
 
 	/*
 	 * Parse command line options
 	 */
-	if (argc < 2) {
-		fprintf(stderr, "USAGE: %s <mtd device> <offset> <block count>\n", PROGRAM_NAME);
-		exit(1);
-	} else if (strncmp(argv[1], "/dev/mtd", 8) != 0) {
-		fprintf(stderr, "'%s' is not a MTD device.  Must specify mtd device: /dev/mtd?\n", argv[1]);
-		exit(1);
-	}
+	if (argc < 2 || argc > 4)
+		usage(1);
+	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
+		usage(0);
 
-	fd = open(argv[1], O_RDWR);
-	if (fd < 0) {
-		fprintf(stderr, "Could not open mtd device: %s\n", argv[1]);
-		exit(1);
-	}
+	dev = argv[1];
+
+	/*
+	 * Get the device info to compare to command line sizes
+	 */
+	fd = open(dev, O_RDWR);
+	if (fd < 0)
+		sys_errmsg_die("could not open: %s", dev);
 
-	if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
-		fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]);
-		close(fd);
-		exit(1);
-	}
+	if (ioctl(fd, MEMGETINFO, &mtdInfo))
+		sys_errmsg_die("could not get mtd info: %s", dev);
 
+	/*
+	 * Make sure user options are valid
+	 */
 	if (argc > 2)
 		mtdLockInfo.start = strtol(argv[2], NULL, 0);
 	else
 		mtdLockInfo.start = 0;
-	if (mtdLockInfo.start > mtdInfo.size) {
-		fprintf(stderr, "%#x is beyond device size %#x\n",
+	if (mtdLockInfo.start > mtdInfo.size)
+		errmsg_die("%#x is beyond device size %#x",
 			mtdLockInfo.start, mtdInfo.size);
-		close(fd);
-		exit(1);
-	}
 
 	if (argc > 3) {
 		count = strtol(argv[3], NULL, 0);
@@ -71,21 +80,19 @@ int main(int argc, char *argv[])
 			mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
 		else
 			mtdLockInfo.length = mtdInfo.erasesize * count;
-	} else {
+	} else
 		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
-	}
-	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size) {
-		fprintf(stderr, "%s range is more than device supports\n", FLASH_MSG);
-		exit(1);
-	}
+	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size)
+		errmsg_die("range is more than device supports: %#x + %#x > %#x",
+			mtdLockInfo.start, mtdLockInfo.length, mtdInfo.size);
 
+	/*
+	 * Finally do the operation
+	 */
 	request = FLASH_UNLOCK ? MEMUNLOCK : MEMLOCK;
-	if (ioctl(fd, request, &mtdLockInfo)) {
-		fprintf(stderr, "Could not %s MTD device: %s\n",
-			FLASH_MSG, argv[1]);
-		close(fd);
-		exit(1);
-	}
+	if (ioctl(fd, request, &mtdLockInfo))
+		sys_errmsg_die("could not %s device: %s\n",
+			FLASH_MSG, dev);
 
 	return 0;
 }
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 00:09:14 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 00:09:14 -0400
Subject: [PATCH 5/5] flash_{lock,
	unlock}: fix off-by-one error for "entire device" length
In-Reply-To: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307333354-26583-5-git-send-email-vapier@gentoo.org>

From: Steven Miao <realmz6 at gmail.com>

This basically reverts commit 43feb39f35a9ee0ed3 which changed the full
length calculation to be one less than one sector.  I don't understand
the logic in the commit message where it states that the length should
be one sector smaller as this results in misbehavior at runtime.

For example, with a mtd device with total size 0x400000 and erase block
size of 0x20000 (which gives us a total of 32 sectors), this new logic
results in:
	mtdLockInfo.start = 0;
	mtdLockInfo.length = 0x3e0000; /* (32 - 1) * 0x20000 */

Calling MEMLOCK/MEMUNLOCK on the device with this range leaves the last
sector unchanged which is certainly not what we want.  So drop this -1
part of the calculation.

To look at it another way, if we only attempt to lock one sector, this
calculation would end up with the .length set to 0.  Calling MEMLOCK
with a length of 0 does not lock the sector as this simple code shows:
	int main(int argc, char *argv[]) {
		erase_info_t e0 = { 0, 0 }, e1 = { 0, 0x20000 };
		int fd = open(argv[1], O_RDONLY);
		ioctl(fd, MEMUNLOCK, &e1);
		printf("%i\n", ioctl(fd, MEMISLOCKED, &e1));
		ioctl(fd, MEMLOCK, &e0);
		printf("%i\n", ioctl(fd, MEMISLOCKED, &e1));
	}
MEMISLOCKED returns 0 both times.  If we change the argument to MEMLOCK
to e1, then MEMISLOCKED returns 1.

CC: Vimal Singh <vimal.newwork at gmail.com>
CC: Vimal Singh <vimalsingh at ti.com>
Signed-off-by: Steven Miao <realmz6 at gmail.com>
Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_unlock.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/flash_unlock.c b/flash_unlock.c
index 3d7dd53..9fb089a 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -77,11 +77,11 @@ int main(int argc, char *argv[])
 	if (argc > 3) {
 		count = strtol(argv[3], NULL, 0);
 		if (count == -1)
-			mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+			mtdLockInfo.length = mtdInfo.size;
 		else
 			mtdLockInfo.length = mtdInfo.erasesize * count;
 	} else
-		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+		mtdLockInfo.length = mtdInfo.size;
 	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size)
 		errmsg_die("range is more than device supports: %#x + %#x > %#x",
 			mtdLockInfo.start, mtdLockInfo.length, mtdInfo.size);
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 00:09:12 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 00:09:12 -0400
Subject: [PATCH 3/5] flash_{lock,unlock}: merge into one util
In-Reply-To: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307333354-26583-3-git-send-email-vapier@gentoo.org>

Now that the utils have equivalent functionality, merge the two source
code bases so they can't diverge in the future.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_lock.c   |   81 ++-----------------------------------------------------
 flash_unlock.c |   22 ++++++++++-----
 2 files changed, 18 insertions(+), 85 deletions(-)

diff --git a/flash_lock.c b/flash_lock.c
index 164eaa4..33f76c7 100644
--- a/flash_lock.c
+++ b/flash_lock.c
@@ -1,83 +1,8 @@
 /*
- * FILE flash_lock.c
- *
- * This utility locks one or more sectors of flash device.
+ * flash_{lock,unlock}
  *
+ * utilities for locking/unlocking sectors of flash devices
  */
 
 #define PROGRAM_NAME "flash_lock"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-#include <string.h>
-
-#include <mtd/mtd-user.h>
-
-int main(int argc, char *argv[])
-{
-	int fd;
-	struct mtd_info_user mtdInfo;
-	struct erase_info_user mtdLockInfo;
-	int count;
-
-	/*
-	 * Parse command line options
-	 */
-	if (argc < 2) {
-		fprintf(stderr, "USAGE: %s <mtd device> <offset> <block count>\n", PROGRAM_NAME);
-		exit(1);
-	} else if (strncmp(argv[1], "/dev/mtd", 8) != 0) {
-		fprintf(stderr, "'%s' is not a MTD device.  Must specify mtd device: /dev/mtd?\n", argv[1]);
-		exit(1);
-	}
-
-	fd = open(argv[1], O_RDWR);
-	if (fd < 0) {
-		fprintf(stderr, "Could not open mtd device: %s\n", argv[1]);
-		exit(1);
-	}
-
-	if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
-		fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]);
-		close(fd);
-		exit(1);
-	}
-
-	if (argc > 2)
-		mtdLockInfo.start = strtol(argv[2], NULL, 0);
-	else
-		mtdLockInfo.start = 0;
-	if (mtdLockInfo.start > mtdInfo.size) {
-		fprintf(stderr, "%#x is beyond device size %#x\n",
-			mtdLockInfo.start, mtdInfo.size);
-		close(fd);
-		exit(1);
-	}
-
-	if (argc > 3) {
-		count = strtol(argv[3], NULL, 0);
-		if (count == -1)
-			mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
-		else
-			mtdLockInfo.length = mtdInfo.erasesize * count;
-	} else {
-		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
-	}
-	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size) {
-		fprintf(stderr, "lock range is more than device supports\n");
-		exit(1);
-	}
-
-	if (ioctl(fd, MEMLOCK, &mtdLockInfo)) {
-		fprintf(stderr, "Could not lock MTD device: %s\n", argv[1]);
-		close(fd);
-		exit(1);
-	}
-
-	return 0;
-}
+#include "flash_unlock.c"
diff --git a/flash_unlock.c b/flash_unlock.c
index 690825d..759a5bc 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -1,11 +1,17 @@
 /*
- * FILE flash_unlock.c
- *
- * This utility unlock all sectors of flash device.
+ * flash_{lock,unlock}
  *
+ * utilities for locking/unlocking sectors of flash devices
  */
 
+#ifndef PROGRAM_NAME
 #define PROGRAM_NAME "flash_unlock"
+#define FLASH_MSG    "unlock"
+#define FLASH_UNLOCK 1
+#else
+#define FLASH_MSG    "lock"
+#define FLASH_UNLOCK 0
+#endif
 
 #include <unistd.h>
 #include <stdlib.h>
@@ -20,7 +26,7 @@
 
 int main(int argc, char *argv[])
 {
-	int fd;
+	int fd, request;
 	struct mtd_info_user mtdInfo;
 	struct erase_info_user mtdLockInfo;
 	int count;
@@ -69,12 +75,14 @@ int main(int argc, char *argv[])
 		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
 	}
 	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size) {
-		fprintf(stderr, "unlock range is more than device supports\n");
+		fprintf(stderr, "%s range is more than device supports\n", FLASH_MSG);
 		exit(1);
 	}
 
-	if (ioctl(fd, MEMUNLOCK, &mtdLockInfo)) {
-		fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]);
+	request = FLASH_UNLOCK ? MEMUNLOCK : MEMLOCK;
+	if (ioctl(fd, request, &mtdLockInfo)) {
+		fprintf(stderr, "Could not %s MTD device: %s\n",
+			FLASH_MSG, argv[1]);
 		close(fd);
 		exit(1);
 	}
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 00:09:11 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 00:09:11 -0400
Subject: [PATCH 2/5] flash_{lock,unlock}: merge functionality
In-Reply-To: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307333354-26583-2-git-send-email-vapier@gentoo.org>

The flash_lock util has a bit of extra argument checking, and it supports
a magic value of "-1" to mean "all blocks".

The flash_unlock util supports automatic 2nd/3rd arguments to unlock the
whole flash.  It also supports multiple bases (not just hex) for selecting
the range of the device to unlock.

So tweak both utilities so that they have equivalent functionality again
by adding the missing features to each.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_lock.c   |   41 +++++++++++++++++++++++------------------
 flash_unlock.c |   17 +++++++++++++++--
 2 files changed, 38 insertions(+), 20 deletions(-)

diff --git a/flash_lock.c b/flash_lock.c
index 8cd1b82..164eaa4 100644
--- a/flash_lock.c
+++ b/flash_lock.c
@@ -23,14 +23,13 @@ int main(int argc, char *argv[])
 	int fd;
 	struct mtd_info_user mtdInfo;
 	struct erase_info_user mtdLockInfo;
-	int num_sectors;
-	int ofs;
+	int count;
 
 	/*
 	 * Parse command line options
 	 */
-	if (argc != 4) {
-		fprintf(stderr, "USAGE: %s <mtd device> <ofs in hex> <num of sectors in decimal or -1 for all sectors>\n", PROGRAM_NAME);
+	if (argc < 2) {
+		fprintf(stderr, "USAGE: %s <mtd device> <offset> <block count>\n", PROGRAM_NAME);
 		exit(1);
 	} else if (strncmp(argv[1], "/dev/mtd", 8) != 0) {
 		fprintf(stderr, "'%s' is not a MTD device.  Must specify mtd device: /dev/mtd?\n", argv[1]);
@@ -48,26 +47,32 @@ int main(int argc, char *argv[])
 		close(fd);
 		exit(1);
 	}
-	sscanf(argv[2], "%x", &ofs);
-	sscanf(argv[3], "%d", &num_sectors);
-	if (ofs > mtdInfo.size - mtdInfo.erasesize) {
-		fprintf(stderr, "%x is beyond device size %x\n", ofs,
-			(unsigned int)(mtdInfo.size - mtdInfo.erasesize));
+
+	if (argc > 2)
+		mtdLockInfo.start = strtol(argv[2], NULL, 0);
+	else
+		mtdLockInfo.start = 0;
+	if (mtdLockInfo.start > mtdInfo.size) {
+		fprintf(stderr, "%#x is beyond device size %#x\n",
+			mtdLockInfo.start, mtdInfo.size);
+		close(fd);
 		exit(1);
 	}
 
-	if (num_sectors == -1) {
-		num_sectors = mtdInfo.size / mtdInfo.erasesize;
+	if (argc > 3) {
+		count = strtol(argv[3], NULL, 0);
+		if (count == -1)
+			mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+		else
+			mtdLockInfo.length = mtdInfo.erasesize * count;
 	} 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));
-			exit(1);
-		}
+		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+	}
+	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size) {
+		fprintf(stderr, "lock range is more than device supports\n");
+		exit(1);
 	}
 
-	mtdLockInfo.start = ofs;
-	mtdLockInfo.length = (num_sectors - 1) * mtdInfo.erasesize;
 	if (ioctl(fd, MEMLOCK, &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 26721a5..690825d 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -29,7 +29,7 @@ int main(int argc, char *argv[])
 	 * Parse command line options
 	 */
 	if (argc < 2) {
-		fprintf(stderr, "USAGE: %s <mtd device> <offset in hex> <block count in decimal number>\n", PROGRAM_NAME);
+		fprintf(stderr, "USAGE: %s <mtd device> <offset> <block count>\n", PROGRAM_NAME);
 		exit(1);
 	} else if (strncmp(argv[1], "/dev/mtd", 8) != 0) {
 		fprintf(stderr, "'%s' is not a MTD device.  Must specify mtd device: /dev/mtd?\n", argv[1]);
@@ -52,13 +52,26 @@ int main(int argc, char *argv[])
 		mtdLockInfo.start = strtol(argv[2], NULL, 0);
 	else
 		mtdLockInfo.start = 0;
+	if (mtdLockInfo.start > mtdInfo.size) {
+		fprintf(stderr, "%#x is beyond device size %#x\n",
+			mtdLockInfo.start, mtdInfo.size);
+		close(fd);
+		exit(1);
+	}
 
 	if (argc > 3) {
 		count = strtol(argv[3], NULL, 0);
-		mtdLockInfo.length = mtdInfo.erasesize * count;
+		if (count == -1)
+			mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
+		else
+			mtdLockInfo.length = mtdInfo.erasesize * count;
 	} else {
 		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
 	}
+	if (mtdLockInfo.start + mtdLockInfo.length > mtdInfo.size) {
+		fprintf(stderr, "unlock range is more than device supports\n");
+		exit(1);
+	}
 
 	if (ioctl(fd, MEMUNLOCK, &mtdLockInfo)) {
 		fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]);
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 00:09:10 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 00:09:10 -0400
Subject: [PATCH 1/5] flash_lock/flash_unlock/flash_info: clean up style
Message-ID: <1307333354-26583-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_info.c   |   31 +++++++++++++------------------
 flash_lock.c   |   37 +++++++++++++++----------------------
 flash_unlock.c |   16 +++++-----------
 3 files changed, 33 insertions(+), 51 deletions(-)

diff --git a/flash_info.c b/flash_info.c
index ad7b30a..f8b7efa 100644
--- a/flash_info.c
+++ b/flash_info.c
@@ -14,44 +14,39 @@
 
 #include <mtd/mtd-user.h>
 
-int main(int argc,char *argv[])
+int main(int argc, char *argv[])
 {
 	int regcount;
-	int Fd;
+	int fd;
 
-	if (1 >= argc)
-	{
-		fprintf(stderr,"Usage: %s device\n", PROGRAM_NAME);
+	if (1 >= argc) {
+		fprintf(stderr, "Usage: %s device\n", PROGRAM_NAME);
 		return 16;
 	}
 
-	// Open and size the device
-	if ((Fd = open(argv[1],O_RDONLY)) < 0)
-	{
-		fprintf(stderr,"File open error\n");
+	/* Open and size the device */
+	fd = open(argv[1], O_RDONLY);
+	if (fd < 0) {
+		fprintf(stderr, "File open error\n");
 		return 8;
 	}
 
-	if (ioctl(Fd,MEMGETREGIONCOUNT,&regcount) == 0)
-	{
+	if (ioctl(fd, MEMGETREGIONCOUNT, &regcount) == 0) {
 		int i;
 		region_info_t reginfo;
 		printf("Device %s has %d erase regions\n", argv[1], regcount);
-		for (i = 0; i < regcount; i++)
-		{
+		for (i = 0; i < regcount; i++) {
 			reginfo.regionindex = i;
-			if(ioctl(Fd, MEMGETREGIONINFO, &reginfo) == 0)
-			{
+			if (ioctl(fd, MEMGETREGIONINFO, &reginfo) == 0) {
 				printf("Region %d is at 0x%x with size 0x%x and "
 						"has 0x%x blocks\n", i, reginfo.offset,
 						reginfo.erasesize, reginfo.numblocks);
-			}
-			else
-			{
+			} else {
 				printf("Strange can not read region %d from a %d region device\n",
 						i, regcount);
 			}
 		}
 	}
+
 	return 0;
 }
diff --git a/flash_lock.c b/flash_lock.c
index ef75234..8cd1b82 100644
--- a/flash_lock.c
+++ b/flash_lock.c
@@ -29,53 +29,46 @@ int main(int argc, char *argv[])
 	/*
 	 * Parse command line options
 	 */
-	if(argc != 4)
-	{
+	if (argc != 4) {
 		fprintf(stderr, "USAGE: %s <mtd device> <ofs in hex> <num of sectors in decimal or -1 for all sectors>\n", PROGRAM_NAME);
 		exit(1);
-	}
-	else if(strncmp(argv[1], "/dev/mtd", 8) != 0)
-	{
+	} else if (strncmp(argv[1], "/dev/mtd", 8) != 0) {
 		fprintf(stderr, "'%s' is not a MTD device.  Must specify mtd device: /dev/mtd?\n", argv[1]);
 		exit(1);
 	}
 
 	fd = open(argv[1], O_RDWR);
-	if(fd < 0)
-	{
+	if (fd < 0) {
 		fprintf(stderr, "Could not open mtd device: %s\n", argv[1]);
 		exit(1);
 	}
 
-	if(ioctl(fd, MEMGETINFO, &mtdInfo))
-	{
+	if (ioctl(fd, MEMGETINFO, &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);
-	if(ofs > mtdInfo.size - mtdInfo.erasesize)
-	{
-		fprintf(stderr, "%x is beyond device size %x\n",ofs,(unsigned int)(mtdInfo.size - mtdInfo.erasesize));
+	sscanf(argv[2], "%x", &ofs);
+	sscanf(argv[3], "%d", &num_sectors);
+	if (ofs > mtdInfo.size - mtdInfo.erasesize) {
+		fprintf(stderr, "%x is beyond device size %x\n", ofs,
+			(unsigned int)(mtdInfo.size - mtdInfo.erasesize));
 		exit(1);
 	}
 
 	if (num_sectors == -1) {
-		num_sectors = mtdInfo.size/mtdInfo.erasesize;
-	}
-	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));
+		num_sectors = mtdInfo.size / mtdInfo.erasesize;
+	} 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));
 			exit(1);
 		}
 	}
 
 	mtdLockInfo.start = ofs;
 	mtdLockInfo.length = (num_sectors - 1) * mtdInfo.erasesize;
-	if(ioctl(fd, MEMLOCK, &mtdLockInfo))
-	{
+	if (ioctl(fd, MEMLOCK, &mtdLockInfo)) {
 		fprintf(stderr, "Could not lock MTD device: %s\n", argv[1]);
 		close(fd);
 		exit(1);
diff --git a/flash_unlock.c b/flash_unlock.c
index 3d29a92..26721a5 100644
--- a/flash_unlock.c
+++ b/flash_unlock.c
@@ -28,26 +28,21 @@ int main(int argc, char *argv[])
 	/*
 	 * Parse command line options
 	 */
-	if(argc < 2)
-	{
+	if (argc < 2) {
 		fprintf(stderr, "USAGE: %s <mtd device> <offset in hex> <block count in decimal number>\n", PROGRAM_NAME);
 		exit(1);
-	}
-	else if(strncmp(argv[1], "/dev/mtd", 8) != 0)
-	{
+	} else if (strncmp(argv[1], "/dev/mtd", 8) != 0) {
 		fprintf(stderr, "'%s' is not a MTD device.  Must specify mtd device: /dev/mtd?\n", argv[1]);
 		exit(1);
 	}
 
 	fd = open(argv[1], O_RDWR);
-	if(fd < 0)
-	{
+	if (fd < 0) {
 		fprintf(stderr, "Could not open mtd device: %s\n", argv[1]);
 		exit(1);
 	}
 
-	if(ioctl(fd, MEMGETINFO, &mtdInfo))
-	{
+	if (ioctl(fd, MEMGETINFO, &mtdInfo)) {
 		fprintf(stderr, "Could not get MTD device info from %s\n", argv[1]);
 		close(fd);
 		exit(1);
@@ -65,8 +60,7 @@ int main(int argc, char *argv[])
 		mtdLockInfo.length = mtdInfo.size - mtdInfo.erasesize;
 	}
 
-	if(ioctl(fd, MEMUNLOCK, &mtdLockInfo))
-	{
+	if (ioctl(fd, MEMUNLOCK, &mtdLockInfo)) {
 		fprintf(stderr, "Could not unlock MTD device: %s\n", argv[1]);
 		close(fd);
 		exit(1);
-- 
1.7.5.3



From hans-christian.egtvedt at atmel.com  Mon Jun  6 01:49:31 2011
From: hans-christian.egtvedt at atmel.com (Hans-Christian Egtvedt)
Date: Mon, 06 Jun 2011 07:49:31 +0200
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
	<1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>
	<BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
Message-ID: <1307339371.9413.5.camel@hcegtvedt.norway.atmel.com>

On Wed, 2011-06-01 at 18:54 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/1/11, Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com> wrote:
> > On Sun, 2011-05-29 at 17:49 +0400, Dmitry Eremin-Solenikov wrote:
> >> Currently atmel_nand driver used by AT91 and AVR32 calls a special
> >> callback
> >> which return nand partition table and number of partitions. However in all
> >> boards this callback returns just static data. So drop this callback and
> >> make atmel_nand use partition table provided statically via platform_data.
> >>
> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >
> > Thanks for this update, always nice seeing code being optimized. I
> > really can't recall why it was made like this in the first place...
> >
> > For the AVR32 related parts:
> >
> > Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>
> >
> > <snipp diff>
> >
> > Will this go through the linux-mtd tree (since it spans two archs) or
> > should it go through an arch tree?
> 
> On one hand, I'd prefer for this to go through the linux-mtd, if noone objects,
> as I'd also like to submit several (a pile) patches cleaning up mtd
> partitioning, which would depend on this.

I'm fine by sending the changes for AVR32 through linux-mtd, they are
minor and so far doesn't touch anything else that is changed.

> OTOH, I think there will be a cleanup of AT91 platform, which would bring
> lot's of conflicts with this patch, if it goes through linux-mtd.

AT91 will probably be worse, yes, should be doable by git to solve the
conflicts on its own. I'll leave it to Nicolas to give his verdict.

-- 
Hans-Christian Egtvedt



From dedekind1 at gmail.com  Mon Jun  6 03:04:55 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 10:04:55 +0300
Subject: [RFC PATCH 000/104] mtd: cleanup partition parsing interface
In-Reply-To: <BANLkTi==kBwqeJLMRzA_VXJ58sky7FE_gg@mail.gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307116515.3069.24.camel@localhost>
	<BANLkTi==kBwqeJLMRzA_VXJ58sky7FE_gg@mail.gmail.com>
Message-ID: <1307343895.3135.3.camel@localhost>

On Sat, 2011-06-04 at 12:25 +0400, Dmitry Eremin-Solenikov wrote:
> I'll then rebase this on top of l2 tree and post a formal pull request
> with both you and dwmw2 in cc. Is this fine from your point of view?

Sure, but also send all the patches to the mailing list.

P.S. Please, do provide a git URL, but note that we usually do not pull.
Instead, we pick patches and add Signed-off-by tags.

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 03:14:59 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 10:14:59 +0300
Subject: [PATCH 006/104] mtdpart: default to cmdlinepart, NULL
	partitions probing
In-Reply-To: <1307026293-8535-4-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-4-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307344499.3135.7.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> Lots of MTD devices default to cmdlinepart, NULL as partition parsing
> order. Make it a default.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/mtdpart.c |    5 +++++
>  1 files changed, 5 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index 630be3e..3477e16 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
> @@ -712,12 +712,17 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
>  }
>  EXPORT_SYMBOL_GPL(deregister_mtd_parser);
>  
> +static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
> +
>  int parse_mtd_partitions(struct mtd_info *master, const char **types,
>  			 struct mtd_partition **pparts, unsigned long origin)
>  {
>  	struct mtd_part_parser *parser;
>  	int ret = 0;
>  
> +	if (!types)
> +		types = default_mtd_part_types;
> +
>  	for ( ; ret <= 0 && *types; types++) {
>  		parser = get_partition_parser(*types);
>  		if (!parser && !request_module("%s", *types))

Pushed patches 4 and 5 to l2-mtd-2.6.git. Going to push this one as
well, but I would be nice go put a piece of descriptive comment above
'parse_mtd_partitions()', preferably a nice kerneldoc comment. As a
separate patch.

Anyway, pushing this one to the l2 tree as well.

P.S. Also added an "mtd:" prefix.




From dedekind1 at gmail.com  Mon Jun  6 03:20:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 10:20:52 +0300
Subject: [PATCH 007/104] mtd: m25p80 don't specify default parsing options
In-Reply-To: <1307026293-8535-5-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-5-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307344852.3135.8.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
> this in every driver, instead pass NULL to force parse_mtd_partitions
> to use default.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 03:23:23 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 10:23:23 +0300
Subject: [PATCH 040/104] mtd: drop mtd_has_cmdlinepart()
In-Reply-To: <1307026293-8535-6-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-6-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307345003.3135.11.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> This function is unused now. Drop it.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

I guess patches 8-39 are like patch 7 and remove explicit cmdline setup.
I guess it does not hurt if I take this patch now - you can omit it from
the next submission.

So, taken to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 03:37:30 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 10:37:30 +0300
Subject: l2-mtd-2.6.git to linux-next
Message-ID: <1307345850.3135.24.camel@localhost>

Stephen,

as we've discussed, please, include l2-mtd-2.6.git tree to linux-next:

git://git.infradead.org/users/dedekind/l2-mtd-2.6.git master

David, Stephen would like to see your explicit ack.

To make a long story short, currently the MTD subsystem maintenance is a
team work:

1. David is the maintainer who has the ultimate authority to merge or
   reject patches, and who holds the biggest MTD experience/knowledge.

2. David is busy with other projects and has no time to routinely
   review patches and merge them to the mtd-2.6.git tree. And I help him
   with my "level 2" l2-mtd-2.6.git tree.

By including l2-mtd-2.6.git into linux-next we want to solve the
following problem: because of lack of time dwmw2 does not always merges
patches to the mtd-2.6.git tree, and often we are in a situation when
MTD patches are exposed to linux-next for a day or 2, during the merge
window, and then they are merged.

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 03:57:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 10:57:34 +0300
Subject: [PATCH 041/104] mtd: prepare to convert
	of_mtd_parse_partitions to partition parser
In-Reply-To: <1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307347054.3135.28.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
> 1) Register ofpart parser
> 2) Internally don't use passed device for error printing
> 3) Add device_node to mtd_info struct
> 4) Move of_mtd_parse_partitions from __devinit to common text section
> 5) add ofpart to the default list of partition parsers
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Good idea, but 

>  #include <linux/mtd/mtd.h>
>  #include <linux/mtd/partitions.h>
> @@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
>  			const struct mtd_partition *parts,
>  			int nr_parts)
>  {
> +#ifdef CONFIG_OF
> +	if (master->node)
> +		of_node_get(master->node);
> +#endif

Could all the OF-specific things be done in the ofpart.c ?

> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -171,6 +171,9 @@ struct mtd_info {
>  	// Kernel-only stuff starts here.
>  	const char *name;
>  	int index;
> +#ifdef CONFIG_OF
> +	struct device_node *node;
> +#endif

And designe-wise this does not look like a good idea to have such fields
in mtd_info ... Who initializes this "node" field?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From nicolas.ferre at atmel.com  Mon Jun  6 04:05:42 2011
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Mon, 06 Jun 2011 10:05:42 +0200
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>	<1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>
	<BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
Message-ID: <4DEC8A56.1030707@atmel.com>

Le 01/06/2011 16:54, Dmitry Eremin-Solenikov :
> On 6/1/11, Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com> wrote:
>> On Sun, 2011-05-29 at 17:49 +0400, Dmitry Eremin-Solenikov wrote:
>>> Currently atmel_nand driver used by AT91 and AVR32 calls a special
>>> callback
>>> which return nand partition table and number of partitions. However in all
>>> boards this callback returns just static data. So drop this callback and
>>> make atmel_nand use partition table provided statically via platform_data.
>>>
>>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>>
>> Thanks for this update, always nice seeing code being optimized. I
>> really can't recall why it was made like this in the first place...
>>
>> For the AVR32 related parts:
>>
>> Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>
>>
>> <snipp diff>
>>
>> Will this go through the linux-mtd tree (since it spans two archs) or
>> should it go through an arch tree?
> 
> On one hand, I'd prefer for this to go through the linux-mtd, if noone objects,
> as I'd also like to submit several (a pile) patches cleaning up mtd
> partitioning, which would depend on this.
> 
> OTOH, I think there will be a cleanup of AT91 platform, which would bring
> lot's of conflicts with this patch, if it goes through linux-mtd.


I am in favor for a mainline inclusion through linux-mtd tree.

On the AT91 side, we will have to take this inclusion into account to
avoid merge conflicts... But as long as this cleanup is not ready yet, I
prefer to go forward this way.

For that purpose, that would be good to see this patch in linux-next.

Thanks to all of you, bye,
-- 
Nicolas Ferre



From dedekind1 at gmail.com  Mon Jun  6 04:02:10 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 11:02:10 +0300
Subject: [PATCH 050/104] physmap_of: separate parse_obsolete_partitions
	to separate parser
In-Reply-To: <1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307347330.3135.29.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> Separate parse_obsolete_partitions() to external ofoldpart partitions parser.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/Kconfig           |   10 +++++
>  drivers/mtd/Makefile          |    1 +
>  drivers/mtd/maps/physmap_of.c |   53 +------------------------
>  drivers/mtd/ofoldpart.c       |   89 +++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 101 insertions(+), 52 deletions(-)
>  create mode 100644 drivers/mtd/ofoldpart.c
> 
> diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
> index 4be8373..2aa8afb 100644
> --- a/drivers/mtd/Kconfig
> +++ b/drivers/mtd/Kconfig
> @@ -144,6 +144,16 @@ config MTD_OF_PARTS
>  	  the partition map from the children of the flash node,
>  	  as described in Documentation/powerpc/booting-without-of.txt.
>  
> +config MTD_OF_OLD_PARTS
> +	bool "Obsolete OF tree partition info"
> +	depends on OF
> +	help
> +	  This provides a partition parsing function which derives
> +	  the partition map from the the flash node, being an obsolete
> +	  way to describe physmap_of partitioning info.
> +
> +	  If you aren't sure you need this, you can say N.

I think this tiny piece of code does not deserve to be a separate
module...

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Mon Jun  6 04:09:41 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 06 Jun 2011 12:09:41 +0400
Subject: [PATCH 050/104] physmap_of: separate parse_obsolete_partitions
	to separate parser
In-Reply-To: <1307347330.3135.29.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>	
	<1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>
	<1307347330.3135.29.camel@localhost>
Message-ID: <4DEC8B45.1020900@gmail.com>

On 06.06.2011 12:02, Artem Bityutskiy wrote:
> On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
>> Separate parse_obsolete_partitions() to external ofoldpart partitions parser.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
>> ---
>>   drivers/mtd/Kconfig           |   10 +++++
>>   drivers/mtd/Makefile          |    1 +
>>   drivers/mtd/maps/physmap_of.c |   53 +------------------------
>>   drivers/mtd/ofoldpart.c       |   89 +++++++++++++++++++++++++++++++++++++++++
>>   4 files changed, 101 insertions(+), 52 deletions(-)
>>   create mode 100644 drivers/mtd/ofoldpart.c
>>
>> diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
>> index 4be8373..2aa8afb 100644
>> --- a/drivers/mtd/Kconfig
>> +++ b/drivers/mtd/Kconfig
>> @@ -144,6 +144,16 @@ config MTD_OF_PARTS
>>   	  the partition map from the children of the flash node,
>>   	  as described in Documentation/powerpc/booting-without-of.txt.
>>
>> +config MTD_OF_OLD_PARTS
>> +	bool "Obsolete OF tree partition info"
>> +	depends on OF
>> +	help
>> +	  This provides a partition parsing function which derives
>> +	  the partition map from the the flash node, being an obsolete
>> +	  way to describe physmap_of partitioning info.
>> +
>> +	  If you aren't sure you need this, you can say N.
>
> I think this tiny piece of code does not deserve to be a separate
> module...

I'd really like to strip it out of physmap_of to simplify things.

It parses the mtd partitions, it's a separate functional part. I can 
argue if it should be a module or just in-kernel part, if it should be 
visible to users (or just autoselected by physmap_of), but I'd 
definitely prefer to have this as a separate source file hooking into
generic mtd_parse subsystem.

-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Mon Jun  6 04:05:48 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 11:05:48 +0300
Subject: [PATCH 041/104] mtd: prepare to convert
	of_mtd_parse_partitions to partition parser
In-Reply-To: <1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307347548.3135.31.camel@localhost>

On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
> 1) Register ofpart parser
> 2) Internally don't use passed device for error printing
> 3) Add device_node to mtd_info struct
> 4) Move of_mtd_parse_partitions from __devinit to common text section
> 5) add ofpart to the default list of partition parsers
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Do not apply this and further changes so far - I had some questions.

Anyway, your series consists of as set of logical steps, which is really
nice, so let's finish with the first cmdline consolidation step, and
then move on.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Mon Jun  6 04:15:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 06 Jun 2011 12:15:01 +0400
Subject: [PATCH 041/104] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307347054.3135.28.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>	
	<1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
	<1307347054.3135.28.camel@localhost>
Message-ID: <4DEC8C85.6090904@gmail.com>

On 06.06.2011 11:57, Artem Bityutskiy wrote:
> On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
>> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
>> 1) Register ofpart parser
>> 2) Internally don't use passed device for error printing
>> 3) Add device_node to mtd_info struct
>> 4) Move of_mtd_parse_partitions from __devinit to common text section
>> 5) add ofpart to the default list of partition parsers
>>
>> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
>
> Good idea, but
>
>>   #include<linux/mtd/mtd.h>
>>   #include<linux/mtd/partitions.h>
>> @@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
>>   			const struct mtd_partition *parts,
>>   			int nr_parts)
>>   {
>> +#ifdef CONFIG_OF
>> +	if (master->node)
>> +		of_node_get(master->node);
>> +#endif
>
> Could all the OF-specific things be done in the ofpart.c ?

Answering both of your questions here:
My idea is to have an of node connected to mtd device, if there is any.
It can be used by ofpart.c, ofoldpart.c (extract from physmap_of),
maybe some other parsers/drivers/etc.

The field is populated by the creator of mtd_info. Then the function
dedicated to registration of the mtd should get the node and other 
functions can just use it. Maybe this should be moved to add_mtd_device,
but this shouldn't be handled in ofpart.c

Another way can be to populate ->node pointer before parsing,
then drop it at the end of parsing/registration. Thus we won't have to
handle getting/putting the of node, but it won't be available during
mtd lifecycle.

>> --- a/include/linux/mtd/mtd.h
>> +++ b/include/linux/mtd/mtd.h
>> @@ -171,6 +171,9 @@ struct mtd_info {
>>   	// Kernel-only stuff starts here.
>>   	const char *name;
>>   	int index;
>> +#ifdef CONFIG_OF
>> +	struct device_node *node;
>> +#endif
>
> And designe-wise this does not look like a good idea to have such fields
> in mtd_info ... Who initializes this "node" field?
>


-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Mon Jun  6 04:11:20 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 11:11:20 +0300
Subject: [PATCH 050/104] physmap_of: separate parse_obsolete_partitions
	to separate parser
In-Reply-To: <4DEC8B45.1020900@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>
	<1307347330.3135.29.camel@localhost>  <4DEC8B45.1020900@gmail.com>
Message-ID: <1307347880.3135.35.camel@localhost>

On Mon, 2011-06-06 at 12:09 +0400, Dmitry Eremin-Solenikov wrote:
> I'd really like to strip it out of physmap_of to simplify things.
> 
> It parses the mtd partitions, it's a separate functional part. I can 
> argue if it should be a module or just in-kernel part, if it should
> be 
> visible to users (or just autoselected by physmap_of), but I'd 
> definitely prefer to have this as a separate source file hooking into
> generic mtd_parse subsystem. 

I understand your desire to keep physmap_of nice and shiny and have all
the crap separate, but that is really too small amount of code to even a
separate file. And after all, that's physmap_of's crap, you can keep it
in separate functions and register as a separate parser, but put it say,
to the end of phusmap_of file with a big fat comment telling that no one
should use it, you can add a deprication date, a warning, etc as well.

P.S. I'm not very aware of OF so if adding a warning is a stupid
suggestion, please just ignore it.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 04:13:38 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 11:13:38 +0300
Subject: [PATCH 050/104] physmap_of: separate parse_obsolete_partitions
	to separate parser
In-Reply-To: <1307347880.3135.35.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>
	<1307347330.3135.29.camel@localhost>  <4DEC8B45.1020900@gmail.com>
	<1307347880.3135.35.camel@localhost>
Message-ID: <1307348018.3135.36.camel@localhost>

On Mon, 2011-06-06 at 11:11 +0300, Artem Bityutskiy wrote:
> I understand your desire to keep physmap_of nice and shiny and have all
> the crap separate, but that is really too small amount of code to even a
> separate file. And after all, that's physmap_of's crap, 

Or rather s/phusmap_of/ofpart/

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 04:19:43 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 11:19:43 +0300
Subject: [PATCH 041/104] mtd: prepare to convert
	of_mtd_parse_partitions to partition parser
In-Reply-To: <4DEC8C85.6090904@gmail.com>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>
	<1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
	<1307347054.3135.28.camel@localhost>  <4DEC8C85.6090904@gmail.com>
Message-ID: <1307348383.3135.41.camel@localhost>

On Mon, 2011-06-06 at 12:15 +0400, Dmitry Eremin-Solenikov wrote:
> Answering both of your questions here:
> My idea is to have an of node connected to mtd device, if there is
> any.

I just think the connection should be different. Probably the best would
be to have an OF-specific object (some struct of_info) containing struct
mtd_info inside, and then OF code can use container_of().

> It can be used by ofpart.c, ofoldpart.c (extract from physmap_of),
> maybe some other parsers/drivers/etc. 

I'm still not convinced we need ofoldpart.c - that is a small piece of
cade which can be put to ofpart.c.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Mon Jun  6 04:24:22 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 06 Jun 2011 12:24:22 +0400
Subject: [PATCH 050/104] physmap_of: separate parse_obsolete_partitions
	to separate parser
In-Reply-To: <1307348018.3135.36.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>	
	<1307026293-8535-16-git-send-email-dbaryshkov@gmail.com>	
	<1307347330.3135.29.camel@localhost> <4DEC8B45.1020900@gmail.com>	
	<1307347880.3135.35.camel@localhost>
	<1307348018.3135.36.camel@localhost>
Message-ID: <4DEC8EB6.4030609@gmail.com>

On 06.06.2011 12:13, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 11:11 +0300, Artem Bityutskiy wrote:
>> I understand your desire to keep physmap_of nice and shiny and have all
>> the crap separate, but that is really too small amount of code to even a
>> separate file. And after all, that's physmap_of's crap,
>
> Or rather s/phusmap_of/ofpart/

I've initially thought about this, but didn't want to put too much crap 
to ofpart. Will follow this way, as you suggest.

-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Mon Jun  6 04:56:03 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 11:56:03 +0300
Subject: [PATCH] mtd: nand: remove unnecessary TODO
In-Reply-To: <1307039906-6462-1-git-send-email-computersforpeace@gmail.com>
References: <1307039906-6462-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307350563.3135.42.camel@localhost>

On Thu, 2011-06-02 at 11:38 -0700, Brian Norris wrote:
> I believe this TODO was unnecessary back when it was introduced:
> 	commit d1e1f4e42b5df063712ca2926e50c07b95c96b96
> 	mtd: nand: add support for reading ONFI parameters...
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

Pushed  to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Mon Jun  6 05:15:52 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:52 +0400
Subject: [PATCH 02/32] mtd: sst25l don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-2-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/sst25l.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index 1e2c430..cd095af 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -423,13 +423,7 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	      flash->mtd.numeraseregions);
 
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[] = {"cmdlinepart", NULL};
-
-		nr_parts = parse_mtd_partitions(&flash->mtd,
-						part_probes,
-						&parts, 0);
-	}
+	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
 
 	if (nr_parts <= 0 && data && data->parts) {
 		parts = data->parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:51 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:51 +0400
Subject: [PATCH 01/32] mtd: mtd_dataflash don't specify default parsing options
Message-ID: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/mtd_dataflash.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 13749d4..4d4a9cd 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -677,12 +677,7 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 			pagesize, otp_tag);
 	dev_set_drvdata(&spi->dev, priv);
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *part_probes[] = { "cmdlinepart", NULL, };
-
-		nr_parts = parse_mtd_partitions(device, part_probes, &parts,
-						0);
-	}
+	nr_parts = parse_mtd_partitions(device, NULL, &parts, 0);
 
 	if (nr_parts <= 0 && pdata && pdata->parts) {
 		parts = pdata->parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:53 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:53 +0400
Subject: [PATCH 03/32] mtd: h720x-flash don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-3-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/h720x-flash.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index 7f03586..f331a2c 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -60,8 +60,6 @@ static struct mtd_partition h720x_partitions[] = {
 
 static int                   nr_mtd_parts;
 static struct mtd_partition *mtd_parts;
-static const char *probes[] = { "cmdlinepart", NULL };
-
 /*
  * Initialize FLASH support
  */
@@ -92,7 +90,7 @@ static int __init h720x_mtd_init(void)
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-		nr_mtd_parts = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
+		nr_mtd_parts = parse_mtd_partitions(mymtd, NULL, &mtd_parts, 0);
 		if (nr_mtd_parts > 0)
 			part_type = "command line";
 		if (nr_mtd_parts <= 0) {
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:54 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:54 +0400
Subject: [PATCH 04/32] mtd: impa7 don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-4-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/impa7.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index 404a50c..2d45a48 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -61,7 +61,6 @@ static struct mtd_partition static_partitions[] =
 static int mtd_parts_nb[NUM_FLASHBANKS];
 static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
 
-static const char *probes[] = { "cmdlinepart", NULL };
 
 static int __init init_impa7(void)
 {
@@ -98,7 +97,7 @@ static int __init init_impa7(void)
 			impa7_mtd[i]->owner = THIS_MODULE;
 			devicesfound++;
 			mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
-							       probes,
+							       NULL,
 							       &mtd_parts[i],
 							       0);
 			if (mtd_parts_nb[i] > 0) {
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:55 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:55 +0400
Subject: [PATCH 05/32] mtd: intel_vr_nor don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-5-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/intel_vr_nor.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index d2f47be..fd612c7 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -72,11 +72,10 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
 static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
 	struct mtd_partition *parts;
-	static const char *part_probes[] = { "cmdlinepart", NULL };
 
 	/* register the flash bank */
 	/* partition the flash bank */
-	p->nr_parts = parse_mtd_partitions(p->info, part_probes, &parts, 0);
+	p->nr_parts = parse_mtd_partitions(p->info, NULL, &parts, 0);
 	return mtd_device_register(p->info, parts, p->nr_parts);
 }
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:56 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:56 +0400
Subject: [PATCH 06/32] mtd: rbtx4939-flash don't specify default parsing
	options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-6-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/rbtx4939-flash.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 761fb45..a272678 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -50,7 +50,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
 }
 
 static const char *rom_probe_types[] = { "cfi_probe", "jedec_probe", NULL };
-static const char *part_probe_types[] = { "cmdlinepart", NULL };
 
 static int rbtx4939_flash_probe(struct platform_device *dev)
 {
@@ -107,8 +106,7 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
 	info->mtd->owner = THIS_MODULE;
 	if (err)
 		goto err_out;
-
-	err = parse_mtd_partitions(info->mtd, part_probe_types,
+	err = parse_mtd_partitions(info->mtd, NULL,
 				&info->parts, 0);
 	if (err > 0) {
 		mtd_device_register(info->mtd, info->parts, err);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:57 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:57 +0400
Subject: [PATCH 07/32] mtd: atmel_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-7-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/atmel_nand.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index 7c35739..2e6c5b9 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -480,10 +480,6 @@ static void atmel_nand_hwctl(struct mtd_info *mtd, int mode)
 	}
 }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
-
 /*
  * Probe for the NAND device.
  */
@@ -654,11 +650,9 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 		goto err_scan_tail;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "atmel_nand";
-	num_partitions = parse_mtd_partitions(mtd, part_probes,
+	num_partitions = parse_mtd_partitions(mtd, NULL,
 					      &partitions, 0);
-#endif
 	if (num_partitions <= 0 && host->board->parts) {
 		partitions = host->board->parts;
 		num_partitions = host->board->num_parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:58 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:58 +0400
Subject: [PATCH 08/32] mtd: bcm_umi_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-8-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/bcm_umi_nand.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index 7ac8607..7752d59 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -52,8 +52,6 @@
 static const __devinitconst char gBanner[] = KERN_INFO \
 	"BCM UMI MTD NAND Driver: 1.00\n";
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 #if NAND_ECC_BCH
 static uint8_t scan_ff_pattern[] = { 0xff };
 
@@ -497,7 +495,7 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 
 		board_mtd->name = "bcm_umi-nand";
 		nr_partitions =
-		    parse_mtd_partitions(board_mtd, part_probes,
+		    parse_mtd_partitions(board_mtd, NULL,
 					 &partition_info, 0);
 
 		if (nr_partitions <= 0) {
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:15:59 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:15:59 +0400
Subject: [PATCH 09/32] mtd: cmx270_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-9-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cmx270_nand.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index 6fc043a..f8f5b7c 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -50,8 +50,6 @@ static struct mtd_partition partition_info[] = {
 };
 #define NUM_PARTITIONS (ARRAY_SIZE(partition_info))
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 static u_char cmx270_read_byte(struct mtd_info *mtd)
 {
 	struct nand_chip *this = mtd->priv;
@@ -222,14 +220,13 @@ static int __init cmx270_init(void)
 		goto err_scan;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, part_probes,
+	mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, NULL,
 					    &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
 		mtd_parts_nb = 0;
-#endif
+
 	if (!mtd_parts_nb) {
 		mtd_parts = partition_info;
 		mtd_parts_nb = NUM_PARTITIONS;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:01 +0400
Subject: [PATCH 11/32] mtd: davinci_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-11-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/davinci_nand.c |    9 +--------
 1 files changed, 1 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index a4c82b4..0c582ed 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -753,14 +753,7 @@ syndrome_done:
 	if (ret < 0)
 		goto err_scan;
 
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] __initconst = {
-			"cmdlinepart", NULL
-		};
-
-		mtd_parts_nb = parse_mtd_partitions(&info->mtd, probes,
-						    &mtd_parts, 0);
-	}
+	mtd_parts_nb = parse_mtd_partitions(&info->mtd, NULL, &mtd_parts, 0);
 
 	if (mtd_parts_nb <= 0) {
 		mtd_parts = pdata->parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:02 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:02 +0400
Subject: [PATCH 12/32] mtd: edb7312 don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-12-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/edb7312.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 8400d0f..2f9374b 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -98,8 +98,6 @@ static int ep7312_device_ready(struct mtd_info *mtd)
 	return 1;
 }
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
@@ -158,7 +156,7 @@ static int __init ep7312_init(void)
 		return -ENXIO;
 	}
 	ep7312_mtd->name = "edb7312-nand";
-	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, part_probes, &mtd_parts, 0);
+	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, NULL, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:03 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:03 +0400
Subject: [PATCH 13/32] mtd: fsl_upm don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-13-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 23752fd..7c782eb 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -158,7 +158,6 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 {
 	int ret;
 	struct device_node *flash_np;
-	static const char *part_types[] = { "cmdlinepart", NULL, };
 
 	fun->chip.IO_ADDR_R = fun->io_base;
 	fun->chip.IO_ADDR_W = fun->io_base;
@@ -192,7 +191,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&fun->mtd, part_types, &fun->parts, 0);
+	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, 0);
 
 #ifdef CONFIG_MTD_OF_PARTS
 	if (ret == 0) {
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:04 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:04 +0400
Subject: [PATCH 14/32] mtd: fsmc_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-14-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsmc_nand.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index e9b275a..80abbb2 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -177,9 +177,6 @@ static struct mtd_partition partition_info_128KB_blk[] = {
 	},
 };
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /**
  * struct fsmc_nand_data - structure for FSMC NAND device state
@@ -716,15 +713,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	 * platform data,
 	 * default partition information present in driver.
 	 */
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	/*
-	 * Check if partition info passed via command line
+	 * Check for partition info passed
 	 */
 	host->mtd.name = "nand";
-	host->nr_partitions = parse_mtd_partitions(&host->mtd, part_probes,
+	host->nr_partitions = parse_mtd_partitions(&host->mtd, NULL,
 			&host->partitions, 0);
 	if (host->nr_partitions <= 0) {
-#endif
 		/*
 		 * Check if partition info passed via command line
 		 */
@@ -769,9 +764,7 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 				}
 			}
 		}
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	}
-#endif
 
 	ret = mtd_device_register(&host->mtd, host->partitions,
 				  host->nr_partitions);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:05 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:05 +0400
Subject: [PATCH 15/32] mtd: h1910 don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-15-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/h1910.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 02a03e6..42f9177 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -136,14 +136,10 @@ static int __init h1910_init(void)
 		iounmap((void *)nandaddr);
 		return -ENXIO;
 	}
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	mtd_parts_nb = parse_cmdline_partitions(h1910_nand_mtd, &mtd_parts, "h1910-nand");
+	mtd_parts_nb = parse_mtd_partitions(h1910_nand_mtd, NULL, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-#endif
-	if (mtd_parts_nb == 0) {
+	else {
 		mtd_parts = partition_info;
 		mtd_parts_nb = NUM_PARTITIONS;
 		part_type = "static";
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:06 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:06 +0400
Subject: [PATCH 16/32] mtd: jz4740_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-16-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/jz4740_nand.c |    9 +--------
 1 files changed, 1 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 6e813da..920719c 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -251,10 +251,6 @@ static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
 	return 0;
 }
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = {"cmdline", NULL};
-#endif
-
 static int jz_nand_ioremap_resource(struct platform_device *pdev,
 	const char *name, struct resource **res, void __iomem **base)
 {
@@ -373,10 +369,7 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
 		goto err_gpio_free;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	num_partitions = parse_mtd_partitions(mtd, part_probes,
-						&partition_info, 0);
-#endif
+	num_partitions = parse_mtd_partitions(mtd, NULL, &partition_info, 0);
 	if (num_partitions <= 0 && pdata) {
 		num_partitions = pdata->num_partitions;
 		partition_info = pdata->partitions;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:07 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:07 +0400
Subject: [PATCH 17/32] mtd: lantiq-flash don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-17-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/lantiq-flash.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index a90cabd..6c7a5b9 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -107,8 +107,6 @@ ltq_copy_to(struct map_info *map, unsigned long to,
 	spin_unlock_irqrestore(&ebu_lock, flags);
 }
 
-static const char const *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int __init
 ltq_mtd_probe(struct platform_device *pdev)
 {
@@ -173,7 +171,7 @@ ltq_mtd_probe(struct platform_device *pdev)
 	cfi->addr_unlock2 ^= 1;
 
 	nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
-				part_probe_types, &parts, 0);
+				NULL, &parts, 0);
 	if (nr_parts > 0) {
 		dev_info(&pdev->dev,
 			"using %d partitions from cmdline", nr_parts);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:08 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:08 +0400
Subject: [PATCH 18/32] mtd: latch-addr-flash don't specify default parsing
	options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-18-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/latch-addr-flash.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index 5936c46..7b2199e 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -97,8 +97,6 @@ static void lf_copy_from(struct map_info *map, void *to,
 
 static char *rom_probe_types[] = { "cfi_probe", NULL };
 
-static char *part_probe_types[] = { "cmdlinepart", NULL };
-
 static int latch_addr_flash_remove(struct platform_device *dev)
 {
 	struct latch_addr_flash_info *info;
@@ -206,7 +204,7 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, (const char **)part_probe_types,
+	err = parse_mtd_partitions(info->mtd, NULL,
 				   &info->parts, 0);
 	if (err > 0) {
 		mtd_device_register(info->mtd, info->parts, err);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:09 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:09 +0400
Subject: [PATCH 19/32] mtd: mpc5121_nfc don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-19-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index e0e0846..0b61367 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -131,8 +131,6 @@ struct mpc5121_nfc_prv {
 
 static void mpc5121_nfc_done(struct mtd_info *mtd);
 
-static const char *mpc5121_nfc_pprobes[] = { "cmdlinepart", NULL };
-
 /* Read NFC register */
 static inline u16 nfc_read(struct mtd_info *mtd, uint reg)
 {
@@ -838,7 +836,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, mpc5121_nfc_pprobes, &parts, 0);
+	retval = parse_mtd_partitions(mtd, NULL, &parts, 0);
 #ifdef CONFIG_MTD_OF_PARTS
 	if (retval == 0)
 		retval = of_mtd_parse_partitions(dev, dn, &parts);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:10 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:10 +0400
Subject: [PATCH 20/32] mtd: ndfc don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-20-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index ea2dea8..cb66fd7 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -159,11 +159,6 @@ static int ndfc_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 static int ndfc_chip_init(struct ndfc_controller *ndfc,
 			  struct device_node *node)
 {
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	static const char *part_types[] = { "cmdlinepart", NULL };
-#else
-	static const char *part_types[] = { NULL };
-#endif
 	struct device_node *flash_np;
 	struct nand_chip *chip = &ndfc->chip;
 	int ret;
@@ -204,7 +199,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, part_types, &ndfc->parts, 0);
+	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, 0);
 	if (ret < 0)
 		goto err;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:11 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:11 +0400
Subject: [PATCH 21/32] mtd: omap2 don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-21-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/omap2.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 0db2c0e..8783c08 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -94,8 +94,6 @@
 #define P4e_s(a)	(TF(a & NAND_Ecc_P4e)		<< 0)
 #define P4o_s(a)	(TF(a & NAND_Ecc_P4o)		<< 1)
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /* oob info generated runtime depending on ecc algorithm and layout selected */
 static struct nand_ecclayout omap_oobinfo;
 /* Define some generic bad / good block scan pattern which are used
@@ -1103,7 +1101,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
+	err = parse_mtd_partitions(&info->mtd, NULL, &info->parts, 0);
 	if (err > 0)
 		mtd_device_register(&info->mtd, info->parts, err);
 	else if (pdata->parts)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:12 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:12 +0400
Subject: [PATCH 22/32] mtd: orion_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-22-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/orion_nand.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 7794d06..5c55981 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -21,8 +21,6 @@
 #include <mach/hardware.h>
 #include <plat/orion_nand.h>
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 static void orion_nand_cmd_ctrl(struct mtd_info *mtd, int cmd, unsigned int ctrl)
 {
 	struct nand_chip *nc = mtd->priv;
@@ -132,10 +130,8 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 		goto no_dev;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
 	mtd->name = "orion_nand";
-	num_part = parse_mtd_partitions(mtd, part_probes, &partitions, 0);
-#endif
+	num_part = parse_mtd_partitions(mtd, NULL, &partitions, 0);
 	/* If cmdline partitions have been passed, let them be used */
 	if (num_part <= 0) {
 		num_part = board->nr_parts;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:13 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:13 +0400
Subject: [PATCH 23/32] mtd: ppchameleonevb don't specify default parsing
	options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-23-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ppchameleonevb.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 3bbb796..9376633 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -99,8 +99,6 @@ static struct mtd_partition partition_info_evb[] = {
 
 #define NUM_PARTITIONS 1
 
-extern int parse_cmdline_partitions(struct mtd_info *master, struct mtd_partition **pparts, const char *mtd_id);
-
 /*
  *	hardware specific access to control-lines
  */
@@ -187,9 +185,6 @@ static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 }
 #endif
 
-const char *part_probes[] = { "cmdlinepart", NULL };
-const char *part_probes_evb[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
@@ -281,7 +276,7 @@ static int __init ppchameleonevb_init(void)
 #endif
 
 	ppchameleon_mtd->name = "ppchameleon-nand";
-	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, part_probes, &mtd_parts, 0);
+	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, NULL, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
@@ -382,7 +377,7 @@ static int __init ppchameleonevb_init(void)
 	}
 
 	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
-	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, part_probes_evb, &mtd_parts, 0);
+	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, NULL, &mtd_parts, 0);
 	if (mtd_parts_nb > 0)
 		part_type = "command line";
 	else
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:14 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:14 +0400
Subject: [PATCH 24/32] mtd: pxa3xx_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-24-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   13 +++++--------
 1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 1fb3b3a..80d65c4 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1129,6 +1129,8 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	struct mtd_partition *parts;
+	int nr_parts;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1146,16 +1148,11 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	if (mtd_has_cmdlinepart()) {
-		const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
 
-		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+	nr_parts = parse_mtd_partitions(info->mtd, NULL, &parts, 0);
 
-		if (nr_parts)
-			return mtd_device_register(info->mtd, parts, nr_parts);
-	}
+	if (nr_parts)
+		return mtd_device_register(info->mtd, parts, nr_parts);
 
 	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:15 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:15 +0400
Subject: [PATCH 25/32] mtd: s3c2410 don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-25-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/s3c2410.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index ec28079..17954ba 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -744,7 +744,6 @@ static int s3c24xx_nand_remove(struct platform_device *pdev)
 	return 0;
 }
 
-const char *part_probes[] = { "cmdlinepart", NULL };
 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
 				      struct s3c2410_nand_set *set)
@@ -756,7 +755,7 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 		return mtd_device_register(&mtd->mtd, NULL, 0);
 
 	mtd->mtd.name = set->name;
-	nr_part = parse_mtd_partitions(&mtd->mtd, part_probes, &part_info, 0);
+	nr_part = parse_mtd_partitions(&mtd->mtd, NULL, &part_info, 0);
 
 	if (nr_part <= 0 && set->nr_partitions > 0) {
 		nr_part = set->nr_partitions;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:16 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:16 +0400
Subject: [PATCH 26/32] mtd: sharpsl don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-26-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/sharpsl.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index 19e24ed..b3377f8 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -103,8 +103,6 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
 	return readb(sharpsl->io + ECCCNTR) != 0;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Main initialization routine
  */
@@ -184,7 +182,7 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 
 	/* Register the partitions */
 	sharpsl->mtd.name = "sharpsl-nand";
-	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, part_probes, &sharpsl_partition_info, 0);
+	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, NULL, &sharpsl_partition_info, 0);
 	if (nr_partitions <= 0) {
 		nr_partitions = data->nr_partitions;
 		sharpsl_partition_info = data->partitions;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:17 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:17 +0400
Subject: [PATCH 27/32] mtd: socrates_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-27-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index ca2d055..6ed53e1 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -155,8 +155,6 @@ static int socrates_nand_device_ready(struct mtd_info *mtd)
 	return 1;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 /*
  * Probe for the NAND device.
  */
@@ -225,14 +223,12 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	num_partitions = parse_mtd_partitions(mtd, part_probes,
+	num_partitions = parse_mtd_partitions(mtd, NULL,
 					      &partitions, 0);
 	if (num_partitions < 0) {
 		res = num_partitions;
 		goto release;
 	}
-#endif
 
 	if (num_partitions == 0) {
 		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:18 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:18 +0400
Subject: [PATCH 28/32] mtd: tmio_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-28-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/tmio_nand.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index 11e8371..b6ffad6 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -121,9 +121,6 @@ struct tmio_nand {
 
 #define mtd_to_tmio(m)			container_of(m, struct tmio_nand, mtd)
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-static const char *part_probes[] = { "cmdlinepart", NULL };
-#endif
 
 /*--------------------------------------------------------------------------*/
 
@@ -461,9 +458,7 @@ static int tmio_probe(struct platform_device *dev)
 		goto err_scan;
 	}
 	/* Register the partitions */
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-	nbparts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-#endif
+	nbparts = parse_mtd_partitions(mtd, NULL, &parts, 0);
 	if (nbparts <= 0 && data) {
 		parts = data->partition;
 		nbparts = data->num_partitions;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:19 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:19 +0400
Subject: [PATCH 29/32] mtd: txx9ndfmc don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-29-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/txx9ndfmc.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index bfba4e3..91b05b9 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -287,7 +287,6 @@ static int txx9ndfmc_nand_scan(struct mtd_info *mtd)
 static int __init txx9ndfmc_probe(struct platform_device *dev)
 {
 	struct txx9ndfmc_platform_data *plat = dev->dev.platform_data;
-	static const char *probes[] = { "cmdlinepart", NULL };
 	int hold, spw;
 	int i;
 	struct txx9ndfmc_drvdata *drvdata;
@@ -393,7 +392,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		}
 		mtd->name = txx9_priv->mtdname;
 
-		nr_parts = parse_mtd_partitions(mtd, probes,
+		nr_parts = parse_mtd_partitions(mtd, NULL,
 						&drvdata->parts[i], 0);
 		mtd_device_register(mtd, drvdata->parts[i], nr_parts);
 		drvdata->mtds[i] = mtd;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:20 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:20 +0400
Subject: [PATCH 30/32] mtd: onenand/generic don't specify default parsing
	options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-30-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/generic.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 2d70d35..bca1c49 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -30,8 +30,6 @@
  */
 #define DRIVER_NAME	"onenand-flash"
 
-static const char *part_probes[] = { "cmdlinepart", NULL,  };
-
 struct onenand_info {
 	struct mtd_info		mtd;
 	struct mtd_partition	*parts;
@@ -73,7 +71,7 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev)
 		goto out_iounmap;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
+	err = parse_mtd_partitions(&info->mtd, NULL, &info->parts, 0);
 	if (err > 0)
 		mtd_device_register(&info->mtd, info->parts, err);
 	else if (err <= 0 && pdata && pdata->parts)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:21 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:21 +0400
Subject: [PATCH 31/32] mtd: onenand/omap2 don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-31-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/omap2.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 0d9073d..5ca2053 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -67,8 +67,6 @@ struct omap2_onenand {
 	struct regulator *regulator;
 };
 
-static const char *part_probes[] = { "cmdlinepart", NULL,  };
-
 static void omap2_onenand_dma_cb(int lch, u16 ch_status, void *data)
 {
 	struct omap2_onenand *c = data;
@@ -754,7 +752,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
+	r = parse_mtd_partitions(&c->mtd, NULL, &c->parts, 0);
 	if (r > 0)
 		r = mtd_device_register(&c->mtd, c->parts, r);
 	else if (pdata->parts != NULL)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:22 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:22 +0400
Subject: [PATCH 32/32] mtd: samsung/onenand don't specify default parsing
	options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-32-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/samsung.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 3306b5b..78a08ea 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -157,8 +157,6 @@ struct s3c_onenand {
 
 static struct s3c_onenand *onenand;
 
-static const char *part_probes[] = { "cmdlinepart", NULL, };
-
 static inline int s3c_read_reg(int offset)
 {
 	return readl(onenand->base + offset);
@@ -1017,7 +1015,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-	err = parse_mtd_partitions(mtd, part_probes, &onenand->parts, 0);
+	err = parse_mtd_partitions(mtd, NULL, &onenand->parts, 0);
 	if (err > 0)
 		mtd_device_register(mtd, onenand->parts, err);
 	else if (err <= 0 && pdata && pdata->parts)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:16:00 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 13:16:00 +0400
Subject: [PATCH 10/32] mtd: cs553x_nand don't specify default parsing options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307351782-7456-10-git-send-email-dbaryshkov@gmail.com>

Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
this in every driver, instead pass NULL to force parse_mtd_partitions
to use default.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cs553x_nand.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index b354961..b2bdf72 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -278,8 +278,6 @@ static int is_geode(void)
 	return 0;
 }
 
-static const char *part_probes[] = { "cmdlinepart", NULL };
-
 static int __init cs553x_init(void)
 {
 	int err = -ENXIO;
@@ -318,9 +316,7 @@ static int __init cs553x_init(void)
 		if (cs553x_mtd[i]) {
 
 			/* If any devices registered, return success. Else the last error. */
-			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], part_probes, &mtd_parts, 0);
-			if (mtd_parts_nb > 0)
-				printk(KERN_NOTICE "Using command line partition definition\n");
+			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], NULL, &mtd_parts, 0);
 			mtd_device_register(cs553x_mtd[i], mtd_parts,
 					    mtd_parts_nb);
 			err = 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 05:21:43 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 06 Jun 2011 13:21:43 +0400
Subject: [PATCH 041/104] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307347548.3135.31.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>	
	<1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>
	<1307347548.3135.31.camel@localhost>
Message-ID: <4DEC9C27.7070508@gmail.com>

On 06.06.2011 12:05, Artem Bityutskiy wrote:
> On Thu, 2011-06-02 at 18:51 +0400, Dmitry Eremin-Solenikov wrote:
>> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
>> 1) Register ofpart parser
>> 2) Internally don't use passed device for error printing
>> 3) Add device_node to mtd_info struct
>> 4) Move of_mtd_parse_partitions from __devinit to common text section
>> 5) add ofpart to the default list of partition parsers
>>
>> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
>
> Do not apply this and further changes so far - I had some questions.
>
> Anyway, your series consists of as set of logical steps, which is really
> nice, so let's finish with the first cmdline consolidation step, and
> then move on.

BTW: what about fixing order of parsing to:
cmdlinepart,
RedBoot,
afs,
ofpart/ofoldpart,
platform-default-hook.

This will allow me to drop "parse order" options from all relevant 
functions.

-- 
With best wishes
Dmitry



From roman.tereshonkov at nokia.com  Mon Jun  6 05:42:29 2011
From: roman.tereshonkov at nokia.com (roman.tereshonkov at nokia.com)
Date: Mon, 6 Jun 2011 09:42:29 +0000
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <1307115701.3069.20.camel@localhost>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
Message-ID: <E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>

 

>-----Original Message-----
>From: ext Artem Bityutskiy [mailto:dedekind1 at gmail.com] 
>Sent: 03 June, 2011 18:42
>To: Kyungmin Park; Tereshonkov Roman (Nokia-SD/Helsinki)
>Cc: linux-mtd at lists.infradead.org; dwmw2 at infradead.org; 
>m.szyprowski at samsung.com
>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 
>4KiB pagesize
>
>On Thu, 2011-06-02 at 15:48 +0900, Kyungmin Park wrote:
>> From: Kyungmin Park <kyungmin.park at samsung.com>
>> 
>> There's no case to use the subpage for 4KiB pagesize.
>> 
>> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
>> ---
>> diff --git a/drivers/mtd/onenand/onenand_base.c 
>b/drivers/mtd/onenand/onenand_base.c
>> index ac9e959..337be7c 100644
>> --- a/drivers/mtd/onenand/onenand_base.c
>> +++ b/drivers/mtd/onenand/onenand_base.c
>> @@ -4047,13 +4047,11 @@ int onenand_scan(struct mtd_info 
>*mtd, int maxchips)
>>  	 */
>>  	switch (mtd->oobsize) {
>>  	case 128:
>> -		if (FLEXONENAND(this)) {
>> +		if (FLEXONENAND(this))
>>  			this->ecclayout = &flexonenand_oob_128;
>> -			mtd->subpage_sft = 0;
>> -		} else {
>> +		else
>>  			this->ecclayout = &onenand_oob_128;
>> -			mtd->subpage_sft = 2;
>> -		}
>> +		mtd->subpage_sft = 0;
>>  		break;
>>  	case 64:
>>  		this->ecclayout = &onenand_oob_64;
>
>Roman, are you happy with this change?
>


What do mean by "no case to use the subpage"?

According to the spec KFM4G16Q4M-xEBx the Number of Partial Program Cycles in the page (NOP)
is equal to 4 -> subpage_sft=2.

Regards
Roman Tereshonkov

>-- 
>Best Regards,
>Artem Bityutskiy (????? ????????)
>
>

From dedekind1 at gmail.com  Mon Jun  6 05:58:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 12:58:36 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTimsanbjqD8ZqJ26wcp42iQWt+vFdw@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
	<1306914686.4405.53.camel@localhost>
	<BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
	<BANLkTimsanbjqD8ZqJ26wcp42iQWt+vFdw@mail.gmail.com>
Message-ID: <1307354316.3112.19.camel@localhost>

On Thu, 2011-06-02 at 14:59 -0400, Matthew L. Creech wrote: 
> On Thu, Jun 2, 2011 at 12:30 AM, Matthew L. Creech <mlcreech at gmail.com> wrote:
> >
> > As for this specific error (ubifs_decompress): tomorrow I'll try to
> > gather & post additional log data for this device.  Thanks!
> >
> 
> Here is a console dump with more information enabled:
> 
> http://mcreech.com/work/ubifs-decompress-err.txt
> 
> I turned on mount & recovery debug messages, although it seems to
> mount & recover correctly, so presumably any info from past recovery
> actions is long gone.  The error actually occurs later on, when our
> main application accesses SQLite databases.
> 
> I dumped out the corrupted node data in 3 places:
> 
> 1. In ubifs_decompress(), I dumped the data buffer, prefixed with
> "compressed node" (redundant with #3, really)
> 
> 2. In read_block(), I page-align the starting offset & size, re-fetch
> the pertinent pages from flash, and dump those with corresponding OOB
> info, prefixed with "data" and "oob" respectively
> 
> 3. There's already a dbg_dump_node() call in read_block(), so I
> enabled that as well

So the corruption starts exactly at the NAND page boundary. This makes
me believe that the reason is most probably power cut recovery. But you
say your client ensures there were none...

Yes, you are right that info from past is gone... What I'd like to see
is a dump of the whole LEB. Could you please add 'dbg_dump_leb()' -
basically I want to look if this LEB was passed through GC.

Because my theory is:

1. You have LEB A which contains this data node, but it is not corrupted
   yet. Let's call this data node X.
2. GC moves valid data from LEB A to LEB B (lnum 3479).
3. We get a power cut while moving the data. We end up with node X
   corrupted in B.
4. UBIFS recovery has a bug and it decides that the copy of node X in
   LEB B is OK, commits, and LEB A is erased at some point.
5. And we are in your situation...

But this is just a theory.

I actually worked on power cut emulation testing improvements lately,
and the current state is that "integck -p" fails sometimes. I need to
investigate it - might turn out to be a bug which cases the effect you
see.

Basically, I've improved UBIFS power cut testing and corrupt the buffer
with random data, not only with 0xFFs, and now integck -p starts
failing. See this commit:

http://git.infradead.org/ubifs-2.6.git/commit/96c32bb596c5a74362a6a825f66fde68b6c3487c

It contains several unrelated changes. Ignore the simple random part,
only the changes in 'cut_data()' are interesting.

But I'll split that change on several changes.

And I'll try to investigate the issue - it might turn out to be
integck's issue, will see.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)




From dedekind1 at gmail.com  Mon Jun  6 06:02:37 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:02:37 +0300
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
Message-ID: <1307354557.3112.21.camel@localhost>

On Mon, 2011-06-06 at 09:42 +0000, roman.tereshonkov at nokia.com wrote:
> What do mean by "no case to use the subpage"?
> 
> According to the spec KFM4G16Q4M-xEBx the Number of Partial Program Cycles in the page (NOP)
> is equal to 4 -> subpage_sft=2.

I thought this means "not supported by HW". But if this is supported,
then I'm very surprised why would we remove it. I'm dropping this patch
from my tree.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Mon Jun  6 06:10:03 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 06 Jun 2011 14:10:03 +0400
Subject: [PATCH 041/104] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307348383.3135.41.camel@localhost>
References: <1307026293-8535-1-git-send-email-dbaryshkov@gmail.com>	
	<1307026293-8535-7-git-send-email-dbaryshkov@gmail.com>	
	<1307347054.3135.28.camel@localhost> <4DEC8C85.6090904@gmail.com>
	<1307348383.3135.41.camel@localhost>
Message-ID: <4DECA77B.8050907@gmail.com>

On 06.06.2011 12:19, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 12:15 +0400, Dmitry Eremin-Solenikov wrote:
>> Answering both of your questions here:
>> My idea is to have an of node connected to mtd device, if there is
>> any.
>
> I just think the connection should be different. Probably the best would
> be to have an OF-specific object (some struct of_info) containing struct
> mtd_info inside, and then OF code can use container_of().

That will be agains current linux coding practices. E.g. check the gpio, 
i2c, etc. code. All add device_node field to existing structs.

>> It can be used by ofpart.c, ofoldpart.c (extract from physmap_of),
>> maybe some other parsers/drivers/etc.
>
> I'm still not convinced we need ofoldpart.c - that is a small piece of
> cade which can be put to ofpart.c.

Agreed.


-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Mon Jun  6 06:06:31 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:06:31 +0300
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <1307354557.3112.21.camel@localhost>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
Message-ID: <1307354791.3112.24.camel@localhost>

On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 09:42 +0000, roman.tereshonkov at nokia.com wrote:
> > What do mean by "no case to use the subpage"?
> > 
> > According to the spec KFM4G16Q4M-xEBx the Number of Partial Program Cycles in the page (NOP)
> > is equal to 4 -> subpage_sft=2.
> 
> I thought this means "not supported by HW". But if this is supported,
> then I'm very surprised why would we remove it. I'm dropping this patch
> from my tree.

OK, I actually did not put it to the l2 tree. And AFAICS this patch
basically reverts commit 99b17c08bca2810f5910b3027f1b9d82edf7a576, but
still leaves the data structures like onenand_oob_128.

So NACK for this patch - poor commit message, weird changes. I'm
surprised to see this from kmpark.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Mon Jun  6 06:07:09 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:07:09 +0300
Subject: [PATCH] mtd: denali: remove calling mtd_device_unregister()
	after nand_release()
In-Reply-To: <1307063535.10001.1.camel@phoenix>
References: <1307063535.10001.1.camel@phoenix>
Message-ID: <1307354829.3112.25.camel@localhost>

On Fri, 2011-06-03 at 09:12 +0800, Axel Lin wrote:
> The implementation of nand_release() already call mtd_device_unregister(),
> no need to call it again.
> 
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Mon Jun  6 06:13:47 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:13:47 +0300
Subject: [PATCH 1/2] mtd: nuc900_nand: add missing nand_release in
	nuc900_nand_remove
In-Reply-To: <1307065913.10001.2.camel@phoenix>
References: <1307065913.10001.2.camel@phoenix>
Message-ID: <1307355227.3112.26.camel@localhost>

On Fri, 2011-06-03 at 09:51 +0800, Axel Lin wrote:
> Signed-off-by: Axel Lin <axel.lin at gmail.com>
> ---
>  drivers/mtd/nand/nuc900_nand.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)

Pushed both to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Mon Jun  6 06:19:30 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:19:30 +0300
Subject: [PATCH 2/2] mtd: nomadik_nand: add missing nand_release in
	nomadik_nand_remove
In-Reply-To: <1307066006.10001.4.camel@phoenix>
References: <1307065913.10001.2.camel@phoenix>
	<1307066006.10001.4.camel@phoenix>
Message-ID: <1307355570.3112.27.camel@localhost>

On Fri, 2011-06-03 at 09:53 +0800, Axel Lin wrote:
> Signed-off-by: Axel Lin <axel.lin at gmail.com>
> ---
>  drivers/mtd/nand/nomadik_nand.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Mon Jun  6 06:19:42 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:19:42 +0300
Subject: [PATCH 1/2] mtd: pxa3xx_nand: fix a memory leak
In-Reply-To: <1307078050.4167.1.camel@phoenix>
References: <1307078050.4167.1.camel@phoenix>
Message-ID: <1307355582.3112.28.camel@localhost>

On Fri, 2011-06-03 at 13:14 +0800, Axel Lin wrote:
> In pxa3xx_nand_remove, we should call nand_release instead of
> mtd_device_unregister to properly free bad block table memory
> and bad block descriptor memory.
> 
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Mon Jun  6 06:20:01 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:20:01 +0300
Subject: [PATCH] mtd: mtdblock: Use DEFINE_MUTEX() for mtdblks_lock
In-Reply-To: <1307081422.6450.2.camel@phoenix>
References: <1307081422.6450.2.camel@phoenix>
Message-ID: <1307355601.3112.29.camel@localhost>

On Fri, 2011-06-03 at 14:10 +0800, Axel Lin wrote:
> mtdblks_lock can be initialized automatically with
> DEFINE_MUTEX() rather than explicitly calling mutex_init().
> 
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Mon Jun  6 06:20:11 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:20:11 +0300
Subject: [PATCH] mtd: pxa3xx_nand: remove unused variable 'mtd'
In-Reply-To: <1307086473.7474.1.camel@phoenix>
References: <1307086473.7474.1.camel@phoenix>
Message-ID: <1307355611.3112.30.camel@localhost>

On Fri, 2011-06-03 at 15:34 +0800, Axel Lin wrote:
> Remove unused variable 'mtd' to eliminate below warning.
> 
>   CC      drivers/mtd/nand/pxa3xx_nand.o
> drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_suspend':
> drivers/mtd/nand/pxa3xx_nand.c:1167: warning: unused variable 'mtd'
> drivers/mtd/nand/pxa3xx_nand.c: In function 'pxa3xx_nand_resume':
> drivers/mtd/nand/pxa3xx_nand.c:1180: warning: unused variable 'mtd'
> 
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 06:40:26 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:40:26 +0300
Subject: [PATCH] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <BANLkTinuqQmp43K4H0iPDbb-H-rDA_nL9w@mail.gmail.com>
References: <BANLkTimos3-Ds4Y8FDfDZegqAhH7nSS4PA@mail.gmail.com>
	<1305865207-7869-1-git-send-email-leiwen@marvell.com>
	<BANLkTinuqQmp43K4H0iPDbb-H-rDA_nL9w@mail.gmail.com>
Message-ID: <1307356826.3112.32.camel@localhost>

On Fri, 2011-06-03 at 23:11 +0800, Lei Wen wrote:
> Tested-by: Daniel Mack <zonque at gmail.com>
> 
> Also cc to MTD maillist and stable kernel.

Please, re-send the patch to the MTD mailing list and add the prober
-stable CC tag.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 06:40:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 13:40:49 +0300
Subject: [PATCH] MTD: pxa3xx_nand: Fix blank page ECC mismatch
In-Reply-To: <BANLkTik1_cuo5UH995agoNYa2FdQ8Qasiw@mail.gmail.com>
References: <1307106198-11965-1-git-send-email-zonque@gmail.com>
	<BANLkTimpLKkfSJbeuM6kc7bUE+JybTmVrA@mail.gmail.com>
	<BANLkTik1_cuo5UH995agoNYa2FdQ8Qasiw@mail.gmail.com>
Message-ID: <1307356849.3112.33.camel@localhost>

On Fri, 2011-06-03 at 23:31 +0800, Lei Wen wrote:
> Also cc to MTD mailist
> Cc: linux-mtd at lists.infradead.org

Please, re-send non-quoted patch.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 07:01:50 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 14:01:50 +0300
Subject: [PATCH 1/2] nanddump: add --skipbad option for bad blocks
In-Reply-To: <1307125501-32558-1-git-send-email-computersforpeace@gmail.com>
References: <1307125501-32558-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307358110.3112.36.camel@localhost>

On Fri, 2011-06-03 at 11:25 -0700, Brian Norris wrote:
> This patch adds a new option "--skipbad" to nanddump. It is subtly
> different than "--omitbad". The following description was included in
> the help message to attempt to clarify the differences.
> 
>  Notes on --omitbad and --skipbad:
>    With either option, we stop dumping data when we encounter a bad block
>    and resume dumping at the next good block. However, with --omitbad, we
>    count the bad block as part of the total dump length, whereas with
>    --skipbad, the bad block is 'skipped,' that is, not counted toward the
>    total dump length.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

Pushed both to mtd-utils.git, thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 07:04:54 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 14:04:54 +0300
Subject: [PATCH 01/32] mtd: mtd_dataflash don't specify default parsing
	options
In-Reply-To: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307358294.3112.38.camel@localhost>

On Mon, 2011-06-06 at 13:15 +0400, Dmitry Eremin-Solenikov wrote:
> Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
> this in every driver, instead pass NULL to force parse_mtd_partitions
> to use default.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Do you have a git URL with these patches?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Mon Jun  6 07:19:44 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 6 Jun 2011 15:19:44 +0400
Subject: [PATCH 01/32] mtd: mtd_dataflash don't specify default parsing
	options
In-Reply-To: <1307358294.3112.38.camel@localhost>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
	<1307358294.3112.38.camel@localhost>
Message-ID: <BANLkTinUq_V_QkGDm6ejtGQ7Gnq1K8EHmA@mail.gmail.com>

Hello,

On Mon, Jun 6, 2011 at 3:04 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Mon, 2011-06-06 at 13:15 +0400, Dmitry Eremin-Solenikov wrote:
>> Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
>> this in every driver, instead pass NULL to force parse_mtd_partitions
>> to use default.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>
> Do you have a git URL with these patches?

Yes. Unfortunately git.kernel.org syncs too slow now, so the kernel
wasn't available
at the time of sending an e-mail.

Here it goes:

The following changes since commit 099fbd4fd91fde9748d9ad927e59b6c36a2651cf:

  mtd: drop mtd_has_cmdlinepart() (2011-06-06 10:31:22 +0300)

are available in the git repository at:
  git://git.kernel.org/pub/scm/linux/kernel/git/lumag/mtd-cleanup.git
mtd-cleanup-cmdline

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Mon Jun  6 07:42:39 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 14:42:39 +0300
Subject: [PATCH 06/32] mtd: rbtx4939-flash don't specify default
	parsing options
In-Reply-To: <1307351782-7456-6-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
	<1307351782-7456-6-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307360559.3112.39.camel@localhost>

On Mon, 2011-06-06 at 13:15 +0400, Dmitry Eremin-Solenikov wrote:
>  static int rbtx4939_flash_probe(struct platform_device *dev)
>  {
> @@ -107,8 +106,7 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
>  	info->mtd->owner = THIS_MODULE;
>  	if (err)
>  		goto err_out;
> -
> -	err = parse_mtd_partitions(info->mtd, part_probe_types,
> +	err = parse_mtd_partitions(info->mtd, NULL,
>  				&info->parts, 0);

This can become one-line. I can do this.

>  	if (err > 0) {
>  		mtd_device_register(info->mtd, info->parts, err);


-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 07:47:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 14:47:40 +0300
Subject: [PATCH 07/32] mtd: atmel_nand don't specify default parsing
	options
In-Reply-To: <1307351782-7456-7-git-send-email-dbaryshkov@gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
	<1307351782-7456-7-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307360860.3112.40.camel@localhost>

On Mon, 2011-06-06 at 13:15 +0400, Dmitry Eremin-Solenikov wrote:
> -	num_partitions = parse_mtd_partitions(mtd, part_probes,
> +	num_partitions = parse_mtd_partitions(mtd, NULL,
>  					      &partitions, 0);

Ditto, this should have become one-liner, I'll do this.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:02:53 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:02:53 +0300
Subject: [PATCH 01/32] mtd: mtd_dataflash don't specify default parsing
	options
In-Reply-To: <BANLkTinUq_V_QkGDm6ejtGQ7Gnq1K8EHmA@mail.gmail.com>
References: <1307351782-7456-1-git-send-email-dbaryshkov@gmail.com>
	<1307358294.3112.38.camel@localhost>
	<BANLkTinUq_V_QkGDm6ejtGQ7Gnq1K8EHmA@mail.gmail.com>
Message-ID: <1307361773.3112.43.camel@localhost>

On Mon, 2011-06-06 at 15:19 +0400, Dmitry Eremin-Solenikov wrote:
> Hello,
> 
> On Mon, Jun 6, 2011 at 3:04 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Mon, 2011-06-06 at 13:15 +0400, Dmitry Eremin-Solenikov wrote:
> >> Since 'cmdline, NULL' is now a default for parse_mtd_partitions, don't specify
> >> this in every driver, instead pass NULL to force parse_mtd_partitions
> >> to use default.
> >>
> >> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >
> > Do you have a git URL with these patches?
> 
> Yes. Unfortunately git.kernel.org syncs too slow now, so the kernel
> wasn't available
> at the time of sending an e-mail.
> 
> Here it goes:
> 
> The following changes since commit 099fbd4fd91fde9748d9ad927e59b6c36a2651cf:
> 
>   mtd: drop mtd_has_cmdlinepart() (2011-06-06 10:31:22 +0300)
> 
> are available in the git repository at:
>   git://git.kernel.org/pub/scm/linux/kernel/git/lumag/mtd-cleanup.git
> mtd-cleanup-cmdline

OK, thanks, all the patches are in the l2 tree now. But one note:
please, after a mechanical change go through the patches and check that
them. E.g., in this case many patches could also merge the list of
parameters. I mean, if you are substituting something long by something
short, you check if you can merge lines. Otherwise, you check if some
lines became too long...

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From david.wagner at free-electrons.com  Mon Jun  6 08:12:15 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Mon, 06 Jun 2011 14:12:15 +0200
Subject: impact of 2X_PROGRAM on read operations
Message-ID: <4DECC41F.5060808@free-electrons.com>

Hello,

I have been trying to understand what does the 2X_PROGRAM configuration
(and the IS_2PLANE macro).
At first, I was confused to see that, in onenand_command(), when the
command is "READ", the IS_2PLANE macro modifies the block and page
address. I was expecting this option only to affect program operations.
Then, after seeing jffs2 not finding its magic bitmask after switching
the 2X_PROGRAM configuration off, I understood that, since the 2X
Program only programs one OOB for two blocks, the read operations had to
be impacted anyway.

So, is the following right/almost/wrong ?
Let the size of physical pages/block sizes be 2KiB/128KiB
A filesystem on top of a 2X_PROGRAM-enabled mtd layer sees 4KiB-big
pages. When this FS wants to read one 4KiB page, the mtd layer will read
2KiB pages, two times. The layout of the blocks and pages is:


       Even plane           Odd plane
+--------------------+--------------------+
|        page 0      |  page 1   (oob 0&1)| <---  one logical page
|        page 2      |  page 3   (oob 2&3)|    as seen by a filesystem
|        page 4      |  page 5   (oob 4&5)|
|          .         |          .         |
|          .         |          .         |
|          .         |          .         |
| (Block 0)          | (Block 1)          |
+--------------------+--------------------+
|       page 128     | page 129 (oob)     |
|          .         |          .         |
|          .         |          .         |
|          .         |          .         |
| (Block 2)          | (Block 3)          |
+--------------------+--------------------+

(the page number is not the one that would be computed within
onenand_command but indicates the order in which pages get read or
programmed.)



Is there a way to safely read without 2X_PROGRAM enabled once it has
been flashed with a 2X_PROGRAM-enabled flasher (e.g. patched u-boot).


Regards,
David Wagner.
-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From dedekind1 at gmail.com  Mon Jun  6 08:10:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:10:46 +0300
Subject: nandwrite with raw oob data
In-Reply-To: <alpine.LSU.2.00.1106051821580.26001@redbean.intranet.gw-instruments.de>
References: <alpine.LSU.2.00.1106051821580.26001@redbean.intranet.gw-instruments.de>
Message-ID: <1307362246.3112.45.camel@localhost>

On Sun, 2011-06-05 at 18:40 +0200, Peter Wippich wrote:
> Dear all,
> 
> I run into the same problem as outlined here before:
> http://lists.infradead.org/pipermail/linux-mtd/2011-March/034516.html
> 
> Going a little bit deeper it looks to me that writing any nand flash data 
> with raw (precomputed ECC) OOB data is not possible at all with a recent 
> Kernel and nandwrite version.
> 
> What happens here is that nandwrite will set MTD_MODE_RAW when noecc is 
> specified. Doing so will force the kernel driver to write OOB data only on 
> a normal write. Obviously this will fail when someone is trying to write 
> normal data to flash in MODE_RAW.
> 
> Question: is this realy the intended behaviour ???
> 
> It may be easy to fix this on kernel level, but may be there is some good 
> reason I don't know to do it as it is. And I don't want to break things.
> 
> Any comments welcome.

I think that is just broken stuff which is rarely used. Please, send a
set of fixes, but please, try to:

1. Fix both nandwrite and the kernel.
2. Test that non-raw functionality is not broken.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:19:19 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:19:19 +0300
Subject: [PATCH 1/5] flash_lock/flash_unlock/flash_info: clean up style
In-Reply-To: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307362759.3112.46.camel@localhost>

On Mon, 2011-06-06 at 00:09 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  flash_info.c   |   31 +++++++++++++------------------
>  flash_lock.c   |   37 +++++++++++++++----------------------
>  flash_unlock.c |   16 +++++-----------
>  3 files changed, 33 insertions(+), 51 deletions(-)

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:19:43 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:19:43 +0300
Subject: [PATCH 1/5] flash_lock/flash_unlock/flash_info: clean up style
In-Reply-To: <1307362759.3112.46.camel@localhost>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
	<1307362759.3112.46.camel@localhost>
Message-ID: <1307362783.3112.47.camel@localhost>

On Mon, 2011-06-06 at 15:19 +0300, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 00:09 -0400, Mike Frysinger wrote:
> > Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> > ---
> >  flash_info.c   |   31 +++++++++++++------------------
> >  flash_lock.c   |   37 +++++++++++++++----------------------
> >  flash_unlock.c |   16 +++++-----------
> >  3 files changed, 33 insertions(+), 51 deletions(-)
> 
> Pushed to l2-mtd-2.6.git, thanks.

Err, sorry, to mtd-utils of course.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:20:38 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:20:38 +0300
Subject: [PATCH 2/5] flash_{lock,unlock}: merge functionality
In-Reply-To: <1307333354-26583-2-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
	<1307333354-26583-2-git-send-email-vapier@gentoo.org>
Message-ID: <1307362838.3112.48.camel@localhost>

On Mon, 2011-06-06 at 00:09 -0400, Mike Frysinger wrote:
> The flash_lock util has a bit of extra argument checking, and it supports
> a magic value of "-1" to mean "all blocks".
> 
> The flash_unlock util supports automatic 2nd/3rd arguments to unlock the
> whole flash.  It also supports multiple bases (not just hex) for selecting
> the range of the device to unlock.
> 
> So tweak both utilities so that they have equivalent functionality again
> by adding the missing features to each.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed to mtd-utils.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:24:48 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:24:48 +0300
Subject: [PATCH 3/5] flash_{lock,unlock}: merge into one util
In-Reply-To: <1307333354-26583-3-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
	<1307333354-26583-3-git-send-email-vapier@gentoo.org>
Message-ID: <1307363088.3112.49.camel@localhost>

On Mon, 2011-06-06 at 00:09 -0400, Mike Frysinger wrote:
> Now that the utils have equivalent functionality, merge the two source
> code bases so they can't diverge in the future.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:26:38 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:26:38 +0300
Subject: [PATCH 4/5] flash_{lock,unlock}: convert to common code
In-Reply-To: <1307333354-26583-4-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
	<1307333354-26583-4-git-send-email-vapier@gentoo.org>
Message-ID: <1307363198.3112.51.camel@localhost>

On Mon, 2011-06-06 at 00:09 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  flash_unlock.c |   75 ++++++++++++++++++++++++++++++-------------------------
>  1 files changed, 41 insertions(+), 34 deletions(-)

Pushed, but tweaked a bit ...

> +	/*
> +	 * Get the device info to compare to command line sizes
> +	 */

Made the comment style to be the same as we use in the kernel - one line
for short comments. Changed the existing comment as well. It could be a
separate patch, but let's use a simplified way in this case :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 08:28:26 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 15:28:26 +0300
Subject: [PATCH 5/5] flash_{lock, unlock}: fix off-by-one error for
	"entire device" length
In-Reply-To: <1307333354-26583-5-git-send-email-vapier@gentoo.org>
References: <1307333354-26583-1-git-send-email-vapier@gentoo.org>
	<1307333354-26583-5-git-send-email-vapier@gentoo.org>
Message-ID: <1307363306.3112.52.camel@localhost>

On Mon, 2011-06-06 at 00:09 -0400, Mike Frysinger wrote:
> From: Steven Miao <realmz6 at gmail.com>
> 
> This basically reverts commit 43feb39f35a9ee0ed3 which changed the full
> length calculation to be one less than one sector.  I don't understand
> the logic in the commit message where it states that the length should
> be one sector smaller as this results in misbehavior at runtime.

Pushed as well, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From pewi at gw-instruments.de  Mon Jun  6 09:11:12 2011
From: pewi at gw-instruments.de (Peter Wippich)
Date: Mon, 6 Jun 2011 15:11:12 +0200 (CEST)
Subject: nandwrite with raw oob data
In-Reply-To: <1307362246.3112.45.camel@localhost>
References: <alpine.LSU.2.00.1106051821580.26001@redbean.intranet.gw-instruments.de>
	<1307362246.3112.45.camel@localhost>
Message-ID: <alpine.LSU.2.00.1106061449030.26001@redbean.intranet.gw-instruments.de>


Hi Artem,

On Mon, 6 Jun 2011, Artem Bityutskiy wrote:

> On Sun, 2011-06-05 at 18:40 +0200, Peter Wippich wrote:
>> Dear all,
>>
>> I run into the same problem as outlined here before:
>> http://lists.infradead.org/pipermail/linux-mtd/2011-March/034516.html
>>
>> Going a little bit deeper it looks to me that writing any nand flash data
>> with raw (precomputed ECC) OOB data is not possible at all with a recent
>> Kernel and nandwrite version.
>>
>> What happens here is that nandwrite will set MTD_MODE_RAW when noecc is
>> specified. Doing so will force the kernel driver to write OOB data only on
>> a normal write. Obviously this will fail when someone is trying to write
>> normal data to flash in MODE_RAW.
>>
>> Question: is this realy the intended behaviour ???
>>
>> It may be easy to fix this on kernel level, but may be there is some good
>> reason I don't know to do it as it is. And I don't want to break things.
>>
>> Any comments welcome.
>
> I think that is just broken stuff which is rarely used. Please, send a
> set of fixes, but please, try to:
>
> 1. Fix both nandwrite and the kernel.
> 2. Test that non-raw functionality is not broken.
>

Digged a little bit deeper. The problem is much simpler:

Indeed write_oob can be used to write the data block. This is just what 
happens when writing in MODE_RAW. However, the initialization 
of the mtd_oob_ops structure used is to lazy and causes the write to fail 
later on. I will send a trivial patch later on.

Cheers,

Peter




From dedekind1 at gmail.com  Mon Jun  6 09:11:55 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 16:11:55 +0300
Subject: [PATCHv2 1/6] nand/denali: convert to dev_() printk helpers
In-Reply-To: <1307097169-11744-2-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
	<1307097169-11744-2-git-send-email-jamie@jamieiles.com>
Message-ID: <1307365915.3112.68.camel@localhost>

On Fri, 2011-06-03 at 11:32 +0100, Jamie Iles wrote:
>  	if ((data_invalid - acc_clks * CLK_X) < 2)
> -		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
> -			__FILE__, __LINE__);
> +		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
> +			 __LINE__);

Do you really need __FILE__ and __LINE__ here? And may be you could also
change the warning message? Just printing "warning!" is a bit silly.

>  
>  	addr_2_data = CEIL_DIV(Tadl[mode], CLK_X);
>  	re_2_we = CEIL_DIV(Trhw[mode], CLK_X);
> @@ -394,9 +393,8 @@ static void get_hynix_nand_para(struct denali_nand_info *denali,
>  		break;
>  	default:
>  		dev_warn(denali->dev,
> -			"Spectra: Unknown Hynix NAND (Device ID: 0x%x)."
> -			"Will use default parameter values instead.\n",
> -			device_id);
> +			 "unknown Hynix NAND (Device ID: 0x%x). Will use default parameter values instead.\n",
> +			 device_id);

Would also be nice to remove the final dot while on it, as
Documentation/CodingStyle suggests in "Chapter 13: Printing kernel
messages".

> @@ -415,8 +413,8 @@ static void find_valid_banks(struct denali_nand_info *denali)
>  		index_addr_read_data(denali,
>  				(uint32_t)(MODE_11 | (i << 24) | 2), &id[i]);
>  
> -		dev_dbg(denali->dev,
> -			"Return 1st ID for bank[%d]: %x\n", i, id[i]);
> +		dev_dbg(denali->dev, "Return 1st ID for bank[%d]: %x\n", i,
> +			id[i]);
>  
>  		if (i == 0) {
>  			if (!(id[i] & 0x0ff))
> @@ -436,13 +434,12 @@ static void find_valid_banks(struct denali_nand_info *denali)
>  		 */
>  		if (denali->total_used_banks != 1) {
>  			dev_err(denali->dev,
> -					"Sorry, Intel CE4100 only supports "
> -					"a single NAND device.\n");
> +				"Sorry, Intel CE4100 only supports a single NAND device.\n");
>  			BUG();

Just a suggestion for a separate patch - doing BUG() is really bad
practice - it is better to return and error up. But this is not related
to this patch...

>  	dev_info(denali->dev,
> -			"Dump timing register values:"
> -			"acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
> -			"we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
> -			"rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
> -			ioread32(denali->flash_reg + ACC_CLKS),
> -			ioread32(denali->flash_reg + RE_2_WE),
> -			ioread32(denali->flash_reg + RE_2_RE),
> -			ioread32(denali->flash_reg + WE_2_RE),
> -			ioread32(denali->flash_reg + ADDR_2_DATA),
> -			ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
> -			ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
> -			ioread32(denali->flash_reg + CS_SETUP_CNT));
> +		 "Dump timing register values: acc_clks: %d, re_2_we: %d, re_2_re: %d\n"
> +		 "we_2_re: %d, addr_2_data: %d, rdwr_en_lo_cnt: %d\n"
> +		 "rdwr_en_hi_cnt: %d, cs_setup_cnt: %d\n",
> +		 ioread32(denali->flash_reg + ACC_CLKS),
> +		 ioread32(denali->flash_reg + RE_2_WE),
> +		 ioread32(denali->flash_reg + RE_2_RE),
> +		 ioread32(denali->flash_reg + WE_2_RE),
> +		 ioread32(denali->flash_reg + ADDR_2_DATA),
> +		 ioread32(denali->flash_reg + RDWR_EN_LO_CNT),
> +		 ioread32(denali->flash_reg + RDWR_EN_HI_CNT),
> +		 ioread32(denali->flash_reg + CS_SETUP_CNT));

I really doubt (but not 100% sure) that multiple \n are handled
correctly. In the kernel all messages have to be prefixed with the
"print level", and the lines after \n will probably not have it. This is
why we have this "KERN_CONT" thing. I suggest you to re-write this print
and use multiple 'dev_info()' calls.

And BTW, why 'dev_info()'? I think it will not be compiled out when
debugging is disabled, and the above info does look like debugging
stuff, so it begs for 'dev_dbg()'.

>  static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
>  {
> @@ -699,8 +691,9 @@ static uint32_t wait_for_irq(struct denali_nand_info *denali, uint32_t irq_mask)
>  
>  	if (comp_res == 0) {
>  		/* timeout */
> -		printk(KERN_ERR "timeout occurred, status = 0x%x, mask = 0x%x\n",
> -				intr_status, irq_mask);
> +		dev_err(&denali->mtd.dev,
> +			"timeout occurred, status = 0x%x, mask = 0x%x\n",
> +			intr_status, irq_mask);

Could this fit 2 lines instead?

>  
>  		intr_status = 0;
>  	}
> @@ -785,9 +778,8 @@ static int denali_send_pipeline_cmd(struct denali_nand_info *denali,
>  
>  			if (irq_status == 0) {
>  				dev_err(denali->dev,
> -						"cmd, page, addr on timeout "
> -						"(0x%x, 0x%x, 0x%x)\n",
> -						cmd, denali->page, addr);
> +					"cmd, page, addr on timeout (0x%x, 0x%x, 0x%x)\n",
> +					cmd, denali->page, addr);
>  				status = FAIL;
>  			} else {
>  				cmd = MODE_01 | addr;
> @@ -889,7 +881,7 @@ static void read_oob_data(struct mtd_info *mtd, uint8_t *buf, int page)
>  
>  		if (irq_status == 0)
>  			dev_err(denali->dev, "page on OOB timeout %d\n",
> -					denali->page);
> +				denali->page);

Did not check, but looks like this can be onelinere, it does not fit 80
lines?

>  
>  		/* We set the device back to MAIN_ACCESS here as I observed
>  		 * instability with the controller if you do a block erase
> @@ -1065,9 +1057,8 @@ static void write_page(struct mtd_info *mtd, struct nand_chip *chip,
>  	irq_status = wait_for_irq(denali, irq_mask);
>  
>  	if (irq_status == 0) {
> -		dev_err(denali->dev,
> -				"timeout on write_page (type = %d)\n",
> -				raw_xfer);
> +		dev_err(denali->dev, "timeout on write_page (type = %d)\n",
> +			raw_xfer);

And this looks like it could be a one-liner ... Could you please check
other messages WRT fitting less lines.

>  		denali->status =
>  			(irq_status & INTR_STATUS__PROGRAM_FAIL) ?
>  			NAND_STATUS_FAIL : PASS;
> @@ -1132,9 +1123,9 @@ static int denali_read_page(struct mtd_info *mtd, struct nand_chip *chip,
>  	bool check_erased_page = false;
>  
>  	if (page != denali->page) {
> -		dev_err(denali->dev, "IN %s: page %d is not"
> -				" equal to denali->page %d, investigate!!",
> -				__func__, page, denali->page);
> +		dev_err(denali->dev,
> +			"IN %s: page %d is not equal to denali->page %d, investigate!!",
> +			__func__, page, denali->page);

I think this "IN" is not needed, and "investigate!!" sounds
"interesting" ... Not really sure we need __func__ here - it just blows
the code size, no?

>  		BUG();

Similar side-note about this BUG() statement...

>  	}
>  
> @@ -1182,9 +1173,8 @@ static int denali_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
>  	uint32_t irq_mask = INTR_STATUS__DMA_CMD_COMP;
>  
>  	if (page != denali->page) {
> -		dev_err(denali->dev, "IN %s: page %d is not"
> -				" equal to denali->page %d, investigate!!",
> -				__func__, page, denali->page);
> +		dev_err(denali->dev, "IN %s: page %d is not equal to denali->page %d, investigate!!",
> +			__func__, page, denali->page);

Ditto.

>  	denali->flash_mem = ioremap_nocache(mem_base, mem_len);
>  	if (!denali->flash_mem) {
> -		printk(KERN_ERR "Spectra: ioremap_nocache failed!");
> +		dev_err(denali->dev, "Spectra: ioremap_nocache failed!");

For consistency with other messages, I'd removed the exclamation mark
here, in on some other messages.

> -		dev_err(&dev->dev, "Spectra: Failed to register MTD: %d\n",
> +		dev_err(denali->dev, "Spectra: Failed to register MTD: %d\n",
>  				ret);
One line?

>  		goto failed_req_irq;
>  	}
> @@ -1701,7 +1688,7 @@ static struct pci_driver denali_pci_driver = {
>  
>  static int __devinit denali_init(void)
>  {
> -	printk(KERN_INFO "Spectra MTD driver\n");
> +	pr_info(KERN_INFO "Spectra MTD driver\n");

Remove KERN_INFO please.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 09:16:24 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 16:16:24 +0300
Subject: [PATCHv2 2/6] nand/denali: annotate pci init/exit functions
	with correct section
In-Reply-To: <1307097169-11744-3-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
	<1307097169-11744-3-git-send-email-jamie@jamieiles.com>
Message-ID: <1307366184.3112.70.camel@localhost>

On Fri, 2011-06-03 at 11:32 +0100, Jamie Iles wrote:
> The module init exit functions should be annotated with __init and
> __exit.
> 
> Cc: David Woodhouse <dwmw2 at infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
> Cc: Artem Bityutskiy <dedekind1 at gmail.com>
> Signed-off-by: Jamie Iles <jamie at jamieiles.com>

Would you please use "mtd: denali:" prefix?

I cannot apply this patch because it depends on the previous patch. You
could re-structure the code and make simpler patches like this go first,
then they could be taken quicker.

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From jamie at jamieiles.com  Mon Jun  6 09:22:16 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Mon, 6 Jun 2011 14:22:16 +0100
Subject: [PATCHv2 1/6] nand/denali: convert to dev_() printk helpers
In-Reply-To: <1307365915.3112.68.camel@localhost>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
	<1307097169-11744-2-git-send-email-jamie@jamieiles.com>
	<1307365915.3112.68.camel@localhost>
Message-ID: <20110606132216.GJ11191@pulham.picochip.com>

On Mon, Jun 06, 2011 at 04:11:55PM +0300, Artem Bityutskiy wrote:
> On Fri, 2011-06-03 at 11:32 +0100, Jamie Iles wrote:
> >  	if ((data_invalid - acc_clks * CLK_X) < 2)
> > -		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
> > -			__FILE__, __LINE__);
> > +		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
> > +			 __LINE__);
> 
> Do you really need __FILE__ and __LINE__ here? And may be you could also
> change the warning message? Just printing "warning!" is a bit silly.

OK, fair point (and the rest of your comments).  I'll respin this and 
try to rationalise the messages at the same time.

Jamie


From dedekind1 at gmail.com  Mon Jun  6 09:18:58 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 16:18:58 +0300
Subject: [PATCHv2 6/6] mtd/denali: support for cmdline partitioning
In-Reply-To: <1307097169-11744-7-git-send-email-jamie@jamieiles.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
	<1307097169-11744-7-git-send-email-jamie@jamieiles.com>
Message-ID: <1307366338.3112.72.camel@localhost>

On Fri, 2011-06-03 at 11:32 +0100, Jamie Iles wrote:
> Add support for command line partitioning.  This is favoured over
> platform data based partitions.
> 
> Cc: David Woodhouse <dwmw2 at infradead.org>
> Cc: Chuanxiao Dong <chuanxiao.dong at intel.com>
> Cc: Artem Bityutskiy <dedekind1 at gmail.com>
> Signed-off-by: Jamie Iles <jamie at jamieiles.com>
> ---
>  drivers/mtd/nand/denali.c |    9 ++++++++-
>  1 files changed, 8 insertions(+), 1 deletions(-)

I've just taken a set of patches from "Dmitry Eremin-Solenikov
<dbaryshkov at gmail.com>" which simplify the way to use just cmdlinepart
parser, please, take a look - it is in the l2 tree.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From jamie at jamieiles.com  Mon Jun  6 09:51:18 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Mon, 6 Jun 2011 14:51:18 +0100
Subject: [PATCHv2 1/6] nand/denali: convert to dev_() printk helpers
In-Reply-To: <1307365915.3112.68.camel@localhost>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
	<1307097169-11744-2-git-send-email-jamie@jamieiles.com>
	<1307365915.3112.68.camel@localhost>
Message-ID: <20110606135118.GK11191@pulham.picochip.com>

On Mon, Jun 06, 2011 at 04:11:55PM +0300, Artem Bityutskiy wrote:
> On Fri, 2011-06-03 at 11:32 +0100, Jamie Iles wrote:
> >  	if ((data_invalid - acc_clks * CLK_X) < 2)
> > -		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
> > -			__FILE__, __LINE__);
> > +		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
> > +			 __LINE__);
> 
> Do you really need __FILE__ and __LINE__ here? And may be you could also
> change the warning message? Just printing "warning!" is a bit silly.

I'm afraid I can't work out from the Denali documentation that we have 
what this is actually warning about.  Chuanxiao, is there a better error 
message we can print here that can help users to debug it?  Is this just 
an unsupported ONFI timing mode or something more sinister?

Jamie


From pewi at gw-instruments.de  Mon Jun  6 09:50:58 2011
From: pewi at gw-instruments.de (Peter Wippich)
Date: Mon, 6 Jun 2011 15:50:58 +0200 (CEST)
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
Message-ID: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>


On writes in MODE_RAW the mtd_oob_ops struct is not sufficiently 
initialized which may cause nandwrite to fail. With this patch
it is possible to write raw nand/oob data without additional ECC
(either for testing or when some sectors need different oob layout
e.g. bootloader) like
nandwrite  -n -r -o  /dev/mtd0 <myfile>

Signed-off-by: Peter Wippich <pewi at gw-instruments.de>

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3f92731..797a34a 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -321,6 +321,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
                         ops.datbuf = kbuf;
                         ops.oobbuf = NULL;
                         ops.len = len;
+                       ops.ooboffs = 0;

                         ret = mtd->write_oob(mtd, *ppos, &ops);
                         retlen = ops.retlen;



From dbaryshkov at gmail.com  Mon Jun  6 10:04:14 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 18:04:14 +0400
Subject: [PATCH 1/3] mtd: add a flags for partitions which should just leave
	smth. after them
In-Reply-To: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307369056-29319-2-git-send-email-dbaryshkov@gmail.com>

Add support for MTDPART_OFS_RETAIN: such partitions start at the current
offset, take as much space as possible, but rain part->size bytes after
the end of the partitions for other parts. Primarily this is intended
for ts72xx arm platforms cleanup.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdpart.c          |   13 +++++++++++++
 include/linux/mtd/partitions.h |    5 ++++-
 2 files changed, 17 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 3477e16..63c19f9 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -479,6 +479,19 @@ static struct mtd_part *allocate_partition(struct mtd_info *master,
 			       (unsigned long long)cur_offset, (unsigned long long)slave->offset);
 		}
 	}
+	if (slave->offset == MTDPART_OFS_RETAIN) {
+		slave->offset = cur_offset;
+		if (master->size - slave->offset >= slave->mtd.size) {
+			slave->mtd.size =
+				master->size - slave->offset - slave->mtd.size;
+		} else {
+			printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
+				part->name,
+				master->size - slave->offset, slave->mtd.size);
+			/* register to preserve ordering */
+			goto out_register;
+		}
+	}
 	if (slave->mtd.size == MTDPART_SIZ_FULL)
 		slave->mtd.size = master->size - slave->offset;
 
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 08c9c7b..1431cf2 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -24,7 +24,9 @@
  * 	will extend to the end of the master MTD device.
  * offset: absolute starting position within the master MTD device; if
  * 	defined as MTDPART_OFS_APPEND, the partition will start where the
- * 	previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block.
+ *	previous one ended; if MTDPART_OFS_NXTBLK, at the next erase block;
+ *	if MTDPART_OFS_RETAIN, consume as much as possible, leaving size
+ *	after the end of partition.
  * mask_flags: contains flags that have to be masked (removed) from the
  * 	master MTD flag set for the corresponding MTD partition.
  * 	For example, to force a read-only partition, simply adding
@@ -42,6 +44,7 @@ struct mtd_partition {
 	struct nand_ecclayout *ecclayout;	/* out of band layout for this partition (NAND only) */
 };
 
+#define MTDPART_OFS_RETAIN	(-3)
 #define MTDPART_OFS_NXTBLK	(-2)
 #define MTDPART_OFS_APPEND	(-1)
 #define MTDPART_SIZ_FULL	(0)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 10:04:13 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 18:04:13 +0400
Subject: [PATCH 0/3] mtd: cleanup plat-nand/ts72xx partitions interface
Message-ID: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>


The following changes since commit d15fed205975d5b552c3f7deee5dc795b002932a:

  mtd: samsung/onenand don't specify default parsing options (2011-06-06 15:06:01 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-retain

Dmitry Eremin-Solenikov (3):
      mtd: add a flags for partitions which should just leave smth. after them
      ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
      mtd: plat-nand: drop unused fields from platform_nand_data

 arch/arm/mach-ep93xx/ts72xx.c  |   23 +++++------------------
 drivers/mtd/mtdpart.c          |   13 +++++++++++++
 drivers/mtd/nand/plat_nand.c   |    2 --
 include/linux/mtd/nand.h       |    2 --
 include/linux/mtd/partitions.h |    5 ++++-
 5 files changed, 22 insertions(+), 23 deletions(-)


From dbaryshkov at gmail.com  Mon Jun  6 10:04:15 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 18:04:15 +0400
Subject: [PATCH 2/3] ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
In-Reply-To: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307369056-29319-3-git-send-email-dbaryshkov@gmail.com>

Instead of specifying a callback for dynamic partitioning, use
MTDPART_OFS_RETAIN for reserving a place near the end of flash for
RedBoot.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Cc: Hartley Sweeten <hsweeten at visionengravers.com>
Cc: Ryan Mallon <ryan at bluewatersys.com>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm/mach-ep93xx/ts72xx.c |   23 +++++------------------
 1 files changed, 5 insertions(+), 18 deletions(-)

diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index c2d2cf4..dea42e2 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -116,8 +116,9 @@ static struct mtd_partition ts72xx_nand_parts[] = {
 		.mask_flags	= MTD_WRITEABLE,	/* force read-only */
 	}, {
 		.name		= "Linux",
-		.offset		= MTDPART_OFS_APPEND,
-		.size		= 0,			/* filled in later */
+		.offset		= MTDPART_OFS_RETAIN,
+		.size		= TS72XX_REDBOOT_PART_SIZE,
+				/* leave so much for last partition */
 	}, {
 		.name		= "RedBoot",
 		.offset		= MTDPART_OFS_APPEND,
@@ -126,28 +127,14 @@ static struct mtd_partition ts72xx_nand_parts[] = {
 	},
 };
 
-static void ts72xx_nand_set_parts(uint64_t size,
-				  struct platform_nand_chip *chip)
-{
-	/* Factory TS-72xx boards only come with 32MiB or 128MiB NAND options */
-	if (size == SZ_32M || size == SZ_128M) {
-		/* Set the "Linux" partition size */
-		ts72xx_nand_parts[1].size = size - TS72XX_REDBOOT_PART_SIZE;
-
-		chip->partitions = ts72xx_nand_parts;
-		chip->nr_partitions = ARRAY_SIZE(ts72xx_nand_parts);
-	} else {
-		pr_warning("Unknown nand disk size:%lluMiB\n", size >> 20);
-	}
-}
-
 static struct platform_nand_data ts72xx_nand_data = {
 	.chip = {
 		.nr_chips	= 1,
 		.chip_offset	= 0,
 		.chip_delay	= 15,
 		.part_probe_types = ts72xx_nand_part_probes,
-		.set_parts	= ts72xx_nand_set_parts,
+		.partitions	= ts72xx_nand_parts,
+		.nr_partitions	= ARRAY_SIZE(ts72xx_nand_parts),
 	},
 	.ctrl = {
 		.cmd_ctrl	= ts72xx_nand_hwcontrol,
-- 
1.7.4.4



From dbaryshkov at gmail.com  Mon Jun  6 10:04:16 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon,  6 Jun 2011 18:04:16 +0400
Subject: [PATCH 3/3] mtd: plat-nand: drop unused fields from platform_nand_data
In-Reply-To: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307369056-29319-4-git-send-email-dbaryshkov@gmail.com>

Drop now unused set_parts from struct platform_nand_data. Also, while we are
at it, drop long unused priv field from platform_nand_data.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/plat_nand.c |    2 --
 include/linux/mtd/nand.h     |    2 --
 2 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 633c04b..1339fa8 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -108,8 +108,6 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
 			return 0;
 		}
 	}
-	if (pdata->chip.set_parts)
-		pdata->chip.set_parts(data->mtd.size, &pdata->chip);
 	if (pdata->chip.partitions) {
 		data->parts = pdata->chip.partitions;
 		err = mtd_device_register(&data->mtd, data->parts,
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index 585d49b..da6e252 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -617,8 +617,6 @@ struct platform_nand_chip {
 	int chip_delay;
 	unsigned int options;
 	const char **part_probe_types;
-	void (*set_parts)(uint64_t size, struct platform_nand_chip *chip);
-	void *priv;
 };
 
 /* Keep gcc happy */
-- 
1.7.4.4



From dedekind1 at gmail.com  Mon Jun  6 10:26:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 17:26:52 +0300
Subject: [PATCH 2/2] mtd: nand: multi-line comment style fixups
In-Reply-To: <1306360741-12770-2-git-send-email-computersforpeace@gmail.com>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>
	<1306360741-12770-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307370412.3112.74.camel@localhost>

On Wed, 2011-05-25 at 14:59 -0700, Brian Norris wrote:
> From: Brian Norris <norris at broadcom.com>
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

I kind of rejected the first patch in this series, but forgot about this
one. I've now pushed it to the l2 tree with additional comments
clean-ups from me - just did them while looking at your patch and to the
code, and accidentally used git commit --amend, so they were merged with
yours. But this should not be a big deal - we ended up with one big
comments cleanup patch.

Thanks - it is in the l2-mtd-2.6.git now.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 10:32:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 17:32:41 +0300
Subject: impact of 2X_PROGRAM on read operations
In-Reply-To: <4DECC41F.5060808@free-electrons.com>
References: <4DECC41F.5060808@free-electrons.com>
Message-ID: <1307370761.3112.76.camel@localhost>

On Mon, 2011-06-06 at 14:12 +0200, David Wagner wrote:
> Is there a way to safely read without 2X_PROGRAM enabled once it has
> been flashed with a 2X_PROGRAM-enabled flasher (e.g. patched u-boot).

Not sure about u-boot, but AFAIK 2x is a completely separate mode which
gives you I/O speed-up but makes things incompatible with "normal" mode.
E.g., you can mount JFFS2 only in one of the modes.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From computersforpeace at gmail.com  Mon Jun  6 11:21:30 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 6 Jun 2011 08:21:30 -0700
Subject: [PATCH 2/2] mtd: nand: multi-line comment style fixups
In-Reply-To: <1307370412.3112.74.camel@localhost>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>
	<1306360741-12770-2-git-send-email-computersforpeace@gmail.com>
	<1307370412.3112.74.camel@localhost>
Message-ID: <BANLkTinQQmXkn6egXZuw+ASA-mitAUaftA@mail.gmail.com>

On Mon, Jun 6, 2011 at 7:26 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> I kind of rejected the first patch in this series, but forgot about this
> one. I've now pushed it to the l2 tree with additional comments
> clean-ups from me - just did them while looking at your patch and to the
> code, and accidentally used git commit --amend, so they were merged with
> yours. But this should not be a big deal - we ended up with one big
> comments cleanup patch.
>
> Thanks - it is in the l2-mtd-2.6.git now.

No problem. Thanks.


From dedekind1 at gmail.com  Mon Jun  6 11:28:02 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 18:28:02 +0300
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
Message-ID: <1307374082.3112.78.camel@localhost>

On Mon, 2011-06-06 at 15:50 +0200, Peter Wippich wrote:
> On writes in MODE_RAW the mtd_oob_ops struct is not sufficiently 
> initialized which may cause nandwrite to fail. With this patch
> it is possible to write raw nand/oob data without additional ECC
> (either for testing or when some sectors need different oob layout
> e.g. bootloader) like
> nandwrite  -n -r -o  /dev/mtd0 <myfile>
> 
> Signed-off-by: Peter Wippich <pewi at gw-instruments.de>

Looks good, thanks. We also need to add this patch to the stable tree.

Ricard, does it solve the issue you reported here

http://lists.infradead.org/pipermail/linux-mtd/2011-March/034516.html

?

> 
> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> index 3f92731..797a34a 100644
> --- a/drivers/mtd/mtdchar.c
> +++ b/drivers/mtd/mtdchar.c
> @@ -321,6 +321,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
>                          ops.datbuf = kbuf;
>                          ops.oobbuf = NULL;
>                          ops.len = len;
> +                       ops.ooboffs = 0;
> 
>                          ret = mtd->write_oob(mtd, *ppos, &ops);
>                          retlen = ops.retlen;
> 

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 11:33:59 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 18:33:59 +0300
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
Message-ID: <1307374439.3112.81.camel@localhost>

On Mon, 2011-06-06 at 15:50 +0200, Peter Wippich wrote:
> On writes in MODE_RAW the mtd_oob_ops struct is not sufficiently 
> initialized which may cause nandwrite to fail. With this patch
> it is possible to write raw nand/oob data without additional ECC
> (either for testing or when some sectors need different oob layout
> e.g. bootloader) like
> nandwrite  -n -r -o  /dev/mtd0 <myfile>
> 
> Signed-off-by: Peter Wippich <pewi at gw-instruments.de>

Pushed your patch to the l2-mtd-2.6.git tree, thanks. It did not apply,
but I amended it. I guess it is against some old kernel tree. Also, I've
added "Cc: stable at kernel.org" to make sure it reaches the -stable tree.

http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/87d5d1460c4e13636406a613f5740ef5e5cdbbfa

A "Tested-by" would be great!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Mon Jun  6 11:35:00 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 18:35:00 +0300
Subject: [PATCHv2 1/6] nand/denali: convert to dev_() printk helpers
In-Reply-To: <20110606135118.GK11191@pulham.picochip.com>
References: <1307097169-11744-1-git-send-email-jamie@jamieiles.com>
	<1307097169-11744-2-git-send-email-jamie@jamieiles.com>
	<1307365915.3112.68.camel@localhost>
	<20110606135118.GK11191@pulham.picochip.com>
Message-ID: <1307374500.3112.82.camel@localhost>

On Mon, 2011-06-06 at 14:51 +0100, Jamie Iles wrote:
> On Mon, Jun 06, 2011 at 04:11:55PM +0300, Artem Bityutskiy wrote:
> > On Fri, 2011-06-03 at 11:32 +0100, Jamie Iles wrote:
> > >  	if ((data_invalid - acc_clks * CLK_X) < 2)
> > > -		dev_warn(denali->dev, "%s, Line %d: Warning!\n",
> > > -			__FILE__, __LINE__);
> > > +		dev_warn(denali->dev, "%s, Line %d: Warning!\n", __FILE__,
> > > +			 __LINE__);
> > 
> > Do you really need __FILE__ and __LINE__ here? And may be you could also
> > change the warning message? Just printing "warning!" is a bit silly.
> 
> I'm afraid I can't work out from the Denali documentation that we have 
> what this is actually warning about.  Chuanxiao, is there a better error 
> message we can print here that can help users to debug it?  Is this just 
> an unsupported ONFI timing mode or something more sinister?

Well, we could kill it or change with "WARN_ON()" may be? Better to het
a comment from Chuanxiao of course ...

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From pewi at gw-instruments.de  Mon Jun  6 11:39:45 2011
From: pewi at gw-instruments.de (Peter Wippich)
Date: Mon, 6 Jun 2011 17:39:45 +0200 (CEST)
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <1307374439.3112.81.camel@localhost>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
	<1307374439.3112.81.camel@localhost>
Message-ID: <alpine.LSU.2.00.1106061737130.3821@redbean.intranet.gw-instruments.de>


Hi Artem,

On Mon, 6 Jun 2011, Artem Bityutskiy wrote:

> On Mon, 2011-06-06 at 15:50 +0200, Peter Wippich wrote:
>> On writes in MODE_RAW the mtd_oob_ops struct is not sufficiently
>> initialized which may cause nandwrite to fail. With this patch
>> it is possible to write raw nand/oob data without additional ECC
>> (either for testing or when some sectors need different oob layout
>> e.g. bootloader) like
>> nandwrite  -n -r -o  /dev/mtd0 <myfile>
>>
>> Signed-off-by: Peter Wippich <pewi at gw-instruments.de>
>
> Pushed your patch to the l2-mtd-2.6.git tree, thanks. It did not apply,
> but I amended it. I guess it is against some old kernel tree. Also, I've
> added "Cc: stable at kernel.org" to make sure it reaches the -stable tree.
>
> http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/87d5d1460c4e13636406a613f5740ef5e5cdbbfa
>
> A "Tested-by" would be great!
>
>

thanks. Thought it was again linux-next. May be a messed up something.
Next time I'll add a tested by .......

Cheers,

Peter




From dedekind1 at gmail.com  Mon Jun  6 11:44:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 18:44:40 +0300
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <alpine.LSU.2.00.1106061737130.3821@redbean.intranet.gw-instruments.de>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
	<1307374439.3112.81.camel@localhost>
	<alpine.LSU.2.00.1106061737130.3821@redbean.intranet.gw-instruments.de>
Message-ID: <1307375080.3112.84.camel@localhost>

On Mon, 2011-06-06 at 17:39 +0200, Peter Wippich wrote:
> Next time I'll add a tested by .......

I meant a tested-by from Ricard, as an independent person :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From pewi at gw-instruments.de  Mon Jun  6 11:49:11 2011
From: pewi at gw-instruments.de (Peter Wippich)
Date: Mon, 6 Jun 2011 17:49:11 +0200 (CEST)
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <1307375080.3112.84.camel@localhost>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
	<1307374439.3112.81.camel@localhost>
	<alpine.LSU.2.00.1106061737130.3821@redbean.intranet.gw-instruments.de>
	<1307375080.3112.84.camel@localhost>
Message-ID: <alpine.LSU.2.00.1106061748440.3821@redbean.intranet.gw-instruments.de>



On Mon, 6 Jun 2011, Artem Bityutskiy wrote:

> On Mon, 2011-06-06 at 17:39 +0200, Peter Wippich wrote:
>> Next time I'll add a tested by .......
>
> I meant a tested-by from Ricard, as an independent person :-)

Yep, makes sense :-).



From Woodrow.Douglass at QinetiQ-NA.com  Mon Jun  6 11:53:19 2011
From: Woodrow.Douglass at QinetiQ-NA.com (Douglass, Woody)
Date: Mon, 6 Jun 2011 11:53:19 -0400
Subject: ubi image only mounts once
In-Reply-To: <BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
	<BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>
Message-ID: <29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>

Matt, 

Thanks for the quick reply. I have tried both ubiformat (passing -f with
my image) and nandwrite, both seem to behave the same way. The
filesystem mounts once, but when I reboot, it doesn't ever mount again.

I cannot upgrade my kernel as my development schedule is too aggressive;
I don't have time. I'm using 2.6.32 for now; if I fail at getting UBI to
work, I can fall back on jffs2, which works, but I prefer UBIFS.

Note that I did successfully load a ubi image with this kernel In the
past with a filesystem image generated from OpenEmbedded. Could my
mkfs.ubifs/ubinize be the issue?

Thanks,
Woody


Woodrow Douglass
Software Design Engineer
QinetiQ North America
Technology Solutions Group
137 Delta Drive
Pittsburgh, PA 15238
(412) 449 1492
woodrow.douglass at qinetiq-na.com

**********************************************************************
THIS MESSAGE IS INTENDED ONLY FOR THE USE OF THE INDIVIDUAL OR ENTITY TO
WHICH IT IS ADDRESSED AND MAY CONTAIN INFORMATION THAT IS PRIVILEGED,
CONFIDENTIAL, AND EXEMPT FROM DISCLOSURE UNDER APPLICABLE LAW. If the
reader of this message is not the intended recipient, or the employee or
agent responsible for delivering the message to the intended recipient,
you are hereby notified that any dissemination, distribution,
forwarding, or copying of this communication is strictly prohibited.
Whilst this message has been swept by anti-virus software, you are
solely responsible for ensuring that any mail or attachments you receive
are virus free. We disclaim liability for any damage you suffer as a
consequence of receiving any virus; further communication will signify
your consent to this. If you have received this communication in error,
please notify info at automatika.com by e-mail or telephone, and delete the
original message. Thank you.
**********************************************************************

> -----Original Message-----
> From: Matthew L. Creech [mailto:mlcreech at gmail.com]
> Sent: Thursday, June 02, 2011 12:04 AM 0
> To: Douglass, Woody
> Cc: linux-mtd at lists.infradead.org
> Subject: Re: ubi image only mounts once
> 
> On Wed, Jun 1, 2011 at 1:52 PM, Douglass, Woody
> <Woodrow.Douglass at qinetiq-na.com> wrote:
> >
> > I am trying to build a linux image to run on a custom omap3530
board.
> I
> > have reached a point where my build system builds a UBI image that
> can
> > be mounted exactly once; subsequent mounts fail. Here is the related
> > dmesg output:
> >
> <snip>
> 
> Hi,
> 
> How are you flashing the image on to NAND - using "ubiformat", or a
> direct flashing utility like "nandwrite"?  I ask because it sounds
> like the problem described here:
> 
> http://linux-mtd.infradead.org/faq/ubifs.html#L_why_ubiformat
> 
> Using "ubiformat" or generating the UBIFS image with the
> free-space-fixup (-F) flag will fix the problem, if that's what it is.
> If you use the mkfs.ubifs fixup flag, you'll need a very recent kernel
> (3.0-rc1), and possibly also Ben Gardiner's patches from a couple days
> ago:
> 
> http://lists.infradead.org/pipermail/linux-mtd/2011-May/035737.html
> 
> --
> Matthew L. Creech


From mlcreech at gmail.com  Mon Jun  6 12:04:42 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Mon, 6 Jun 2011 12:04:42 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307354316.3112.19.camel@localhost>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
	<1306914686.4405.53.camel@localhost>
	<BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
	<BANLkTimsanbjqD8ZqJ26wcp42iQWt+vFdw@mail.gmail.com>
	<1307354316.3112.19.camel@localhost>
Message-ID: <BANLkTimNweAZ0wKT+LApBsWAV0W8Akmijg@mail.gmail.com>

On Mon, Jun 6, 2011 at 5:58 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> So the corruption starts exactly at the NAND page boundary. This makes
> me believe that the reason is most probably power cut recovery. But you
> say your client ensures there were none...
>
> Yes, you are right that info from past is gone... What I'd like to see
> is a dump of the whole LEB. Could you please add 'dbg_dump_leb()' -
> basically I want to look if this LEB was passed through GC.
>

[Repost, gmail mangled my node dump]

The dbg_dump_leb() call fails due to a bad CRC; I've posted its output
plus the corresponding raw LEB dump (obtained via mtd->read_oob())
here:

http://mcreech.com/work/ubifs-decompress-err-rawleb.txt

-- 
Matthew L. Creech


From jamie at jamieiles.com  Mon Jun  6 12:11:34 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Mon,  6 Jun 2011 17:11:34 +0100
Subject: [PATCH] mtd: denali: detect the number of banks before resetting NAND
Message-ID: <1307376694-17905-1-git-send-email-jamie@jamieiles.com>

Commit c89eeda810f0ec4f0eee0206ebb79e476df9f83e (mtd: denali: detect the
number of banks) introduced runtime detection of the number of banks.

However, denali_nand_reset() uses uses denanli_nand_info::max_banks so
we need to detect the maximum number of banks before doing the reset.

Cc: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Cc: David Woodhouse <David.Woodhouse at intel.com>
Signed-off-by: Jamie Iles <jamie at jamieiles.com>
---

Artem, I believe that this one will be needed for 3.0 to avoid breakage
on Moorestown.

 drivers/mtd/nand/denali.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index eebdfb5..3984d48 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1346,6 +1346,7 @@ static void denali_hw_init(struct denali_nand_info *denali)
 	 * */
 	denali->bbtskipbytes = ioread32(denali->flash_reg +
 						SPARE_AREA_SKIP_BYTES);
+	detect_max_banks(denali);
 	denali_nand_reset(denali);
 	iowrite32(0x0F, denali->flash_reg + RB_PIN_ENABLED);
 	iowrite32(CHIP_EN_DONT_CARE__FLAG,
@@ -1356,7 +1357,6 @@ static void denali_hw_init(struct denali_nand_info *denali)
 	/* Should set value for these registers when init */
 	iowrite32(0, denali->flash_reg + TWO_ROW_ADDR_CYCLES);
 	iowrite32(1, denali->flash_reg + ECC_ENABLE);
-	detect_max_banks(denali);
 	denali_nand_timing_set(denali);
 	denali_irq_init(denali);
 }
-- 
1.7.4.1



From dedekind1 at gmail.com  Mon Jun  6 12:08:03 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 19:08:03 +0300
Subject: ubi image only mounts once
In-Reply-To: <29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
	<BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>
	<29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>
Message-ID: <1307376483.3112.94.camel@localhost>

On Mon, 2011-06-06 at 11:53 -0400, Douglass, Woody wrote:
> Matt, 
> 
> Thanks for the quick reply. I have tried both ubiformat (passing -f with
> my image) and nandwrite, both seem to behave the same way. The
> filesystem mounts once, but when I reboot, it doesn't ever mount again.
> 
> I cannot upgrade my kernel as my development schedule is too aggressive;
> I don't have time. I'm using 2.6.32 for now; if I fail at getting UBI to
> work, I can fall back on jffs2, which works, but I prefer UBIFS.
> 
> Note that I did successfully load a ubi image with this kernel In the
> past with a filesystem image generated from OpenEmbedded. Could my
> mkfs.ubifs/ubinize be the issue?

I am sure the problem is your OMAP flash driver - it does not support
sub-pages correctly. There were several discussions. I have not idea
what is your kernel and which hacks it has.

Anyway, first try to check if I was right - run the mtd_subpagetest
test: http://www.linux-mtd.infradead.org/doc/general.html#L_mtd_tests

My prediction - it will fail. Let's check this.

If I'm right - you have 2 choices:

1. Fix the driver.
2. Do not use sub-pages (means you'll waste a bit more flash space).

For the latter - assume your sub-page size = page size = 2048 bytes, and
adjust your mkfs.ubifs/ubinise/ubisformat parameters accordingly. Feel
free to ask for more help - I do not want to write much now before you
have verified my theory.

Also, running all mtd tests is a good idea.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From mlcreech at gmail.com  Mon Jun  6 12:13:21 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Mon, 6 Jun 2011 12:13:21 -0400
Subject: ubi image only mounts once
In-Reply-To: <29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
	<BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>
	<29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>
Message-ID: <BANLkTik=6Q5conreu-GYbQ-Q7YZk65QEqQ@mail.gmail.com>

On Mon, Jun 6, 2011 at 11:53 AM, Douglass, Woody
<Woodrow.Douglass at qinetiq-na.com> wrote:
> Matt,
>
> Thanks for the quick reply. I have tried both ubiformat (passing -f with
> my image) and nandwrite, both seem to behave the same way. The
> filesystem mounts once, but when I reboot, it doesn't ever mount again.
>

OK, if you tried using ubiformat and got the same error, then it's not
the problem I mentioned.

> I cannot upgrade my kernel as my development schedule is too aggressive;
> I don't have time. I'm using 2.6.32 for now; if I fail at getting UBI to
> work, I can fall back on jffs2, which works, but I prefer UBIFS.
>

That's fine, an upgrade should only be necessary to add support for
the fixup flag, which you don't need if you use ubiformat.

So it looks like it's something else (maybe platform-specific?), sorry.

-- 
Matthew L. Creech


From dedekind1 at gmail.com  Mon Jun  6 12:18:11 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 06 Jun 2011 19:18:11 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTimNweAZ0wKT+LApBsWAV0W8Akmijg@mail.gmail.com>
References: <BANLkTik+35hH5ADOGJ+qXtVJjtPd_AKz3g@mail.gmail.com>
	<BANLkTin9hvdNCMeVRSj806R19obN_91v5w@mail.gmail.com>
	<BANLkTinyQ1hoRDzJ8QKNZYP1m8X+AyPUGQ@mail.gmail.com>
	<BANLkTim+sNbXG3yk_DGZk4=+0Za+gb65BA@mail.gmail.com>
	<BANLkTimyNmXpKeCP3oHwx1SV2gdb4r7oNg@mail.gmail.com>
	<1306914686.4405.53.camel@localhost>
	<BANLkTi=ATYnYKrRvZLyFPxfbW0_RVwTROA@mail.gmail.com>
	<BANLkTimsanbjqD8ZqJ26wcp42iQWt+vFdw@mail.gmail.com>
	<1307354316.3112.19.camel@localhost>
	<BANLkTimNweAZ0wKT+LApBsWAV0W8Akmijg@mail.gmail.com>
Message-ID: <1307377091.3112.100.camel@localhost>

On Mon, 2011-06-06 at 12:04 -0400, Matthew L. Creech wrote:
> On Mon, Jun 6, 2011 at 5:58 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >
> > So the corruption starts exactly at the NAND page boundary. This makes
> > me believe that the reason is most probably power cut recovery. But you
> > say your client ensures there were none...
> >
> > Yes, you are right that info from past is gone... What I'd like to see
> > is a dump of the whole LEB. Could you please add 'dbg_dump_leb()' -
> > basically I want to look if this LEB was passed through GC.
> >
> 
> [Repost, gmail mangled my node dump]
> 
> The dbg_dump_leb() call fails due to a bad CRC; I've posted its output
> plus the corresponding raw LEB dump (obtained via mtd->read_oob())
> here:

I have to go home now - could you please improve dbg_dump_leb().
Currently it calls ubifs_scan(), which scans, finds corrupted node,
prints corruption information and returns -EUCLEAN and destroys the
scanned data.

Instead, we could do:

1. Add another parameter to ubifs_scan() which makes it to _not_ free
scanned data on corruption.

2. In dbg_dump_leb() when you get -EUCLEAN - just go ahead and print the
scanned information instead of exiting. Should not be too difficult to
do.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Mon Jun  6 13:15:01 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 13:15:01 -0400
Subject: [PATCH] ignore (FLAT) gdb files
Message-ID: <1307380501-30946-1-git-send-email-vapier@gentoo.org>

Linux FLAT toolchains produce .gdb files alongside the normal program
for debugging purposes (so linking to "foo" will also produce "foo.gdb").
Ignore these too.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 .gitignore |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/.gitignore b/.gitignore
index 2dbf198..849265d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
 # Normal rules
 #
 .*
+*.gdb
 *.o
 *.a
 *.s
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 14:22:14 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 14:22:14 -0400
Subject: [PATCH 1/4] flash_info: convert to common.h
Message-ID: <1307384537-9607-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_info.c |   27 +++++++++++++++++----------
 1 files changed, 17 insertions(+), 10 deletions(-)

diff --git a/flash_info.c b/flash_info.c
index f8b7efa..d4887da 100644
--- a/flash_info.c
+++ b/flash_info.c
@@ -12,24 +12,31 @@
 #include <sys/ioctl.h>
 #include <sys/mount.h>
 
+#include "common.h"
 #include <mtd/mtd-user.h>
 
+static void usage(int status)
+{
+	fprintf(status ? stderr : stdout,
+		"Usage: %s <device>\n",
+		PROGRAM_NAME);
+	exit(status);
+}
+
 int main(int argc, char *argv[])
 {
 	int regcount;
 	int fd;
 
-	if (1 >= argc) {
-		fprintf(stderr, "Usage: %s device\n", PROGRAM_NAME);
-		return 16;
-	}
+	if (argc < 2)
+		usage(1);
+	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
+		usage(0);
 
 	/* Open and size the device */
 	fd = open(argv[1], O_RDONLY);
-	if (fd < 0) {
-		fprintf(stderr, "File open error\n");
-		return 8;
-	}
+	if (fd < 0)
+		sys_errmsg_die("could not open: %s", argv[1]);
 
 	if (ioctl(fd, MEMGETREGIONCOUNT, &regcount) == 0) {
 		int i;
@@ -42,8 +49,8 @@ int main(int argc, char *argv[])
 						"has 0x%x blocks\n", i, reginfo.offset,
 						reginfo.erasesize, reginfo.numblocks);
 			} else {
-				printf("Strange can not read region %d from a %d region device\n",
-						i, regcount);
+				warnmsg("can not read region %d from a %d region device",
+					i, regcount);
 			}
 		}
 	}
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 14:22:16 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 14:22:16 -0400
Subject: =?UTF-8?q?=5BPATCH=203/4=5D=20include/mtd=3A=20sync=20with=20kernel?=
In-Reply-To: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307384537-9607-3-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/mtd/mtd-abi.h  |   34 ++++++++++++++++++++++++++++------
 include/mtd/mtd-user.h |   19 ++++++++++++++++---
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/include/mtd/mtd-abi.h b/include/mtd/mtd-abi.h
index c6954ed..a86364a 100644
--- a/include/mtd/mtd-abi.h
+++ b/include/mtd/mtd-abi.h
@@ -1,5 +1,20 @@
 /*
- * Portions of MTD ABI definition which are shared by kernel and user space
+ * Copyright ? 1999-2010 David Woodhouse <dwmw2 at infradead.org> et al.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
  */
 
 #ifndef __MTD_ABI_H__
@@ -37,6 +52,7 @@ struct mtd_oob_buf64 {
 #define MTD_NANDFLASH		4
 #define MTD_DATAFLASH		6
 #define MTD_UBIVOLUME		7
+#define MTD_MLCNANDFLASH	8
 
 #define MTD_WRITEABLE		0x400	/* Device is writeable */
 #define MTD_BIT_WRITEABLE	0x800	/* Single bits can be flipped */
@@ -104,12 +120,13 @@ struct otp_info {
 #define OTPGETREGIONCOUNT	_IOW('M', 14, int)
 #define OTPGETREGIONINFO	_IOW('M', 15, struct otp_info)
 #define OTPLOCK			_IOR('M', 16, struct otp_info)
-#define ECCGETLAYOUT		_IOR('M', 17, struct nand_ecclayout)
+#define ECCGETLAYOUT		_IOR('M', 17, struct nand_ecclayout_user)
 #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 MEMISLOCKED		_IOR('M', 23, struct erase_info_user)
 
 /*
  * Obsolete legacy interface. Keep it in order not to break userspace
@@ -128,13 +145,18 @@ struct nand_oobfree {
 };
 
 #define MTD_MAX_OOBFREE_ENTRIES	8
+#define MTD_MAX_ECCPOS_ENTRIES	64
 /*
- * ECC layout control structure. Exported to userspace for
- * diagnosis and to allow creation of raw images
+ * OBSOLETE: ECC layout control structure. Exported to user-space via ioctl
+ * ECCGETLAYOUT for backwards compatbility and should not be mistaken as a
+ * complete set of ECC information. The ioctl truncates the larger internal
+ * structure to retain binary compatibility with the static declaration of the
+ * ioctl. Note that the "MTD_MAX_..._ENTRIES" macros represent the max size of
+ * the user struct, not the MAX size of the internal struct nand_ecclayout.
  */
-struct nand_ecclayout {
+struct nand_ecclayout_user {
 	__u32 eccbytes;
-	__u32 eccpos[64];
+	__u32 eccpos[MTD_MAX_ECCPOS_ENTRIES];
 	__u32 oobavail;
 	struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
 };
diff --git a/include/mtd/mtd-user.h b/include/mtd/mtd-user.h
index 713f34d..83327c8 100644
--- a/include/mtd/mtd-user.h
+++ b/include/mtd/mtd-user.h
@@ -1,7 +1,20 @@
 /*
- * $Id: mtd-user.h,v 1.2 2004/05/05 14:44:57 dwmw2 Exp $
+ * Copyright ? 1999-2010 David Woodhouse <dwmw2 at infradead.org>
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  *
- * MTD ABI header for use by user space only.
  */
 
 #ifndef __MTD_USER_H__
@@ -16,6 +29,6 @@ typedef struct mtd_info_user mtd_info_t;
 typedef struct erase_info_user erase_info_t;
 typedef struct region_info_user region_info_t;
 typedef struct nand_oobinfo nand_oobinfo_t;
-typedef struct nand_ecclayout nand_ecclayout_t;
+typedef struct nand_ecclayout_user nand_ecclayout_t;
 
 #endif /* __MTD_USER_H__ */
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 14:22:17 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 14:22:17 -0400
Subject: [PATCH 4/4] flash_info: display MEMGETINFO and MEMISLOCKED
In-Reply-To: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307384537-9607-4-git-send-email-vapier@gentoo.org>

I found the existing flash_info output to be a little lacking, so
add decoders for MEMGETINFO and MEMISLOCKED.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_info.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 87 insertions(+), 11 deletions(-)

diff --git a/flash_info.c b/flash_info.c
index 6c518b2..0e056f3 100644
--- a/flash_info.c
+++ b/flash_info.c
@@ -23,6 +23,52 @@ static void usage(int status)
 	exit(status);
 }
 
+#define T(t) [MTD_##t] = #t
+static const char * const mtdtypes[] = {
+	T(ABSENT),
+	T(RAM),
+	T(ABSENT),
+	T(RAM),
+	T(ROM),
+	T(NORFLASH),
+	T(NANDFLASH),
+	T(DATAFLASH),
+	T(UBIVOLUME),
+};
+static const char *mtdtype(int type)
+{
+	if (type < ARRAY_SIZE(mtdtypes) && mtdtypes[type])
+		return mtdtypes[type];
+	return "UNKNOWN";
+}
+
+/* Show a pretty map of all the sectors on this device */
+static void show_sector_map(int fd, const region_info_t *reginfo)
+{
+	erase_info_t einfo;
+	int i, width;
+
+	printf(" sector map:\n");
+
+	einfo.length = reginfo->erasesize;
+	/* figure out the number of spaces to pad w/out libm */
+	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
+		continue;
+
+	for (i = 0; i < reginfo->numblocks; ++i) {
+		einfo.start = reginfo->offset + i * reginfo->erasesize;
+		printf(" %*i: %08x ", width, i, einfo.start);
+		if (ioctl(fd, MEMISLOCKED, &einfo))
+			printf("RO ");
+		else
+			printf("   ");
+		if (((i + 1) % 4) == 0)
+			printf("\n");
+	}
+	if (i % 4)
+		printf("\n");
+}
+
 int main(int argc, char *argv[])
 {
 	int fd, i, regcount;
@@ -36,6 +82,7 @@ int main(int argc, char *argv[])
 		const char *dev = argv[i];
 		int r;
 		region_info_t reginfo;
+		mtd_info_t mtdinfo;
 
 		/* Open and size the device */
 		fd = open(dev, O_RDONLY);
@@ -44,20 +91,49 @@ int main(int argc, char *argv[])
 			continue;
 		}
 
-		if (ioctl(fd, MEMGETREGIONCOUNT, &regcount))
+		/* Print out general device info first */
+		if (ioctl(fd, MEMGETINFO, &mtdinfo)) {
+			sys_errmsg("could not get mtd info: %s", dev);
 			continue;
+		}
+
+		printf("%s: type: %i (%s)\n flags: %#x ( ",
+			dev, mtdinfo.type, mtdtype(mtdinfo.type), mtdinfo.flags);
+		if (mtdinfo.flags & MTD_POWERUP_LOCK)
+			printf("powerup_lock ");
+		if (mtdinfo.flags & MTD_NO_ERASE)
+			printf("no_erase ");
+		if (mtdinfo.flags & MTD_BIT_WRITEABLE)
+			printf("bit_writeable ");
+		if (mtdinfo.flags & MTD_WRITEABLE)
+			printf("writeable ");
+		printf(")\n sizes: total %#x write %#x erase %#x oob %#x\n",
+			mtdinfo.size, mtdinfo.writesize,
+			mtdinfo.erasesize, mtdinfo.oobsize);
 
-		printf("%s: %d erase regions\n", dev, regcount);
-		for (r = 0; r < regcount; ++r) {
-			reginfo.regionindex = r;
-			if (ioctl(fd, MEMGETREGIONINFO, &reginfo) == 0) {
-				printf("Region %d is at 0x%x with size 0x%x and "
-						"has 0x%x blocks\n", r, reginfo.offset,
-						reginfo.erasesize, reginfo.numblocks);
-			} else {
-				warnmsg("can not read region %d from a %d region device",
-					r, regcount);
+		/* Print out the region info (if the device has any) */
+		if (ioctl(fd, MEMGETREGIONCOUNT, &regcount) == 0) {
+			printf(" erase regions: %i\n", regcount);
+			for (r = 0; r < regcount; ++r) {
+				reginfo.regionindex = r;
+				if (ioctl(fd, MEMGETREGIONINFO, &reginfo) == 0) {
+					printf(" region %i: offset: %#x size: %#x numblocks: %#x\n",
+						r, reginfo.offset, reginfo.erasesize,
+						reginfo.numblocks);
+					show_sector_map(fd, &reginfo);
+				} else
+					warnmsg(" region %i: can not read region info!?", r);
 			}
+		} else
+			regcount = 0;
+
+		/* If the flash has no regions, then show the whole thing */
+		if (regcount == 0) {
+			reginfo.offset = 0;
+			reginfo.erasesize = mtdinfo.erasesize;
+			reginfo.numblocks = mtdinfo.size / mtdinfo.erasesize,
+			reginfo.regionindex = 0;
+			show_sector_map(fd, &reginfo);
 		}
 	}
 
-- 
1.7.5.3



From vapier at gentoo.org  Mon Jun  6 14:22:15 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Mon,  6 Jun 2011 14:22:15 -0400
Subject: [PATCH 2/4] flash_info: allow people to get info on multiple devices
In-Reply-To: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307384537-9607-2-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 flash_info.c |   36 +++++++++++++++++++++---------------
 1 files changed, 21 insertions(+), 15 deletions(-)

diff --git a/flash_info.c b/flash_info.c
index d4887da..6c518b2 100644
--- a/flash_info.c
+++ b/flash_info.c
@@ -18,39 +18,45 @@
 static void usage(int status)
 {
 	fprintf(status ? stderr : stdout,
-		"Usage: %s <device>\n",
+		"Usage: %s <device> [devices]\n",
 		PROGRAM_NAME);
 	exit(status);
 }
 
 int main(int argc, char *argv[])
 {
-	int regcount;
-	int fd;
+	int fd, i, regcount;
 
 	if (argc < 2)
 		usage(1);
 	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
 		usage(0);
 
-	/* Open and size the device */
-	fd = open(argv[1], O_RDONLY);
-	if (fd < 0)
-		sys_errmsg_die("could not open: %s", argv[1]);
-
-	if (ioctl(fd, MEMGETREGIONCOUNT, &regcount) == 0) {
-		int i;
+	for (i = 1; i < argc; ++i) {
+		const char *dev = argv[i];
+		int r;
 		region_info_t reginfo;
-		printf("Device %s has %d erase regions\n", argv[1], regcount);
-		for (i = 0; i < regcount; i++) {
-			reginfo.regionindex = i;
+
+		/* Open and size the device */
+		fd = open(dev, O_RDONLY);
+		if (fd < 0) {
+			sys_errmsg("could not open: %s", dev);
+			continue;
+		}
+
+		if (ioctl(fd, MEMGETREGIONCOUNT, &regcount))
+			continue;
+
+		printf("%s: %d erase regions\n", dev, regcount);
+		for (r = 0; r < regcount; ++r) {
+			reginfo.regionindex = r;
 			if (ioctl(fd, MEMGETREGIONINFO, &reginfo) == 0) {
 				printf("Region %d is at 0x%x with size 0x%x and "
-						"has 0x%x blocks\n", i, reginfo.offset,
+						"has 0x%x blocks\n", r, reginfo.offset,
 						reginfo.erasesize, reginfo.numblocks);
 			} else {
 				warnmsg("can not read region %d from a %d region device",
-					i, regcount);
+					r, regcount);
 			}
 		}
 	}
-- 
1.7.5.3



From Woodrow.Douglass at QinetiQ-NA.com  Mon Jun  6 14:31:51 2011
From: Woodrow.Douglass at QinetiQ-NA.com (Douglass, Woody)
Date: Mon, 6 Jun 2011 14:31:51 -0400
Subject: ubi image only mounts once
In-Reply-To: <1307376483.3112.94.camel@localhost>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
	<BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>
	<29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>
	<1307376483.3112.94.camel@localhost>
Message-ID: <29EDD457F13D0846B91A4845A68C3836E466A0@BOSQNAOMAIL1.qnao.net>

Artem,

Thanks, you're correct, subpages aren't working properly! First I tried applying this patch to solve the issue: https://patchwork.kernel.org/patch/749762/

The test still fails. Next, I changed the -s argument to ubinize from 512 to 2048; I also added -s 2048 to my ubiformat arguments.

Now, on boot, this happens:

[  357.992767] UBI: attaching mtd4 to ubi0
[  357.996673] UBI: physical eraseblock size:   131072 bytes (128 KiB)
[  358.003631] UBI: logical eraseblock size:    129024 bytes
[  358.009185] UBI: smallest flash I/O unit:    2048
[  358.013916] UBI: sub-page size:              512
[  358.018646] UBI: VID header offset:          512 (aligned 512)
[  358.024505] UBI: data offset:                2048
[  358.030639] UBI error: validate_ec_hdr: bad VID header offset 2048, expected 512
[  358.038085] UBI error: validate_ec_hdr: bad EC header
[  358.043426] UBI error: ubi_io_read_ec_hdr: validation failed for PEB 0
[  358.050292] UBI error: ubi_init: cannot attach mtd4
[  358.057708] UBI error: ubi_init: UBI error: cannot initialize UBI, error -22

How can I re set the sub-page size?

-Woody


> -----Original Message-----
> From: Artem Bityutskiy [mailto:dedekind1 at gmail.com]
> Sent: Monday, June 06, 2011 12:08 PM 12
> To: Douglass, Woody
> Cc: Matthew L. Creech; linux-mtd at lists.infradead.org
> Subject: RE: ubi image only mounts once
> 
> On Mon, 2011-06-06 at 11:53 -0400, Douglass, Woody wrote:
> > Matt,
> >
> > Thanks for the quick reply. I have tried both ubiformat (passing -f
> with
> > my image) and nandwrite, both seem to behave the same way. The
> > filesystem mounts once, but when I reboot, it doesn't ever mount
> again.
> >
> > I cannot upgrade my kernel as my development schedule is too
> aggressive;
> > I don't have time. I'm using 2.6.32 for now; if I fail at getting UBI
> to
> > work, I can fall back on jffs2, which works, but I prefer UBIFS.
> >
> > Note that I did successfully load a ubi image with this kernel In the
> > past with a filesystem image generated from OpenEmbedded. Could my
> > mkfs.ubifs/ubinize be the issue?
> 
> I am sure the problem is your OMAP flash driver - it does not support
> sub-pages correctly. There were several discussions. I have not idea
> what is your kernel and which hacks it has.
> 
> Anyway, first try to check if I was right - run the mtd_subpagetest
> test: http://www.linux-mtd.infradead.org/doc/general.html#L_mtd_tests
> 
> My prediction - it will fail. Let's check this.
> 
> If I'm right - you have 2 choices:
> 
> 1. Fix the driver.
> 2. Do not use sub-pages (means you'll waste a bit more flash space).
> 
> For the latter - assume your sub-page size = page size = 2048 bytes,
> and
> adjust your mkfs.ubifs/ubinise/ubisformat parameters accordingly. Feel
> free to ask for more help - I do not want to write much now before you
> have verified my theory.
> 
> Also, running all mtd tests is a good idea.
> 
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)


From computersforpeace at gmail.com  Mon Jun  6 14:47:53 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 6 Jun 2011 11:47:53 -0700
Subject: [PATCH 3/4] include/mtd: sync with kernel
In-Reply-To: <1307384537-9607-3-git-send-email-vapier@gentoo.org>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307384537-9607-3-git-send-email-vapier@gentoo.org>
Message-ID: <BANLkTik+8WBu6T-OT6a+4qZfZQ_kNHUWHw@mail.gmail.com>

On Mon, Jun 6, 2011 at 11:22 AM, Mike Frysinger <vapier at gentoo.org> wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

I probably should have done this a while ago alongside the
ECCGETLAYOUT changes...

Acked-by: Brian Norris <computersforpeace at gmail.com>


From dedekind1 at gmail.com  Mon Jun  6 14:53:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 6 Jun 2011 21:53:46 +0300
Subject: ubi image only mounts once
In-Reply-To: <29EDD457F13D0846B91A4845A68C3836E466A0@BOSQNAOMAIL1.qnao.net>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net>
	<BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com>
	<29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net>
	<1307376483.3112.94.camel@localhost>
	<29EDD457F13D0846B91A4845A68C3836E466A0@BOSQNAOMAIL1.qnao.net>
Message-ID: <BANLkTimrmjMXAMg9yJ_Fmi+1oXgYi7A7FQ@mail.gmail.com>

On Mon, Jun 6, 2011 at 9:31 PM, Douglass, Woody
<Woodrow.Douglass at qinetiq-na.com> wrote:
>
> Artem,
>
> Thanks, you're correct, subpages aren't working properly! First I tried applying this patch to solve the issue: https://patchwork.kernel.org/patch/749762/
>
> The test still fails. Next, I changed the -s argument to ubinize from 512 to 2048; I also added -s 2048 to my ubiformat arguments.
>
> Now, on boot, this happens:
>
> [ ?357.992767] UBI: attaching mtd4 to ubi0
> [ ?357.996673] UBI: physical eraseblock size: ? 131072 bytes (128 KiB)
> [ ?358.003631] UBI: logical eraseblock size: ? ?129024 bytes
> [ ?358.009185] UBI: smallest flash I/O unit: ? ?2048
> [ ?358.013916] UBI: sub-page size: ? ? ? ? ? ? ?512
> [ ?358.018646] UBI: VID header offset: ? ? ? ? ?512 (aligned 512)
> [ ?358.024505] UBI: data offset: ? ? ? ? ? ? ? ?2048
> [ ?358.030639] UBI error: validate_ec_hdr: bad VID header offset 2048, expected 512
> [ ?358.038085] UBI error: validate_ec_hdr: bad EC header
> [ ?358.043426] UBI error: ubi_io_read_ec_hdr: validation failed for PEB 0
> [ ?358.050292] UBI error: ubi_init: cannot attach mtd4
> [ ?358.057708] UBI error: ubi_init: UBI error: cannot initialize UBI, error -22
>
> How can I re set the sub-page size?

Take a look here:
http://linux-mtd.infradead.org/faq/ubi.html#L_vid_offset_mismatch

Also modinfo ubi

If you attach UBI using the kernel boot parameters, use mtd=X,2048,
where X is your number.

--
Best Regards,
Artem Bityutskiy (???????? ?????)


From Woodrow.Douglass at QinetiQ-NA.com  Mon Jun  6 15:14:30 2011
From: Woodrow.Douglass at QinetiQ-NA.com (Douglass, Woody)
Date: Mon, 6 Jun 2011 15:14:30 -0400
Subject: ubi image only mounts once
In-Reply-To: <BANLkTimrmjMXAMg9yJ_Fmi+1oXgYi7A7FQ@mail.gmail.com>
References: <29EDD457F13D0846B91A4845A68C3836DF7DEF@BOSQNAOMAIL1.qnao.net><BANLkTi=ymbNh93riTAjJ5RVFXogYt9HPYg@mail.gmail.com><29EDD457F13D0846B91A4845A68C3836E4657A@BOSQNAOMAIL1.qnao.net><1307376483.3112.94.camel@localhost><29EDD457F13D0846B91A4845A68C3836E466A0@BOSQNAOMAIL1.qnao.net>
	<BANLkTimrmjMXAMg9yJ_Fmi+1oXgYi7A7FQ@mail.gmail.com>
Message-ID: <29EDD457F13D0846B91A4845A68C3836E46705@BOSQNAOMAIL1.qnao.net>

Artem,

That fixed it!

Thanks for all of your help; My next task is to find the right set of patches for this nand driver; but I have a temporary solution in the mean time.

Thanks again,
Woody


> -----Original Message-----
> From: Artem Bityutskiy [mailto:dedekind1 at gmail.com]
> Sent: Monday, June 06, 2011 2:54 PM 14
> To: Douglass, Woody
> Cc: linux-mtd at lists.infradead.org
> Subject: Re: ubi image only mounts once
> 
> On Mon, Jun 6, 2011 at 9:31 PM, Douglass, Woody
> <Woodrow.Douglass at qinetiq-na.com> wrote:
> >
> > Artem,
> >
> > Thanks, you're correct, subpages aren't working properly! First I
> tried applying this patch to solve the issue:
> https://patchwork.kernel.org/patch/749762/
> >
> > The test still fails. Next, I changed the -s argument to ubinize from
> 512 to 2048; I also added -s 2048 to my ubiformat arguments.
> >
> > Now, on boot, this happens:
> >
> > [ ?357.992767] UBI: attaching mtd4 to ubi0
> > [ ?357.996673] UBI: physical eraseblock size: ? 131072 bytes (128
> KiB)
> > [ ?358.003631] UBI: logical eraseblock size: ? ?129024 bytes
> > [ ?358.009185] UBI: smallest flash I/O unit: ? ?2048
> > [ ?358.013916] UBI: sub-page size: ? ? ? ? ? ? ?512
> > [ ?358.018646] UBI: VID header offset: ? ? ? ? ?512 (aligned 512)
> > [ ?358.024505] UBI: data offset: ? ? ? ? ? ? ? ?2048
> > [ ?358.030639] UBI error: validate_ec_hdr: bad VID header offset
> 2048, expected 512
> > [ ?358.038085] UBI error: validate_ec_hdr: bad EC header
> > [ ?358.043426] UBI error: ubi_io_read_ec_hdr: validation failed for
> PEB 0
> > [ ?358.050292] UBI error: ubi_init: cannot attach mtd4
> > [ ?358.057708] UBI error: ubi_init: UBI error: cannot initialize UBI,
> error -22
> >
> > How can I re set the sub-page size?
> 
> Take a look here:
> http://linux-mtd.infradead.org/faq/ubi.html#L_vid_offset_mismatch
> 
> Also modinfo ubi
> 
> If you attach UBI using the kernel boot parameters, use mtd=X,2048,
> where X is your number.
> 
> --
> Best Regards,
> Artem Bityutskiy (???????? ?????)

From mlcreech at gmail.com  Mon Jun  6 15:52:06 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Mon,  6 Jun 2011 15:52:06 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307377091.3112.100.camel@localhost>
References: <1307377091.3112.100.camel@localhost>
Message-ID: <1307389926-12209-1-git-send-email-mlcreech@gmail.com>

On Mon, Jun 6, 2011 at 12:18 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> I have to go home now - could you please improve dbg_dump_leb().
> Currently it calls ubifs_scan(), which scans, finds corrupted node,
> prints corruption information and returns -EUCLEAN and destroys the
> scanned data.
>

Will something like this be okay?  Or do you still want to dump the
partially-parsed data from the corrupt node as well (not just the raw contents
of the LEB)?


Currently an error in ubifs_scan() will cause dbg_dump_leb() to abort without
completing the dump.  Instead, we should abandon parsing the data, but dump
the raw (uninterpreted) LEB contents instead.

Signed-off-by: Matthew L. Creech <mlcreech at gmail.com>
---
 fs/ubifs/debug.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 26d4c61..6ab43e4 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -901,6 +901,9 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 	sleb = ubifs_scan(c, lnum, 0, buf, 0);
 	if (IS_ERR(sleb)) {
 		ubifs_err("scan error %d", (int)PTR_ERR(sleb));
+		printk(KERN_DEBUG "\tLEB data buffer:\n");
+		print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1,
+			       buf, c->leb_size, 0);
 		goto out;
 	}
 
-- 
1.6.3.3



From kmpark at infradead.org  Mon Jun  6 19:55:54 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Tue, 7 Jun 2011 08:55:54 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <1307354791.3112.24.camel@localhost>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
Message-ID: <BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>

On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>> On Mon, 2011-06-06 at 09:42 +0000, roman.tereshonkov at nokia.com wrote:
>> > What do mean by "no case to use the subpage"?
>> >
>> > According to the spec KFM4G16Q4M-xEBx the Number of Partial Program Cycles in the page (NOP)
>> > is equal to 4 -> subpage_sft=2.

It's really strange. Two OneNAND spec which has 4KiB pagesize say it has 1 NOP.

Number of Partial Program Cycles in the page (Including main and spare
area) NOP - - 1 cycles
(KFM4G16Q5M-xEBx)

that's reason I first set subpage_sft = 0 at original code.

The different thing between you and me is the page architecture
number. yes 4 is the correct number but 5 also has the 4KiB pagesize.
I think it's mean the manufacturing difference. can you check the
which XXnm manufacturing for your devices?
In our case. it's 3Xnm. and previous is 4Xnm.

>>
>> I thought this means "not supported by HW". But if this is supported,
>> then I'm very surprised why would we remove it. I'm dropping this patch
>> from my tree.
>
> OK, I actually did not put it to the l2 tree. And AFAICS this patch
> basically reverts commit 99b17c08bca2810f5910b3027f1b9d82edf7a576, but
> still leaves the data structures like onenand_oob_128.
>
> So NACK for this patch - poor commit message, weird changes. I'm
> surprised to see this from kmpark.

since we got some different OneNAND Spec. even though it has same 4KiB pagesize.

Thank you,
Kyungmin Park
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>


From dedekind1 at gmail.com  Tue Jun  7 00:20:02 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:20:02 +0300
Subject: [PATCH 1/3] mtd: add a flags for partitions which should just
	leave smth. after them
In-Reply-To: <1307369056-29319-2-git-send-email-dbaryshkov@gmail.com>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
	<1307369056-29319-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307420402.11104.4.camel@localhost>

On Mon, 2011-06-06 at 18:04 +0400, Dmitry Eremin-Solenikov wrote:
> +			printk(KERN_ERR "mtd partition \"%s\" doesn't have enough space: %#llx < %#llx, disabled\n",
> +				part->name,
> +				master->size - slave->offset, slave->mtd.size);
> +			/* register to preserve ordering */

Tweaked this patch a tiny bit, and push all 3 to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Tue Jun  7 00:23:26 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:23:26 +0300
Subject: [PATCH] mtd: denali: detect the number of banks before
	resetting NAND
In-Reply-To: <1307376694-17905-1-git-send-email-jamie@jamieiles.com>
References: <1307376694-17905-1-git-send-email-jamie@jamieiles.com>
Message-ID: <1307420606.11104.5.camel@localhost>


On Mon, 2011-06-06 at 17:11 +0100, Jamie Iles wrote:
> Commit c89eeda810f0ec4f0eee0206ebb79e476df9f83e (mtd: denali: detect the
> number of banks) introduced runtime detection of the number of banks.
> 
> However, denali_nand_reset() uses uses denanli_nand_info::max_banks so
> we need to detect the maximum number of banks before doing the reset.
> 
> Cc: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> Cc: David Woodhouse <David.Woodhouse at intel.com>
> Signed-off-by: Jamie Iles <jamie at jamieiles.com>

Pushed to l2-mtd-2.6.git, thanks.

> Artem, I believe that this one will be needed for 3.0 to avoid breakage
> on Moorestown.

All the upstream merging is done by David, not me.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 00:31:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:31:04 +0300
Subject: [PATCH 1/4] flash_info: convert to common.h
In-Reply-To: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307421064.11104.7.camel@localhost>

On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  flash_info.c |   27 +++++++++++++++++----------
>  1 files changed, 17 insertions(+), 10 deletions(-)

How about killing this utility completely and use mtdinfo from ubi-utils
instead? Yes, before creating mtdinfo I should have noticed flash_info,
but I did not. Did you look at mtdinfo?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 00:31:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:31:41 +0300
Subject: [PATCH] ignore (FLAT) gdb files
In-Reply-To: <1307380501-30946-1-git-send-email-vapier@gentoo.org>
References: <1307380501-30946-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307421101.11104.8.camel@localhost>

On Mon, 2011-06-06 at 13:15 -0400, Mike Frysinger wrote:
> Linux FLAT toolchains produce .gdb files alongside the normal program
> for debugging purposes (so linking to "foo" will also produce "foo.gdb").
> Ignore these too.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed this patch to mtd-utils.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 00:34:26 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:34:26 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307389926-12209-1-git-send-email-mlcreech@gmail.com>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
Message-ID: <1307421266.11104.10.camel@localhost>

On Mon, 2011-06-06 at 15:52 -0400, Matthew L. Creech wrote:
>  		ubifs_err("scan error %d", (int)PTR_ERR(sleb));
> +		printk(KERN_DEBUG "\tLEB data buffer:\n");
> +		print_hex_dump(KERN_DEBUG, "\t", DUMP_PREFIX_OFFSET, 32, 1,
> +			       buf, c->leb_size, 0);

No, I have difficulties reading hexdumps. You have set of good nodes
following by one broken node. I wanted to see a human-readable dump of
the good nodes at the beginning of the LEB.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Tue Jun  7 00:41:10 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 00:41:10 -0400
Subject: [PATCH 1/4] flash_info: convert to common.h
In-Reply-To: <1307421064.11104.7.camel@localhost>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307421064.11104.7.camel@localhost>
Message-ID: <BANLkTimBGH0UW-YP=CZ7aDf_-nXXDhfz4Q@mail.gmail.com>

On Tue, Jun 7, 2011 at 00:31, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
>> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>> ---
>> ?flash_info.c | ? 27 +++++++++++++++++----------
>> ?1 files changed, 17 insertions(+), 10 deletions(-)
>
> How about killing this utility completely and use mtdinfo from ubi-utils
> instead? Yes, before creating mtdinfo I should have noticed flash_info,
> but I did not. Did you look at mtdinfo?

didnt even notice it :P

if mtdinfo provides all the details that my new flash_info does, then
i dont care about punting it.  be nice to merge my fixes before
deleting it though, otherwise i feel like i wasted quite a bit of time
for nothing ;).
-mike


From dedekind1 at gmail.com  Tue Jun  7 00:40:15 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:40:15 +0300
Subject: l2-mtd-2.6.git to linux-next
In-Reply-To: <1307345850.3135.24.camel@localhost>
References: <1307345850.3135.24.camel@localhost>
Message-ID: <1307421615.11104.14.camel@localhost>

David,

On Mon, 2011-06-06 at 10:37 +0300, Artem Bityutskiy wrote:
> Stephen,
> 
> as we've discussed, please, include l2-mtd-2.6.git tree to linux-next:
> 
> git://git.infradead.org/users/dedekind/l2-mtd-2.6.git master

although you already asked about this, sfr wanted your deliberate ack.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 00:42:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:42:40 +0300
Subject: [PATCH 1/4] flash_info: convert to common.h
In-Reply-To: <BANLkTimBGH0UW-YP=CZ7aDf_-nXXDhfz4Q@mail.gmail.com>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307421064.11104.7.camel@localhost>
	<BANLkTimBGH0UW-YP=CZ7aDf_-nXXDhfz4Q@mail.gmail.com>
Message-ID: <1307421760.11104.16.camel@localhost>

On Tue, 2011-06-07 at 00:41 -0400, Mike Frysinger wrote:
> On Tue, Jun 7, 2011 at 00:31, Artem Bityutskiy wrote:
> > On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> >> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> >> ---
> >>  flash_info.c |   27 +++++++++++++++++----------
> >>  1 files changed, 17 insertions(+), 10 deletions(-)
> >
> > How about killing this utility completely and use mtdinfo from ubi-utils
> > instead? Yes, before creating mtdinfo I should have noticed flash_info,
> > but I did not. Did you look at mtdinfo?
> 
> didnt even notice it :P
> 
> if mtdinfo provides all the details that my new flash_info does, then
> i dont care about punting it.  be nice to merge my fixes before
> deleting it though, otherwise i feel like i wasted quite a bit of time
> for nothing ;).

I think it provides everything except of region information, which
flash_info provides :)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 00:45:38 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 07:45:38 +0300
Subject: [PATCH 1/4] flash_info: convert to common.h
In-Reply-To: <1307421760.11104.16.camel@localhost>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307421064.11104.7.camel@localhost>
	<BANLkTimBGH0UW-YP=CZ7aDf_-nXXDhfz4Q@mail.gmail.com>
	<1307421760.11104.16.camel@localhost>
Message-ID: <1307421938.11104.17.camel@localhost>

On Tue, 2011-06-07 at 07:42 +0300, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 00:41 -0400, Mike Frysinger wrote:
> > On Tue, Jun 7, 2011 at 00:31, Artem Bityutskiy wrote:
> > > On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> > >> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> > >> ---
> > >>  flash_info.c |   27 +++++++++++++++++----------
> > >>  1 files changed, 17 insertions(+), 10 deletions(-)
> > >
> > > How about killing this utility completely and use mtdinfo from ubi-utils
> > > instead? Yes, before creating mtdinfo I should have noticed flash_info,
> > > but I did not. Did you look at mtdinfo?
> > 
> > didnt even notice it :P
> > 
> > if mtdinfo provides all the details that my new flash_info does, then
> > i dont care about punting it.  be nice to merge my fixes before
> > deleting it though, otherwise i feel like i wasted quite a bit of time
> > for nothing ;).
> 
> I think it provides everything except of region information, which
> flash_info provides :)

And it does not show a map of sectors. May be we can add this to mtdinfo
instead?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Tue Jun  7 00:51:06 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 00:51:06 -0400
Subject: [PATCH 1/4] flash_info: convert to common.h
In-Reply-To: <1307421938.11104.17.camel@localhost>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307421064.11104.7.camel@localhost>
	<BANLkTimBGH0UW-YP=CZ7aDf_-nXXDhfz4Q@mail.gmail.com>
	<1307421760.11104.16.camel@localhost>
	<1307421938.11104.17.camel@localhost>
Message-ID: <BANLkTim=bc76w9g3_59pLk92J0H5GgsCgQ@mail.gmail.com>

On Tue, Jun 7, 2011 at 00:45, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 07:42 +0300, Artem Bityutskiy wrote:
>> On Tue, 2011-06-07 at 00:41 -0400, Mike Frysinger wrote:
>> > On Tue, Jun 7, 2011 at 00:31, Artem Bityutskiy wrote:
>> > > On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
>> > >> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>> > >> ---
>> > >> ?flash_info.c | ? 27 +++++++++++++++++----------
>> > >> ?1 files changed, 17 insertions(+), 10 deletions(-)
>> > >
>> > > How about killing this utility completely and use mtdinfo from ubi-utils
>> > > instead? Yes, before creating mtdinfo I should have noticed flash_info,
>> > > but I did not. Did you look at mtdinfo?
>> >
>> > didnt even notice it :P
>> >
>> > if mtdinfo provides all the details that my new flash_info does, then
>> > i dont care about punting it. ?be nice to merge my fixes before
>> > deleting it though, otherwise i feel like i wasted quite a bit of time
>> > for nothing ;).
>>
>> I think it provides everything except of region information, which
>> flash_info provides :)
>
> And it does not show a map of sectors. May be we can add this to mtdinfo
> instead?

if you merge the patches i posted here, i'll see about extending
mtdinfo to include the new functionality and then i'll post another
patch to punt flash_info ;).
-mike


From dedekind1 at gmail.com  Tue Jun  7 01:01:26 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 08:01:26 +0300
Subject: [PATCH 4/4] flash_info: display MEMGETINFO and MEMISLOCKED
In-Reply-To: <1307384537-9607-4-git-send-email-vapier@gentoo.org>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307384537-9607-4-git-send-email-vapier@gentoo.org>
Message-ID: <1307422886.11104.21.camel@localhost>

On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> I found the existing flash_info output to be a little lacking, so
> add decoders for MEMGETINFO and MEMISLOCKED.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  flash_info.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++------
>  1 files changed, 87 insertions(+), 11 deletions(-)

Pushed patches 1-3.

WRT this patch - I think the sector map should be a separate option,
because it outputs too much for a default option.

> +	for (i = 0; i < reginfo->numblocks; ++i) {
> +		einfo.start = reginfo->offset + i * reginfo->erasesize;
> +		printf(" %*i: %08x ", width, i, einfo.start);
> +		if (ioctl(fd, MEMISLOCKED, &einfo))
> +			printf("RO ");
> +		else
> +			printf("   ");


MEMISLOCKED is quite new ioctl, so you should check for ENOTTY. E.g.,
with my stock Fedora 14 + nandsim I see all sectors as RO, which is
obviously not true.

Otherwise the patch looks very good.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 01:01:54 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 08:01:54 +0300
Subject: [PATCH 1/4] flash_info: convert to common.h
In-Reply-To: <BANLkTim=bc76w9g3_59pLk92J0H5GgsCgQ@mail.gmail.com>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307421064.11104.7.camel@localhost>
	<BANLkTimBGH0UW-YP=CZ7aDf_-nXXDhfz4Q@mail.gmail.com>
	<1307421760.11104.16.camel@localhost>
	<1307421938.11104.17.camel@localhost>
	<BANLkTim=bc76w9g3_59pLk92J0H5GgsCgQ@mail.gmail.com>
Message-ID: <1307422914.11104.22.camel@localhost>

On Tue, 2011-06-07 at 00:51 -0400, Mike Frysinger wrote:
> On Tue, Jun 7, 2011 at 00:45, Artem Bityutskiy wrote:
> > On Tue, 2011-06-07 at 07:42 +0300, Artem Bityutskiy wrote:
> >> On Tue, 2011-06-07 at 00:41 -0400, Mike Frysinger wrote:
> >> > On Tue, Jun 7, 2011 at 00:31, Artem Bityutskiy wrote:
> >> > > On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> >> > >> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> >> > >> ---
> >> > >>  flash_info.c |   27 +++++++++++++++++----------
> >> > >>  1 files changed, 17 insertions(+), 10 deletions(-)
> >> > >
> >> > > How about killing this utility completely and use mtdinfo from ubi-utils
> >> > > instead? Yes, before creating mtdinfo I should have noticed flash_info,
> >> > > but I did not. Did you look at mtdinfo?
> >> >
> >> > didnt even notice it :P
> >> >
> >> > if mtdinfo provides all the details that my new flash_info does, then
> >> > i dont care about punting it.  be nice to merge my fixes before
> >> > deleting it though, otherwise i feel like i wasted quite a bit of time
> >> > for nothing ;).
> >>
> >> I think it provides everything except of region information, which
> >> flash_info provides :)
> >
> > And it does not show a map of sectors. May be we can add this to mtdinfo
> > instead?
> 
> if you merge the patches i posted here, i'll see about extending
> mtdinfo to include the new functionality and then i'll post another
> patch to punt flash_info ;).

Sure, thanks, I've sent you some feed-back for the last patch, though.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 01:05:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 08:05:08 +0300
Subject: [PATCH 4/4] flash_info: display MEMGETINFO and MEMISLOCKED
In-Reply-To: <1307422886.11104.21.camel@localhost>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307384537-9607-4-git-send-email-vapier@gentoo.org>
	<1307422886.11104.21.camel@localhost>
Message-ID: <1307423108.11104.24.camel@localhost>

On Tue, 2011-06-07 at 08:01 +0300, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> > I found the existing flash_info output to be a little lacking, so
> > add decoders for MEMGETINFO and MEMISLOCKED.
> > 
> > Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> > ---
> >  flash_info.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++------
> >  1 files changed, 87 insertions(+), 11 deletions(-)
> 
> Pushed patches 1-3.
> 
> WRT this patch - I think the sector map should be a separate option,
> because it outputs too much for a default option.

Hmm, actually, for this utility it is probably ok this way.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Tue Jun  7 01:14:05 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 01:14:05 -0400
Subject: [PATCH 4/4] flash_info: display MEMGETINFO and MEMISLOCKED
In-Reply-To: <1307422886.11104.21.camel@localhost>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307384537-9607-4-git-send-email-vapier@gentoo.org>
	<1307422886.11104.21.camel@localhost>
Message-ID: <BANLkTik0YrwYWFiQMZucSp83zD0cS+emgQ@mail.gmail.com>

On Tue, Jun 7, 2011 at 01:01, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
>> I found the existing flash_info output to be a little lacking, so
>> add decoders for MEMGETINFO and MEMISLOCKED.
>>
>> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>> ---
>> ?flash_info.c | ? 98 +++++++++++++++++++++++++++++++++++++++++++++++++++------
>> ?1 files changed, 87 insertions(+), 11 deletions(-)
>
> Pushed patches 1-3.
>
> WRT this patch - I think the sector map should be a separate option,
> because it outputs too much for a default option.

i'm adding regioninfo(-r)/sectormap(-s) as options to mtdinfo so users
get the extended info only when they ask for it

>> + ? ? for (i = 0; i < reginfo->numblocks; ++i) {
>> + ? ? ? ? ? ? einfo.start = reginfo->offset + i * reginfo->erasesize;
>> + ? ? ? ? ? ? printf(" %*i: %08x ", width, i, einfo.start);
>> + ? ? ? ? ? ? if (ioctl(fd, MEMISLOCKED, &einfo))
>> + ? ? ? ? ? ? ? ? ? ? printf("RO ");
>> + ? ? ? ? ? ? else
>> + ? ? ? ? ? ? ? ? ? ? printf(" ? ");
>
>
> MEMISLOCKED is quite new ioctl, so you should check for ENOTTY. E.g.,
> with my stock Fedora 14 + nandsim I see all sectors as RO, which is
> obviously not true.

i'll take care of this as i implement regioninfo/islocked in libmtd
-mike


From dedekind1 at gmail.com  Tue Jun  7 01:11:59 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 08:11:59 +0300
Subject: [PATCH 4/4] flash_info: display MEMGETINFO and MEMISLOCKED
In-Reply-To: <BANLkTik0YrwYWFiQMZucSp83zD0cS+emgQ@mail.gmail.com>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307384537-9607-4-git-send-email-vapier@gentoo.org>
	<1307422886.11104.21.camel@localhost>
	<BANLkTik0YrwYWFiQMZucSp83zD0cS+emgQ@mail.gmail.com>
Message-ID: <1307423519.11104.25.camel@localhost>

On Tue, 2011-06-07 at 01:14 -0400, Mike Frysinger wrote:
...

> i'm adding regioninfo(-r)/sectormap(-s) as options to mtdinfo so users
> get the extended info only when they ask for it

...

> i'll take care of this as i implement regioninfo/islocked in libmtd

Many thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 01:18:07 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 08:18:07 +0300
Subject: [PATCH 4/4] flash_info: display MEMGETINFO and MEMISLOCKED
In-Reply-To: <BANLkTik0YrwYWFiQMZucSp83zD0cS+emgQ@mail.gmail.com>
References: <1307384537-9607-1-git-send-email-vapier@gentoo.org>
	<1307384537-9607-4-git-send-email-vapier@gentoo.org>
	<1307422886.11104.21.camel@localhost>
	<BANLkTik0YrwYWFiQMZucSp83zD0cS+emgQ@mail.gmail.com>
Message-ID: <1307423887.11104.27.camel@localhost>

On Tue, 2011-06-07 at 01:14 -0400, Mike Frysinger wrote:
> On Tue, Jun 7, 2011 at 01:01, Artem Bityutskiy wrote:
> > On Mon, 2011-06-06 at 14:22 -0400, Mike Frysinger wrote:
> >> I found the existing flash_info output to be a little lacking, so
> >> add decoders for MEMGETINFO and MEMISLOCKED.
> >>
> >> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> >> ---
> >>  flash_info.c |   98 +++++++++++++++++++++++++++++++++++++++++++++++++++------
> >>  1 files changed, 87 insertions(+), 11 deletions(-)
> >
> > Pushed patches 1-3.
> >
> > WRT this patch - I think the sector map should be a separate option,
> > because it outputs too much for a default option.
> 
> i'm adding regioninfo(-r)/sectormap(-s) as options to mtdinfo so users
> get the extended info only when they ask for it

Region info is probably not worth a separate option - I do not believe
there are flashes with more than 2-3 of them.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier.adi at gmail.com  Tue Jun  7 01:24:26 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 7 Jun 2011 01:24:26 -0400
Subject: region info exposed via sysfs ?
Message-ID: <BANLkTi=EFZfoDAK7g-+8RMck5vneCOoKhA@mail.gmail.com>

i see that while MEMGETINFO and MEMGETREGIONCOUNT are accessible via
sysfs, i cant find the equivalent for MEMGETREGIONINFO.  but i also
dont have any devices here that have numeraseregions > 0 as both my
physmap nor flashes and nand flashes all report numeraseregions == 0.

is it exposed via sysfs and i'm just not seeing it ?  or is this info
only available via the ioctl ?
-mike


From dedekind1 at gmail.com  Tue Jun  7 01:25:21 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 08:25:21 +0300
Subject: region info exposed via sysfs ?
In-Reply-To: <BANLkTi=EFZfoDAK7g-+8RMck5vneCOoKhA@mail.gmail.com>
References: <BANLkTi=EFZfoDAK7g-+8RMck5vneCOoKhA@mail.gmail.com>
Message-ID: <1307424321.11104.33.camel@localhost>

On Tue, 2011-06-07 at 01:24 -0400, Mike Frysinger wrote:
> i see that while MEMGETINFO and MEMGETREGIONCOUNT are accessible via
> sysfs, i cant find the equivalent for MEMGETREGIONINFO.  but i also
> dont have any devices here that have numeraseregions > 0 as both my
> physmap nor flashes and nand flashes all report numeraseregions == 0.
> 
> is it exposed via sysfs and i'm just not seeing it ?  or is this info
> only available via the ioctl ?

I think MEMGETREGIONINFO is not exposed via sysfs.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Tue Jun  7 02:19:05 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 02:19:05 -0400
Subject: [PATCH 3/6] libmtd: use O_CLOEXEC
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307427548-29306-3-git-send-email-vapier@gentoo.org>

Not strictly necessary, but this is good library behavior and
should carry no runtime overhead.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/common.h |    5 +++++
 lib/libmtd.c     |   10 +++++-----
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/include/common.h b/include/common.h
index c37660c..7ea282c 100644
--- a/include/common.h
+++ b/include/common.h
@@ -23,6 +23,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
+#include <fcntl.h>
 #include <errno.h>
 
 #ifndef PROGRAM_NAME
@@ -42,6 +43,10 @@ extern "C" {
 #define min(a, b) MIN(a, b) /* glue for linux kernel source */
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+
 /* Verbose messages */
 #define bareverbose(verbose, fmt, ...) do {                        \
 	if (verbose)                                               \
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 7fabd80..a651808 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -77,7 +77,7 @@ static int read_data(const char *file, void *buf, int buf_len)
 {
 	int fd, rd, tmp, tmp1;
 
-	fd = open(file, O_RDONLY);
+	fd = open(file, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return -1;
 
@@ -201,7 +201,7 @@ static int read_hex_ll(const char *file, long long *value)
 	int fd, rd;
 	char buf[50];
 
-	fd = open(file, O_RDONLY);
+	fd = open(file, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return -1;
 
@@ -253,7 +253,7 @@ static int read_pos_ll(const char *file, long long *value)
 	int fd, rd;
 	char buf[50];
 
-	fd = open(file, O_RDONLY);
+	fd = open(file, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return -1;
 
@@ -538,7 +538,7 @@ static int sysfs_is_supported(struct libmtd *lib)
 		return 0;
 
 	sprintf(file, lib->mtd_name, num);
-	fd = open(file, O_RDONLY);
+	fd = open(file, O_RDONLY | O_CLOEXEC);
 	if (fd == -1)
 		return 0;
 
@@ -1193,7 +1193,7 @@ int mtd_write_img(const struct mtd_dev_info *mtd, int fd, int eb, int offs,
 		return -1;
 	}
 
-	in_fd = open(img_name, O_RDONLY);
+	in_fd = open(img_name, O_RDONLY | O_CLOEXEC);
 	if (in_fd == -1)
 		return sys_errmsg("cannot open \"%s\"", img_name);
 
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 02:19:04 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 02:19:04 -0400
Subject: [PATCH 2/6] mtdinfo: send help/version info to stdout
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307427548-29306-2-git-send-email-vapier@gentoo.org>

Usage/version information should go to stdout when it is expected behavior
(i.e. the user requested it explicitly).  This info should go to stderr
only when the usage info is being shown as a result of incorrect options.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 ubi-utils/src/mtdinfo.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index c9f6f58..f20fe49 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -110,13 +110,13 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'h':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			printf("%s\n", PROGRAM_VERSION);
 			exit(EXIT_SUCCESS);
 
 		case ':':
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 02:19:03 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 02:19:03 -0400
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
Message-ID: <1307427548-29306-1-git-send-email-vapier@gentoo.org>

The external lzo dep can be a pain to deal with when cross-compiling,
so make it optional for jffs2.  This is useful if people aren't even
using the functionality, or for quicker development.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 Makefile    |    9 +++++++--
 compr_lzo.c |   15 +++++++++++++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/Makefile b/Makefile
index 6a65258..8bdba8e 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,11 @@ CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
 ifeq ($(WITHOUT_XATTR), 1)
   CPPFLAGS += -DWITHOUT_XATTR
 endif
+ifeq ($(WITHOUT_LZO), 1)
+  CPPFLAGS += -DWITHOUT_LZO
+else
+  LZOLDLIBS = -llzo2
+endif
 
 SUBDIRS = lib ubi-utils mkfs.ubifs
 TESTS = tests
@@ -48,11 +53,11 @@ $(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\
 	compr_rtime.o mkfs.jffs2.o compr_zlib.o compr_lzo.o \
 	compr.o rbtree.o)
 LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_mkfs.jffs2  = -lz -llzo2
+LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
 
 $(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o
 LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_jffs2reader  = -lz -llzo2
+LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
 
 $(BUILDDIR)/lib/libmtd.a: subdirs_lib_all ;
 
diff --git a/compr_lzo.c b/compr_lzo.c
index d0f0ed7..d2e2afc 100644
--- a/compr_lzo.c
+++ b/compr_lzo.c
@@ -24,6 +24,8 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <string.h>
+
+#ifndef WITHOUT_LZO
 #include <asm/types.h>
 #include <linux/jffs2.h>
 #include <lzo/lzo1x.h>
@@ -118,3 +120,16 @@ void jffs2_lzo_exit(void)
 	free(lzo_compress_buf);
 	free(lzo_mem);
 }
+
+#else
+
+int jffs2_lzo_init(void)
+{
+	return 0;
+}
+
+void jffs2_lzo_exit(void)
+{
+}
+
+#endif
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 02:19:06 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 02:19:06 -0400
Subject: [PATCH 4/6] libmtd: add helper funcs for getting fds, regioninfo,
	and locked info
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307427548-29306-4-git-send-email-vapier@gentoo.org>

This extends the libmtd with the helper functions:
	mtd_open_dev1: open a MTD device by its number
	mtd_regioninfo: interface to MEMGETREGIONINFO
	mtd_islocked: interface to MEMISLOCKED

Users of these functions will follow shortly ...

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 include/libmtd.h |   37 +++++++++++++++++++++++++++++++++++++
 lib/libmtd.c     |   51 +++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 88 insertions(+), 0 deletions(-)

diff --git a/include/libmtd.h b/include/libmtd.h
index e30c8a6..ba1348a 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -35,6 +35,9 @@ extern "C" {
 /* MTD library descriptor */
 typedef void * libmtd_t;
 
+/* Forward decls */
+struct region_info_user;
+
 /**
  * @mtd_dev_cnt: count of MTD devices in system
  * @lowest_mtd_num: lowest MTD device number in system
@@ -138,6 +141,15 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd);
 int mtd_get_dev_info1(libmtd_t desc, int mtd_num, struct mtd_dev_info *mtd);
 
 /**
+ * mtd_open_dev1 - get a fd to an MTD device.
+ * @desc: MTD library descriptor
+ * @mtd_num: MTD device number to fetch information about
+ *
+ * Based on a MTD device number, attempt to open the corresponding node.
+ */
+int mtd_open_dev1(int mtd_num);
+
+/**
  * mtd_lock - lock eraseblocks.
  * @desc: MTD library descriptor
  * @mtd: MTD device description object
@@ -174,6 +186,31 @@ int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb);
 int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
 
 /**
+ * mtd_regioninfo - get information about an erase region.
+ * @fd: MTD device node file descriptor
+ * @regidx: index of region to look up
+ * @reginfo: the region information is returned here
+ *
+ * This function gets information about an erase region defined by the
+ * @regidx index and saves this information in the @reginfo object.
+ * Returns %0 in case of success and %-1 in case of failure. If the
+ * @regidx is not valid or unavailable, errno is set to @ENODEV.
+ */
+int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo);
+
+/**
+ * mtd_islocked - see if the specified eraseblock is locked.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to check
+ *
+ * This function checks to see if eraseblock @eb of MTD device described
+ * by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and
+ * %-1 in case of failure.
+ */
+int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
  * mtd_torture - torture an eraseblock.
  * @desc: MTD library descriptor
  * @mtd: MTD device description object
diff --git a/lib/libmtd.c b/lib/libmtd.c
index a651808..3be28c4 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -787,6 +787,25 @@ int mtd_get_dev_info(libmtd_t desc, const char *node, struct mtd_dev_info *mtd)
 	return mtd_get_dev_info1(desc, mtd_num, mtd);
 }
 
+int mtd_open_dev1(int mtd_num)
+{
+	char devpath[128];
+	int fd;
+
+	sprintf(devpath, "/dev/mtd%i", mtd_num);
+	fd = open(devpath, O_RDONLY | O_CLOEXEC);
+	if (fd < 0)
+		return sys_errmsg("cannot open \"%s\"", devpath);
+
+	/*
+	 * XXX: We could do a stat on the fd and make sure the dev
+	 *      major/minor matches what is expected ... but no real
+	 *      way for us to recover from a mismatch.
+	 */
+
+	return fd;
+}
+
 static inline int mtd_ioctl_error(const struct mtd_dev_info *mtd, int eb,
 				  const char *sreq)
 {
@@ -883,6 +902,38 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
 	return 0;
 }
 
+int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
+{
+	int ret;
+
+	if (regidx < 0) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	ret = ioctl(fd, MEMGETREGIONINFO, reginfo);
+	if (ret < 0)
+		return sys_errmsg("%s ioctl failed for erase region %d",
+			"MEMGETREGIONINFO", regidx);
+
+	return 0;
+}
+
+int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int ret;
+	erase_info_t ei;
+
+	ei.start = eb * mtd->eb_size;
+	ei.length = mtd->eb_size;
+
+	ret = ioctl(fd, MEMISLOCKED, &ei);
+	if (ret < 0)
+		return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
+
+	return ret;
+}
+
 /* Patterns to write to a physical eraseblock when torturing it */
 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
 
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 02:19:07 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 02:19:07 -0400
Subject: [PATCH 5/6] mtdinfo: add regioninfo/sectormap display
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307427548-29306-5-git-send-email-vapier@gentoo.org>

This brings the mtdinfo utility in line with the functionality
of the flash_info utility.  It dumps the erase regioninfo (if
the devices has it) as well as showing a handy sector map (if
the user has requested it).  The sector map also utilizes the
MEMISLOCKED ioctl in order to show which sectors exactly are
locked.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 ubi-utils/src/mtdinfo.c |   75 +++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 70 insertions(+), 5 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index f20fe49..3dab27a 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -29,6 +29,7 @@
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <mtd/mtd-user.h>
 
 #include <libubigen.h>
@@ -41,6 +42,7 @@ struct args {
 	int mtdn;
 	unsigned int all:1;
 	unsigned int ubinfo:1;
+	unsigned int sectormap:1;
 	const char *node;
 };
 
@@ -58,14 +60,15 @@ static const char optionsstr[] =
 "-m, --mtdn=<MTD device number>  MTD device number to get information about\n"
 "-u, --ubi-info                  print what would UBI layout be if it was put\n"
 "                                on this MTD device\n"
+"-s, --sector-map                print sector map\n"
 "-a, --all                       print information about all MTD devices\n"
 "-h, --help                      print help message\n"
 "-V, --version                   print program version";
 
 static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-h] [-V] [--mtdn <MTD device number>]\n"
+"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-s] [-h] [-V] [--mtdn <MTD device number>]\n"
 "\t\t[--ubi-info] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-h] [-V] [--ubi-info] [--help]\n"
+"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-s] [-h] [-V] [--ubi-info] [--help]\n"
 "\t\t[--version]\n"
 "Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
 "Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
@@ -78,6 +81,7 @@ static const char usage[] =
 static const struct option long_options[] = {
 	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
 	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
+	{ .name = "sector-map",.has_arg = 0, .flag = NULL, .val = 's' },
 	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
 	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
 	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
@@ -89,7 +93,7 @@ static int parse_opt(int argc, char * const argv[])
 	while (1) {
 		int key, error = 0;
 
-		key = getopt_long(argc, argv, "am:uhV", long_options, NULL);
+		key = getopt_long(argc, argv, "am:ushV", long_options, NULL);
 		if (key == -1)
 			break;
 
@@ -109,6 +113,10 @@ static int parse_opt(int argc, char * const argv[])
 
 			break;
 
+		case 's':
+			args.sectormap = 1;
+			break;
+
 		case 'h':
 			printf("%s\n\n", doc);
 			printf("%s\n\n", usage);
@@ -159,9 +167,36 @@ static int translate_dev(libmtd_t libmtd, const char *node)
 	return 0;
 }
 
+static void print_sector_map(const struct mtd_dev_info *mtd, int fd,
+			     const region_info_t *reginfo)
+{
+	unsigned long start;
+	int i, width;
+
+	printf("Sector map:\n");
+
+	/* figure out the number of spaces to pad w/out libm */
+	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
+		continue;
+
+	for (i = 0; i < reginfo->numblocks; ++i) {
+		start = reginfo->offset + i * reginfo->erasesize;
+		printf(" %*i: %08lx ", width, i, start);
+		if (mtd_islocked(mtd, fd, i) == 1)
+			printf("RO ");
+		else
+			printf("   ");
+		if (((i + 1) % 4) == 0)
+			printf("\n");
+	}
+	if (i % 4)
+		printf("\n");
+}
+
 static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
 {
-	int err;
+	int err, fd = -1;
+	region_info_t reginfo;
 	struct mtd_dev_info mtd;
 	struct ubigen_info ui;
 
@@ -195,8 +230,25 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	if (mtd.oob_size > 0)
 		printf("OOB size:                       %d bytes\n",
 		       mtd.oob_size);
-	if (mtd.region_cnt > 0)
+	if (mtd.region_cnt > 0) {
 		printf("Additional erase regions:       %d\n", mtd.oob_size);
+		fd = mtd_open_dev1(mtdn);
+		if (fd != -1) {
+			int r;
+
+			for (r = 0; r < mtd.region_cnt; ++r) {
+				printf(" region %i: ", r);
+				if (mtd_regioninfo(fd, r, &reginfo) == 0) {
+					printf(" offset: %#x size: %#x numblocks: %#x\n",
+						reginfo.offset, reginfo.erasesize,
+						reginfo.numblocks);
+					if (args.sectormap)
+						print_sector_map(&mtd, fd, &reginfo);
+				} else
+					printf(" info is unavailable\n");
+			}
+		}
+	}
 	if (mtd_info->sysfs_supported)
 		printf("Character device major/minor:   %d:%d\n",
 		       mtd.major, mtd.minor);
@@ -224,6 +276,19 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
 
 out:
+	if (args.sectormap && mtd.region_cnt == 0) {
+		if (fd == -1)
+			fd = mtd_open_dev1(mtdn);
+		reginfo.offset = 0;
+		reginfo.erasesize = mtd.eb_size;
+		reginfo.numblocks = mtd.eb_cnt;
+		reginfo.regionindex = 0;
+		print_sector_map(&mtd, fd, &reginfo);
+	}
+
+	if (fd != -1)
+		close(fd);
+
 	printf("\n");
 	return 0;
 }
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 02:19:08 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 02:19:08 -0400
Subject: [PATCH 6/6] flash_info: punt in favor of mtdinfo
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307427548-29306-6-git-send-email-vapier@gentoo.org>

Now that the mtdinfo utility can do everything that flash_info
could do (and better), punt it.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 Makefile     |    2 +-
 flash_info.c |  141 ----------------------------------------------------------
 2 files changed, 1 insertions(+), 142 deletions(-)
 delete mode 100644 flash_info.c

diff --git a/Makefile b/Makefile
index 8bdba8e..0c8eb9f 100644
--- a/Makefile
+++ b/Makefile
@@ -16,7 +16,7 @@ SUBDIRS = lib ubi-utils mkfs.ubifs
 TESTS = tests
 
 TARGETS = ftl_format flash_erase nanddump doc_loadbios \
-	ftl_check mkfs.jffs2 flash_lock flash_unlock flash_info \
+	ftl_check mkfs.jffs2 flash_lock flash_unlock \
 	flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \
 	jffs2dump \
 	nftldump nftl_format docfdisk \
diff --git a/flash_info.c b/flash_info.c
deleted file mode 100644
index 0e056f3..0000000
--- a/flash_info.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * flash_info.c -- print info about a MTD device
- */
-
-#define PROGRAM_NAME "flash_info"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-
-#include "common.h"
-#include <mtd/mtd-user.h>
-
-static void usage(int status)
-{
-	fprintf(status ? stderr : stdout,
-		"Usage: %s <device> [devices]\n",
-		PROGRAM_NAME);
-	exit(status);
-}
-
-#define T(t) [MTD_##t] = #t
-static const char * const mtdtypes[] = {
-	T(ABSENT),
-	T(RAM),
-	T(ABSENT),
-	T(RAM),
-	T(ROM),
-	T(NORFLASH),
-	T(NANDFLASH),
-	T(DATAFLASH),
-	T(UBIVOLUME),
-};
-static const char *mtdtype(int type)
-{
-	if (type < ARRAY_SIZE(mtdtypes) && mtdtypes[type])
-		return mtdtypes[type];
-	return "UNKNOWN";
-}
-
-/* Show a pretty map of all the sectors on this device */
-static void show_sector_map(int fd, const region_info_t *reginfo)
-{
-	erase_info_t einfo;
-	int i, width;
-
-	printf(" sector map:\n");
-
-	einfo.length = reginfo->erasesize;
-	/* figure out the number of spaces to pad w/out libm */
-	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
-		continue;
-
-	for (i = 0; i < reginfo->numblocks; ++i) {
-		einfo.start = reginfo->offset + i * reginfo->erasesize;
-		printf(" %*i: %08x ", width, i, einfo.start);
-		if (ioctl(fd, MEMISLOCKED, &einfo))
-			printf("RO ");
-		else
-			printf("   ");
-		if (((i + 1) % 4) == 0)
-			printf("\n");
-	}
-	if (i % 4)
-		printf("\n");
-}
-
-int main(int argc, char *argv[])
-{
-	int fd, i, regcount;
-
-	if (argc < 2)
-		usage(1);
-	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
-		usage(0);
-
-	for (i = 1; i < argc; ++i) {
-		const char *dev = argv[i];
-		int r;
-		region_info_t reginfo;
-		mtd_info_t mtdinfo;
-
-		/* Open and size the device */
-		fd = open(dev, O_RDONLY);
-		if (fd < 0) {
-			sys_errmsg("could not open: %s", dev);
-			continue;
-		}
-
-		/* Print out general device info first */
-		if (ioctl(fd, MEMGETINFO, &mtdinfo)) {
-			sys_errmsg("could not get mtd info: %s", dev);
-			continue;
-		}
-
-		printf("%s: type: %i (%s)\n flags: %#x ( ",
-			dev, mtdinfo.type, mtdtype(mtdinfo.type), mtdinfo.flags);
-		if (mtdinfo.flags & MTD_POWERUP_LOCK)
-			printf("powerup_lock ");
-		if (mtdinfo.flags & MTD_NO_ERASE)
-			printf("no_erase ");
-		if (mtdinfo.flags & MTD_BIT_WRITEABLE)
-			printf("bit_writeable ");
-		if (mtdinfo.flags & MTD_WRITEABLE)
-			printf("writeable ");
-		printf(")\n sizes: total %#x write %#x erase %#x oob %#x\n",
-			mtdinfo.size, mtdinfo.writesize,
-			mtdinfo.erasesize, mtdinfo.oobsize);
-
-		/* Print out the region info (if the device has any) */
-		if (ioctl(fd, MEMGETREGIONCOUNT, &regcount) == 0) {
-			printf(" erase regions: %i\n", regcount);
-			for (r = 0; r < regcount; ++r) {
-				reginfo.regionindex = r;
-				if (ioctl(fd, MEMGETREGIONINFO, &reginfo) == 0) {
-					printf(" region %i: offset: %#x size: %#x numblocks: %#x\n",
-						r, reginfo.offset, reginfo.erasesize,
-						reginfo.numblocks);
-					show_sector_map(fd, &reginfo);
-				} else
-					warnmsg(" region %i: can not read region info!?", r);
-			}
-		} else
-			regcount = 0;
-
-		/* If the flash has no regions, then show the whole thing */
-		if (regcount == 0) {
-			reginfo.offset = 0;
-			reginfo.erasesize = mtdinfo.erasesize;
-			reginfo.numblocks = mtdinfo.size / mtdinfo.erasesize,
-			reginfo.regionindex = 0;
-			show_sector_map(fd, &reginfo);
-		}
-	}
-
-	return 0;
-}
-- 
1.7.5.3



From dedekind1 at gmail.com  Tue Jun  7 02:34:42 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 09:34:42 +0300
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307428482.11104.38.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> The external lzo dep can be a pain to deal with when cross-compiling,
> so make it optional for jffs2.  This is useful if people aren't even
> using the functionality, or for quicker development.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

How about mkfs.ubifs - it requires lzo as well. And then mkfs.jffs2
wants libacl which might be the same PITA.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 02:36:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 09:36:49 +0300
Subject: [PATCH 2/6] mtdinfo: send help/version info to stdout
In-Reply-To: <1307427548-29306-2-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-2-git-send-email-vapier@gentoo.org>
Message-ID: <1307428609.11104.39.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> Usage/version information should go to stdout when it is expected behavior
> (i.e. the user requested it explicitly).  This info should go to stderr
> only when the usage info is being shown as a result of incorrect options.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

This is fine, but all other ubi utils need this change then as well. I
think this piece of code was copypasted in all ubi-utils, so you should
easily find it and change.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 02:45:16 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 09:45:16 +0300
Subject: [PATCH 3/6] libmtd: use O_CLOEXEC
In-Reply-To: <1307427548-29306-3-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-3-git-send-email-vapier@gentoo.org>
Message-ID: <1307429116.11104.40.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> Not strictly necessary, but this is good library behavior and
> should carry no runtime overhead.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  include/common.h |    5 +++++
>  lib/libmtd.c     |   10 +++++-----
>  2 files changed, 10 insertions(+), 5 deletions(-)

Pushed this one, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 02:50:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 09:50:36 +0300
Subject: [PATCH 4/6] libmtd: add helper funcs for getting fds,
	regioninfo, and locked info
In-Reply-To: <1307427548-29306-4-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-4-git-send-email-vapier@gentoo.org>
Message-ID: <1307429436.11104.43.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote: 
> +int mtd_open_dev1(int mtd_num)
> +{
> +	char devpath[128];
> +	int fd;
> +
> +	sprintf(devpath, "/dev/mtd%i", mtd_num);
> +	fd = open(devpath, O_RDONLY | O_CLOEXEC);
> +	if (fd < 0)
> +		return sys_errmsg("cannot open \"%s\"", devpath);
> +

Could we avoid hard-coding device node names?

We indeed have -m option in mtdutils which opens a device by its number.
But I think it was a mistake. Generally, MTD devices can have any name,
it is up to udev configuration. So I'd rather deprecate and would
require a list of device node names.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Tue Jun  7 02:59:54 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 02:59:54 -0400
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
In-Reply-To: <1307428482.11104.38.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307428482.11104.38.camel@localhost>
Message-ID: <BANLkTi=A_TjJ4JwRQLjgTz217ZhR0eCHVQ@mail.gmail.com>

On Tue, Jun 7, 2011 at 02:34, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
>> The external lzo dep can be a pain to deal with when cross-compiling,
>> so make it optional for jffs2. ?This is useful if people aren't even
>> using the functionality, or for quicker development.
>
> How about mkfs.ubifs - it requires lzo as well. And then mkfs.jffs2
> wants libacl which might be the same PITA.

libacl already has a knob.  i didnt bother with mkfs.ubifs because it
additionally requires libuuid which comes from util-linux.  also, it
seemed like lzo is the only compression supported by UBI, so making it
optional didnt seem like it'd result in anything useful.  at least
jffs2 can operate without it by using other compression schemes.
-mike


From dedekind1 at gmail.com  Tue Jun  7 02:56:09 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 09:56:09 +0300
Subject: [PATCH 4/6] libmtd: add helper funcs for getting fds,
	regioninfo, and locked info
In-Reply-To: <1307429436.11104.43.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-4-git-send-email-vapier@gentoo.org>
	<1307429436.11104.43.camel@localhost>
Message-ID: <1307429769.11104.47.camel@localhost>

On Tue, 2011-06-07 at 09:50 +0300, Artem Bityutskiy wrote:
> We indeed have -m option in mtdutils which opens a device by its number.
> But I think it was a mistake. Generally, MTD devices can have any name,
> it is up to udev configuration. So I'd rather deprecate and would
> require a list of device node names.

Sorry, I was not clear. I wanted to say that supports -m and does
hard-code the mtd device name. But this was a mistake because it gives a
bad example, and adding more hard-coded names is bad.

So I think this option can be deprecated and removed, and we should only
accept full device node names.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From vapier at gentoo.org  Tue Jun  7 03:04:01 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 03:04:01 -0400
Subject: [PATCH 4/6] libmtd: add helper funcs for getting fds, regioninfo, 
	and locked info
In-Reply-To: <1307429769.11104.47.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-4-git-send-email-vapier@gentoo.org>
	<1307429436.11104.43.camel@localhost>
	<1307429769.11104.47.camel@localhost>
Message-ID: <BANLkTi=AaX1aSeHM5CLhh8XujKCUysWRhw@mail.gmail.com>

On Tue, Jun 7, 2011 at 02:56, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 09:50 +0300, Artem Bityutskiy wrote:
>> We indeed have -m option in mtdutils which opens a device by its number.
>> But I think it was a mistake. Generally, MTD devices can have any name,
>> it is up to udev configuration. So I'd rather deprecate and would
>> require a list of device node names.
>
> Sorry, I was not clear. I wanted to say that supports -m and does
> hard-code the mtd device name. But this was a mistake because it gives a
> bad example, and adding more hard-coded names is bad.
>
> So I think this option can be deprecated and removed, and we should only
> accept full device node names.

i only added this because mtdinfo has the -m option.  i have no
problem with punting that and going back to requiring people to
specify the path to the device nodes.  i'm off now though, so i'll get
to it tomorrow.
-mike


From dedekind1 at gmail.com  Tue Jun  7 03:16:19 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 10:16:19 +0300
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307430979.11104.50.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> +
> +#else
> +
> +int jffs2_lzo_init(void)
> +{
> +	return 0;
> +}

This function should return -1, I think, so that mkfs.jffs2 would fail
if lzo was not compiled-in.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 03:20:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 10:20:51 +0300
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
In-Reply-To: <BANLkTi=A_TjJ4JwRQLjgTz217ZhR0eCHVQ@mail.gmail.com>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307428482.11104.38.camel@localhost>
	<BANLkTi=A_TjJ4JwRQLjgTz217ZhR0eCHVQ@mail.gmail.com>
Message-ID: <1307431251.11104.55.camel@localhost>

On Tue, 2011-06-07 at 02:59 -0400, Mike Frysinger wrote:
> On Tue, Jun 7, 2011 at 02:34, Artem Bityutskiy wrote:
> > On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> >> The external lzo dep can be a pain to deal with when cross-compiling,
> >> so make it optional for jffs2.  This is useful if people aren't even
> >> using the functionality, or for quicker development.
> >
> > How about mkfs.ubifs - it requires lzo as well. And then mkfs.jffs2
> > wants libacl which might be the same PITA.
> 
> libacl already has a knob.

OK.

>   i didnt bother with mkfs.ubifs because it
> additionally requires libuuid which comes from util-linux.

Yeah. The only reason for this is that it wants to generate an UUID for
the new file-system. We could just use pseudo-random numbers as a
work-around.

>   also, it
> seemed like lzo is the only compression supported by UBI, so making it
> optional didnt seem like it'd result in anything useful.

Not really, UBIFS currently supports lzo, zlib, and no compression. But
lzo is the default.

>   at least
> jffs2 can operate without it by using other compression schemes.

UBIFS as well.

But please, do not bother with UBIFS if you do not need this. Just
verify that mkfs.jffs2 fails if you have not compiled lzo and try to use
it. I mean, mkfs.jffs2 should not silently use zlib in this case.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From grinberg at compulab.co.il  Tue Jun  7 03:26:27 2011
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Tue, 07 Jun 2011 10:26:27 +0300
Subject: [PATCH 1/2] mtd: nand: generalized error messages with __func__
In-Reply-To: <BANLkTi=BYeQ+cBMpRodDDY_KapjEoHVA+A@mail.gmail.com>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>	<4DDDE19D.9010505@compulab.co.il>	<1306387008.2785.138.camel@localhost>	<BANLkTimsTWAcR4HgOoHguDMv9P-Eox=kbg@mail.gmail.com>	<1306924235.4405.102.camel@localhost>
	<BANLkTi=BYeQ+cBMpRodDDY_KapjEoHVA+A@mail.gmail.com>
Message-ID: <4DEDD2A3.8030408@compulab.co.il>

On 06/01/11 21:37, Brian Norris wrote:

> On Wed, Jun 1, 2011 at 3:30 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>>> or should we define our own pr_fmt in include/linux/mtd.h?
>> Yes, before you include files.
> Well, I've tried this, and as I suspected, I can't just include it in
> mtd.h at the top, since we can't guarantee that <linux/mtd/mtd.h> is
> going to be the first included header in other files. Specifically, in
> include/linux/mtd/nand.h, we include other headers before mtd.h and so
> printk.h has already defined pr_fmt() for us, so this doesn't work.
> I'm not sure if there's a nice place to define pr_fmt() right now...

You should not define pr_fmt() in .h file.
pr_fmt() should be defined in _.c_ file at the top - _before any include is done_.
And yes, like Artem already said, _only_ in those _.c_ files where we want to use it.


-- 
Regards,
Igor.



From dedekind1 at gmail.com  Tue Jun  7 03:30:32 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 10:30:32 +0300
Subject: [PATCH 4/6] libmtd: add helper funcs for getting fds,
	regioninfo, and locked info
In-Reply-To: <BANLkTi=AaX1aSeHM5CLhh8XujKCUysWRhw@mail.gmail.com>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-4-git-send-email-vapier@gentoo.org>
	<1307429436.11104.43.camel@localhost>
	<1307429769.11104.47.camel@localhost>
	<BANLkTi=AaX1aSeHM5CLhh8XujKCUysWRhw@mail.gmail.com>
Message-ID: <1307431832.11104.57.camel@localhost>

On Tue, 2011-06-07 at 03:04 -0400, Mike Frysinger wrote:
> On Tue, Jun 7, 2011 at 02:56, Artem Bityutskiy wrote:
> > On Tue, 2011-06-07 at 09:50 +0300, Artem Bityutskiy wrote:
> >> We indeed have -m option in mtdutils which opens a device by its number.
> >> But I think it was a mistake. Generally, MTD devices can have any name,
> >> it is up to udev configuration. So I'd rather deprecate and would
> >> require a list of device node names.
> >
> > Sorry, I was not clear. I wanted to say that supports -m and does
> > hard-code the mtd device name. But this was a mistake because it gives a
> > bad example, and adding more hard-coded names is bad.
> >
> > So I think this option can be deprecated and removed, and we should only
> > accept full device node names.
> 
> i only added this because mtdinfo has the -m option.  i have no
> problem with punting that and going back to requiring people to
> specify the path to the device nodes.  i'm off now though, so i'll get
> to it tomorrow.

Thanks! I've just pushed the following patch which deprecates it:

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
Date: Tue, 7 Jun 2011 10:36:26 +0300
Subject: [PATCH] mtdinfo: deprecate the -m option

... because mtd device node name do not have to follow the "/dev/mtd%d"
pattern.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 feature-removal-schedule.txt |    9 +++++++--
 ubi-utils/src/mtdinfo.c      |    3 ++-
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index 30f0403..6e2bfc9 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -20,11 +20,16 @@ neither --squash-rino-perm nor --nosquash-rino-perm were used,
 mkfs.ubifs printed a warning. This was introduced in mtd-utils-1.4.0 (13 Sep 2010).
 
 Now we have removed a warning and made --nosquash-rino-perm to be the
-default. Also, both options are declared depricated, so users should try
+default. Also, both options are declared deprecated, so users should try
 to stop using them.
 
 The further step is to remove both of them.
 
 ---------------------------
-2.
+2. Kill -m parameter of mtdinfo
+
+We cannot assume that mtd device names follow the "/dev/mtd%d" pattern,
+because it is up to udev rules to name the devices. So we are removing
+the -m option. For now, we just have a warning, but the option will be
+removed in release 1.4.6.
 ---------------------------
diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index c9f6f58..820c16d 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -56,6 +56,7 @@ static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
 
 static const char optionsstr[] =
 "-m, --mtdn=<MTD device number>  MTD device number to get information about\n"
+"                                (deprecated option, will be removed, do not use)\n"
 "-u, --ubi-info                  print what would UBI layout be if it was put\n"
 "                                on this MTD device\n"
 "-a, --all                       print information about all MTD devices\n"
@@ -106,7 +107,7 @@ static int parse_opt(int argc, char * const argv[])
 			args.mtdn = simple_strtoul(optarg, &error);
 			if (error || args.mtdn < 0)
 				return errmsg("bad MTD device number: \"%s\"", optarg);
-
+			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
 			break;
 
 		case 'h':
-- 
1.7.2.3



-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 03:41:03 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 10:41:03 +0300
Subject: [PATCH 5/6] mtdinfo: add regioninfo/sectormap display
In-Reply-To: <1307427548-29306-5-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-5-git-send-email-vapier@gentoo.org>
Message-ID: <1307432463.11104.65.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> @@ -58,14 +60,15 @@ static const char optionsstr[] =
>  "-m, --mtdn=<MTD device number>  MTD device number to get information about\n"
>  "-u, --ubi-info                  print what would UBI layout be if it was put\n"
>  "                                on this MTD device\n"
> +"-s, --sector-map                print sector map\n"
>  "-a, --all                       print information about all MTD devices\n"
>  "-h, --help                      print help message\n"
>  "-V, --version                   print program version";
>  
>  static const char usage[] =
> -"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-h] [-V] [--mtdn <MTD device number>]\n"
> +"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-s] [-h] [-V] [--mtdn <MTD device number>]\n"
>  "\t\t[--ubi-info] [--help] [--version]\n"
> -"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-h] [-V] [--ubi-info] [--help]\n"
> +"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-s] [-h] [-V] [--ubi-info] [--help]\n"
>  "\t\t[--version]\n"
>  "Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
>  "Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
> @@ -78,6 +81,7 @@ static const char usage[] =
>  static const struct option long_options[] = {
>  	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
>  	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
> +	{ .name = "sector-map",.has_arg = 0, .flag = NULL, .val = 's' },

Is sector-map a good name? May be we should call this feature "lock
info" or something which suggests this is about detailed lock
information? In this case you should also print an error message if the
ISLOCKED ioctl is not supported. Probably adding a "islocked_supported"
flag to 'struct mtd_info' (similarly to sysfs_supported) makes sense?
Then you could just check this flag and refuse -s option?

Also, could we avoid using term sector because it is overloaded and
confusing. Could you please use term "eraseblock" instead (in prints and
in internal names)?

Or you meant that this is like general per-sector info? So if we have
more information to print, we add it there? In this case, could you
please print "bad" or something for bad eraseblocks as well?

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 03:43:11 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 10:43:11 +0300
Subject: [PATCH 6/6] flash_info: punt in favor of mtdinfo
In-Reply-To: <1307427548-29306-6-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-6-git-send-email-vapier@gentoo.org>
Message-ID: <1307432591.11104.67.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> Now that the mtdinfo utility can do everything that flash_info
> could do (and better), punt it.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  Makefile     |    2 +-
>  flash_info.c |  141 ----------------------------------------------------------
>  2 files changed, 1 insertions(+), 142 deletions(-)
>  delete mode 100644 flash_info.c

Let's give it some deprecation period. Would it be possible to add an
entry to feature-removal-schedule.txt instead, and print a warning in
flash_info that it will be removed in mtd-utils-1.4.6. So we'll let it
be in 1.4.5 with this warning. Then I'll remove it myself in 1.4.6.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From ffainelli at freebox.fr  Tue Jun  7 04:40:56 2011
From: ffainelli at freebox.fr (Florian Fainelli)
Date: Tue, 7 Jun 2011 10:40:56 +0200
Subject: [PATCH 2/6] mtdinfo: send help/version info to stdout
In-Reply-To: <1307427548-29306-2-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-2-git-send-email-vapier@gentoo.org>
Message-ID: <201106071040.56793.ffainelli@freebox.fr>

On Tuesday 07 June 2011 08:19:04 Mike Frysinger wrote:
> Usage/version information should go to stdout when it is expected behavior
> (i.e. the user requested it explicitly).  This info should go to stderr
> only when the usage info is being shown as a result of incorrect options.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  ubi-utils/src/mtdinfo.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
> index c9f6f58..f20fe49 100644
> --- a/ubi-utils/src/mtdinfo.c
> +++ b/ubi-utils/src/mtdinfo.c
> @@ -110,13 +110,13 @@ static int parse_opt(int argc, char * const argv[])
>  			break;
> 
>  		case 'h':
> -			fprintf(stderr, "%s\n\n", doc);
> -			fprintf(stderr, "%s\n\n", usage);
> -			fprintf(stderr, "%s\n", optionsstr);
> +			printf("%s\n\n", doc);
> +			printf("%s\n\n", usage);
> +			printf("%s\n", optionsstr);

Why not use fprintf(stdout ...), instead of printf()? to be consistent with was is existing?

>  			exit(EXIT_SUCCESS);
> 
>  		case 'V':
> -			fprintf(stderr, "%s\n", PROGRAM_VERSION);
> +			printf("%s\n", PROGRAM_VERSION);
>  			exit(EXIT_SUCCESS);
> 
>  		case ':':


From ricard.wanderlof at axis.com  Tue Jun  7 05:28:29 2011
From: ricard.wanderlof at axis.com (Ricard Wanderlof)
Date: Tue, 7 Jun 2011 11:28:29 +0200 (CEST)
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <1307374082.3112.78.camel@localhost>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
	<1307374082.3112.78.camel@localhost>
Message-ID: <Pine.LNX.4.64.1106071125260.8642@lnxricardw.se.axis.com>


On Mon, 6 Jun 2011, Artem Bityutskiy wrote:

> On Mon, 2011-06-06 at 15:50 +0200, Peter Wippich wrote:
> On writes in MODE_RAW the mtd_oob_ops struct is not sufficiently 
> initialized which may cause nandwrite to fail. With this patch
> it is possible to write raw nand/oob data without additional ECC
> (either for testing or when some sectors need different oob layout
> e.g. bootloader) like
> nandwrite  -n -r -o  /dev/mtd0 <myfile>
> 
> Signed-off-by: Peter Wippich <pewi at gw-instruments.de>

Looks good, thanks. We also need to add this patch to the stable tree.

Ricard, does it solve the issue you reported here

http://lists.infradead.org/pipermail/linux-mtd/2011-March/034516.html

Yes, it does, it seems to work beautifully. The error messages I reported 
in the post are gone, nandwrite reports success, and the resulting data in 
the flash appears to be ok. Thanks Peter for finding the root cause and 
the elegantly trivial patch.

Tested-by: Ricard Wanderlof <ricardw at axis.com>

/Ricard

> 
> diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
> index 3f92731..797a34a 100644
> --- a/drivers/mtd/mtdchar.c
> +++ b/drivers/mtd/mtdchar.c
> @@ -321,6 +321,7 @@ static ssize_t mtd_write(struct file *file, const char __user *buf, size_t count
>                          ops.datbuf = kbuf;
>                          ops.oobbuf = NULL;
>                          ops.len = len;
> +                       ops.ooboffs = 0;
>
>                          ret = mtd->write_oob(mtd, *ppos, &ops);
>                          retlen = ops.retlen;
>


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
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  Tue Jun  7 05:38:42 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 12:38:42 +0300
Subject: [PATCH 1/1] MTD mtdchar: add missing initializer on raw write
In-Reply-To: <Pine.LNX.4.64.1106071125260.8642@lnxricardw.se.axis.com>
References: <alpine.LSU.2.00.1106061541210.26001@redbean.intranet.gw-instruments.de>
	<1307374082.3112.78.camel@localhost>
	<Pine.LNX.4.64.1106071125260.8642@lnxricardw.se.axis.com>
Message-ID: <1307439522.11104.74.camel@localhost>

On Tue, 2011-06-07 at 11:28 +0200, Ricard Wanderlof wrote:
> Tested-by: Ricard Wanderlof <ricardw at axis.com>

Thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From roman.tereshonkov at nokia.com  Tue Jun  7 05:54:24 2011
From: roman.tereshonkov at nokia.com (roman.tereshonkov at nokia.com)
Date: Tue, 7 Jun 2011 09:54:24 +0000
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
Message-ID: <E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>

 

>-----Original Message-----
>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On 
>Behalf Of ext Kyungmin Park
>Sent: 07 June, 2011 02:56
>To: dedekind1 at gmail.com
>Cc: Tereshonkov Roman (Nokia-SD/Helsinki); 
>linux-mtd at lists.infradead.org; dwmw2 at infradead.org; 
>m.szyprowski at samsung.com
>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 
>4KiB pagesize
>
>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy 
><dedekind1 at gmail.com> wrote:
>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>> On Mon, 2011-06-06 at 09:42 +0000, 
>roman.tereshonkov at nokia.com wrote:
>>> > What do mean by "no case to use the subpage"?
>>> >
>>> > According to the spec KFM4G16Q4M-xEBx the Number of 
>Partial Program Cycles in the page (NOP)
>>> > is equal to 4 -> subpage_sft=2.
>
>It's really strange. Two OneNAND spec which has 4KiB pagesize 
>say it has 1 NOP.
>
>Number of Partial Program Cycles in the page (Including main and spare
>area) NOP - - 1 cycles
>(KFM4G16Q5M-xEBx)
>
>that's reason I first set subpage_sft = 0 at original code.
>
>The different thing between you and me is the page architecture
>number. yes 4 is the correct number but 5 also has the 4KiB pagesize.
>I think it's mean the manufacturing difference. can you check the
>which XXnm manufacturing for your devices?
>In our case. it's 3Xnm. and previous is 4Xnm.



It seems the spec does not specify the nm-technology used.

Can we somehow use the DeviceID and VersionID registers to differ
our chips?
For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.

BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.



>
>>>
>>> I thought this means "not supported by HW". But if this is 
>supported,
>>> then I'm very surprised why would we remove it. I'm 
>dropping this patch
>>> from my tree.
>>
>> OK, I actually did not put it to the l2 tree. And AFAICS this patch
>> basically reverts commit 
>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>> still leaves the data structures like onenand_oob_128.
>>
>> So NACK for this patch - poor commit message, weird changes. I'm
>> surprised to see this from kmpark.
>
>since we got some different OneNAND Spec. even though it has 
>same 4KiB pagesize.
>
>Thank you,
>Kyungmin Park
>>
>> --
>> Best Regards,
>> Artem Bityutskiy (????? ????????)
>>
>>
>

From leiwen at marvell.com  Tue Jun  7 06:01:07 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue,  7 Jun 2011 03:01:07 -0700
Subject: [PATCH 2/2] MTD: pxa3xx_nand: Fix blank page ECC mismatch
In-Reply-To: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
Message-ID: <1307440867-18993-2-git-send-email-leiwen@marvell.com>

From: Daniel Mack <zonque at gmail.com>

This bug was introduced in f8155a40 ("mtd: pxa3xx_nand: rework irq
logic") and causes the PXA3xx NAND controller fail to operate with NAND
flash that has empty pages. According to the comment in this block, the
hardware controller will report a double-bit error for empty pages,
which can and must be ignored.

This patch restores the original behaviour of the driver.

Signed-off-by: Daniel Mack <zonque at gmail.com>
Acked-by: Lei Wen <leiwen at marvell.com>
Cc: Haojian Zhuang <haojian.zhuang at marvell.com>
Cc: David Woodhouse <David.Woodhouse at intel.com>
Cc: stable at kernel.org
---
 drivers/mtd/nand/pxa3xx_nand.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index faa0edd..30689cc 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -685,6 +685,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		 * OOB, ignore such double bit errors
 		 */
 		if (is_buf_blank(buf, mtd->writesize))
+			info->retcode = ERR_NONE;
+		else
 			mtd->ecc_stats.failed++;
 	}
 
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun  7 06:01:06 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue,  7 Jun 2011 03:01:06 -0700
Subject: [PATCH 1/2] MTD: pxa3xx_nand: fix nand detection issue
Message-ID: <1307440867-18993-1-git-send-email-leiwen@marvell.com>

When keep_config is set, the detection would goes different routine.
That the driver would read out the setting which is set previously
by bootloader. While most bootloader keep the irq mask as off, and
current driver need all irq default open, keep_config behavior would
lead to no irq at all.

Signed-off-by: Lei Wen <leiwen at marvell.com>
Tested-by: Daniel Mack <zonque at gmail.com>
Cc: stable at kernel.org
---
 drivers/mtd/nand/pxa3xx_nand.c |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 1fb3b3a..faa0edd 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -813,7 +813,7 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
 	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
-	info->reg_ndcr = ndcr;
+	info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
 	info->cmdset = &default_cmdset;
 
 	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
@@ -882,7 +882,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	struct pxa3xx_nand_info *info = mtd->priv;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
-	struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} };
+	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
 	const struct pxa3xx_nand_flash *f = NULL;
 	struct nand_chip *chip = mtd->priv;
 	uint32_t id = -1;
@@ -942,8 +942,10 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
 	if (f->flash_width == 16)
 		pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
+	pxa3xx_flash_ids[1].name = NULL;
+	def = pxa3xx_flash_ids;
 KEEP_CONFIG:
-	if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+	if (nand_scan_ident(mtd, 1, def))
 		return -ENODEV;
 	/* calculate addressing information */
 	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
@@ -954,9 +956,9 @@ KEEP_CONFIG:
 		info->row_addr_cycles = 2;
 	mtd->name = mtd_names[0];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = f->page_size;
+	chip->ecc.size = info->page_size;
 
-	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
 	chip->options |= NAND_NO_AUTOINCR;
 	chip->options |= NAND_NO_READRDY;
 
-- 
1.7.0.4



From kmpark at infradead.org  Tue Jun  7 06:10:15 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Tue, 7 Jun 2011 19:10:15 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
Message-ID: <BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>

2011/6/7  <roman.tereshonkov at nokia.com>:
>
>
>>-----Original Message-----
>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>Behalf Of ext Kyungmin Park
>>Sent: 07 June, 2011 02:56
>>To: dedekind1 at gmail.com
>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>m.szyprowski at samsung.com
>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>4KiB pagesize
>>
>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>><dedekind1 at gmail.com> wrote:
>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>roman.tereshonkov at nokia.com wrote:
>>>> > What do mean by "no case to use the subpage"?
>>>> >
>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>Partial Program Cycles in the page (NOP)
>>>> > is equal to 4 -> subpage_sft=2.
>>
>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>say it has 1 NOP.
>>
>>Number of Partial Program Cycles in the page (Including main and spare
>>area) NOP - - 1 cycles
>>(KFM4G16Q5M-xEBx)
>>
>>that's reason I first set subpage_sft = 0 at original code.
>>
>>The different thing between you and me is the page architecture
>>number. yes 4 is the correct number but 5 also has the 4KiB pagesize.
>>I think it's mean the manufacturing difference. can you check the
>>which XXnm manufacturing for your devices?
>>In our case. it's 3Xnm. and previous is 4Xnm.
>
>
>
> It seems the spec does not specify the nm-technology used.
>
> Can we somehow use the DeviceID and VersionID registers to differ
> our chips?
> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>
> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.

Here's my device register values.
005000ec 0800013e 01010200 00000000
DeviceID=0x0050, VersionID=0x013e

The lower 4 bits of VersionID is different. even though VersionID is
different. it's dangerous to detect the NOP 4 or not.

I sent the email to OneNAND person and share the result soon. (he's on
business trip and return at June 9).

Thank you,
Kyungmin Park


>
>
>
>>
>>>>
>>>> I thought this means "not supported by HW". But if this is
>>supported,
>>>> then I'm very surprised why would we remove it. I'm
>>dropping this patch
>>>> from my tree.
>>>
>>> OK, I actually did not put it to the l2 tree. And AFAICS this patch
>>> basically reverts commit
>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>> still leaves the data structures like onenand_oob_128.
>>>
>>> So NACK for this patch - poor commit message, weird changes. I'm
>>> surprised to see this from kmpark.
>>
>>since we got some different OneNAND Spec. even though it has
>>same 4KiB pagesize.
>>
>>Thank you,
>>Kyungmin Park
>>>
>>> --
>>> Best Regards,
>>> Artem Bityutskiy (????? ????????)
>>>
>>>
>>


From dedekind1 at gmail.com  Tue Jun  7 06:24:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 13:24:14 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307389926-12209-1-git-send-email-mlcreech@gmail.com>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
Message-ID: <1307442254.11104.75.camel@localhost>

On Mon, 2011-06-06 at 15:52 -0400, Matthew L. Creech wrote:
> On Mon, Jun 6, 2011 at 12:18 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >
> > I have to go home now - could you please improve dbg_dump_leb().
> > Currently it calls ubifs_scan(), which scans, finds corrupted node,
> > prints corruption information and returns -EUCLEAN and destroys the
> > scanned data.
> >
> 
> Will something like this be okay?  Or do you still want to dump the
> partially-parsed data from the corrupt node as well (not just the raw contents
> of the LEB)?

Probably a temporary hack like this should work.

diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 37383e8..c709045 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -352,8 +352,9 @@ corrupted:
 		ubifs_err("LEB %d scanning failed", lnum);
 	}
 	err = -EUCLEAN;
-	ubifs_scan_destroy(sleb);
-	return ERR_PTR(err);
+//	ubifs_scan_destroy(sleb);
+//	return ERR_PTR(err);
+	return sleb;
 
 error:
 	ubifs_err("LEB %d scanning failed, error %d", lnum, err);

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dwmw2 at infradead.org  Tue Jun  7 06:55:28 2011
From: dwmw2 at infradead.org (David Woodhouse)
Date: Tue, 07 Jun 2011 11:55:28 +0100
Subject: l2-mtd-2.6.git to linux-next
In-Reply-To: <1307421615.11104.14.camel@localhost>
References: <1307345850.3135.24.camel@localhost>
	<1307421615.11104.14.camel@localhost>
Message-ID: <1307444129.24181.33.camel@i7.infradead.org>

On Tue, 2011-06-07 at 07:40 +0300, Artem Bityutskiy wrote:
> David,
> 
> On Mon, 2011-06-06 at 10:37 +0300, Artem Bityutskiy wrote:
> > Stephen,
> > 
> > as we've discussed, please, include l2-mtd-2.6.git tree to linux-next:
> > 
> > git://git.infradead.org/users/dedekind/l2-mtd-2.6.git master
> 
> although you already asked about this, sfr wanted your deliberate ack.

Ack.

Thanks.

-- 
dwmw2



From dedekind1 at gmail.com  Tue Jun  7 07:06:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 14:06:47 +0300
Subject: [PATCH v2] nand: nand_base: Always initialise oob_poi before
	writing OOB data
In-Reply-To: <E14CAA9D00C5044EACE0C59FC2A1C7F5059A95632E@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059A8DF591@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1306396908.2785.152.camel@localhost>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059A95632E@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
Message-ID: <1307444807.11104.76.camel@localhost>

On Thu, 2011-05-26 at 17:15 +0200, THOMSON, Adam (Adam) wrote:
> Having looked briefly at the read side code in nand_base.c,
> it does look like it should be enough to remove the second
> memset and leave the read side code as is, but will examine
> it more thoroughly before I post a patch.

Any news? :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 07:07:19 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 14:07:19 +0300
Subject: Setting security XATTR on ubifs
In-Reply-To: <1306746744.4405.22.camel@localhost>
References: <1305934601.10340.12.camel@subodh-desktop>
	<1306162677.2785.30.camel@localhost>
	<C7A5B00EFC707A46AB67997D02152167010F582C@mx1.grid-net.com>
	<1306746744.4405.22.camel@localhost>
Message-ID: <1307444839.11104.77.camel@localhost>

On Mon, 2011-05-30 at 12:12 +0300, Artem Bityutskiy wrote:
> Could you please submit a separate patch for this with
> 
> Cc: stable at kernel.org

Hi, should I expect a patch?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 07:16:35 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 14:16:35 +0300
Subject: [PATCH 1/2] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
Message-ID: <1307445395.11104.78.camel@localhost>

On Tue, 2011-06-07 at 03:01 -0700, Lei Wen wrote:
> When keep_config is set, the detection would goes different routine.
> That the driver would read out the setting which is set previously
> by bootloader. While most bootloader keep the irq mask as off, and
> current driver need all irq default open, keep_config behavior would
> lead to no irq at all.
> 
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Tested-by: Daniel Mack <zonque at gmail.com>
> Cc: stable at kernel.org

When the regression was introduced? Commit id?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 07:17:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 14:17:47 +0300
Subject: [PATCH 2/2] MTD: pxa3xx_nand: Fix blank page ECC mismatch
In-Reply-To: <1307440867-18993-2-git-send-email-leiwen@marvell.com>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
	<1307440867-18993-2-git-send-email-leiwen@marvell.com>
Message-ID: <1307445467.11104.80.camel@localhost>

On Tue, 2011-06-07 at 03:01 -0700, Lei Wen wrote:
> From: Daniel Mack <zonque at gmail.com>
> 
> This bug was introduced in f8155a40 ("mtd: pxa3xx_nand: rework irq
> logic") and causes the PXA3xx NAND controller fail to operate with NAND
> flash that has empty pages. According to the comment in this block, the
> hardware controller will report a double-bit error for empty pages,
> which can and must be ignored.
> 
> This patch restores the original behaviour of the driver.
> 
> Signed-off-by: Daniel Mack <zonque at gmail.com>
> Acked-by: Lei Wen <leiwen at marvell.com>
> Cc: Haojian Zhuang <haojian.zhuang at marvell.com>
> Cc: David Woodhouse <David.Woodhouse at intel.com>
> Cc: stable at kernel.org

This was introduced in 2.6.38, so let's make it:

Cc: stable at kernel.org [2.6.38+]

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From adrian.wenl at gmail.com  Tue Jun  7 08:27:07 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Tue, 7 Jun 2011 20:27:07 +0800
Subject: [PATCH 1/2] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <1307445395.11104.78.camel@localhost>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
	<1307445395.11104.78.camel@localhost>
Message-ID: <BANLkTin7yd3YL9sPAV+4YfDzQqSe5=NBFA@mail.gmail.com>

Hi Artem,

On Tue, Jun 7, 2011 at 7:16 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-07 at 03:01 -0700, Lei Wen wrote:
>> When keep_config is set, the detection would goes different routine.
>> That the driver would read out the setting which is set previously
>> by bootloader. While most bootloader keep the irq mask as off, and
>> current driver need all irq default open, keep_config behavior would
>> lead to no irq at all.
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> Tested-by: Daniel Mack <zonque at gmail.com>
>> Cc: stable at kernel.org
>
> When the regression was introduced? Commit id?

This regression should be introduced by below commit:

commit f8155a404db95656f1519b28fdb96cb68f8b2364
Author: Lei Wen <leiwen at marvell.com>
Date:   Mon Feb 28 10:32:11 2011 +0800

    mtd: pxa3xx_nand: rework irq logic

So its should be:
Cc: stable at kernel.org [2.6.38+]

Best regards,
Lei


From adrian.wenl at gmail.com  Tue Jun  7 08:28:17 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Tue, 7 Jun 2011 20:28:17 +0800
Subject: [PATCH 2/2] MTD: pxa3xx_nand: Fix blank page ECC mismatch
In-Reply-To: <1307445467.11104.80.camel@localhost>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
	<1307440867-18993-2-git-send-email-leiwen@marvell.com>
	<1307445467.11104.80.camel@localhost>
Message-ID: <BANLkTin_Z8ndAjp9vw6QcNb5bT82uoR9ng@mail.gmail.com>

On Tue, Jun 7, 2011 at 7:17 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-07 at 03:01 -0700, Lei Wen wrote:
>> From: Daniel Mack <zonque at gmail.com>
>>
>> This bug was introduced in f8155a40 ("mtd: pxa3xx_nand: rework irq
>> logic") and causes the PXA3xx NAND controller fail to operate with NAND
>> flash that has empty pages. According to the comment in this block, the
>> hardware controller will report a double-bit error for empty pages,
>> which can and must be ignored.
>>
>> This patch restores the original behaviour of the driver.
>>
>> Signed-off-by: Daniel Mack <zonque at gmail.com>
>> Acked-by: Lei Wen <leiwen at marvell.com>
>> Cc: Haojian Zhuang <haojian.zhuang at marvell.com>
>> Cc: David Woodhouse <David.Woodhouse at intel.com>
>> Cc: stable at kernel.org
>
> This was introduced in 2.6.38, so let's make it:
>
> Cc: stable at kernel.org [2.6.38+]
>
Thanks for correcting this.

Best regards,
Lei


From dedekind1 at gmail.com  Tue Jun  7 08:33:30 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 15:33:30 +0300
Subject: [PATCH 1/2] MTD: pxa3xx_nand: fix nand detection issue
In-Reply-To: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
Message-ID: <1307450010.11104.81.camel@localhost>

On Tue, 2011-06-07 at 03:01 -0700, Lei Wen wrote:
> When keep_config is set, the detection would goes different routine.
> That the driver would read out the setting which is set previously
> by bootloader. While most bootloader keep the irq mask as off, and
> current driver need all irq default open, keep_config behavior would
> lead to no irq at all.
> 
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> Tested-by: Daniel Mack <zonque at gmail.com>
> Cc: stable at kernel.org

Pushed both patches to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Tue Jun  7 09:00:30 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 07 Jun 2011 16:00:30 +0300
Subject: [PATCH v2] nand: nand_base: Always initialise oob_poi before
	writing OOB data
In-Reply-To: <E14CAA9D00C5044EACE0C59FC2A1C7F5059A9CEE2C@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059A8DF591@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1306396908.2785.152.camel@localhost>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059A95632E@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1307444807.11104.76.camel@localhost>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059A9CEE2C@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
Message-ID: <1307451630.11104.82.camel@localhost>

On Tue, 2011-06-07 at 15:00 +0200, THOMSON, Adam (Adam) wrote:
> Apologies. Have been sidetracked with other work. Have put changes
> together but want to check them over just so I'm happy, in particular
> verifying them on some hardware to make sure all still works as
> expected. Hopefully should have something in the next week for
> you. :o)

OK, thanks, although next week I'll be busy and sidetracked :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From adam.thomson at alcatel-lucent.com  Tue Jun  7 09:00:18 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Tue, 7 Jun 2011 15:00:18 +0200
Subject: [PATCH v2] nand: nand_base: Always initialise oob_poi before
	writing OOB data
In-Reply-To: <1307444807.11104.76.camel@localhost>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059A8DF591@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1306396908.2785.152.camel@localhost>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059A95632E@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1307444807.11104.76.camel@localhost>
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059A9CEE2C@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

> -----Original Message-----
> From: Artem Bityutskiy [mailto:dedekind1 at gmail.com] 
> Sent: 07 June 2011 12:07
> To: THOMSON, Adam (Adam)
> Cc: linux-mtd at lists.infradead.org
> Subject: RE: [PATCH v2] nand: nand_base: Always initialise 
> oob_poi before writing OOB data
> 
> On Thu, 2011-05-26 at 17:15 +0200, THOMSON, Adam (Adam) wrote:
> > Having looked briefly at the read side code in nand_base.c, it does 
> > look like it should be enough to remove the second memset and leave 
> > the read side code as is, but will examine it more 
> thoroughly before I 
> > post a patch.
> 
> Any news? :-)

Apologies. Have been sidetracked with other work. Have put changes together but want to check them over just so I'm happy, in particular verifying them on some hardware to make sure all still works as expected. Hopefully should have something in the next week for you. :o)

Thanks

Adam

> 
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
> 
> 

From dbaryshkov at gmail.com  Tue Jun  7 09:36:00 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:00 +0400
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>

Lots (nearly all) mtd drivers contain nearly the similar code that
calls parse_mtd_partitions, provides some platform-default values, if
parsing fails, and registers  mtd device.

This is an aim to provide single implementation of this scenario:
mtd_device_parse_register() which will handle all this parsing and
defaults.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c   |   30 ++++++++++++++++++++++++++++++
 include/linux/mtd/mtd.h |    5 +++++
 2 files changed, 35 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c510aff..ac871ad 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -451,6 +451,36 @@ int mtd_device_register(struct mtd_info *master,
 }
 EXPORT_SYMBOL_GPL(mtd_device_register);
 
+int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts)
+{
+	int err;
+	struct mtd_partition *parts;
+
+	err = parse_mtd_partitions(mtd, part_probe_types, &parts, origin);
+	if (err <= 0 && defnr_parts) {
+		unsigned long size = sizeof(*parts) * defnr_parts;
+		err = defnr_parts;
+		parts = kzalloc(size, GFP_KERNEL);
+		memcpy(parts, defparts, size);
+	}
+
+	if (err > 0) {
+		err = add_mtd_partitions(mtd, parts, err);
+		kfree(parts);
+	} else {
+		err = add_mtd_device(mtd);
+		if (err == 1)
+			err = -ENODEV;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(mtd_device_parse_register);
+
 /**
  * mtd_device_unregister - unregister an existing MTD device.
  *
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 2541fb8..d28a241 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -327,6 +327,11 @@ struct mtd_partition;
 extern int mtd_device_register(struct mtd_info *master,
 			       const struct mtd_partition *parts,
 			       int nr_parts);
+extern int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts);
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:35:59 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:35:59 +0400
Subject: [PATCH 00/44] Cleanup of parse/register scenario
Message-ID: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>

Lots of mtd drivers have more or less the same common logic:
parse partitions, then register them. Currently this ends up
with lots of code duplication, each copy having it's own features
and bugs. In this patch serie I create a special function
(mtd_device_parse_register) which handles all issues with acquiring
partition information, registering mtd device(s) and returning correct
error code.

The following changes since commit 85bd7e882840f4cb4d213768d252c754f22440ac:

  mtd: pxa3xx_nand: Fix blank page ECC mismatch (2011-06-07 15:40:29 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-parse-1st

Dmitry Eremin-Solenikov (44):
      mtd: add new API for handling MTD registration
      mtd: lart.c: use mtd_device_parse_register
      mtd: mtd_dataflash.c: use mtd_device_parse_register
      mtd: sst25l.c: use mtd_device_parse_register
      mtd: bfin-async-flash.c: use mtd_device_parse_register
      mtd: dc21285.c: use mtd_device_parse_register
      mtd: gpio-addr-flash.c: use mtd_device_parse_register
      mtd: h720x-flash.c: use mtd_device_parse_register
      mtd: impa7.c: use mtd_device_parse_register
      mtd: intel_vr_nor.c: use mtd_device_parse_register
      mtd: ixp2000.c: use mtd_device_parse_register
      mtd: ixp4xx.c: use mtd_device_parse_register
      mtd: lantiq-flash.c: use mtd_device_parse_register
      mtd: latch-addr-flash.c: use mtd_device_parse_register
      mtd: physmap.c: use mtd_device_parse_register
      mtd: plat-ram.c: use mtd_device_parse_register
      mtd: pxa2xx-flash.c: use mtd_device_parse_register
      mtd: rbtx4939-flash.c: use mtd_device_parse_register
      mtd: sa1100-flash.c: use mtd_device_parse_register
      mtd: solutionengine.c: use mtd_device_parse_register
      mtd: wr_sbc82xx_flash.c: use mtd_device_parse_register
      mtd: atmel_nand.c: use mtd_device_parse_register
      mtd: bcm_umi_nand.c: use mtd_device_parse_register
      mtd: cafe_nand.c: use mtd_device_parse_register
      mtd: cmx270_nand.c: use mtd_device_parse_register
      mtd: cs553x_nand.c: use mtd_device_parse_register
      mtd: davinci_nand.c: use mtd_device_parse_register
      mtd: edb7312.c: use mtd_device_parse_register
      mtd: fsmc_nand.c: use mtd_device_parse_register
      mtd: h1910.c: use mtd_device_parse_register
      mtd: jz4740_nand.c: use mtd_device_parse_register
      mtd: mxc_nand.c: use mtd_device_parse_register
      mtd: omap2.c: use mtd_device_parse_register
      mtd: orion_nand.c: use mtd_device_parse_register
      mtd: plat_nand.c: use mtd_device_parse_register
      mtd: ppchameleonevb.c: use mtd_device_parse_register
      mtd: pxa3xx_nand.c: use mtd_device_parse_register
      mtd: s3c2410.c: use mtd_device_parse_register
      mtd: sharpsl.c: use mtd_device_parse_register
      mtd: tmio_nand.c: use mtd_device_parse_register
      mtd: txx9ndfmc.c: use mtd_device_parse_register
      mtd: onenand/generic.c: use mtd_device_parse_register
      mtd: onenand/omap2.c: use mtd_device_parse_register
      mtd: onenand/samsung.c: use mtd_device_parse_register

 drivers/mtd/devices/lart.c          |   12 ++----
 drivers/mtd/devices/mtd_dataflash.c |   21 ++---------
 drivers/mtd/devices/sst25l.c        |   32 ++---------------
 drivers/mtd/maps/bfin-async-flash.c |   16 +-------
 drivers/mtd/maps/dc21285.c          |    9 +----
 drivers/mtd/maps/gpio-addr-flash.c  |   16 +-------
 drivers/mtd/maps/h720x-flash.c      |   21 +----------
 drivers/mtd/maps/impa7.c            |   25 ++-----------
 drivers/mtd/maps/intel_vr_nor.c     |    6 +---
 drivers/mtd/maps/ixp2000.c          |   11 +-----
 drivers/mtd/maps/ixp4xx.c           |   29 ++-------------
 drivers/mtd/maps/lantiq-flash.c     |   14 +------
 drivers/mtd/maps/latch-addr-flash.c |   21 +----------
 drivers/mtd/maps/physmap.c          |   23 +-----------
 drivers/mtd/maps/plat-ram.c         |   23 +-----------
 drivers/mtd/maps/pxa2xx-flash.c     |   20 +----------
 drivers/mtd/maps/rbtx4939-flash.c   |   18 +--------
 drivers/mtd/maps/sa1100-flash.c     |   30 ++--------------
 drivers/mtd/maps/solutionengine.c   |   30 ++++------------
 drivers/mtd/maps/wr_sbc82xx_flash.c |   30 ++++++----------
 drivers/mtd/mtdcore.c               |   30 ++++++++++++++++
 drivers/mtd/nand/atmel_nand.c       |   19 +---------
 drivers/mtd/nand/bcm_umi_nand.c     |   19 +---------
 drivers/mtd/nand/cafe_nand.c        |   11 +-----
 drivers/mtd/nand/cmx270_nand.c      |   20 +---------
 drivers/mtd/nand/cs553x_nand.c      |    7 +---
 drivers/mtd/nand/davinci_nand.c     |   25 +------------
 drivers/mtd/nand/edb7312.c          |   17 +--------
 drivers/mtd/nand/fsmc_nand.c        |   66 +++++------------------------------
 drivers/mtd/nand/h1910.c            |   15 +-------
 drivers/mtd/nand/jz4740_nand.c      |   11 ++----
 drivers/mtd/nand/mxc_nand.c         |   15 ++------
 drivers/mtd/nand/omap2.c            |   10 +----
 drivers/mtd/nand/orion_nand.c       |   12 +-----
 drivers/mtd/nand/plat_nand.c        |   22 ++----------
 drivers/mtd/nand/ppchameleonevb.c   |   42 +++++-----------------
 drivers/mtd/nand/pxa3xx_nand.c      |   11 +-----
 drivers/mtd/nand/s3c2410.c          |   18 ++-------
 drivers/mtd/nand/sharpsl.c          |   11 +-----
 drivers/mtd/nand/tmio_nand.c        |   12 ++-----
 drivers/mtd/nand/txx9ndfmc.c        |    7 +---
 drivers/mtd/onenand/generic.c       |   11 ++----
 drivers/mtd/onenand/omap2.c         |   13 ++-----
 drivers/mtd/onenand/samsung.c       |   11 ++----
 include/linux/mtd/mtd.h             |    5 +++
 45 files changed, 163 insertions(+), 684 deletions(-)




From dbaryshkov at gmail.com  Tue Jun  7 09:36:02 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:02 +0400
Subject: [PATCH 03/44] mtd: mtd_dataflash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-4-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/mtd_dataflash.c |   21 +++------------------
 1 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 4d4a9cd..8f6b02c 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -637,8 +637,6 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	char				*otp_tag = "";
 	int				err = 0;
-	struct mtd_partition		*parts;
-	int				nr_parts = 0;
 
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
@@ -677,23 +675,10 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 			pagesize, otp_tag);
 	dev_set_drvdata(&spi->dev, priv);
 
-	nr_parts = parse_mtd_partitions(device, NULL, &parts, 0);
+	err = mtd_device_parse_register(device, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
-	if (nr_parts <= 0 && pdata && pdata->parts) {
-		parts = pdata->parts;
-		nr_parts = pdata->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		priv->partitioned = 1;
-		err = mtd_device_register(device, parts, nr_parts);
-		goto out;
-	}
-
-	if (mtd_device_register(device, NULL, 0) == 1)
-		err = -ENODEV;
-
-out:
 	if (!err)
 		return 0;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:01 +0400
Subject: [PATCH 02/44] mtd: lart.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-3-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/lart.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 772a0ff..48b513f 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -619,6 +619,10 @@ static struct mtd_partition lart_partitions[] = {
 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
 	}
 };
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
+#else
+#define lart_partitions NULL
+#define NUM_PARTITIONS 0
 #endif
 
 static int __init lart_flash_init (void)
@@ -683,23 +687,15 @@ static int __init lart_flash_init (void)
 #endif
 #endif
 
-#ifndef HAVE_PARTITIONS
-   result = mtd_device_register(&mtd, NULL, 0);
-#else
    result = mtd_device_register(&mtd, lart_partitions,
                                 ARRAY_SIZE(lart_partitions));
-#endif
 
    return (result);
 }
 
 static void __exit lart_flash_exit (void)
 {
-#ifndef HAVE_PARTITIONS
    mtd_device_unregister(&mtd);
-#else
-   mtd_device_unregister(&mtd);
-#endif
 }
 
 module_init (lart_flash_init);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:03 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:03 +0400
Subject: [PATCH 04/44] mtd: sst25l.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-5-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/sst25l.c |   32 ++++----------------------------
 1 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index cd095af..faa9d3b 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -53,7 +53,6 @@ struct sst25l_flash {
 	struct mutex		lock;
 	struct mtd_info		mtd;
 
-	int 			partitioned;
 };
 
 struct flash_info {
@@ -381,8 +380,6 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	struct sst25l_flash *flash;
 	struct flash_platform_data *data;
 	int ret, i;
-	struct mtd_partition *parts = NULL;
-	int nr_parts = 0;
 
 	flash_info = sst25l_match_device(spi);
 	if (!flash_info)
@@ -423,31 +420,10 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	      flash->mtd.numeraseregions);
 
 
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-
-		flash->partitioned = 1;
-		return mtd_device_register(&flash->mtd, parts,
-					   nr_parts);
-	}
-
-	ret = mtd_device_register(&flash->mtd, NULL, 0);
-	if (ret == 1) {
+	ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
+	if (ret) {
 		kfree(flash);
 		dev_set_drvdata(&spi->dev, NULL);
 		return -ENODEV;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:04 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:04 +0400
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/bfin-async-flash.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index d4297a9..246890e 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -41,7 +41,6 @@ struct async_state {
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	unsigned long irq_flags;
-	struct mtd_partition *parts;
 };
 
 static void switch_to_flash(struct async_state *state)
@@ -165,18 +164,8 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
-	if (ret > 0) {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
-		mtd_device_register(state->mtd, pdata->parts, ret);
-		state->parts = pdata->parts;
-	} else if (pdata->nr_parts) {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
-		mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
-	} else {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
-		mtd_device_register(state->mtd, NULL, 0);
-	}
+	mtd_device_parse_register(state->mtd, part_probe_types, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, state);
 
@@ -188,7 +177,6 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
 	struct async_state *state = platform_get_drvdata(pdev);
 	gpio_free(state->enet_flash_pin);
 	mtd_device_unregister(state->mtd);
-	kfree(state->parts);
 	map_destroy(state->mtd);
 	kfree(state);
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:06 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:06 +0400
Subject: [PATCH 07/44] mtd: gpio-addr-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-8-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/gpio-addr-flash.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 7568c5f..1ec66f0 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -187,7 +187,6 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
  */
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 {
-	int nr_parts;
 	size_t i, arr_size;
 	struct physmap_flash_data *pdata;
 	struct resource *memory;
@@ -252,20 +251,9 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	nr_parts = parse_mtd_partitions(state->mtd, part_probe_types,
-					&pdata->parts, 0);
-	if (nr_parts > 0) {
-		pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
-		kfree(pdata->parts);
-	} else if (pdata->nr_parts) {
-		pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
-		nr_parts = pdata->nr_parts;
-	} else {
-		pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
-		nr_parts = 0;
-	}
 
-	mtd_device_register(state->mtd, pdata->parts, nr_parts);
+	mtd_device_parse_register(state->mtd, part_probe_types, 0,
+			pdata->parts, pdata->nr_parts);
 
 	return 0;
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:05 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:05 +0400
Subject: [PATCH 06/44] mtd: dc21285.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-7-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/dc21285.c |    9 +--------
 1 files changed, 1 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 7a9e198..f43b365 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -145,14 +145,10 @@ static struct map_info dc21285_map = {
 
 
 /* Partition stuff */
-static struct mtd_partition *dc21285_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int __init init_dc21285(void)
 {
-
-	int nrparts;
-
 	/* Determine bankwidth */
 	switch (*CSR_SA110_CNTL & (3<<14)) {
 		case SA110_CNTL_ROMWIDTH_8:
@@ -200,8 +196,7 @@ static int __init init_dc21285(void)
 
 	dc21285_mtd->owner = THIS_MODULE;
 
-	nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
-	mtd_device_register(dc21285_mtd, dc21285_parts, nrparts);
+	mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0);
 
 	if(machine_is_ebsa285()) {
 		/*
@@ -224,8 +219,6 @@ static int __init init_dc21285(void)
 static void __exit cleanup_dc21285(void)
 {
 	mtd_device_unregister(dc21285_mtd);
-	if (dc21285_parts)
-		kfree(dc21285_parts);
 	map_destroy(dc21285_mtd);
 	iounmap(dc21285_map.virt);
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:07 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:07 +0400
Subject: [PATCH 08/44] mtd: h720x-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-9-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/h720x-flash.c |   21 ++-------------------
 1 files changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index f331a2c..49c1418 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -58,16 +58,11 @@ static struct mtd_partition h720x_partitions[] = {
 
 #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
 
-static int                   nr_mtd_parts;
-static struct mtd_partition *mtd_parts;
 /*
  * Initialize FLASH support
  */
 static int __init h720x_mtd_init(void)
 {
-
-	char	*part_type = NULL;
-
 	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
 
 	if (!h720x_map.virt) {
@@ -90,16 +85,8 @@ static int __init h720x_mtd_init(void)
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-		nr_mtd_parts = parse_mtd_partitions(mymtd, NULL, &mtd_parts, 0);
-		if (nr_mtd_parts > 0)
-			part_type = "command line";
-		if (nr_mtd_parts <= 0) {
-			mtd_parts = h720x_partitions;
-			nr_mtd_parts = NUM_PARTITIONS;
-			part_type = "builtin";
-		}
-		printk(KERN_INFO "Using %s partition table\n", part_type);
-		mtd_device_register(mymtd, mtd_parts, nr_mtd_parts);
+		mtd_device_parse_register(mymtd, NULL, 0,
+				h720x_partitions, NUM_PARTITIONS);
 		return 0;
 	}
 
@@ -118,10 +105,6 @@ static void __exit h720x_mtd_cleanup(void)
 		map_destroy(mymtd);
 	}
 
-	/* Free partition info, if commandline partition was used */
-	if (mtd_parts && (mtd_parts != h720x_partitions))
-		kfree (mtd_parts);
-
 	if (h720x_map.virt) {
 		iounmap((void *)h720x_map.virt);
 		h720x_map.virt = 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:08 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:08 +0400
Subject: [PATCH 09/44] mtd: impa7.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-10-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/impa7.c |   25 +++----------------------
 1 files changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index 2d45a48..7b8b5d8 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -58,15 +58,10 @@ static struct mtd_partition static_partitions[] =
 	},
 };
 
-static int mtd_parts_nb[NUM_FLASHBANKS];
-static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
-
-
 static int __init init_impa7(void)
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -96,23 +91,9 @@ static int __init init_impa7(void)
 		if (impa7_mtd[i]) {
 			impa7_mtd[i]->owner = THIS_MODULE;
 			devicesfound++;
-			mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
-							       NULL,
-							       &mtd_parts[i],
-							       0);
-			if (mtd_parts_nb[i] > 0) {
-				part_type = "command line";
-			} else {
-				mtd_parts[i] = static_partitions;
-				mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
-				part_type = "static";
-			}
-
-			printk(KERN_NOTICE MSG_PREFIX
-			       "using %s partition definition\n",
-			       part_type);
-			mtd_device_register(impa7_mtd[i],
-					    mtd_parts[i], mtd_parts_nb[i]);
+			mtd_device_parse_register(impa7_mtd[i], NULL, 0,
+					static_partitions,
+					ARRAY_SIZE(static_partitions));
 		}
 		else
 			iounmap((void *)impa7_map[i].virt);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:09 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:09 +0400
Subject: [PATCH 10/44] mtd: intel_vr_nor.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-11-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/intel_vr_nor.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index fd612c7..08c2396 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -44,7 +44,6 @@ struct vr_nor_mtd {
 	void __iomem *csr_base;
 	struct map_info map;
 	struct mtd_info *info;
-	int nr_parts;
 	struct pci_dev *dev;
 };
 
@@ -71,12 +70,9 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
 
 static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
-	struct mtd_partition *parts;
-
 	/* register the flash bank */
 	/* partition the flash bank */
-	p->nr_parts = parse_mtd_partitions(p->info, NULL, &parts, 0);
-	return mtd_device_register(p->info, parts, p->nr_parts);
+	return mtd_device_parse_register(p->info, NULL, 0, NULL, 0);
 }
 
 static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:10 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:10 +0400
Subject: [PATCH 11/44] mtd: ixp2000.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-12-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/ixp2000.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index c00b917..93bf83d 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -38,7 +38,6 @@
 struct ixp2000_flash_info {
 	struct		mtd_info *mtd;
 	struct		map_info map;
-	struct		mtd_partition *partitions;
 	struct		resource *res;
 };
 
@@ -125,8 +124,6 @@ static int ixp2000_flash_remove(struct platform_device *dev)
 	if (info->map.map_priv_1)
 		iounmap((void *) info->map.map_priv_1);
 
-	kfree(info->partitions);
-
 	if (info->res) {
 		release_resource(info->res);
 		kfree(info->res);
@@ -228,13 +225,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
-	if (err > 0) {
-		err = mtd_device_register(info->mtd, info->partitions, err);
-		if(err)
-			dev_err(&dev->dev, "Could not parse partitions\n");
-	}
-
+	err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
 	if (err)
 		goto Error;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:11 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:11 +0400
Subject: [PATCH 12/44] mtd: ixp4xx.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-13-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/ixp4xx.c |   29 ++++-------------------------
 1 files changed, 4 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 155b219..3040901 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -145,7 +145,6 @@ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 struct ixp4xx_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-	struct mtd_partition *partitions;
 	struct resource *res;
 };
 
@@ -168,8 +167,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
 	if (info->map.virt)
 		iounmap(info->map.virt);
 
-	kfree(info->partitions);
-
 	if (info->res) {
 		release_resource(info->res);
 		kfree(info->res);
@@ -185,8 +182,6 @@ 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)
@@ -252,28 +247,12 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	/* Use the fast version */
 	info->map.write = ixp4xx_write16;
 
-	nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
-					dev->resource->start);
-	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");
-	else
-		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
-			"definition\n", part_type);
-
-	err = mtd_device_register(info->mtd, info->partitions, nr_parts);
-	if (err)
+	err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
+			plat->parts, plat->nr_parts);
+	if (err) {
 		printk(KERN_ERR "Could not parse partitions\n");
-
-	if (err)
 		goto Error;
+	}
 
 	return 0;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:12 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:12 +0400
Subject: [PATCH 13/44] mtd: lantiq-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-14-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/lantiq-flash.c |   14 ++------------
 1 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index 57ea3fe..f750784 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -112,9 +112,7 @@ ltq_mtd_probe(struct platform_device *pdev)
 {
 	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
 	struct ltq_mtd *ltq_mtd;
-	struct mtd_partition *parts;
 	struct resource *res;
-	int nr_parts = 0;
 	struct cfi_private *cfi;
 	int err;
 
@@ -170,16 +168,8 @@ ltq_mtd_probe(struct platform_device *pdev)
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 1;
 
-	nr_parts = parse_mtd_partitions(ltq_mtd->mtd, NULL, &parts, 0);
-	if (nr_parts > 0) {
-		dev_info(&pdev->dev,
-			"using %d partitions from cmdline", nr_parts);
-	} else {
-		nr_parts = ltq_mtd_data->nr_parts;
-		parts = ltq_mtd_data->parts;
-	}
-
-	err = add_mtd_partitions(ltq_mtd->mtd, parts, nr_parts);
+	err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
+			ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		goto err_destroy;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:13 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:13 +0400
Subject: [PATCH 14/44] mtd: latch-addr-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-15-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/latch-addr-flash.c |   21 ++-------------------
 1 files changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index 09cf704..119baa7 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -33,9 +33,6 @@ struct latch_addr_flash_info {
 	/* cache; could be found out of res */
 	unsigned long		win_mask;
 
-	int			nr_parts;
-	struct mtd_partition	*parts;
-
 	spinlock_t		lock;
 };
 
@@ -110,8 +107,6 @@ static int latch_addr_flash_remove(struct platform_device *dev)
 	latch_addr_data = dev->dev.platform_data;
 
 	if (info->mtd != NULL) {
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
@@ -204,20 +199,8 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, NULL, &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->mtd, info->parts, err);
-		return 0;
-	}
-	if (latch_addr_data->nr_parts) {
-		pr_notice("Using latch-addr-flash partition information\n");
-		mtd_device_register(info->mtd,
-				    latch_addr_data->parts,
-				    latch_addr_data->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->mtd, NULL, 0);
+	mtd_device_parse_register(info->mtd, NULL, 0,
+			latch_addr_data->parts, latch_addr_data->nr_parts);
 	return 0;
 
 iounmap:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:14 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:14 +0400
Subject: [PATCH 15/44] mtd: physmap.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-16-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap.c |   23 ++---------------------
 1 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 2174d10..256f787 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -27,8 +27,6 @@ struct physmap_flash_info {
 	struct mtd_info		*mtd[MAX_RESOURCES];
 	struct mtd_info		*cmtd;
 	struct map_info		map[MAX_RESOURCES];
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 
 static int physmap_flash_remove(struct platform_device *dev)
@@ -46,8 +44,6 @@ static int physmap_flash_remove(struct platform_device *dev)
 
 	if (info->cmtd) {
 		mtd_device_unregister(info->cmtd);
-		if (info->nr_parts)
-			kfree(info->parts);
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
 	}
@@ -175,23 +171,8 @@ static int physmap_flash_probe(struct platform_device *dev)
 	if (err)
 		goto err_out;
 
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->cmtd, info->parts, err);
-		info->nr_parts = err;
-		return 0;
-	}
-
-	if (physmap_data->nr_parts) {
-		printk(KERN_NOTICE "Using physmap partition information\n");
-		mtd_device_register(info->cmtd, physmap_data->parts,
-				    physmap_data->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->cmtd, NULL, 0);
-
+	mtd_device_parse_register(info->cmtd, part_probe_types, 0,
+			physmap_data->parts, physmap_data->nr_parts);
 	return 0;
 
 err_out:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:15 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:15 +0400
Subject: [PATCH 16/44] mtd: plat-ram.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-17-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/plat-ram.c |   23 ++---------------------
 1 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 9ca1ecc..94f5534 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -44,8 +44,6 @@ struct platram_info {
 	struct device		*dev;
 	struct mtd_info		*mtd;
 	struct map_info		 map;
-	struct mtd_partition	*partitions;
-	bool			free_partitions;
 	struct resource		*area;
 	struct platdata_mtd_ram	*pdata;
 };
@@ -95,10 +93,6 @@ static int platram_remove(struct platform_device *pdev)
 
 	if (info->mtd) {
 		mtd_device_unregister(info->mtd);
-		if (info->partitions) {
-			if (info->free_partitions)
-				kfree(info->partitions);
-		}
 		map_destroy(info->mtd);
 	}
 
@@ -228,21 +222,8 @@ static int platram_probe(struct platform_device *pdev)
 	/* check to see if there are any available partitions, or wether
 	 * to add this device whole */
 
-	if (!pdata->nr_partitions) {
-		/* try to probe using the supplied probe type */
-		if (pdata->probes) {
-			err = parse_mtd_partitions(info->mtd, pdata->probes,
-					   &info->partitions, 0);
-			info->free_partitions = 1;
-			if (err > 0)
-				err = mtd_device_register(info->mtd,
-					info->partitions, err);
-		}
-	}
-	/* use the static mapping */
-	else
-		err = mtd_device_register(info->mtd, pdata->partitions,
-					  pdata->nr_partitions);
+	err = mtd_device_parse_register(info->mtd, pdata->probes, 0,
+			pdata->partitions, pdata->nr_partitions);
 	if (!err)
 		dev_info(&pdev->dev, "registered mtd device\n");
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:16 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:16 +0400
Subject: [PATCH 17/44] mtd: pxa2xx-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-18-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/pxa2xx-flash.c |   20 +-------------------
 1 files changed, 1 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index f59d62f..8fb8198 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -41,8 +41,6 @@ static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
 }
 
 struct pxa2xx_flash_info {
-	struct mtd_partition	*parts;
-	int			nr_parts;
 	struct mtd_info		*mtd;
 	struct map_info		map;
 };
@@ -55,9 +53,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
-	struct mtd_partition *parts;
 	struct resource *res;
-	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -71,8 +67,6 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
 	info->map.size = res->end - res->start + 1;
-	info->parts = flash->parts;
-	info->nr_parts = flash->nr_parts;
 
 	info->map.virt = ioremap(info->map.phys, info->map.size);
 	if (!info->map.virt) {
@@ -104,18 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
-
-	if (ret > 0) {
-		info->nr_parts = ret;
-		info->parts = parts;
-	}
-
-	if (!info->nr_parts)
-		printk("Registering %s as whole device\n",
-		       info->map.name);
-
-	mtd_device_register(info->mtd, info->parts, info->nr_parts);
+	mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
 
 	platform_set_drvdata(pdev, info);
 	return 0;
@@ -133,7 +116,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
 	iounmap(info->map.virt);
 	if (info->map.cached)
 		iounmap(info->map.cached);
-	kfree(info->parts);
 	kfree(info);
 	return 0;
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:17 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:17 +0400
Subject: [PATCH 18/44] mtd: rbtx4939-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-19-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/rbtx4939-flash.c |   18 ++----------------
 1 files changed, 2 insertions(+), 16 deletions(-)

diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 5d15b6b..95f816c 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -25,8 +25,6 @@
 struct rbtx4939_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-	int nr_parts;
-	struct mtd_partition *parts;
 };
 
 static int rbtx4939_flash_remove(struct platform_device *dev)
@@ -41,8 +39,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
 	if (info->mtd) {
 		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
@@ -106,18 +102,8 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
 	info->mtd->owner = THIS_MODULE;
 	if (err)
 		goto err_out;
-	err = parse_mtd_partitions(info->mtd, NULL, &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->mtd, info->parts, err);
-		info->nr_parts = err;
-		return 0;
-	}
-
-	if (pdata->nr_parts) {
-		pr_notice("Using rbtx4939 partition information\n");
-		mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
-		return 0;
-	}
+	err = mtd_device_parse_register(info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	mtd_device_register(info->mtd, NULL, 0);
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:18 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:18 +0400
Subject: [PATCH 19/44] mtd: sa1100-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-20-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/sa1100-flash.c |   30 +++---------------------------
 1 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index a9b5e0e..fa9c0a9 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -131,10 +131,8 @@ struct sa_subdev_info {
 };
 
 struct sa_info {
-	struct mtd_partition	*parts;
 	struct mtd_info		*mtd;
 	int			num_subdev;
-	unsigned int		nr_parts;
 	struct sa_subdev_info	subdev[0];
 };
 
@@ -231,8 +229,6 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
 			mtd_concat_destroy(info->mtd);
 	}
 
-	kfree(info->parts);
-
 	for (i = info->num_subdev - 1; i >= 0; i--)
 		sa1100_destroy_subdev(&info->subdev[i]);
 	kfree(info);
@@ -341,10 +337,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *plat = pdev->dev.platform_data;
-	struct mtd_partition *parts;
-	const char *part_type = NULL;
 	struct sa_info *info;
-	int err, nr_parts = 0;
+	int err;
 
 	if (!plat)
 		return -ENODEV;
@@ -358,26 +352,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 	/*
 	 * Partition selection stuff.
 	 */
-	nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
-	if (nr_parts > 0) {
-		info->parts = parts;
-		part_type = "dynamic";
-	} else {
-		parts = plat->parts;
-		nr_parts = plat->nr_parts;
-		part_type = "static";
-	}
-
-	if (nr_parts == 0)
-		printk(KERN_NOTICE "SA1100 flash: no partition info "
-			"available, registering whole flash\n");
-	else
-		printk(KERN_NOTICE "SA1100 flash: using %s partition "
-			"definition\n", part_type);
-
-	mtd_device_register(info->mtd, parts, nr_parts);
-
-	info->nr_parts = nr_parts;
+	mtd_device_parse_register(info->mtd, part_probes, 0,
+			plat->parts, plat->nr_parts);
 
 	platform_set_drvdata(pdev, info);
 	err = 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:19 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:19 +0400
Subject: [PATCH 20/44] mtd: solutionengine.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-21-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/solutionengine.c |   30 +++++++-----------------------
 1 files changed, 7 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c
index cbf6bad..496c407 100644
--- a/drivers/mtd/maps/solutionengine.c
+++ b/drivers/mtd/maps/solutionengine.c
@@ -19,8 +19,6 @@
 static struct mtd_info *flash_mtd;
 static struct mtd_info *eprom_mtd;
 
-static struct mtd_partition *parsed_parts;
-
 struct map_info soleng_eprom_map = {
 	.name = "Solution Engine EPROM",
 	.size = 0x400000,
@@ -51,12 +49,14 @@ static struct mtd_partition superh_se_partitions[] = {
 		.size = MTDPART_SIZ_FULL,
 	}
 };
+#define NUM_PARTITIONS ARRAY_SIZE(superh_se_partitions)
+#else
+#define superh_se_partitions NULL
+#define NUM_PARTITIONS 0
 #endif /* CONFIG_MTD_SUPERH_RESERVE */
 
 static int __init init_soleng_maps(void)
 {
-	int nr_parts = 0;
-
 	/* First probe at offset 0 */
 	soleng_flash_map.phys = 0;
 	soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
@@ -92,21 +92,8 @@ static int __init init_soleng_maps(void)
 		mtd_device_register(eprom_mtd, NULL, 0);
 	}
 
-	nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
-
-#ifdef CONFIG_MTD_SUPERH_RESERVE
-	if (nr_parts <= 0) {
-		printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
-		       CONFIG_MTD_SUPERH_RESERVE);
-		parsed_parts = superh_se_partitions;
-		nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
-	}
-#endif /* CONFIG_MTD_SUPERH_RESERVE */
-
-	if (nr_parts > 0)
-		mtd_device_register(flash_mtd, parsed_parts, nr_parts);
-	else
-		mtd_device_register(flash_mtd, NULL, 0);
+	mtd_device_parse_register(flash_mtd, probes, 0,
+			superh_se_partitions, NUM_PARTITIONS);
 
 	return 0;
 }
@@ -118,10 +105,7 @@ static void __exit cleanup_soleng_maps(void)
 		map_destroy(eprom_mtd);
 	}
 
-	if (parsed_parts)
-		mtd_device_unregister(flash_mtd);
-	else
-		mtd_device_unregister(flash_mtd);
+	mtd_device_unregister(flash_mtd);
 	map_destroy(flash_mtd);
 }
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:20 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:20 +0400
Subject: [PATCH 21/44] mtd: wr_sbc82xx_flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-22-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/wr_sbc82xx_flash.c |   30 +++++++++++-------------------
 1 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c
index 901ce96..aaec902 100644
--- a/drivers/mtd/maps/wr_sbc82xx_flash.c
+++ b/drivers/mtd/maps/wr_sbc82xx_flash.c
@@ -20,7 +20,6 @@
 #include <asm/immap_cpm2.h>
 
 static struct mtd_info *sbcmtd[3];
-static struct mtd_partition *sbcmtd_parts[3];
 
 struct map_info sbc82xx_flash_map[3] = {
 	{.name = "Boot flash"},
@@ -101,6 +100,7 @@ static int __init init_sbc82xx_flash(void)
 	for (i=0; i<3; i++) {
 		int8_t flashcs[3] = { 0, 6, 1 };
 		int nr_parts;
+		struct mtd_partition *defparts;
 
 		printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
 		       sbc82xx_flash_map[i].name,
@@ -129,24 +129,20 @@ static int __init init_sbc82xx_flash(void)
 
 		sbcmtd[i]->owner = THIS_MODULE;
 
-		nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
-						&sbcmtd_parts[i], 0);
-		if (nr_parts > 0) {
-			mtd_device_register(sbcmtd[i], sbcmtd_parts[i],
-					    nr_parts);
-			continue;
-		}
-
 		/* No partitioning detected. Use default */
 		if (i == 2) {
-			mtd_device_register(sbcmtd[i], NULL, 0);
+			defparts = NULL;
+			nr_parts = 0;
 		} else if (i == bigflash) {
-			mtd_device_register(sbcmtd[i], bigflash_parts,
-					    ARRAY_SIZE(bigflash_parts));
+			defparts = bigflash_parts;
+			nr_parts = ARRAY_SIZE(bigflash_parts);
 		} else {
-			mtd_device_register(sbcmtd[i], smallflash_parts,
-					    ARRAY_SIZE(smallflash_parts));
+			defparts = smallflash_parts;
+			nr_parts = ARRAY_SIZE(smallflash_parts);
 		}
+
+		mtd_device_parse_register(sbcmtd[i], part_probes, 0,
+				defparts, nr_parts);
 	}
 	return 0;
 }
@@ -159,12 +155,8 @@ static void __exit cleanup_sbc82xx_flash(void)
 		if (!sbcmtd[i])
 			continue;
 
-		if (i<2 || sbcmtd_parts[i])
-			mtd_device_unregister(sbcmtd[i]);
-		else
-			mtd_device_unregister(sbcmtd[i]);
+		mtd_device_unregister(sbcmtd[i]);
 
-		kfree(sbcmtd_parts[i]);
 		map_destroy(sbcmtd[i]);
 
 		iounmap((void *)sbc82xx_flash_map[i].virt);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:21 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:21 +0400
Subject: [PATCH 22/44] mtd: atmel_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-23-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/atmel_nand.c |   19 ++-----------------
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index a19a112..6702208 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -491,8 +491,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	struct resource *regs;
 	struct resource *mem;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -651,24 +649,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	}
 
 	mtd->name = "atmel_nand";
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, 0);
-	if (num_partitions <= 0 && host->board->parts) {
-		partitions = host->board->parts;
-		num_partitions = host->board->num_parts;
-	}
-
-	if ((!partitions) || (num_partitions == 0)) {
-		printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
-		res = -ENXIO;
-		goto err_no_partitions;
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, 0,
+			host->board->parts, host->board->num_parts);
 	if (!res)
 		return res;
 
-err_no_partitions:
-	nand_release(mtd);
 err_scan_tail:
 err_scan_ident:
 err_no_card:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:22 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:22 +0400
Subject: [PATCH 23/44] mtd: bcm_umi_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-24-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/bcm_umi_nand.c |   19 ++-----------------
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index e0230c5..d98bc48 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -489,23 +489,8 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 	}
 
 	/* Register the partitions */
-	{
-		int nr_partitions;
-		struct mtd_partition *partition_info;
-
-		board_mtd->name = "bcm_umi-nand";
-		nr_partitions = parse_mtd_partitions(board_mtd, NULL,
-						     &partition_info, 0);
-
-		if (nr_partitions <= 0) {
-			printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n",
-			       nr_partitions);
-			iounmap(bcm_umi_io_base);
-			kfree(board_mtd);
-			return -EIO;
-		}
-		mtd_device_register(board_mtd, partition_info, nr_partitions);
-	}
+	board_mtd->name = "bcm_umi-nand";
+	mtd_device_parse_register(board_mtd, NULL, 0, NULL, 0);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:23 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:23 +0400
Subject: [PATCH 24/44] mtd: cafe_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-25-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cafe_nand.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 88ac4b5..db3bfac 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -57,7 +57,6 @@
 
 struct cafe_priv {
 	struct nand_chip nand;
-	struct mtd_partition *parts;
 	struct pci_dev *pdev;
 	void __iomem *mmio;
 	struct rs_control *rs;
@@ -630,8 +629,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	struct cafe_priv *cafe;
 	uint32_t ctrl;
 	int err = 0;
-	struct mtd_partition *parts;
-	int nr_parts;
 
 	/* Very old versions shared the same PCI ident for all three
 	   functions on the chip. Verify the class too... */
@@ -804,12 +801,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	mtd_device_register(mtd, NULL, 0);
 
 	mtd->name = "cafe_nand";
-	nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-	if (nr_parts > 0) {
-		cafe->parts = parts;
-		dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts);
-		mtd_device_register(mtd, parts, nr_parts);
-	}
+	mtd_device_parse_register(mtd, part_probes, 0, NULL, 0);
+
 	goto out;
 
  out_irq:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:24 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:24 +0400
Subject: [PATCH 25/44] mtd: cmx270_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-26-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cmx270_nand.c |   20 ++------------------
 1 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index f8f5b7c..8305692 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -149,9 +149,6 @@ static int cmx270_device_ready(struct mtd_info *mtd)
 static int __init cmx270_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type;
-	struct mtd_partition *mtd_parts;
-	int mtd_parts_nb = 0;
 	int ret;
 
 	if (!(machine_is_armcore() && cpu_is_pxa27x()))
@@ -220,22 +217,9 @@ static int __init cmx270_init(void)
 		goto err_scan;
 	}
 
-	mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, NULL,
-					    &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (!mtd_parts_nb) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
-
 	/* Register the partitions */
-	pr_notice("Using %s partition definition\n", part_type);
-	ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
+	ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 	if (ret)
 		goto err_scan;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:25 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:25 +0400
Subject: [PATCH 26/44] mtd: cs553x_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-27-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cs553x_nand.c |    7 ++-----
 1 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index b2bdf72..4aac849 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -283,8 +283,6 @@ static int __init cs553x_init(void)
 	int err = -ENXIO;
 	int i;
 	uint64_t val;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = NULL;
 
 	/* If the CPU isn't a Geode GX or LX, abort */
 	if (!is_geode())
@@ -316,9 +314,8 @@ static int __init cs553x_init(void)
 		if (cs553x_mtd[i]) {
 
 			/* If any devices registered, return success. Else the last error. */
-			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], NULL, &mtd_parts, 0);
-			mtd_device_register(cs553x_mtd[i], mtd_parts,
-					    mtd_parts_nb);
+			mtd_device_parse_register(cs553x_mtd[i], NULL, 0,
+					NULL, 0);
 			err = 0;
 		}
 	}
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:26 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:26 +0400
Subject: [PATCH 27/44] mtd: davinci_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-28-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/davinci_nand.c |   25 ++-----------------------
 1 files changed, 2 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 0c582ed..6492213 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -57,7 +57,6 @@ struct davinci_nand_info {
 
 	struct device		*dev;
 	struct clk		*clk;
-	bool			partitioned;
 
 	bool			is_readmode;
 
@@ -530,8 +529,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
 	int				ret;
 	uint32_t			val;
 	nand_ecc_modes_t		ecc_mode;
-	struct mtd_partition		*mtd_parts = NULL;
-	int				mtd_parts_nb = 0;
 
 	/* insist on board-specific configuration */
 	if (!pdata)
@@ -753,26 +750,8 @@ syndrome_done:
 	if (ret < 0)
 		goto err_scan;
 
-	mtd_parts_nb = parse_mtd_partitions(&info->mtd, NULL, &mtd_parts, 0);
-
-	if (mtd_parts_nb <= 0) {
-		mtd_parts = pdata->parts;
-		mtd_parts_nb = pdata->nr_parts;
-	}
-
-	/* Register any partitions */
-	if (mtd_parts_nb > 0) {
-		ret = mtd_device_register(&info->mtd, mtd_parts,
-					  mtd_parts_nb);
-		if (ret == 0)
-			info->partitioned = true;
-	}
-
-	/* If there's no partition info, just package the whole chip
-	 * as a single MTD device.
-	 */
-	if (!info->partitioned)
-		ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0;
+	ret = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	if (ret < 0)
 		goto err_scan;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:27 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:27 +0400
Subject: [PATCH 28/44] mtd: edb7312.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-29-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/edb7312.c |   17 ++---------------
 1 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 2f9374b..0b1bb91 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -104,9 +104,6 @@ static int ep7312_device_ready(struct mtd_info *mtd)
 static int __init ep7312_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *ep7312_fio_base;
 
 	/* Allocate memory for MTD device structure and private data */
@@ -156,20 +153,10 @@ static int __init ep7312_init(void)
 		return -ENXIO;
 	}
 	ep7312_mtd->name = "edb7312-nand";
-	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_register(ep7312_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:28 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:28 +0400
Subject: [PATCH 29/44] mtd: fsmc_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-30-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsmc_nand.c |   66 ++++++------------------------------------
 1 files changed, 9 insertions(+), 57 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index a39c224..8cc8065 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -146,7 +146,7 @@ static struct mtd_partition partition_info_16KB_blk[] = {
 	{
 		.name = "Root File System",
 		.offset = 0x460000,
-		.size = 0,
+		.size = MTDPART_SIZ_FULL,
 	},
 };
 
@@ -173,7 +173,7 @@ static struct mtd_partition partition_info_128KB_blk[] = {
 	{
 		.name = "Root File System",
 		.offset = 0x800000,
-		.size = 0,
+		.size = MTDPART_SIZ_FULL,
 	},
 };
 
@@ -184,8 +184,6 @@ static struct mtd_partition partition_info_128KB_blk[] = {
  * @pid:		Part ID on the AMBA PrimeCell format
  * @mtd:		MTD info for a NAND flash.
  * @nand:		Chip related info for a NAND flash.
- * @partitions:		Partition info for a NAND Flash.
- * @nr_partitions:	Total number of partition of a NAND flash.
  *
  * @ecc_place:		ECC placing locations in oobfree type format.
  * @bank:		Bank number for probed device.
@@ -200,8 +198,6 @@ struct fsmc_nand_data {
 	u32			pid;
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
-	struct mtd_partition	*partitions;
-	unsigned int		nr_partitions;
 
 	struct fsmc_eccplace	*ecc_place;
 	unsigned int		bank;
@@ -717,57 +713,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	 * Check for partition info passed
 	 */
 	host->mtd.name = "nand";
-	host->nr_partitions = parse_mtd_partitions(&host->mtd, NULL,
-			&host->partitions, 0);
-	if (host->nr_partitions <= 0) {
-		/*
-		 * Check if partition info passed via command line
-		 */
-		if (pdata->partitions) {
-			host->partitions = pdata->partitions;
-			host->nr_partitions = pdata->nr_partitions;
-		} else {
-			struct mtd_partition *partition;
-			int i;
-
-			/* Select the default partitions info */
-			switch (host->mtd.size) {
-			case 0x01000000:
-			case 0x02000000:
-			case 0x04000000:
-				host->partitions = partition_info_16KB_blk;
-				host->nr_partitions =
-					sizeof(partition_info_16KB_blk) /
-					sizeof(struct mtd_partition);
-				break;
-			case 0x08000000:
-			case 0x10000000:
-			case 0x20000000:
-			case 0x40000000:
-				host->partitions = partition_info_128KB_blk;
-				host->nr_partitions =
-					sizeof(partition_info_128KB_blk) /
-					sizeof(struct mtd_partition);
-				break;
-			default:
-				ret = -ENXIO;
-				pr_err("Unsupported NAND size\n");
-				goto err_probe;
-			}
-
-			partition = host->partitions;
-			for (i = 0; i < host->nr_partitions; i++, partition++) {
-				if (partition->size == 0) {
-					partition->size = host->mtd.size -
-						partition->offset;
-					break;
-				}
-			}
-		}
-	}
-
-	ret = mtd_device_register(&host->mtd, host->partitions,
-				  host->nr_partitions);
+	ret = mtd_device_parse_register(&host->mtd, NULL, 0,
+			host->mtd.size <= 0x04000000 ?
+				partition_info_16KB_blk :
+				partition_info_128KB_blk,
+			host->mtd.size <= 0x04000000 ?
+				ARRAY_SIZE(partition_info_16KB_blk) :
+				ARRAY_SIZE(partition_info_128KB_blk),
 	if (ret)
 		goto err_probe;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:29 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:29 +0400
Subject: [PATCH 30/44] mtd: h1910.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-31-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/h1910.c |   15 ++-------------
 1 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 42f9177..5dc6f0d 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -81,9 +81,6 @@ static int h1910_device_ready(struct mtd_info *mtd)
 static int __init h1910_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *nandaddr;
 
 	if (!machine_is_h1900())
@@ -136,18 +133,10 @@ static int __init h1910_init(void)
 		iounmap((void *)nandaddr);
 		return -ENXIO;
 	}
-	mtd_parts_nb = parse_mtd_partitions(h1910_nand_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(h1910_nand_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:30 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:30 +0400
Subject: [PATCH 31/44] mtd: jz4740_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-32-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/jz4740_nand.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 920719c..e266407 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -295,8 +295,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
-	struct mtd_partition *partition_info;
-	int num_partitions = 0;
 
 	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
 	if (!nand) {
@@ -369,12 +367,9 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
 		goto err_gpio_free;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partition_info, 0);
-	if (num_partitions <= 0 && pdata) {
-		num_partitions = pdata->num_partitions;
-		partition_info = pdata->partitions;
-	}
-	ret = mtd_device_register(mtd, partition_info, num_partitions);
+	ret = mtd_device_parse_register(mtd, NULL, 0,
+			pdata ? pdata->partitions : NULL,
+			pdata ? pdata->num_partitions : 0);
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add mtd device\n");
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:35 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:35 +0400
Subject: [PATCH 36/44] mtd: ppchameleonevb.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-37-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ppchameleonevb.c |   42 ++++++++----------------------------
 1 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 9376633..7e52af5 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -191,9 +191,6 @@ static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 static int __init ppchameleonevb_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *ppchameleon_fio_base;
 	void __iomem *ppchameleonevb_fio_base;
 
@@ -276,24 +273,13 @@ static int __init ppchameleonevb_init(void)
 #endif
 
 	ppchameleon_mtd->name = "ppchameleon-nand";
-	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (mtd_parts_nb == 0) {
-		if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
-			mtd_parts = partition_info_me;
-		else
-			mtd_parts = partition_info_hi;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(ppchameleon_mtd, NULL, 0,
+			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+				partition_info_me :
+				partition_info_hi,
+			NUM_PARTITIONS);
 
  nand_evb_init:
 	/****************************
@@ -377,21 +363,13 @@ static int __init ppchameleonevb_init(void)
 	}
 
 	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
-	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info_evb;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(ppchameleonevb_mtd, NULL, 0,
+			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+				partition_info_me :
+				partition_info_hi,
+			NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:36 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:36 +0400
Subject: [PATCH 37/44] mtd: pxa3xx_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-38-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 5c3af2f..b7db1b2 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1133,8 +1133,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-	struct mtd_partition *parts;
-	int nr_parts;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1152,13 +1150,8 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-
-	nr_parts = parse_mtd_partitions(info->mtd, NULL, &parts, 0);
-
-	if (nr_parts)
-		return mtd_device_register(info->mtd, parts, nr_parts);
-
-	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
+	return mtd_device_parse_register(info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 }
 
 #ifdef CONFIG_PM
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:31 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:31 +0400
Subject: [PATCH 32/44] mtd: mxc_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-33-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mxc_nand.c |   15 +++------------
 1 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index ca42c8f..4c2bb4a 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -143,7 +143,6 @@
 struct mxc_nand_host {
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
-	struct mtd_partition	*parts;
 	struct device		*dev;
 
 	void			*spare0;
@@ -1044,7 +1043,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct mxc_nand_host *host;
 	struct resource *res;
-	int err = 0, __maybe_unused nr_parts = 0;
+	int err = 0;
 	struct nand_ecclayout *oob_smallpage, *oob_largepage;
 
 	/* Allocate memory for MTD device structure and private data */
@@ -1231,16 +1230,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	}
 
 	/* Register the partitions */
-	nr_parts =
-	    parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
-	if (nr_parts > 0)
-		mtd_device_register(mtd, host->parts, nr_parts);
-	else if (pdata->parts)
-		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-	else {
-		pr_info("Registering %s as whole device\n", mtd->name);
-		mtd_device_register(mtd, NULL, 0);
-	}
+	mtd_device_parse_register(mtd, part_probes, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, host);
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:32 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:32 +0400
Subject: [PATCH 33/44] mtd: omap2.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-34-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/omap2.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 8783c08..c5e33fd 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -112,7 +112,6 @@ struct omap_nand_info {
 	struct nand_hw_control		controller;
 	struct omap_nand_platform_data	*pdata;
 	struct mtd_info			mtd;
-	struct mtd_partition		*parts;
 	struct nand_chip		nand;
 	struct platform_device		*pdev;
 
@@ -1101,13 +1100,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, NULL, &info->parts, 0);
-	if (err > 0)
-		mtd_device_register(&info->mtd, info->parts, err);
-	else if (pdata->parts)
-		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-	else
-		mtd_device_register(&info->mtd, NULL, 0);
+	mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, &info->mtd);
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:33 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:33 +0400
Subject: [PATCH 34/44] mtd: orion_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-35-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/orion_nand.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 5c55981..29f505a 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -79,8 +79,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 	struct resource *res;
 	void __iomem *io_base;
 	int ret = 0;
-	struct mtd_partition *partitions = NULL;
-	int num_part = 0;
 
 	nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
 	if (!nc) {
@@ -131,14 +129,8 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 	}
 
 	mtd->name = "orion_nand";
-	num_part = parse_mtd_partitions(mtd, NULL, &partitions, 0);
-	/* If cmdline partitions have been passed, let them be used */
-	if (num_part <= 0) {
-		num_part = board->nr_parts;
-		partitions = board->parts;
-	}
-
-	ret = mtd_device_register(mtd, partitions, num_part);
+	ret = mtd_device_parse_register(mtd, NULL, 0,
+			board->parts, board->nr_parts);
 	if (ret) {
 		nand_release(mtd);
 		goto no_dev;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:34 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:34 +0400
Subject: [PATCH 35/44] mtd: plat_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-36-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/plat_nand.c |   22 +++-------------------
 1 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 1339fa8..e62468b 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -21,8 +21,6 @@ struct plat_nand_data {
 	struct nand_chip	chip;
 	struct mtd_info		mtd;
 	void __iomem		*io_base;
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 
 /*
@@ -99,21 +97,9 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	if (pdata->chip.part_probe_types) {
-		err = parse_mtd_partitions(&data->mtd,
-					pdata->chip.part_probe_types,
-					&data->parts, 0);
-		if (err > 0) {
-			mtd_device_register(&data->mtd, data->parts, err);
-			return 0;
-		}
-	}
-	if (pdata->chip.partitions) {
-		data->parts = pdata->chip.partitions;
-		err = mtd_device_register(&data->mtd, data->parts,
-			pdata->chip.nr_partitions);
-	} else
-		err = mtd_device_register(&data->mtd, NULL, 0);
+	err = mtd_device_parse_register(&data->mtd,
+			pdata->chip.part_probe_types, 0,
+			pdata->chip.partitions, pdata->chip.nr_partitions);
 
 	if (!err)
 		return err;
@@ -143,8 +129,6 @@ static int __devexit plat_nand_remove(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	nand_release(&data->mtd);
-	if (data->parts && data->parts != pdata->chip.partitions)
-		kfree(data->parts);
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
 	iounmap(data->io_base);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:37 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:37 +0400
Subject: [PATCH 38/44] mtd: s3c2410.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-39-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/s3c2410.c |   18 ++++--------------
 1 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 17954ba..b0f8e77 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -748,21 +748,11 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
 				      struct s3c2410_nand_set *set)
 {
-	struct mtd_partition *part_info;
-	int nr_part = 0;
+	if (set)
+		mtd->mtd.name = set->name;
 
-	if (set == NULL)
-		return mtd_device_register(&mtd->mtd, NULL, 0);
-
-	mtd->mtd.name = set->name;
-	nr_part = parse_mtd_partitions(&mtd->mtd, NULL, &part_info, 0);
-
-	if (nr_part <= 0 && set->nr_partitions > 0) {
-		nr_part = set->nr_partitions;
-		part_info = set->partitions;
-	}
-
-	return mtd_device_register(&mtd->mtd, part_info, nr_part);
+	return mtd_device_parse_register(&mtd->mtd, NULL, 0,
+			set->partitions, set->nr_partitions);
 }
 
 /**
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:38 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:38 +0400
Subject: [PATCH 39/44] mtd: sharpsl.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-40-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/sharpsl.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index b3377f8..619d2a5 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -109,8 +109,6 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
 static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
-	struct mtd_partition *sharpsl_partition_info;
-	int nr_partitions;
 	struct resource *r;
 	int err = 0;
 	struct sharpsl_nand *sharpsl;
@@ -182,14 +180,9 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 
 	/* Register the partitions */
 	sharpsl->mtd.name = "sharpsl-nand";
-	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, NULL, &sharpsl_partition_info, 0);
-	if (nr_partitions <= 0) {
-		nr_partitions = data->nr_partitions;
-		sharpsl_partition_info = data->partitions;
-	}
 
-	err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info,
-				  nr_partitions);
+	err = mtd_device_parse_register(&sharpsl->mtd, NULL, 0,
+			data->partitions, data->nr_partitions);
 	if (err)
 		goto err_add;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:39 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:39 +0400
Subject: [PATCH 40/44] mtd: tmio_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-41-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/tmio_nand.c |   12 +++---------
 1 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index b6ffad6..d476857 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -378,8 +378,6 @@ static int tmio_probe(struct platform_device *dev)
 	struct tmio_nand *tmio;
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
-	struct mtd_partition *parts;
-	int nbparts = 0;
 	int retval;
 
 	if (data == NULL)
@@ -458,13 +456,9 @@ static int tmio_probe(struct platform_device *dev)
 		goto err_scan;
 	}
 	/* Register the partitions */
-	nbparts = parse_mtd_partitions(mtd, NULL, &parts, 0);
-	if (nbparts <= 0 && data) {
-		parts = data->partition;
-		nbparts = data->num_partitions;
-	}
-
-	retval = mtd_device_register(mtd, parts, nbparts);
+	retval = mtd_device_register(mtd, NULL, 0,
+			data ? data->partition : NULL,
+			data ? data->num_partitions : 0);
 	if (!retval)
 		return retval;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:40 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:40 +0400
Subject: [PATCH 41/44] mtd: txx9ndfmc.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-42-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/txx9ndfmc.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 91b05b9..ace46fd 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -74,7 +74,6 @@ struct txx9ndfmc_drvdata {
 	unsigned char hold;	/* in gbusclock */
 	unsigned char spw;	/* in gbusclock */
 	struct nand_hw_control hw_control;
-	struct mtd_partition *parts[MAX_TXX9NDFMC_DEV];
 };
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
@@ -332,7 +331,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		struct txx9ndfmc_priv *txx9_priv;
 		struct nand_chip *chip;
 		struct mtd_info *mtd;
-		int nr_parts;
 
 		if (!(plat->ch_mask & (1 << i)))
 			continue;
@@ -392,9 +390,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		}
 		mtd->name = txx9_priv->mtdname;
 
-		nr_parts = parse_mtd_partitions(mtd, NULL,
-						&drvdata->parts[i], 0);
-		mtd_device_register(mtd, drvdata->parts[i], nr_parts);
+		mtd_device_parse_register(mtd, NULL, 0, NULL, 0);
 		drvdata->mtds[i] = mtd;
 	}
 
@@ -420,7 +416,6 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
 		txx9_priv = chip->priv;
 
 		nand_release(mtd);
-		kfree(drvdata->parts[i]);
 		kfree(txx9_priv->mtdname);
 		kfree(txx9_priv);
 	}
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:41 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:41 +0400
Subject: [PATCH 42/44] mtd: onenand/generic.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-43-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/generic.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index bca1c49..8152a31 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -32,7 +32,6 @@
 
 struct onenand_info {
 	struct mtd_info		mtd;
-	struct mtd_partition	*parts;
 	struct onenand_chip	onenand;
 };
 
@@ -71,13 +70,9 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev)
 		goto out_iounmap;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, NULL, &info->parts, 0);
-	if (err > 0)
-		mtd_device_register(&info->mtd, info->parts, err);
-	else if (err <= 0 && pdata && pdata->parts)
-		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-	else
-		err = mtd_device_register(&info->mtd, NULL, 0);
+	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
 	platform_set_drvdata(pdev, info);
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:42 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:42 +0400
Subject: [PATCH 43/44] mtd: onenand/omap2.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-44-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/omap2.c |   13 +++----------
 1 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 5ca2053..eb9cbd9 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -57,7 +57,6 @@ struct omap2_onenand {
 	unsigned long phys_base;
 	int gpio_irq;
 	struct mtd_info mtd;
-	struct mtd_partition *parts;
 	struct onenand_chip onenand;
 	struct completion irq_done;
 	struct completion dma_done;
@@ -752,13 +751,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	r = parse_mtd_partitions(&c->mtd, NULL, &c->parts, 0);
-	if (r > 0)
-		r = mtd_device_register(&c->mtd, c->parts, r);
-	else if (pdata->parts != NULL)
-		r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts);
-	else
-		r = mtd_device_register(&c->mtd, NULL, 0);
+	r = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 	if (r)
 		goto err_release_onenand;
 
@@ -785,7 +780,6 @@ err_release_mem_region:
 err_free_cs:
 	gpmc_cs_free(c->gpmc_cs);
 err_kfree:
-	kfree(c->parts);
 	kfree(c);
 
 	return r;
@@ -808,7 +802,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 	iounmap(c->onenand.base);
 	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 	gpmc_cs_free(c->gpmc_cs);
-	kfree(c->parts);
 	kfree(c);
 
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Tue Jun  7 09:36:43 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 17:36:43 +0400
Subject: [PATCH 44/44] mtd: onenand/samsung.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307453803-31950-45-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/samsung.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 78a08ea..597dffc 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -147,7 +147,6 @@ struct s3c_onenand {
 	struct resource *dma_res;
 	unsigned long	phys_base;
 	struct completion	complete;
-	struct mtd_partition *parts;
 };
 
 #define CMD_MAP_00(dev, addr)		(dev->cmd_map(MAP_00, ((addr) << 1)))
@@ -1015,13 +1014,9 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-	err = parse_mtd_partitions(mtd, NULL, &onenand->parts, 0);
-	if (err > 0)
-		mtd_device_register(mtd, onenand->parts, err);
-	else if (err <= 0 && pdata && pdata->parts)
-		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-	else
-		err = mtd_device_register(mtd, NULL, 0);
+	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
 	platform_set_drvdata(pdev, mtd);
 
-- 
1.7.4.4



From jamie at jamieiles.com  Tue Jun  7 09:44:30 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Tue, 7 Jun 2011 14:44:30 +0100
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <20110607134429.GE21174@pulham.picochip.com>

Hi Dmitry,

This sounds like a good idea.  Nitpick inline.

Jamie

On Tue, Jun 07, 2011 at 05:36:00PM +0400, Dmitry Eremin-Solenikov wrote:
> Lots (nearly all) mtd drivers contain nearly the similar code that
> calls parse_mtd_partitions, provides some platform-default values, if
> parsing fails, and registers  mtd device.
> 
> This is an aim to provide single implementation of this scenario:
> mtd_device_parse_register() which will handle all this parsing and
> defaults.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/mtdcore.c   |   30 ++++++++++++++++++++++++++++++
>  include/linux/mtd/mtd.h |    5 +++++
>  2 files changed, 35 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c510aff..ac871ad 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -451,6 +451,36 @@ int mtd_device_register(struct mtd_info *master,
>  }
>  EXPORT_SYMBOL_GPL(mtd_device_register);
>  
> +int mtd_device_parse_register(struct mtd_info *mtd,
> +			      const char **part_probe_types,
> +			      unsigned long origin,
> +			      const struct mtd_partition *defparts,
> +			      int defnr_parts)
> +{
> +	int err;
> +	struct mtd_partition *parts;
> +
> +	err = parse_mtd_partitions(mtd, part_probe_types, &parts, origin);
> +	if (err <= 0 && defnr_parts) {
> +		unsigned long size = sizeof(*parts) * defnr_parts;
> +		err = defnr_parts;
> +		parts = kzalloc(size, GFP_KERNEL);
> +		memcpy(parts, defparts, size);

Shouldn't this check the return of kzalloc()?  How about using kmemdup() 
instead of kzalloc() + memcpy()?  Also some kernel-doc to describe the 
search order would be nice.

Jamie


From dbaryshkov at gmail.com  Tue Jun  7 10:33:58 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue, 07 Jun 2011 18:33:58 +0400
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <20110607134429.GE21174@pulham.picochip.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>
	<20110607134429.GE21174@pulham.picochip.com>
Message-ID: <4DEE36D6.2070009@gmail.com>

On 07.06.2011 17:44, Jamie Iles wrote:
> Hi Dmitry,
>
> This sounds like a good idea.  Nitpick inline.
>
> Jamie
>
> On Tue, Jun 07, 2011 at 05:36:00PM +0400, Dmitry Eremin-Solenikov wrote:
>> Lots (nearly all) mtd drivers contain nearly the similar code that
>> calls parse_mtd_partitions, provides some platform-default values, if
>> parsing fails, and registers  mtd device.
>>
>> This is an aim to provide single implementation of this scenario:
>> mtd_device_parse_register() which will handle all this parsing and
>> defaults.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
>> ---
>>   drivers/mtd/mtdcore.c   |   30 ++++++++++++++++++++++++++++++
>>   include/linux/mtd/mtd.h |    5 +++++
>>   2 files changed, 35 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
>> index c510aff..ac871ad 100644
>> --- a/drivers/mtd/mtdcore.c
>> +++ b/drivers/mtd/mtdcore.c
>> @@ -451,6 +451,36 @@ int mtd_device_register(struct mtd_info *master,
>>   }
>>   EXPORT_SYMBOL_GPL(mtd_device_register);
>>
>> +int mtd_device_parse_register(struct mtd_info *mtd,
>> +			      const char **part_probe_types,
>> +			      unsigned long origin,
>> +			      const struct mtd_partition *defparts,
>> +			      int defnr_parts)
>> +{
>> +	int err;
>> +	struct mtd_partition *parts;
>> +
>> +	err = parse_mtd_partitions(mtd, part_probe_types,&parts, origin);
>> +	if (err<= 0&&  defnr_parts) {
>> +		unsigned long size = sizeof(*parts) * defnr_parts;
>> +		err = defnr_parts;
>> +		parts = kzalloc(size, GFP_KERNEL);
>> +		memcpy(parts, defparts, size);
>
> Shouldn't this check the return of kzalloc()?  How about using kmemdup()
> instead of kzalloc() + memcpy()?

Good catch! Thank you.

>  Also some kernel-doc to describe the search order would be nice.

Search order is mainly detailed either by defaults specified in 
mtdpart.c or by probe types which user specifies.

-- 
With best wishes
Dmitry



From axel.lin at gmail.com  Tue Jun  7 10:55:21 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Tue, 07 Jun 2011 22:55:21 +0800
Subject: [PATCH] mtd: ndfc: fix a memory leak in ndfc_remove
Message-ID: <1307458521.22584.1.camel@phoenix>

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index ea2dea8..7995470 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -288,6 +288,7 @@ static int __devexit ndfc_remove(struct platform_device *ofdev)
 	struct ndfc_controller *ndfc = dev_get_drvdata(&ofdev->dev);
 
 	nand_release(&ndfc->mtd);
+	kfree(ndfc->mtd.name);
 
 	return 0;
 }
-- 
1.7.4.1





From vapier at gentoo.org  Tue Jun  7 11:00:13 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 11:00:13 -0400
Subject: [PATCH 2/6] mtdinfo: send help/version info to stdout
In-Reply-To: <1307428609.11104.39.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-2-git-send-email-vapier@gentoo.org>
	<1307428609.11104.39.camel@localhost>
Message-ID: <BANLkTikQzMtE6A=zNBU9ADjPKdOeTUzgtg@mail.gmail.com>

On Tue, Jun 7, 2011 at 02:36, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
>> Usage/version information should go to stdout when it is expected behavior
>> (i.e. the user requested it explicitly). ?This info should go to stderr
>> only when the usage info is being shown as a result of incorrect options.
>
> This is fine, but all other ubi utils need this change then as well. I
> think this piece of code was copypasted in all ubi-utils, so you should
> easily find it and change.

you just like making me work :p
-mike


From vapier at gentoo.org  Tue Jun  7 11:02:02 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 11:02:02 -0400
Subject: [PATCH v2] ubi-utils: send help/version info to stdout
In-Reply-To: <1307427548-29306-2-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-2-git-send-email-vapier@gentoo.org>
Message-ID: <1307458922-1082-1-git-send-email-vapier@gentoo.org>

Usage/version information should go to stdout when it is expected behavior
(i.e. the user requested it explicitly).  This info should go to stderr
only when the usage info is being shown as a result of incorrect options.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- convert all ubi-utils

 ubi-utils/src/mtdinfo.c      |    8 ++++----
 ubi-utils/src/ubiattach.c    |    6 +++---
 ubi-utils/src/ubicrc32.c     |    6 +++---
 ubi-utils/src/ubidetach.c    |    6 +++---
 ubi-utils/src/ubiformat.c    |    6 +++---
 ubi-utils/src/ubimkvol.c     |    6 +++---
 ubi-utils/src/ubinfo.c       |    6 +++---
 ubi-utils/src/ubinize.c      |    8 ++++----
 ubi-utils/src/ubirmvol.c     |    6 +++---
 ubi-utils/src/ubirsvol.c     |    6 +++---
 ubi-utils/src/ubiupdatevol.c |    6 +++---
 11 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index 820c16d..666d739 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -111,13 +111,13 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'h':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			printf("%s\n", PROGRAM_VERSION);
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/src/ubiattach.c
index 9297b56..4f18e99 100644
--- a/ubi-utils/src/ubiattach.c
+++ b/ubi-utils/src/ubiattach.c
@@ -123,9 +123,9 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'h':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c
index a09f053..73ec595 100644
--- a/ubi-utils/src/ubicrc32.c
+++ b/ubi-utils/src/ubicrc32.c
@@ -64,9 +64,9 @@ static int parse_opt(int argc, char * const argv[])
 
 		switch (key) {
 		case 'h':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/src/ubidetach.c
index 5ee55f1..668f1bd 100644
--- a/ubi-utils/src/ubidetach.c
+++ b/ubi-utils/src/ubidetach.c
@@ -107,9 +107,9 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'h':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c
index 6e5cdb8..c4b944a 100644
--- a/ubi-utils/src/ubiformat.c
+++ b/ubi-utils/src/ubiformat.c
@@ -211,9 +211,9 @@ static int parse_opt(int argc, char * const argv[])
 
 		case 'h':
 		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c
index 935f068..25065e3 100644
--- a/ubi-utils/src/ubimkvol.c
+++ b/ubi-utils/src/ubimkvol.c
@@ -167,9 +167,9 @@ static int parse_opt(int argc, char * const argv[])
 
 		case 'h':
 		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/src/ubinfo.c
index 2bfee16..8e14e6e 100644
--- a/ubi-utils/src/ubinfo.c
+++ b/ubi-utils/src/ubinfo.c
@@ -118,9 +118,9 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'h':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/src/ubinize.c
index 52a193f..3085b66 100644
--- a/ubi-utils/src/ubinize.c
+++ b/ubi-utils/src/ubinize.c
@@ -227,10 +227,10 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'h':
-			ubiutils_print_text(stderr, doc, 80);
-			fprintf(stderr, "\n%s\n\n", ini_doc);
-			fprintf(stderr, "%s\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			ubiutils_print_text(stdout, doc, 80);
+			printf("\n%s\n\n", ini_doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c
index 5a7217a..5725d90 100644
--- a/ubi-utils/src/ubirmvol.c
+++ b/ubi-utils/src/ubirmvol.c
@@ -111,9 +111,9 @@ static int parse_opt(int argc, char * const argv[])
 
 		case 'h':
 		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubirsvol.c b/ubi-utils/src/ubirsvol.c
index 34321b8..65f579c 100644
--- a/ubi-utils/src/ubirsvol.c
+++ b/ubi-utils/src/ubirsvol.c
@@ -140,9 +140,9 @@ static int parse_opt(int argc, char * const argv[])
 
 		case 'h':
 		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c
index 62f140b..24f38fe 100644
--- a/ubi-utils/src/ubiupdatevol.c
+++ b/ubi-utils/src/ubiupdatevol.c
@@ -97,9 +97,9 @@ static int parse_opt(int argc, char * const argv[])
 
 		case 'h':
 		case '?':
-			fprintf(stderr, "%s\n\n", doc);
-			fprintf(stderr, "%s\n\n", usage);
-			fprintf(stderr, "%s\n", optionsstr);
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 11:11:37 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 11:11:37 -0400
Subject: [PATCH v2] flash_info: deprecate
In-Reply-To: <1307427548-29306-6-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-6-git-send-email-vapier@gentoo.org>
Message-ID: <1307459497-2226-1-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- just deprecate for now rather than straight up removal

 feature-removal-schedule.txt |    7 +++++++
 flash_info.c                 |    2 ++
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index 6e2bfc9..a5980f7 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -32,4 +32,11 @@ We cannot assume that mtd device names follow the "/dev/mtd%d" pattern,
 because it is up to udev rules to name the devices. So we are removing
 the -m option. For now, we just have a warning, but the option will be
 removed in release 1.4.6.
+
+---------------------------
+3. flash_info utility
+
+This is duplicating behavior with the mtdinfo utility.  Now the util
+warns when people use it, but it'll be removed in release 1.4.6.
+
 ---------------------------
diff --git a/flash_info.c b/flash_info.c
index b710034..b15e0a9 100644
--- a/flash_info.c
+++ b/flash_info.c
@@ -73,6 +73,8 @@ int main(int argc, char *argv[])
 {
 	int fd, i, regcount;
 
+	warnmsg("this is deprecated in favor of `mtdinfo`");
+
 	if (argc < 2)
 		usage(1);
 	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 11:16:46 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 11:16:46 -0400
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
In-Reply-To: <1307430979.11104.50.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307430979.11104.50.camel@localhost>
Message-ID: <BANLkTinEya=-wOVrT-D_bQmF2jY857ijZA@mail.gmail.com>

On Tue, Jun 7, 2011 at 03:16, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
>> +int jffs2_lzo_init(void)
>> +{
>> + ? ? return 0;
>> +}
>
> This function should return -1, I think, so that mkfs.jffs2 would fail
> if lzo was not compiled-in.

i didnt do that because the func is always called and i was afraid
that it'd prevent normal execution.  the runtime code should already
fail when lzo is requested because the compression routines are looked
up on the fly and when the requested compressor isnt found, it fails
at that time.  (at least that's my understanding of things)
-mike


From vapier at gentoo.org  Tue Jun  7 11:28:02 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 11:28:02 -0400
Subject: [PATCH v2] libmtd: add helper funcs for getting regioninfo and locked
	info
In-Reply-To: <1307427548-29306-4-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-4-git-send-email-vapier@gentoo.org>
Message-ID: <1307460482-3745-1-git-send-email-vapier@gentoo.org>

This extends the libmtd with the helper functions:
	mtd_regioninfo: interface to MEMGETREGIONINFO
	mtd_islocked: interface to MEMISLOCKED

Users of these functions will follow shortly ...

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- drop the open-by-mtd-num func

 include/libmtd.h |   28 ++++++++++++++++++++++++++++
 lib/libmtd.c     |   32 ++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+), 0 deletions(-)

diff --git a/include/libmtd.h b/include/libmtd.h
index e30c8a6..7275246 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -35,6 +35,9 @@ extern "C" {
 /* MTD library descriptor */
 typedef void * libmtd_t;
 
+/* Forward decls */
+struct region_info_user;
+
 /**
  * @mtd_dev_cnt: count of MTD devices in system
  * @lowest_mtd_num: lowest MTD device number in system
@@ -174,6 +177,31 @@ int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb);
 int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
 
 /**
+ * mtd_regioninfo - get information about an erase region.
+ * @fd: MTD device node file descriptor
+ * @regidx: index of region to look up
+ * @reginfo: the region information is returned here
+ *
+ * This function gets information about an erase region defined by the
+ * @regidx index and saves this information in the @reginfo object.
+ * Returns %0 in case of success and %-1 in case of failure. If the
+ * @regidx is not valid or unavailable, errno is set to @ENODEV.
+ */
+int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo);
+
+/**
+ * mtd_islocked - see if the specified eraseblock is locked.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to check
+ *
+ * This function checks to see if eraseblock @eb of MTD device described
+ * by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and
+ * %-1 in case of failure.
+ */
+int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
  * mtd_torture - torture an eraseblock.
  * @desc: MTD library descriptor
  * @mtd: MTD device description object
diff --git a/lib/libmtd.c b/lib/libmtd.c
index a651808..0086a85 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -883,6 +883,38 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
 	return 0;
 }
 
+int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
+{
+	int ret;
+
+	if (regidx < 0) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	ret = ioctl(fd, MEMGETREGIONINFO, reginfo);
+	if (ret < 0)
+		return sys_errmsg("%s ioctl failed for erase region %d",
+			"MEMGETREGIONINFO", regidx);
+
+	return 0;
+}
+
+int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int ret;
+	erase_info_t ei;
+
+	ei.start = eb * mtd->eb_size;
+	ei.length = mtd->eb_size;
+
+	ret = ioctl(fd, MEMISLOCKED, &ei);
+	if (ret < 0)
+		return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
+
+	return ret;
+}
+
 /* Patterns to write to a physical eraseblock when torturing it */
 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
 
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 11:31:02 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue, 7 Jun 2011 11:31:02 -0400
Subject: [PATCH 5/6] mtdinfo: add regioninfo/sectormap display
In-Reply-To: <1307432463.11104.65.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-5-git-send-email-vapier@gentoo.org>
	<1307432463.11104.65.camel@localhost>
Message-ID: <BANLkTimY1DwxBBi=peQzqwoLktgVna-0KA@mail.gmail.com>

On Tue, Jun 7, 2011 at 03:41, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
>> @@ -58,14 +60,15 @@ static const char optionsstr[] =
>> ?"-m, --mtdn=<MTD device number> ?MTD device number to get information about\n"
>> ?"-u, --ubi-info ? ? ? ? ? ? ? ? ?print what would UBI layout be if it was put\n"
>> ?" ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?on this MTD device\n"
>> +"-s, --sector-map ? ? ? ? ? ? ? ?print sector map\n"
>> ?"-a, --all ? ? ? ? ? ? ? ? ? ? ? print information about all MTD devices\n"
>> ?"-h, --help ? ? ? ? ? ? ? ? ? ? ?print help message\n"
>> ?"-V, --version ? ? ? ? ? ? ? ? ? print program version";
>>
>> ?static const char usage[] =
>> -"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-h] [-V] [--mtdn <MTD device number>]\n"
>> +"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-s] [-h] [-V] [--mtdn <MTD device number>]\n"
>> ?"\t\t[--ubi-info] [--help] [--version]\n"
>> -"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-h] [-V] [--ubi-info] [--help]\n"
>> +"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-s] [-h] [-V] [--ubi-info] [--help]\n"
>> ?"\t\t[--version]\n"
>> ?"Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
>> ?"Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
>> @@ -78,6 +81,7 @@ static const char usage[] =
>> ?static const struct option long_options[] = {
>> ? ? ? { .name = "mtdn", ? ? ?.has_arg = 1, .flag = NULL, .val = 'm' },
>> ? ? ? { .name = "ubi-info", ?.has_arg = 0, .flag = NULL, .val = 'u' },
>> + ? ? { .name = "sector-map",.has_arg = 0, .flag = NULL, .val = 's' },
>
> Is sector-map a good name?

it's what i'm used to calling it ;)

> May be we should call this feature "lock
> info" or something which suggests this is about detailed lock
> information? In this case you should also print an error message if the
> ISLOCKED ioctl is not supported. Probably adding a "islocked_supported"
> flag to 'struct mtd_info' (similarly to sysfs_supported) makes sense?
> Then you could just check this flag and refuse -s option?

honestly, i was more interested in the sector map than the ISLOCKED
info.  that was just a bonus for me.

> Also, could we avoid using term sector because it is overloaded and
> confusing. Could you please use term "eraseblock" instead (in prints and
> in internal names)?

ok

> Or you meant that this is like general per-sector info? So if we have
> more information to print, we add it there? In this case, could you
> please print "bad" or something for bad eraseblocks as well?

if MEMGETBADBLOCK provides that info, should be easy to add
-mike


From dbaryshkov at gmail.com  Tue Jun  7 11:48:58 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue,  7 Jun 2011 19:48:58 +0400
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <20110607134429.GE21174@pulham.picochip.com>
References: <20110607134429.GE21174@pulham.picochip.com>
Message-ID: <1307461738-16811-1-git-send-email-dbaryshkov@gmail.com>

Lots (nearly all) mtd drivers contain nearly the similar code that
calls parse_mtd_partitions, provides some platform-default values, if
parsing fails, and registers  mtd device.

This is an aim to provide single implementation of this scenario:
mtd_device_parse_register() which will handle all this parsing and
defaults.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c   |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/mtd.h |    5 +++++
 2 files changed, 52 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c510aff..d538e0a 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -452,6 +452,53 @@ int mtd_device_register(struct mtd_info *master,
 EXPORT_SYMBOL_GPL(mtd_device_register);
 
 /**
+ * mtd_device_parse_register - register an MTD device.
+ *
+ * @mtd: the MTD device to register
+ * @part_probe_types: the list of MTD partition probes to try
+ * @origin: start address of MTD device. =0 unless you are sure you need this.
+ * @defparts: default partition information to register. Only valid if
+ *		defnr_parts > 0
+ * @defnr_parts: the number of partitions in defparts.  If zero then the full
+ *		MTD device is registered if no partition info is found
+ *
+ * Extract partition info and register MTD device (partitions or a whole device)
+ * It calls parse_mtd_partitions(), checks the result. If there were no
+ * partitions found, it uses default info specified (via defparts/defnr_parts)
+ * and then registers either partitions, or (if no partitions were
+ * found/specified) the whow MTD.
+ */
+int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts)
+{
+	int err;
+	struct mtd_partition *parts;
+
+	err = parse_mtd_partitions(mtd, part_probe_types, &parts, origin);
+	if (err <= 0 && defnr_parts) {
+		parts = kmemdup(defparts, sizeof(*parts) * defnr_parts,
+				GFP_KERNEL);
+		if (!parts)
+			err = -ENOMEM;
+	}
+
+	if (err > 0) {
+		err = add_mtd_partitions(mtd, parts, err);
+		kfree(parts);
+	} else if (err == 0) {
+		err = add_mtd_device(mtd);
+		if (err == 1)
+			err = -ENODEV;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(mtd_device_parse_register);
+
+/**
  * mtd_device_unregister - unregister an existing MTD device.
  *
  * @master: the MTD device to unregister.  This will unregister both the master
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 2541fb8..d28a241 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -327,6 +327,11 @@ struct mtd_partition;
 extern int mtd_device_register(struct mtd_info *master,
 			       const struct mtd_partition *parts,
 			       int nr_parts);
+extern int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts);
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
-- 
1.7.4.4



From vapier at gentoo.org  Tue Jun  7 11:52:05 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 11:52:05 -0400
Subject: [PATCH v3] libmtd: add helper funcs for getting regioninfo and locked
	info
In-Reply-To: <1307460482-3745-1-git-send-email-vapier@gentoo.org>
References: <1307460482-3745-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307461925-6420-1-git-send-email-vapier@gentoo.org>

This extends the libmtd with the helper functions:
	mtd_regioninfo: interface to MEMGETREGIONINFO
	mtd_islocked: interface to MEMISLOCKED

Users of these functions will follow shortly ...

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v3
	- add a "islocked_supported" field to handle older kernels nicely

 include/libmtd.h |   28 ++++++++++++++++++++++++++++
 lib/libmtd.c     |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 lib/libmtd_int.h |    1 +
 3 files changed, 76 insertions(+), 0 deletions(-)

diff --git a/include/libmtd.h b/include/libmtd.h
index e30c8a6..2da12c3 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -35,6 +35,9 @@ extern "C" {
 /* MTD library descriptor */
 typedef void * libmtd_t;
 
+/* Forward decls */
+struct region_info_user;
+
 /**
  * @mtd_dev_cnt: count of MTD devices in system
  * @lowest_mtd_num: lowest MTD device number in system
@@ -174,6 +177,31 @@ int mtd_unlock(const struct mtd_dev_info *mtd, int fd, int eb);
 int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
 
 /**
+ * mtd_regioninfo - get information about an erase region.
+ * @fd: MTD device node file descriptor
+ * @regidx: index of region to look up
+ * @reginfo: the region information is returned here
+ *
+ * This function gets information about an erase region defined by the
+ * @regidx index and saves this information in the @reginfo object.
+ * Returns %0 in case of success and %-1 in case of failure. If the
+ * @regidx is not valid or unavailable, errno is set to @ENODEV.
+ */
+int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo);
+
+/**
+ * mtd_is_locked - see if the specified eraseblock is locked.
+ * @mtd: MTD device description object
+ * @fd: MTD device node file descriptor
+ * @eb: eraseblock to check
+ *
+ * This function checks to see if eraseblock @eb of MTD device described
+ * by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and
+ * %-1 in case of failure.
+ */
+int mtd_is_locked(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
+
+/**
  * mtd_torture - torture an eraseblock.
  * @desc: MTD library descriptor
  * @mtd: MTD device description object
diff --git a/lib/libmtd.c b/lib/libmtd.c
index a651808..d6094c1 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -557,6 +557,7 @@ libmtd_t libmtd_open(void)
 	lib = xzalloc(sizeof(*lib));
 
 	lib->offs64_ioctls = OFFS64_IOCTLS_UNKNOWN;
+	lib->islocked_ioctl = 1;
 
 	lib->sysfs_mtd = mkpath("/sys", SYSFS_MTD);
 	if (!lib->sysfs_mtd)
@@ -883,6 +884,52 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
 	return 0;
 }
 
+int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
+{
+	int ret;
+
+	if (regidx < 0) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	ret = ioctl(fd, MEMGETREGIONINFO, reginfo);
+	if (ret < 0)
+		return sys_errmsg("%s ioctl failed for erase region %d",
+			"MEMGETREGIONINFO", regidx);
+
+	return 0;
+}
+
+int mtd_is_locked(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb)
+{
+	int ret;
+	struct libmtd *lib = (struct libmtd *)desc;
+	erase_info_t ei;
+
+	if (lib->islocked_ioctl == 0)
+		return -1;
+
+	ei.start = eb * mtd->eb_size;
+	ei.length = mtd->eb_size;
+
+	ret = ioctl(fd, MEMISLOCKED, &ei);
+	if (ret < 0) {
+		if (errno == ENOTTY) {
+			/* An old system w/out MEMISLOCKED */
+			lib->islocked_ioctl = 0;
+			return -1;
+		} else if (errno == EOPNOTSUPP) {
+			/* MTD doesn't support locking */
+			lib->islocked_ioctl = 0;
+			return -1;
+		}
+		return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
+	}
+
+	return ret;
+}
+
 /* Patterns to write to a physical eraseblock when torturing it */
 static uint8_t patterns[] = {0xa5, 0x5a, 0x0};
 
diff --git a/lib/libmtd_int.h b/lib/libmtd_int.h
index bb48d35..87e7f12 100644
--- a/lib/libmtd_int.h
+++ b/lib/libmtd_int.h
@@ -91,6 +91,7 @@ struct libmtd
 	char *mtd_region_cnt;
 	char *mtd_flags;
 	unsigned int sysfs_supported:1;
+	unsigned int islocked_ioctl:1;
 	unsigned int offs64_ioctls:2;
 };
 
-- 
1.7.5.3



From vapier at gentoo.org  Tue Jun  7 11:53:19 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Tue,  7 Jun 2011 11:53:19 -0400
Subject: [PATCH v2] mtdinfo: add regioninfo/eraseblock map display
In-Reply-To: <1307427548-29306-5-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-5-git-send-email-vapier@gentoo.org>
Message-ID: <1307461999-6483-1-git-send-email-vapier@gentoo.org>

This brings the mtdinfo utility in line with the functionality
of the flash_info utility.  It dumps the erase regioninfo (if
the devices has it) as well as showing a handy eraseblock map
(if the user has requested it).  The eraseblock map also shows
which blocks are locked and which ones are bad.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- rename sector map to eraseblock map
	- include bad block info in map
	- update libmtd api calls

 ubi-utils/src/mtdinfo.c |   82 ++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index 666d739..5572199 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -29,6 +29,7 @@
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <mtd/mtd-user.h>
 
 #include <libubigen.h>
@@ -41,6 +42,7 @@ struct args {
 	int mtdn;
 	unsigned int all:1;
 	unsigned int ubinfo:1;
+	unsigned int map:1;
 	const char *node;
 };
 
@@ -59,14 +61,15 @@ static const char optionsstr[] =
 "                                (deprecated option, will be removed, do not use)\n"
 "-u, --ubi-info                  print what would UBI layout be if it was put\n"
 "                                on this MTD device\n"
+"-M, --map                       print eraseblock map\n"
 "-a, --all                       print information about all MTD devices\n"
 "-h, --help                      print help message\n"
 "-V, --version                   print program version";
 
 static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-h] [-V] [--mtdn <MTD device number>]\n"
+"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n"
 "\t\t[--ubi-info] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-h] [-V] [--ubi-info] [--help]\n"
+"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
 "\t\t[--version]\n"
 "Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
 "Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
@@ -79,6 +82,7 @@ static const char usage[] =
 static const struct option long_options[] = {
 	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
 	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
+	{ .name = "map",       .has_arg = 0, .flag = NULL, .val = 'M' },
 	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
 	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
 	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
@@ -90,7 +94,7 @@ static int parse_opt(int argc, char * const argv[])
 	while (1) {
 		int key, error = 0;
 
-		key = getopt_long(argc, argv, "am:uhV", long_options, NULL);
+		key = getopt_long(argc, argv, "am:uMhV", long_options, NULL);
 		if (key == -1)
 			break;
 
@@ -110,6 +114,10 @@ static int parse_opt(int argc, char * const argv[])
 			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
 			break;
 
+		case 'M':
+			args.map = 1;
+			break;
+
 		case 'h':
 			printf("%s\n\n", doc);
 			printf("%s\n\n", usage);
@@ -160,9 +168,40 @@ static int translate_dev(libmtd_t libmtd, const char *node)
 	return 0;
 }
 
+static void print_map(libmtd_t libmtd, const struct mtd_dev_info *mtd,
+		      int fd, const region_info_t *reginfo)
+{
+	unsigned long start;
+	int i, width;
+
+	printf("Eraseblock map:\n");
+
+	/* figure out the number of spaces to pad w/out libm */
+	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
+		continue;
+
+	for (i = 0; i < reginfo->numblocks; ++i) {
+		start = reginfo->offset + i * reginfo->erasesize;
+		printf(" %*i: %08lx ", width, i, start);
+		if (mtd_is_locked(libmtd, mtd, fd, i) == 1)
+			printf("RO ");
+		else
+			printf("   ");
+		if (mtd_is_bad(mtd, fd, i) == 1)
+			printf("BAD ");
+		else
+			printf("    ");
+		if (((i + 1) % 4) == 0)
+			printf("\n");
+	}
+	if (i % 4)
+		printf("\n");
+}
+
 static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
 {
-	int err;
+	int err, fd = -1;
+	region_info_t reginfo;
 	struct mtd_dev_info mtd;
 	struct ubigen_info ui;
 
@@ -196,8 +235,26 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	if (mtd.oob_size > 0)
 		printf("OOB size:                       %d bytes\n",
 		       mtd.oob_size);
-	if (mtd.region_cnt > 0)
+	if (mtd.region_cnt > 0) {
 		printf("Additional erase regions:       %d\n", mtd.oob_size);
+		if (args.node)
+			fd = open(args.node, O_RDONLY | O_CLOEXEC);
+		if (fd != -1) {
+			int r;
+
+			for (r = 0; r < mtd.region_cnt; ++r) {
+				printf(" region %i: ", r);
+				if (mtd_regioninfo(fd, r, &reginfo) == 0) {
+					printf(" offset: %#x size: %#x numblocks: %#x\n",
+						reginfo.offset, reginfo.erasesize,
+						reginfo.numblocks);
+					if (args.map)
+						print_map(libmtd, &mtd, fd, &reginfo);
+				} else
+					printf(" info is unavailable\n");
+			}
+		}
+	}
 	if (mtd_info->sysfs_supported)
 		printf("Character device major/minor:   %d:%d\n",
 		       mtd.major, mtd.minor);
@@ -225,6 +282,21 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
 
 out:
+	if (args.map && mtd.region_cnt == 0 && args.node) {
+		if (fd == -1)
+			fd = open(args.node, O_RDONLY | O_CLOEXEC);
+		if (fd != -1) {
+			reginfo.offset = 0;
+			reginfo.erasesize = mtd.eb_size;
+			reginfo.numblocks = mtd.eb_cnt;
+			reginfo.regionindex = 0;
+			print_map(libmtd, &mtd, fd, &reginfo);
+		}
+	}
+
+	if (fd != -1)
+		close(fd);
+
 	printf("\n");
 	return 0;
 }
-- 
1.7.5.3



From mlcreech at gmail.com  Tue Jun  7 16:41:16 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Tue, 7 Jun 2011 16:41:16 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307421266.11104.10.camel@localhost>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
	<1307421266.11104.10.camel@localhost>
Message-ID: <BANLkTikKVMQFxtE0S1VL4-SUPWNydgexLw@mail.gmail.com>

On Tue, Jun 7, 2011 at 12:34 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> No, I have difficulties reading hexdumps. You have set of good nodes
> following by one broken node. I wanted to see a human-readable dump of
> the good nodes at the beginning of the LEB.
>

Oh I see - sorry, I thought you wanted to debug the corrupted portion.

Here's the output for my corrupt flash:

http://mcreech.com/work/ubifs-2011-06-07.txt

I'll follow up with a patch.

-- 
Matthew L. Creech


From mlcreech at gmail.com  Tue Jun  7 16:52:47 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Tue,  7 Jun 2011 16:52:47 -0400
Subject: [PATCH] UBIFS: optionally return partial LEB scan results
Message-ID: <1307479967-3909-1-git-send-email-mlcreech@gmail.com>

ubifs_scan() currently returns -EUCLEAN when it encounters corrupted data
while scanning a LEB.  This is usually the right thing to do, but it prevents
us from debugging certain kinds of corruption, since ubifs_scan() is called
from dbg_dump_leb().

Add a flag which makes ubifs_scan() return partial node data when corruption
is encountered, and use that flag in dbg_dump_leb().

Signed-off-by: Matthew L. Creech <mlcreech at gmail.com>
---
 fs/ubifs/debug.c      |    2 +-
 fs/ubifs/gc.c         |    2 +-
 fs/ubifs/log.c        |    2 +-
 fs/ubifs/lprops.c     |    2 +-
 fs/ubifs/master.c     |    4 ++--
 fs/ubifs/orphan.c     |    4 ++--
 fs/ubifs/recovery.c   |    2 +-
 fs/ubifs/replay.c     |    4 ++--
 fs/ubifs/scan.c       |   16 ++++++++++++----
 fs/ubifs/tnc_commit.c |    2 +-
 fs/ubifs/ubifs.h      |    2 +-
 11 files changed, 25 insertions(+), 17 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 26d4c61..d6239d2 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -898,7 +898,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 		return;
 	}
 
-	sleb = ubifs_scan(c, lnum, 0, buf, 0);
+	sleb = ubifs_scan(c, lnum, 0, buf, 0, 1);
 	if (IS_ERR(sleb)) {
 		ubifs_err("scan error %d", (int)PTR_ERR(sleb));
 		goto out;
diff --git a/fs/ubifs/gc.c b/fs/ubifs/gc.c
index ded29f6..5266dc6 100644
--- a/fs/ubifs/gc.c
+++ b/fs/ubifs/gc.c
@@ -513,7 +513,7 @@ int ubifs_garbage_collect_leb(struct ubifs_info *c, struct ubifs_lprops *lp)
 	 * We scan the entire LEB even though we only really need to scan up to
 	 * (c->leb_size - lp->free).
 	 */
-	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0);
+	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0, 0);
 	if (IS_ERR(sleb))
 		return PTR_ERR(sleb);
 
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index affea94..472aff6 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -662,7 +662,7 @@ int ubifs_consolidate_log(struct ubifs_info *c)
 	lnum = c->ltail_lnum;
 	write_lnum = lnum;
 	while (1) {
-		sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0);
+		sleb = ubifs_scan(c, lnum, 0, c->sbuf, 0, 0);
 		if (IS_ERR(sleb)) {
 			err = PTR_ERR(sleb);
 			goto out_free;
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index 98b8e73..2384463 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -1105,7 +1105,7 @@ static int scan_check_cb(struct ubifs_info *c,
 		return LPT_SCAN_CONTINUE;
 	}
 
-	sleb = ubifs_scan(c, lnum, 0, buf, 0);
+	sleb = ubifs_scan(c, lnum, 0, buf, 0, 0);
 	if (IS_ERR(sleb)) {
 		ret = PTR_ERR(sleb);
 		if (ret == -EUCLEAN) {
diff --git a/fs/ubifs/master.c b/fs/ubifs/master.c
index 278c238..8b86712 100644
--- a/fs/ubifs/master.c
+++ b/fs/ubifs/master.c
@@ -41,7 +41,7 @@ static int scan_for_master(struct ubifs_info *c)
 
 	lnum = UBIFS_MST_LNUM;
 
-	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
+	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1, 0);
 	if (IS_ERR(sleb))
 		return PTR_ERR(sleb);
 	nodes_cnt = sleb->nodes_cnt;
@@ -57,7 +57,7 @@ static int scan_for_master(struct ubifs_info *c)
 
 	lnum += 1;
 
-	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
+	sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1, 0);
 	if (IS_ERR(sleb))
 		return PTR_ERR(sleb);
 	if (sleb->nodes_cnt != nodes_cnt)
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index a5422ff..76fba30 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -670,7 +670,7 @@ static int kill_orphans(struct ubifs_info *c)
 		struct ubifs_scan_leb *sleb;
 
 		dbg_rcvry("LEB %d", lnum);
-		sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1);
+		sleb = ubifs_scan(c, lnum, 0, c->sbuf, 1, 0);
 		if (IS_ERR(sleb)) {
 			if (PTR_ERR(sleb) == -EUCLEAN)
 				sleb = ubifs_recover_leb(c, lnum, 0,
@@ -908,7 +908,7 @@ static int dbg_scan_orphans(struct ubifs_info *c, struct check_info *ci)
 	for (lnum = c->orph_first; lnum <= c->orph_last; lnum++) {
 		struct ubifs_scan_leb *sleb;
 
-		sleb = ubifs_scan(c, lnum, 0, buf, 0);
+		sleb = ubifs_scan(c, lnum, 0, buf, 0, 0);
 		if (IS_ERR(sleb)) {
 			err = PTR_ERR(sleb);
 			break;
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 783d8e0..2456dd0 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -878,7 +878,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 		 * We can only recover at the end of the log, so check that the
 		 * next log LEB is empty or out of date.
 		 */
-		sleb = ubifs_scan(c, next_lnum, 0, sbuf, 0);
+		sleb = ubifs_scan(c, next_lnum, 0, sbuf, 0, 0);
 		if (IS_ERR(sleb))
 			return sleb;
 		if (sleb->nodes_cnt) {
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 5e97161..53eb2bb 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -559,7 +559,7 @@ static int replay_bud(struct ubifs_info *c, struct bud_entry *b)
 		 */
 		sleb = ubifs_recover_leb(c, lnum, offs, c->sbuf, b->bud->jhead);
 	else
-		sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0);
+		sleb = ubifs_scan(c, lnum, offs, c->sbuf, 0, 0);
 	if (IS_ERR(sleb))
 		return PTR_ERR(sleb);
 
@@ -832,7 +832,7 @@ static int replay_log_leb(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 	const struct ubifs_cs_node *node;
 
 	dbg_mnt("replay log LEB %d:%d", lnum, offs);
-	sleb = ubifs_scan(c, lnum, offs, sbuf, c->need_recovery);
+	sleb = ubifs_scan(c, lnum, offs, sbuf, c->need_recovery, 0);
 	if (IS_ERR(sleb)) {
 		if (PTR_ERR(sleb) != -EUCLEAN || !c->need_recovery)
 			return PTR_ERR(sleb);
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 36216b4..3f70d47 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -256,17 +256,21 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
  * @offs: offset to start at (usually zero)
  * @sbuf: scan buffer (must be of @c->leb_size bytes in size)
  * @quiet: print no messages
+ * @partial: return partial results when corruption is encountered (vs. error)
  *
  * This function scans LEB number @lnum and returns complete information about
- * its contents. Returns the scaned information in case of success and,
- * %-EUCLEAN if the LEB neads recovery, and other negative error codes in case
- * of failure.
+ * its contents. Returns the scaned information in case of success,
+ * %-EUCLEAN if the LEB neads recovery (and @partial is not set), and other
+ * negative error codes in case of failure.
  *
  * If @quiet is non-zero, this function does not print large and scary
  * error messages and flash dumps in case of errors.
+ *
+ * If @partial is non-zero, this function returns partial scan data if the LEB
+ * is corrupt.  This can be useful for debugging.
  */
 struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
-				  int offs, void *sbuf, int quiet)
+				  int offs, void *sbuf, int quiet, int partial)
 {
 	void *buf = sbuf + offs;
 	int err, len = c->leb_size - offs;
@@ -352,6 +356,10 @@ corrupted:
 		ubifs_err("LEB %d scanning failed", lnum);
 	}
 	err = -EUCLEAN;
+	if (partial) {
+		dbg_err("returning partial results for %d:%d", lnum, offs);
+		return sleb;
+	}
 	ubifs_scan_destroy(sleb);
 	return ERR_PTR(err);
 
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index d6fab1a..f831abd 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -249,7 +249,7 @@ static int layout_leb_in_gaps(struct ubifs_info *c, int *p)
 	 * it is more comprehensive and less efficient than is needed for this
 	 * purpose.
 	 */
-	sleb = ubifs_scan(c, lnum, 0, c->ileb_buf, 0);
+	sleb = ubifs_scan(c, lnum, 0, c->ileb_buf, 0, 0);
 	c->ileb_len = 0;
 	if (IS_ERR(sleb))
 		return PTR_ERR(sleb);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 3304aad..dfa5012 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1491,7 +1491,7 @@ int ubifs_sync_wbufs_by_inode(struct ubifs_info *c, struct inode *inode);
 
 /* scan.c */
 struct ubifs_scan_leb *ubifs_scan(const struct ubifs_info *c, int lnum,
-				  int offs, void *sbuf, int quiet);
+				  int offs, void *sbuf, int quiet, int partial);
 void ubifs_scan_destroy(struct ubifs_scan_leb *sleb);
 int ubifs_scan_a_node(const struct ubifs_info *c, void *buf, int len, int lnum,
 		      int offs, int quiet);
-- 
1.6.3.3



From computersforpeace at gmail.com  Tue Jun  7 18:57:22 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 7 Jun 2011 15:57:22 -0700
Subject: [PATCH 1/2] mtd: nand: generalized error messages with __func__
In-Reply-To: <4DEDD2A3.8030408@compulab.co.il>
References: <1306360741-12770-1-git-send-email-computersforpeace@gmail.com>
	<4DDDE19D.9010505@compulab.co.il>
	<1306387008.2785.138.camel@localhost>
	<BANLkTimsTWAcR4HgOoHguDMv9P-Eox=kbg@mail.gmail.com>
	<1306924235.4405.102.camel@localhost>
	<BANLkTi=BYeQ+cBMpRodDDY_KapjEoHVA+A@mail.gmail.com>
	<4DEDD2A3.8030408@compulab.co.il>
Message-ID: <BANLkTimo0iHCmgc1wfSG=1OUO8f0G2Vccg@mail.gmail.com>

On Tue, Jun 7, 2011 at 12:26 AM, Igor Grinberg <grinberg at compulab.co.il> wrote:
> You should not define pr_fmt() in .h file.
> pr_fmt() should be defined in _.c_ file at the top - _before any include is done_.
> And yes, like Artem already said, _only_ in those _.c_ files where we want to use it.

Hmm, well I guess I'll try defining pr_fmt() in nand_bbt.c only. Look
for the following patchset shortly:
* removing those printk's when a memory allocations fail
* changing other printk's to pr_*'s
* changing some DEBUG messages to dev_dbg
* define pr_fmt() to include __func__ in debug messages for nand_bbt.c

The only inconsistency with the 4th patch is that it adds the __func__
prefix to some print messages that didn't have them previously. Thus,
I'd be fine if the 4th patch is dropped.

Thanks,
Brian


From computersforpeace at gmail.com  Tue Jun  7 19:01:57 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 7 Jun 2011 16:01:57 -0700
Subject: [PATCH 4/4] mtd: nand: define pr_fmt() to include __func__ in
	debug output
In-Reply-To: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307487717-25402-5-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_bbt.c |   23 ++++++++++++-----------
 1 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 4d18098..e2c9948 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -59,6 +59,8 @@
  *
  */
 
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
@@ -205,10 +207,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		res = mtd->read(mtd, from, len, &retlen, buf);
 		if (res < 0) {
 			if (retlen != len) {
-				pr_info("nand_bbt: Error reading bad block table\n");
+				pr_info("Error reading bad block table\n");
 				return res;
 			}
-			pr_warn("nand_bbt: ECC error while reading bad block table\n");
+			pr_warn("ECC error while reading bad block table\n");
 		}
 
 		/* Analyse data */
@@ -219,13 +221,13 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
-					pr_debug("nand_read_bbt: Reserved block at 0x%012llx\n",
+					pr_debug("Reserved block at 0x%012llx\n",
 					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
-				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
+				pr_debug("Bad block at 0x%012llx\n",
 				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
@@ -491,7 +493,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = 0;
 	} else {
 		if (chip >= this->numchips) {
-			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
+			pr_warn("chipnr (%d) > available chips (%d)\n",
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
@@ -754,14 +756,13 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			res = mtd->read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
-					pr_info("nand_bbt: Error "
+					pr_info("Error "
 					       "reading block for writing "
 					       "the bad block table\n");
 					return res;
 				}
-				pr_warn("nand_bbt: ECC error "
-				       "while reading block for writing "
-				       "bad block table\n");
+				pr_warn("ECC error while reading block for "
+					"writing bad block table\n");
 			}
 			/* Read oob data */
 			ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
@@ -845,7 +846,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	return 0;
 
  outerr:
-	pr_warning("nand_bbt: Error while writing bad block table %d\n", res);
+	pr_warning("Error while writing bad block table %d\n", res);
 	return res;
 }
 
@@ -1125,7 +1126,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	 */
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
-			pr_err("nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			pr_err("Can't scan flash and build the RAM-based BBT\n");
 			kfree(this->bbt);
 			this->bbt = NULL;
 		}
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun  7 19:01:53 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 7 Jun 2011 16:01:53 -0700
Subject: [PATCH 0/4] debug, printk cleanup
Message-ID: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>

These patches come from discussion at:
http://lists.infradead.org/pipermail/linux-mtd/2011-June/036161.html

They are based on the mtd-2.6 git tree, plus a few of the cleanup
patches already in Artem's l2 git tree.

Note:
The 4th patch adds the __func__ prefix to some print messages that
didn't have them previously. Thus, I'd be fine if the 4th patch is
dropped.

Thanks,
Brian

Brian Norris (4):
  mtd: remove printk's for [kv][mz]alloc failures
  mtd: nand: convert printk() to pr_*()
  mtd: nand: replace DEBUG() with dev_dbg()
  mtd: nand: define pr_fmt() to include __func__ in debug output

 drivers/mtd/cmdlinepart.c         |    3 -
 drivers/mtd/inftlcore.c           |    4 +-
 drivers/mtd/nand/nand_base.c      |   90 ++++++++++++++++++------------------
 drivers/mtd/nand/nand_bbt.c       |   66 +++++++++++---------------
 drivers/mtd/nand/rtc_from4.c      |    1 -
 drivers/mtd/nftlcore.c            |    4 +-
 drivers/mtd/onenand/onenand_bbt.c |    4 +-
 drivers/mtd/ssfdc.c               |   10 +---
 8 files changed, 78 insertions(+), 104 deletions(-)




From computersforpeace at gmail.com  Tue Jun  7 19:01:54 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 7 Jun 2011 16:01:54 -0700
Subject: [PATCH 1/4] mtd: remove printk's for [kv][mz]alloc failures
In-Reply-To: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307487717-25402-2-git-send-email-computersforpeace@gmail.com>

When a memory allocation fails, the kernel will print out a backtrace
automatically. These print statements are unnecessary.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/cmdlinepart.c         |    3 ---
 drivers/mtd/inftlcore.c           |    4 +---
 drivers/mtd/nand/nand_bbt.c       |   13 +++----------
 drivers/mtd/nand/rtc_from4.c      |    1 -
 drivers/mtd/nftlcore.c            |    4 +---
 drivers/mtd/onenand/onenand_bbt.c |    4 +---
 drivers/mtd/ssfdc.c               |   10 ++--------
 7 files changed, 8 insertions(+), 31 deletions(-)

diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index e790f38..be0c121 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -188,10 +188,7 @@ static struct mtd_partition * newpart(char *s,
 			     extra_mem_size;
 		parts = kzalloc(alloc_size, GFP_KERNEL);
 		if (!parts)
-		{
-			printk(KERN_ERR ERRP "out of memory\n");
 			return NULL;
-		}
 		extra_mem = (unsigned char *)(parts + *num_parts);
 	}
 	/* enter this partition (offset will be calculated later if it is zero at this point) */
diff --git a/drivers/mtd/inftlcore.c b/drivers/mtd/inftlcore.c
index d7592e6..c9a31e6 100644
--- a/drivers/mtd/inftlcore.c
+++ b/drivers/mtd/inftlcore.c
@@ -67,10 +67,8 @@ static void inftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 
 	inftl = kzalloc(sizeof(*inftl), GFP_KERNEL);
 
-	if (!inftl) {
-		printk(KERN_WARNING "INFTL: Out of memory for data structures\n");
+	if (!inftl)
 		return;
-	}
 
 	inftl->mbd.mtd = mtd;
 	inftl->mbd.devnum = -1;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index ba40166..8875d6d 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -1121,10 +1121,8 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	 * table.
 	 */
 	this->bbt = kzalloc(len, GFP_KERNEL);
-	if (!this->bbt) {
-		printk(KERN_ERR "nand_scan_bbt: Out of memory\n");
+	if (!this->bbt)
 		return -ENOMEM;
-	}
 
 	/*
 	 * If no primary table decriptor is given, scan the device to build a
@@ -1146,7 +1144,6 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	len += (len >> this->page_shift) * mtd->oobsize;
 	buf = vmalloc(len);
 	if (!buf) {
-		printk(KERN_ERR "nand_bbt: Out of memory\n");
 		kfree(this->bbt);
 		this->bbt = NULL;
 		return -ENOMEM;
@@ -1195,10 +1192,8 @@ int nand_update_bbt(struct mtd_info *mtd, loff_t offs)
 	len = (1 << this->bbt_erase_shift);
 	len += (len >> this->page_shift) * mtd->oobsize;
 	buf = kmalloc(len, GFP_KERNEL);
-	if (!buf) {
-		printk(KERN_ERR "nand_update_bbt: Out of memory\n");
+	if (!buf)
 		return -ENOMEM;
-	}
 
 	writeops = md != NULL ? 0x03 : 0x01;
 
@@ -1307,10 +1302,8 @@ static int nand_create_default_bbt_descr(struct nand_chip *this)
 		return -EINVAL;
 	}
 	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-	if (!bd) {
-		printk(KERN_ERR "nand_create_default_bbt_descr: Out of memory\n");
+	if (!bd)
 		return -ENOMEM;
-	}
 	bd->options = this->bbt_options;
 	bd->offs = this->badblockpos;
 	bd->len = (this->options & NAND_BUSWIDTH_16) ? 2 : 1;
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index c9f9127..a07da2a 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -444,7 +444,6 @@ static int rtc_from4_errstat(struct mtd_info *mtd, struct nand_chip *this,
 		len = mtd->writesize;
 		buf = kmalloc(len, GFP_KERNEL);
 		if (!buf) {
-			printk(KERN_ERR "rtc_from4_errstat: Out of memory!\n");
 			er_stat = 1;
 			goto out;
 		}
diff --git a/drivers/mtd/nftlcore.c b/drivers/mtd/nftlcore.c
index b155666..f3b3239 100644
--- a/drivers/mtd/nftlcore.c
+++ b/drivers/mtd/nftlcore.c
@@ -67,10 +67,8 @@ static void nftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 
 	nftl = kzalloc(sizeof(struct NFTLrecord), GFP_KERNEL);
 
-	if (!nftl) {
-		printk(KERN_WARNING "NFTL: out of memory for data structures\n");
+	if (!nftl)
 		return;
-	}
 
 	nftl->mbd.mtd = mtd;
 	nftl->mbd.devnum = -1;
diff --git a/drivers/mtd/onenand/onenand_bbt.c b/drivers/mtd/onenand/onenand_bbt.c
index fc2c16a..09a7d1f 100644
--- a/drivers/mtd/onenand/onenand_bbt.c
+++ b/drivers/mtd/onenand/onenand_bbt.c
@@ -188,10 +188,8 @@ int onenand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	len = this->chipsize >> (this->erase_shift + 2);
 	/* Allocate memory (2bit per block) and clear the memory bad block table */
 	bbm->bbt = kzalloc(len, GFP_KERNEL);
-	if (!bbm->bbt) {
-		printk(KERN_ERR "onenand_scan_bbt: Out of memory\n");
+	if (!bbm->bbt)
 		return -ENOMEM;
-	}
 
 	/* Set the bad block position */
 	bbm->badblockpos = ONENAND_BADBLOCK_POS;
diff --git a/drivers/mtd/ssfdc.c b/drivers/mtd/ssfdc.c
index 5cd1897..00d1405 100644
--- a/drivers/mtd/ssfdc.c
+++ b/drivers/mtd/ssfdc.c
@@ -304,11 +304,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 		return;
 
 	ssfdc = kzalloc(sizeof(struct ssfdcr_record), GFP_KERNEL);
-	if (!ssfdc) {
-		printk(KERN_WARNING
-			"SSFDC_RO: out of memory for data structures\n");
+	if (!ssfdc)
 		return;
-	}
 
 	ssfdc->mbd.mtd = mtd;
 	ssfdc->mbd.devnum = -1;
@@ -342,11 +339,8 @@ static void ssfdcr_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 	/* Allocate logical block map */
 	ssfdc->logic_block_map = kmalloc(sizeof(ssfdc->logic_block_map[0]) *
 					 ssfdc->map_len, GFP_KERNEL);
-	if (!ssfdc->logic_block_map) {
-		printk(KERN_WARNING
-			"SSFDC_RO: out of memory for data structures\n");
+	if (!ssfdc->logic_block_map)
 		goto out_err;
-	}
 	memset(ssfdc->logic_block_map, 0xff, sizeof(ssfdc->logic_block_map[0]) *
 		ssfdc->map_len);
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun  7 19:01:56 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 7 Jun 2011 16:01:56 -0700
Subject: [PATCH 3/4] mtd: nand: replace DEBUG() with dev_dbg()
In-Reply-To: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307487717-25402-4-git-send-email-computersforpeace@gmail.com>

Start moving away from the MTD_DEBUG_LEVEL messages. The dynamic
debugging feature is a generic kernel feature that provides more
flexibility.

(See Documentation/dynamic-debug-howto.txt)

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_base.c |   46 +++++++++++++++++++++---------------------
 drivers/mtd/nand/nand_bbt.c  |    9 ++-----
 2 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9a11eea..95a4e71 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -113,20 +113,20 @@ static int check_offs_len(struct mtd_info *mtd,
 
 	/* Start address must align on block boundary */
 	if (ofs & ((1 << chip->phys_erase_shift) - 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__);
+		dev_dbg(&mtd->dev, "%s: Unaligned address\n", __func__);
 		ret = -EINVAL;
 	}
 
 	/* Length must align on block boundary */
 	if (len & ((1 << chip->phys_erase_shift) - 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
+		dev_dbg(&mtd->dev, "%s: Length not block aligned\n",
 					__func__);
 		ret = -EINVAL;
 	}
 
 	/* Do not allow past end of device */
 	if (ofs + len > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n",
+		dev_dbg(&mtd->dev, "%s: Past end of device\n",
 					__func__);
 		ret = -EINVAL;
 	}
@@ -912,7 +912,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+		dev_dbg(&mtd->dev, "%s: Error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
 	}
@@ -934,7 +934,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	int chipnr;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	dev_dbg(&mtd->dev, "%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
 
 	if (check_offs_len(mtd, ofs, len))
@@ -953,7 +953,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		dev_dbg(&mtd->dev, "%s: Device is write protected!!!\n",
 					__func__);
 		ret = -EIO;
 		goto out;
@@ -987,7 +987,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	int chipnr, status, page;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	dev_dbg(&mtd->dev, "%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
 
 	if (check_offs_len(mtd, ofs, len))
@@ -1002,7 +1002,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		dev_dbg(&mtd->dev, "%s: Device is write protected!!!\n",
 					__func__);
 		status = MTD_ERASE_FAILED;
 		ret = -EIO;
@@ -1018,7 +1018,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+		dev_dbg(&mtd->dev, "%s: Error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
 		goto out;
@@ -1757,7 +1757,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 	int len;
 	uint8_t *buf = ops->oobbuf;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
+	dev_dbg(&mtd->dev, "%s: from = 0x%08Lx, len = %i\n",
 			__func__, (unsigned long long)from, readlen);
 
 	if (ops->mode == MTD_OOB_AUTO)
@@ -1766,7 +1766,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 		len = mtd->oobsize;
 
 	if (unlikely(ops->ooboffs >= len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read "
+		dev_dbg(&mtd->dev, "%s: Attempt to start read "
 					"outside oob\n", __func__);
 		return -EINVAL;
 	}
@@ -1775,7 +1775,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 	if (unlikely(from >= mtd->size ||
 		     ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
 					(from >> chip->page_shift)) * len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end "
+		dev_dbg(&mtd->dev, "%s: Attempt read beyond end "
 					"of device\n", __func__);
 		return -EINVAL;
 	}
@@ -1851,7 +1851,7 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 
 	/* Do not allow reads past end of device */
 	if (ops->datbuf && (from + ops->len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read "
+		dev_dbg(&mtd->dev, "%s: Attempt read "
 				"beyond end of device\n", __func__);
 		return -EINVAL;
 	}
@@ -2341,7 +2341,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 	int chipnr, page, status, len;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+	dev_dbg(&mtd->dev, "%s: to = 0x%08x, len = %i\n",
 			 __func__, (unsigned int)to, (int)ops->ooblen);
 
 	if (ops->mode == MTD_OOB_AUTO)
@@ -2351,13 +2351,13 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 
 	/* Do not allow write past end of page */
 	if ((ops->ooboffs + ops->ooblen) > len) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write "
+		dev_dbg(&mtd->dev, "%s: Attempt to write "
 				"past end of page\n", __func__);
 		return -EINVAL;
 	}
 
 	if (unlikely(ops->ooboffs >= len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start "
+		dev_dbg(&mtd->dev, "%s: Attempt to start "
 				"write outside oob\n", __func__);
 		return -EINVAL;
 	}
@@ -2367,7 +2367,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 		     ops->ooboffs + ops->ooblen >
 			((mtd->size >> chip->page_shift) -
 			 (to >> chip->page_shift)) * len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
+		dev_dbg(&mtd->dev, "%s: Attempt write beyond "
 				"end of device\n", __func__);
 		return -EINVAL;
 	}
@@ -2423,7 +2423,7 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 
 	/* Do not allow writes past end of device */
 	if (ops->datbuf && (to + ops->len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
+		dev_dbg(&mtd->dev, "%s: Attempt write beyond "
 				"end of device\n", __func__);
 		return -EINVAL;
 	}
@@ -2513,7 +2513,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 	unsigned int bbt_masked_page = 0xffffffff;
 	loff_t len;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	dev_dbg(&mtd->dev, "%s: start = 0x%012llx, len = %llu\n",
 				__func__, (unsigned long long)instr->addr,
 				(unsigned long long)instr->len);
 
@@ -2537,7 +2537,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		dev_dbg(&mtd->dev, "%s: Device is write protected!!!\n",
 					__func__);
 		instr->state = MTD_ERASE_FAILED;
 		goto erase_exit;
@@ -2589,7 +2589,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
 		/* See if block erase succeeded */
 		if (status & NAND_STATUS_FAIL) {
-			DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, "
+			dev_dbg(&mtd->dev, "%s: Failed erase, "
 					"page 0x%08x\n", __func__, page);
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr =
@@ -2650,7 +2650,7 @@ erase_exit:
 		if (!rewrite_bbt[chipnr])
 			continue;
 		/* Update the BBT for chip */
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
+		dev_dbg(&mtd->dev, "%s: nand_update_bbt "
 			"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
 			rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
 		nand_update_bbt(mtd, rewrite_bbt[chipnr]);
@@ -2670,7 +2670,7 @@ static void nand_sync(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+	dev_dbg(&mtd->dev, "%s: called\n", __func__);
 
 	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_SYNCING);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index b8551e9..4d18098 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -225,10 +225,6 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
-				/*
-				 * Leave it for now, if it's matured we can
-				 * move this message to MTD_DEBUG_LEVEL0.
-				 */
 				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
 				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
@@ -1378,8 +1374,9 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	block = (int)(offs >> (this->bbt_erase_shift - 1));
 	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-	      (unsigned int)offs, block >> 1, res);
+	dev_dbg(&mtd->dev, "nand_isbad_bbt(): bbt info for offs 0x%08x: "
+			   "(block %d) 0x%02x\n",
+			   (unsigned int)offs, block >> 1, res);
 
 	switch ((int)res) {
 	case 0x00:
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun  7 19:01:55 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 7 Jun 2011 16:01:55 -0700
Subject: [PATCH 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307487717-25402-3-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_base.c |   44 +++++++++++++++++++++---------------------
 drivers/mtd/nand/nand_bbt.c  |   39 ++++++++++++++++++-------------------
 2 files changed, 41 insertions(+), 42 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 019187b..9a11eea 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2167,7 +2167,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
 	/* Reject writes, which are not page aligned */
 	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
-		printk(KERN_NOTICE "%s: Attempt to write not "
+		pr_notice("%s: Attempt to write not "
 				"page aligned data\n", __func__);
 		return -EINVAL;
 	}
@@ -2561,7 +2561,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		/* Heck if we have a bad block, we do not erase bad blocks! */
 		if (nand_block_checkbad(mtd, ((loff_t) page) <<
 					chip->page_shift, 0, allowbbt)) {
-			printk(KERN_WARNING "%s: attempt to erase a bad block "
+			pr_warning("%s: attempt to erase a bad block "
 					"at page 0x%08x\n", __func__, page);
 			instr->state = MTD_ERASE_FAILED;
 			goto erase_exit;
@@ -2735,7 +2735,7 @@ static void nand_resume(struct mtd_info *mtd)
 	if (chip->state == FL_PM_SUSPENDED)
 		nand_release_device(mtd);
 	else
-		printk(KERN_ERR "%s called for a chip which is not "
+		pr_err("%s called for a chip which is not "
 		       "in suspended state\n", __func__);
 }
 
@@ -2827,13 +2827,13 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
 		return 0;
 
-	printk(KERN_INFO "ONFI flash detected\n");
+	pr_info("ONFI flash detected\n");
 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
 	for (i = 0; i < 3; i++) {
 		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
 		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
 				le16_to_cpu(p->crc)) {
-			printk(KERN_INFO "ONFI param page %d valid\n", i);
+			pr_info("ONFI param page %d valid\n", i);
 			break;
 		}
 	}
@@ -2857,7 +2857,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->onfi_version = 0;
 
 	if (!chip->onfi_version) {
-		printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
+		pr_info("%s: unsupported ONFI version: %d\n",
 								__func__, val);
 		return 0;
 	}
@@ -2923,7 +2923,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		id_data[i] = chip->read_byte(mtd);
 
 	if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-		printk(KERN_INFO "%s: second ID read did not match "
+		pr_info("%s: second ID read did not match "
 		       "%02x,%02x against %02x,%02x\n", __func__,
 		       *maf_id, *dev_id, id_data[0], id_data[1]);
 		return ERR_PTR(-ENODEV);
@@ -3068,10 +3068,10 @@ ident_done:
 	 * chip correct!
 	 */
 	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
-		printk(KERN_INFO "NAND device: Manufacturer ID:"
+		pr_info("NAND device: Manufacturer ID:"
 		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
 		       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
+		pr_warning("NAND bus width %d instead %d bit\n",
 		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
 		       busw ? 16 : 8);
 		return ERR_PTR(-EINVAL);
@@ -3129,7 +3129,7 @@ ident_done:
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
-	printk(KERN_INFO "NAND device: Manufacturer ID:"
+	pr_info("NAND device: Manufacturer ID:"
 		" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
 		nand_manuf_ids[maf_idx].name,
 		chip->onfi_version ? chip->onfi_params.model : type->name);
@@ -3166,7 +3166,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 
 	if (IS_ERR(type)) {
 		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
-			printk(KERN_WARNING "No NAND device found.\n");
+			pr_warning("No NAND device found.\n");
 		chip->select_chip(mtd, -1);
 		return PTR_ERR(type);
 	}
@@ -3184,7 +3184,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 			break;
 	}
 	if (i > 1)
-		printk(KERN_INFO "%d NAND chips detected\n", i);
+		pr_info("%d NAND chips detected\n", i);
 
 	/* Store the number of chips and calc total size for mtd */
 	chip->numchips = i;
@@ -3234,7 +3234,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 			chip->ecc.layout = &nand_oob_128;
 			break;
 		default:
-			printk(KERN_WARNING "No oob scheme defined for "
+			pr_warning("No oob scheme defined for "
 			       "oobsize %d\n", mtd->oobsize);
 			BUG();
 		}
@@ -3253,7 +3253,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		/* Similar to NAND_ECC_HW, but a separate read_page handle */
 		if (!chip->ecc.calculate || !chip->ecc.correct ||
 		     !chip->ecc.hwctl) {
-			printk(KERN_WARNING "No ECC functions supplied; "
+			pr_warning("No ECC functions supplied; "
 			       "Hardware ECC not possible\n");
 			BUG();
 		}
@@ -3282,7 +3282,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		     chip->ecc.read_page == nand_read_page_hwecc ||
 		     !chip->ecc.write_page ||
 		     chip->ecc.write_page == nand_write_page_hwecc)) {
-			printk(KERN_WARNING "No ECC functions supplied; "
+			pr_warning("No ECC functions supplied; "
 			       "Hardware ECC not possible\n");
 			BUG();
 		}
@@ -3302,7 +3302,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 		if (mtd->writesize >= chip->ecc.size)
 			break;
-		printk(KERN_WARNING "%d byte HW ECC not possible on "
+		pr_warning("%d byte HW ECC not possible on "
 		       "%d byte page size, fallback to SW ECC\n",
 		       chip->ecc.size, mtd->writesize);
 		chip->ecc.mode = NAND_ECC_SOFT;
@@ -3324,7 +3324,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 	case NAND_ECC_SOFT_BCH:
 		if (!mtd_nand_has_bch()) {
-			printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n");
+			pr_warning("CONFIG_MTD_ECC_BCH not enabled\n");
 			BUG();
 		}
 		chip->ecc.calculate = nand_bch_calculate_ecc;
@@ -3351,13 +3351,13 @@ int nand_scan_tail(struct mtd_info *mtd)
 					       chip->ecc.bytes,
 					       &chip->ecc.layout);
 		if (!chip->ecc.priv) {
-			printk(KERN_WARNING "BCH ECC initialization failed!\n");
+			pr_warning("BCH ECC initialization failed!\n");
 			BUG();
 		}
 		break;
 
 	case NAND_ECC_NONE:
-		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
+		pr_warning("NAND_ECC_NONE selected by board driver. "
 		       "This is not recommended !!\n");
 		chip->ecc.read_page = nand_read_page_raw;
 		chip->ecc.write_page = nand_write_page_raw;
@@ -3370,7 +3370,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		break;
 
 	default:
-		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
+		pr_warning("Invalid NAND_ECC_MODE %d\n",
 		       chip->ecc.mode);
 		BUG();
 	}
@@ -3392,7 +3392,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	 */
 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
 	if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
-		printk(KERN_WARNING "Invalid ecc parameters\n");
+		pr_warning("Invalid ecc parameters\n");
 		BUG();
 	}
 	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
@@ -3483,7 +3483,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
 
 	/* Many callers got this wrong, so check for it for a while... */
 	if (!mtd->owner && caller_is_module()) {
-		printk(KERN_CRIT "%s called with NULL mtd->owner!\n",
+		pr_crit("%s called with NULL mtd->owner!\n",
 				__func__);
 		BUG();
 	}
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 8875d6d..b8551e9 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -205,10 +205,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		res = mtd->read(mtd, from, len, &retlen, buf);
 		if (res < 0) {
 			if (retlen != len) {
-				printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
+				pr_info("nand_bbt: Error reading bad block table\n");
 				return res;
 			}
-			printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
+			pr_warn("nand_bbt: ECC error while reading bad block table\n");
 		}
 
 		/* Analyse data */
@@ -219,7 +219,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
-					printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
+					pr_debug("nand_read_bbt: Reserved block at 0x%012llx\n",
 					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
 					mtd->ecc_stats.bbtblocks++;
@@ -229,7 +229,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				 * Leave it for now, if it's matured we can
 				 * move this message to MTD_DEBUG_LEVEL0.
 				 */
-				printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
+				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
 				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
@@ -383,7 +383,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
-		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+		pr_debug("Bad block table at page %d, version 0x%02X\n",
 		       td->pages[0], td->version[0]);
 	}
 
@@ -392,7 +392,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
-		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+		pr_debug("Bad block table at page %d, version 0x%02X\n",
 		       md->pages[0], md->version[0]);
 	}
 	return 1;
@@ -466,7 +466,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	loff_t from;
 	size_t readlen;
 
-	printk(KERN_INFO "Scanning device for bad blocks\n");
+	pr_info("Scanning device for bad blocks\n");
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -495,7 +495,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = 0;
 	} else {
 		if (chip >= this->numchips) {
-			printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
@@ -524,7 +524,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 		if (ret) {
 			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-			printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",
+			pr_warn("Bad eraseblock %d at 0x%012llx\n",
 			       i >> 1, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
@@ -607,10 +607,10 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 	/* Check, if we found a bbt for each requested chip */
 	for (i = 0; i < chips; i++) {
 		if (td->pages[i] == -1)
-			printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
+			pr_warn("Bad block table not found for chip %d\n", i);
 		else
-			printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
-			       td->version[i]);
+			pr_debug("Bad block table found at page %d, version "
+				 "0x%02X\n", td->pages[i], td->version[i]);
 	}
 	return 0;
 }
@@ -723,7 +723,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			if (!md || md->pages[chip] != page)
 				goto write;
 		}
-		printk(KERN_ERR "No space left to write bad block table\n");
+		pr_err("No space left to write bad block table\n");
 		return -ENOSPC;
 	write:
 
@@ -758,12 +758,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			res = mtd->read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
-					printk(KERN_INFO "nand_bbt: Error "
+					pr_info("nand_bbt: Error "
 					       "reading block for writing "
 					       "the bad block table\n");
 					return res;
 				}
-				printk(KERN_WARNING "nand_bbt: ECC error "
+				pr_warn("nand_bbt: ECC error "
 				       "while reading block for writing "
 				       "bad block table\n");
 			}
@@ -840,7 +840,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		if (res < 0)
 			goto outerr;
 
-		printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
+		pr_debug("Bad block table written to 0x%012llx, version "
 		       "0x%02X\n", (unsigned long long)to, td->version[chip]);
 
 		/* Mark it as used */
@@ -849,8 +849,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	return 0;
 
  outerr:
-	printk(KERN_WARNING
-	       "nand_bbt: Error while writing bad block table %d\n", res);
+	pr_warning("nand_bbt: Error while writing bad block table %d\n", res);
 	return res;
 }
 
@@ -1130,7 +1129,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	 */
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
-			printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			pr_err("nand_bbt: Can't scan flash and build the RAM-based BBT\n");
 			kfree(this->bbt);
 			this->bbt = NULL;
 		}
@@ -1298,7 +1297,7 @@ static int nand_create_default_bbt_descr(struct nand_chip *this)
 {
 	struct nand_bbt_descr *bd;
 	if (this->badblock_pattern) {
-		printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+		pr_warn("BBT descr already allocated; not replacing.\n");
 		return -EINVAL;
 	}
 	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-- 
1.7.0.4




From sfr at canb.auug.org.au  Tue Jun  7 20:31:22 2011
From: sfr at canb.auug.org.au (Stephen Rothwell)
Date: Wed, 8 Jun 2011 10:31:22 +1000
Subject: l2-mtd-2.6.git to linux-next
In-Reply-To: <1307345850.3135.24.camel@localhost>
References: <1307345850.3135.24.camel@localhost>
Message-ID: <20110608103122.5b7b54d0.sfr@canb.auug.org.au>

Hi Artem,

On Mon, 06 Jun 2011 10:37:30 +0300 Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> as we've discussed, please, include l2-mtd-2.6.git tree to linux-next:
> 
> git://git.infradead.org/users/dedekind/l2-mtd-2.6.git master

I have added this today.

Thanks for adding your subsystem tree as a participant of linux-next.  As
you may know, this is not a judgment of your code.  The purpose of
linux-next is for integration testing and to lower the impact of
conflicts between subsystems in the next merge window. 

You will need to ensure that the patches/commits in your tree/series have
been:
     * submitted under GPL v2 (or later) and include the Contributor's
	Signed-off-by,
     * posted to the relevant mailing list,
     * reviewed by you (or another maintainer of your subsystem tree),
     * successfully unit tested, and 
     * destined for the current or next Linux merge window.

Basically, this should be just what you would send to Linus (or ask him
to fetch).  It is allowed to be rebased if you deem it necessary.

-- 
Cheers,
Stephen Rothwell 
sfr at canb.auug.org.au

Legal Stuff:
By participating in linux-next, your subsystem tree contributions are
public and will be included in the linux-next trees.  You may be sent
e-mail messages indicating errors or other issues when the
patches/commits from your subsystem tree are merged and tested in
linux-next.  These messages may also be cross-posted to the linux-next
mailing list, the linux-kernel mailing list, etc.  The linux-next tree
project and IBM (my employer) make no warranties regarding the linux-next
project, the testing procedures, the results, the e-mails, etc.  If you
don't agree to these ground rules, let me know and I'll remove your tree
from participation in linux-next.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 490 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110608/55841d4c/attachment-0001.sig>

From kmpark at infradead.org  Tue Jun  7 20:59:13 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 8 Jun 2011 09:59:13 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
Message-ID: <BANLkTin3zBCy3MFHS0Q=L4uoRyG3YERE-g@mail.gmail.com>

2011/6/7 Kyungmin Park <kmpark at infradead.org>:
> 2011/6/7 ?<roman.tereshonkov at nokia.com>:
>>
>>
>>>-----Original Message-----
>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>Behalf Of ext Kyungmin Park
>>>Sent: 07 June, 2011 02:56
>>>To: dedekind1 at gmail.com
>>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>>m.szyprowski at samsung.com
>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>4KiB pagesize
>>>
>>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>>><dedekind1 at gmail.com> wrote:
>>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>>roman.tereshonkov at nokia.com wrote:
>>>>> > What do mean by "no case to use the subpage"?
>>>>> >
>>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>>Partial Program Cycles in the page (NOP)
>>>>> > is equal to 4 -> subpage_sft=2.
>>>
>>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>>say it has 1 NOP.
>>>
>>>Number of Partial Program Cycles in the page (Including main and spare
>>>area) NOP - - 1 cycles
>>>(KFM4G16Q5M-xEBx)
>>>
>>>that's reason I first set subpage_sft = 0 at original code.
>>>
>>>The different thing between you and me is the page architecture
>>>number. yes 4 is the correct number but 5 also has the 4KiB pagesize.
>>>I think it's mean the manufacturing difference. can you check the
>>>which XXnm manufacturing for your devices?
>>>In our case. it's 3Xnm. and previous is 4Xnm.
>>
>>
>>
>> It seems the spec does not specify the nm-technology used.
>>
>> Can we somehow use the DeviceID and VersionID registers to differ
>> our chips?
>> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
>> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>>
>> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.
>
> Here's my device register values.
> 005000ec 0800013e 01010200 00000000
> DeviceID=0x0050, VersionID=0x013e
>
> The lower 4 bits of VersionID is different. even though VersionID is
> different. it's dangerous to detect the NOP 4 or not.
>
> I sent the email to OneNAND person and share the result soon. (he's on
> business trip and return at June 9).

BOTH are right.
Now you have the NOP 4. but my chip has NOP 1. Memory division splits
the chip for each customer.

then how to detect the NOP for similar chip? Using VersionID? or
simply the minimum value?

Please give your opinions.

Thank you,
Kyungmin Park
>
> Thank you,
> Kyungmin Park
>
>
>>
>>
>>
>>>
>>>>>
>>>>> I thought this means "not supported by HW". But if this is
>>>supported,
>>>>> then I'm very surprised why would we remove it. I'm
>>>dropping this patch
>>>>> from my tree.
>>>>
>>>> OK, I actually did not put it to the l2 tree. And AFAICS this patch
>>>> basically reverts commit
>>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>>> still leaves the data structures like onenand_oob_128.
>>>>
>>>> So NACK for this patch - poor commit message, weird changes. I'm
>>>> surprised to see this from kmpark.
>>>
>>>since we got some different OneNAND Spec. even though it has
>>>same 4KiB pagesize.
>>>
>>>Thank you,
>>>Kyungmin Park
>>>>
>>>> --
>>>> Best Regards,
>>>> Artem Bityutskiy (????? ????????)
>>>>
>>>>
>>>
>


From kmpark at infradead.org  Tue Jun  7 21:56:25 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 08 Jun 2011 10:56:25 +0900
Subject: [PATCH] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
Message-ID: <20110608015625.GA27537@july>

From: Kyungmin Park <kyungmin.park at samsung.com>

There are two different 4KiB pagesize chips
KFM4G16Q4M series have NOP 4 with version ID 0x0131
But KFM4G16Q5M has NOP 1 with versoin ID 0x013e

Note that Q5M means that it has NOP 1.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ac9e959..2adca63 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -3429,6 +3429,13 @@ static void onenand_check_features(struct mtd_info *mtd)
 		else if (numbufs == 1) {
 			this->options |= ONENAND_HAS_4KB_PAGE;
 			this->options |= ONENAND_HAS_CACHE_PROGRAM;
+			/*
+			 * There are two different 4KiB pagesize chips
+			 * KFM4G16Q4M has NOP 4 with version ID 0x0131
+			 * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
+			 */
+			if ((this->version_id & 0xf) == 0xe)
+				this->options |= ONENAND_HAS_NOP_1;
 		}
 
 	case ONENAND_DEVICE_DENSITY_2Gb:
@@ -4054,6 +4061,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 			this->ecclayout = &onenand_oob_128;
 			mtd->subpage_sft = 2;
 		}
+		if (ONENAND_IS_NOP_1(this))
+			mtd->subpage_sft = 0;
 		break;
 	case 64:
 		this->ecclayout = &onenand_oob_64;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 52b6f18..4596503 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -184,6 +184,9 @@ struct onenand_chip {
 #define ONENAND_IS_CACHE_PROGRAM(this)					\
 	(this->options & ONENAND_HAS_CACHE_PROGRAM)
 
+#define ONENAND_IS_NOP_1(this)						\
+	(this->options & ONENAND_HAS_NOP_1)
+
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
 
@@ -195,6 +198,7 @@ struct onenand_chip {
 #define ONENAND_HAS_2PLANE		(0x0004)
 #define ONENAND_HAS_4KB_PAGE		(0x0008)
 #define ONENAND_HAS_CACHE_PROGRAM	(0x0010)
+#define ONENAND_HAS_NOP_1		(0x0020)
 #define ONENAND_SKIP_UNLOCK_CHECK	(0x0100)
 #define ONENAND_PAGEBUF_ALLOC		(0x1000)
 #define ONENAND_OOBBUF_ALLOC		(0x2000)


From dedekind1 at gmail.com  Wed Jun  8 04:37:31 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 11:37:31 +0300
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <4DEE36D6.2070009@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>
	<20110607134429.GE21174@pulham.picochip.com>
	<4DEE36D6.2070009@gmail.com>
Message-ID: <1307522251.31223.10.camel@localhost>

On Tue, 2011-06-07 at 18:33 +0400, Dmitry Eremin-Solenikov wrote:
> >  Also some kernel-doc to describe the search order would be nice.
> 
> Search order is mainly detailed either by defaults specified in 
> mtdpart.c or by probe types which user specifies.

I look at the functions and they are difficult to understand. We need to
start with good kerneldoc comment for 'parse_mtd_partitions()'. The
default behavior has to be well-documented. I'd like to apply this
patch, how does it look to you?



From Artem.Bityutskiy at nokia.com  Wed Jun  8 04:42:27 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Wed, 8 Jun 2011 11:42:27 +0300
Subject: [PATCH] mtd: document parse_mtd_partitions
Message-ID: <mailman.8.1307522517.24103.linux-mtd@lists.infradead.org>

Add a kerneldoc comment for the 'parse_mtd_partitions()' function - its
behavior has changed recently so it is good idea to have it documented.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/mtdpart.c |   22 ++++++++++++++++++++++
 1 files changed, 22 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index b7372050..2b71ccb 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -725,8 +725,30 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
 }
 EXPORT_SYMBOL_GPL(deregister_mtd_parser);
 
+/*
+ * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
+ * are changing this array!
+ */
 static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
 
+/**
+ * parse_mtd_partitions - parse MTD partitions
+ * @master: the master partition (describes whole MTD device)
+ * @types: names of partition parsers to try or %NULL
+ * @pparts: array of partitions found is returned here
+ * @origin: MTD device start address (use %0 if unsure)
+ *
+ * This function tries to find partition on MTD device @master. It uses MTD
+ * partition parsers, specified in @types. However, if @types is %NULL, then
+ * the default list of parsers is used. The default list contains only the
+ * "cmdlinepart" parser ATM.
+ *
+ * This function may return:
+ * o a negative error code in case of failure
+ * o zero if no partitions were found
+ * o a positive number of found partitions, in which case on exit @pparts will
+ *   point to an array containing this number of &struct mtd_info objects.
+ */
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
 			 struct mtd_partition **pparts, unsigned long origin)
 {
-- 
1.7.2.3


-- 
Best Regards,
Artem Bityutskiy (?????????? ????????????????)



From dbaryshkov at gmail.com  Wed Jun  8 04:57:41 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 12:57:41 +0400
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <1307522251.31223.10.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>
	<20110607134429.GE21174@pulham.picochip.com>
	<4DEE36D6.2070009@gmail.com> <1307522251.31223.10.camel@localhost>
Message-ID: <BANLkTimzBiuJd+rupHi=ka0UB3MaxqZ2zw@mail.gmail.com>

On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-07 at 18:33 +0400, Dmitry Eremin-Solenikov wrote:
>> >  Also some kernel-doc to describe the search order would be nice.
>>
>> Search order is mainly detailed either by defaults specified in
>> mtdpart.c or by probe types which user specifies.
>
> I look at the functions and they are difficult to understand. We need to
> start with good kerneldoc comment for 'parse_mtd_partitions()'. The
> default behavior has to be well-documented. I'd like to apply this
> patch, how does it look to you?

Looks good.


> From 1606f9966d891cb79bdfb935baf87038a7029198 Mon Sep 17 00:00:00 2001
> From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> Date: Wed, 8 Jun 2011 11:42:27 +0300
> Subject: [PATCH] mtd: document parse_mtd_partitions
>
> Add a kerneldoc comment for the 'parse_mtd_partitions()' function - its
> behavior has changed recently so it is good idea to have it documented.
>
> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> ---
>  drivers/mtd/mtdpart.c |   22 ++++++++++++++++++++++
>  1 files changed, 22 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index b7372050..2b71ccb 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
> @@ -725,8 +725,30 @@ int deregister_mtd_parser(struct mtd_part_parser *p)
>  }
>  EXPORT_SYMBOL_GPL(deregister_mtd_parser);
>
> +/*
> + * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if
> you
> + * are changing this array!
> + */
>  static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
>
> +/**
> + * parse_mtd_partitions - parse MTD partitions
> + * @master: the master partition (describes whole MTD device)
> + * @types: names of partition parsers to try or %NULL
> + * @pparts: array of partitions found is returned here
> + * @origin: MTD device start address (use %0 if unsure)
> + *
> + * This function tries to find partition on MTD device @master. It uses MTD
> + * partition parsers, specified in @types. However, if @types is %NULL,
> then
> + * the default list of parsers is used. The default list contains only the
> + * "cmdlinepart" parser ATM.
> + *
> + * This function may return:
> + * o a negative error code in case of failure
> + * o zero if no partitions were found
> + * o a positive number of found partitions, in which case on exit @pparts
> will
> + *   point to an array containing this number of &struct mtd_info objects.
> + */
>  int parse_mtd_partitions(struct mtd_info *master, const char **types,
>  			 struct mtd_partition **pparts, unsigned long origin)
>  {
> --
> 1.7.2.3
>
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>


-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Wed Jun  8 04:55:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 11:55:40 +0300
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <1307461738-16811-1-git-send-email-dbaryshkov@gmail.com>
References: <20110607134429.GE21174@pulham.picochip.com>
	<1307461738-16811-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307523340.31223.28.camel@localhost>

I agree we need a good comment, but I find this one difficult to follow.

On Tue, 2011-06-07 at 19:48 +0400, Dmitry Eremin-Solenikov wrote:
>  /**
> + * mtd_device_parse_register - register an MTD device.

Not just register, it also contains parsing functionality.

> + *
> + * @mtd: the MTD device to register
> + * @part_probe_types: the list of MTD partition probes to try

Please, name it 'types' to be consistent with 'parse_mtd_partitions()'.
Also, you do not say that this can be %NULL. With my patch, you can
refer the reader like "see 'parse_mtd_partitions()' for more
information'.

> + * @origin: start address of MTD device. =0 unless you are sure you need this.

Try to avoid using dots. Also, constants should be prefixed with %,
i.e., use %0.

> + * @defparts: default partition information to register. Only valid if
> + *		defnr_parts > 0

Ditto about a dot, prefix variables with @, i.e., in this case:
@defnr_parts > %0.

Also about naming: why "default"? What is default there? This is more
like "alternative, or fall-back" - you first try to detect partition
specified in @part_probe_types, if if you fail - you use "alternative"
partitions.

Please, rename it.

> + * @defnr_parts: the number of partitions in defparts.  If zero then the full
> + *		MTD device is registered if no partition info is found

Ditto.

> + *
> + * Extract partition info and register MTD device (partitions or a whole device)
> + * It calls parse_mtd_partitions(), checks the result. If there were no
> + * partitions found, it uses default info specified (via defparts/defnr_parts)
> + * and then registers either partitions, or (if no partitions were
> + * found/specified) the whow MTD.
> + */

Sorry, I find this unreadable.

I suggest something like this.

This function aggregates MTD partitions parsing (done by
'parse_mtd_partitions()') and MTD device and partitions registering. It
basically follows the most common pattern found in many MTD drivers:

o It first tries to probe partitions on MTD device @mtd using parsers
  specified in @types (if @types is %NULL, then the default list of
  parsers is used, see 'parse_mtd_partitions()' for more information).
o If this succeeds, this function registers the found partitions, as
  well as the whole MTD device @mtd.
o If no partitions were found this function just registers the MTD
  device @mtd and exits.

Returns zero in case of success and a negative error code in case of
failure.

Would you please amend the patch and re-send?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 04:57:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 11:57:40 +0300
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <BANLkTimzBiuJd+rupHi=ka0UB3MaxqZ2zw@mail.gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-2-git-send-email-dbaryshkov@gmail.com>
	<20110607134429.GE21174@pulham.picochip.com>
	<4DEE36D6.2070009@gmail.com> <1307522251.31223.10.camel@localhost>
	<BANLkTimzBiuJd+rupHi=ka0UB3MaxqZ2zw@mail.gmail.com>
Message-ID: <1307523460.31223.29.camel@localhost>

On Wed, 2011-06-08 at 12:57 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Tue, 2011-06-07 at 18:33 +0400, Dmitry Eremin-Solenikov wrote:
> >> >  Also some kernel-doc to describe the search order would be nice.
> >>
> >> Search order is mainly detailed either by defaults specified in
> >> mtdpart.c or by probe types which user specifies.
> >
> > I look at the functions and they are difficult to understand. We need to
> > start with good kerneldoc comment for 'parse_mtd_partitions()'. The
> > default behavior has to be well-documented. I'd like to apply this
> > patch, how does it look to you?
> 
> Looks good.

OK, pushed to l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 04:59:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 11:59:51 +0300
Subject: [PATCH 02/44] mtd: lart.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-3-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-3-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307523591.31223.30.camel@localhost>

On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> Replace custom invocations of parse_mtd_partitions and mtd_device_register
> with common mtd_device_parse_register call. This would bring: standard
> handling of all errors, fallback to default partitions, etc.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Sorry, but the code does not match the description: you do not use
'mtd_device_parse_register(); there.

> ---
>  drivers/mtd/devices/lart.c |   12 ++++--------
>  1 files changed, 4 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
> index 772a0ff..48b513f 100644
> --- a/drivers/mtd/devices/lart.c
> +++ b/drivers/mtd/devices/lart.c
> @@ -619,6 +619,10 @@ static struct mtd_partition lart_partitions[] = {
>  		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
>  	}
>  };
> +#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
> +#else
> +#define lart_partitions NULL
> +#define NUM_PARTITIONS 0
>  #endif
>  
>  static int __init lart_flash_init (void)
> @@ -683,23 +687,15 @@ static int __init lart_flash_init (void)
>  #endif
>  #endif
>  
> -#ifndef HAVE_PARTITIONS
> -   result = mtd_device_register(&mtd, NULL, 0);
> -#else
>     result = mtd_device_register(&mtd, lart_partitions,
>                                  ARRAY_SIZE(lart_partitions));
> -#endif
>  
>     return (result);
>  }
>  
>  static void __exit lart_flash_exit (void)
>  {
> -#ifndef HAVE_PARTITIONS
>     mtd_device_unregister(&mtd);
> -#else
> -   mtd_device_unregister(&mtd);
> -#endif
>  }
>  
>  module_init (lart_flash_init);


-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 05:00:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 12:00:49 +0300
Subject: [PATCH 04/44] mtd: sst25l.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-5-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-5-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307523649.31223.31.camel@localhost>

On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> Replace custom invocations of parse_mtd_partitions and mtd_device_register
> with common mtd_device_parse_register call. This would bring: standard
> handling of all errors, fallback to default partitions, etc.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/devices/sst25l.c |   32 ++++----------------------------
>  1 files changed, 4 insertions(+), 28 deletions(-)
> 
> diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
> index cd095af..faa9d3b 100644
> --- a/drivers/mtd/devices/sst25l.c
> +++ b/drivers/mtd/devices/sst25l.c
> @@ -53,7 +53,6 @@ struct sst25l_flash {
>  	struct mutex		lock;
>  	struct mtd_info		mtd;
>  
> -	int 			partitioned;
>  };

How about removing the unneeded newline as well? :-)


-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 05:01:22 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 12:01:22 +0300
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307523682.31223.32.camel@localhost>

On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
> +                       pdata->parts, pdata->nr_parts);

How about checking the return code? :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 05:02:45 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 12:02:45 +0300
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <1307523682.31223.32.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
	<1307523682.31223.32.camel@localhost>
Message-ID: <1307523765.31223.33.camel@localhost>

On Wed, 2011-06-08 at 12:01 +0300, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> > +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
> > +                       pdata->parts, pdata->nr_parts);
> 
> How about checking the return code? :-)

Ok, you did not do it because the original function did not do it. Fair
enough, this is a separate thing.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 05:19:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 12:19:34 +0300
Subject: [PATCH 26/44] mtd: cs553x_nand.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-27-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-27-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307524774.31223.34.camel@localhost>

On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> +                       mtd_device_parse_register(cs553x_mtd[i], NULL,
> 0,
> +                                       NULL, 0); 

You do not need 2 lines here.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 05:20:10 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 12:20:10 +0300
Subject: [PATCH 28/44] mtd: edb7312.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-29-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-29-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307524810.31223.35.camel@localhost>

On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> -	mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
> +	mtd_device_register(ep7312_mtd, NULL, 0,
> +			partition_info, NUM_PARTITIONS);

And probably here?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 05:26:18 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 12:26:18 +0300
Subject: [PATCH 00/44] Cleanup of parse/register scenario
In-Reply-To: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307525178.31223.38.camel@localhost>

On Tue, 2011-06-07 at 17:35 +0400, Dmitry Eremin-Solenikov wrote:
> Lots of mtd drivers have more or less the same common logic:
> parse partitions, then register them. Currently this ends up
> with lots of code duplication, each copy having it's own features
> and bugs. In this patch serie I create a special function
> (mtd_device_parse_register) which handles all issues with acquiring
> partition information, registering mtd device(s) and returning correct
> error code.
> 
> The following changes since commit 85bd7e882840f4cb4d213768d252c754f22440ac:
> 
>   mtd: pxa3xx_nand: Fix blank page ECC mismatch (2011-06-07 15:40:29 +0300)
> 
> are available in the git repository at:
>   git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-parse-1st

Dmitry, the patch-set is a great clean-up! Could you please address few
nit-picks I sent and also go through your patches and join the
unnecessary 2 lines in your 'mtd_device_parse_register()' invocations? I
think I can see several of them.

I mean,

mtd_device_parse_register(x, y, z,
			a, b)

should become

mtd_device_parse_register(x, y, z, a, b)

if this fits 80 characters.

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From roman.tereshonkov at nokia.com  Wed Jun  8 05:56:53 2011
From: roman.tereshonkov at nokia.com (roman.tereshonkov at nokia.com)
Date: Wed, 8 Jun 2011 09:56:53 +0000
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
Message-ID: <E942AFD653C85241BF3CCD5F471BEDA203FD4B1D@008-AM1MPN1-042.mgdnok.nokia.com>

 

>-----Original Message-----
>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On 
>Behalf Of ext Kyungmin Park
>Sent: 07 June, 2011 13:10
>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org; 
>dwmw2 at infradead.org; m.szyprowski at samsung.com
>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 
>4KiB pagesize
>
>2011/6/7  <roman.tereshonkov at nokia.com>:
>>
>>
>>>-----Original Message-----
>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>Behalf Of ext Kyungmin Park
>>>Sent: 07 June, 2011 02:56
>>>To: dedekind1 at gmail.com
>>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>>m.szyprowski at samsung.com
>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>4KiB pagesize
>>>
>>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>>><dedekind1 at gmail.com> wrote:
>>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>>roman.tereshonkov at nokia.com wrote:
>>>>> > What do mean by "no case to use the subpage"?
>>>>> >
>>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>>Partial Program Cycles in the page (NOP)
>>>>> > is equal to 4 -> subpage_sft=2.
>>>
>>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>>say it has 1 NOP.
>>>
>>>Number of Partial Program Cycles in the page (Including main 
>and spare
>>>area) NOP - - 1 cycles
>>>(KFM4G16Q5M-xEBx)
>>>
>>>that's reason I first set subpage_sft = 0 at original code.
>>>
>>>The different thing between you and me is the page architecture
>>>number. yes 4 is the correct number but 5 also has the 4KiB pagesize.
>>>I think it's mean the manufacturing difference. can you check the
>>>which XXnm manufacturing for your devices?
>>>In our case. it's 3Xnm. and previous is 4Xnm.
>>
>>
>>
>> It seems the spec does not specify the nm-technology used.
>>
>> Can we somehow use the DeviceID and VersionID registers to differ
>> our chips?
>> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
>> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>>
>> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.
>
>Here's my device register values.
>005000ec 0800013e 01010200 00000000
>DeviceID=0x0050, VersionID=0x013e


Our difference is in Stepping field of the VersionId register:
0xe means "Version 1.0 (initial)", and 0x1 means "CS version 1.0".

Does anybody know what does "CS" mean in this context? Is it Customer SoC or something else?

How do different Stepping versions differ from each other?


Regards
Roman Tereshonkov


>
>The lower 4 bits of VersionID is different. even though VersionID is
>different. it's dangerous to detect the NOP 4 or not.
>
>I sent the email to OneNAND person and share the result soon. (he's on
>business trip and return at June 9).
>
>Thank you,
>Kyungmin Park
>
>
>>
>>
>>
>>>
>>>>>
>>>>> I thought this means "not supported by HW". But if this is
>>>supported,
>>>>> then I'm very surprised why would we remove it. I'm
>>>dropping this patch
>>>>> from my tree.
>>>>
>>>> OK, I actually did not put it to the l2 tree. And AFAICS this patch
>>>> basically reverts commit
>>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>>> still leaves the data structures like onenand_oob_128.
>>>>
>>>> So NACK for this patch - poor commit message, weird changes. I'm
>>>> surprised to see this from kmpark.
>>>
>>>since we got some different OneNAND Spec. even though it has
>>>same 4KiB pagesize.
>>>
>>>Thank you,
>>>Kyungmin Park
>>>>
>>>> --
>>>> Best Regards,
>>>> Artem Bityutskiy (????? ????????)
>>>>
>>>>
>>>
>

From kmpark at infradead.org  Wed Jun  8 06:04:28 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 8 Jun 2011 19:04:28 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <E942AFD653C85241BF3CCD5F471BEDA203FD4B1D@008-AM1MPN1-042.mgdnok.nokia.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD4B1D@008-AM1MPN1-042.mgdnok.nokia.com>
Message-ID: <BANLkTikQqZ1oWOWRat8NkwuGt+0yqgV6MQ@mail.gmail.com>

2011/6/8  <roman.tereshonkov at nokia.com>:
>
>
>>-----Original Message-----
>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>Behalf Of ext Kyungmin Park
>>Sent: 07 June, 2011 13:10
>>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org;
>>dwmw2 at infradead.org; m.szyprowski at samsung.com
>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>4KiB pagesize
>>
>>2011/6/7 ?<roman.tereshonkov at nokia.com>:
>>>
>>>
>>>>-----Original Message-----
>>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>>Behalf Of ext Kyungmin Park
>>>>Sent: 07 June, 2011 02:56
>>>>To: dedekind1 at gmail.com
>>>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>>>m.szyprowski at samsung.com
>>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>>4KiB pagesize
>>>>
>>>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>>>><dedekind1 at gmail.com> wrote:
>>>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>>>roman.tereshonkov at nokia.com wrote:
>>>>>> > What do mean by "no case to use the subpage"?
>>>>>> >
>>>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>>>Partial Program Cycles in the page (NOP)
>>>>>> > is equal to 4 -> subpage_sft=2.
>>>>
>>>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>>>say it has 1 NOP.
>>>>
>>>>Number of Partial Program Cycles in the page (Including main
>>and spare
>>>>area) NOP - - 1 cycles
>>>>(KFM4G16Q5M-xEBx)
>>>>
>>>>that's reason I first set subpage_sft = 0 at original code.
>>>>
>>>>The different thing between you and me is the page architecture
>>>>number. yes 4 is the correct number but 5 also has the 4KiB pagesize.
>>>>I think it's mean the manufacturing difference. can you check the
>>>>which XXnm manufacturing for your devices?
>>>>In our case. it's 3Xnm. and previous is 4Xnm.
>>>
>>>
>>>
>>> It seems the spec does not specify the nm-technology used.
>>>
>>> Can we somehow use the DeviceID and VersionID registers to differ
>>> our chips?
>>> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
>>> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>>>
>>> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.
>>
>>Here's my device register values.
>>005000ec 0800013e 01010200 00000000
>>DeviceID=0x0050, VersionID=0x013e
>
>
> Our difference is in Stepping field of the VersionId register:
> 0xe means "Version 1.0 (initial)", and 0x1 means "CS version 1.0".
>
> Does anybody know what does "CS" mean in this context? Is it Customer SoC or something else?
Consumer Sample.

but 0x013e is shipped widely. Nexus S also uses this chip. so it
should be fixed at mainline.

Please see another patch. there's no way to detect the version ID even
though it's ugly.

Thank you,
Kyungmin Park
>
> How do different Stepping versions differ from each other?
>
>
> Regards
> Roman Tereshonkov
>
>
>>
>>The lower 4 bits of VersionID is different. even though VersionID is
>>different. it's dangerous to detect the NOP 4 or not.
>>
>>I sent the email to OneNAND person and share the result soon. (he's on
>>business trip and return at June 9).
>>
>>Thank you,
>>Kyungmin Park
>>
>>
>>>
>>>
>>>
>>>>
>>>>>>
>>>>>> I thought this means "not supported by HW". But if this is
>>>>supported,
>>>>>> then I'm very surprised why would we remove it. I'm
>>>>dropping this patch
>>>>>> from my tree.
>>>>>
>>>>> OK, I actually did not put it to the l2 tree. And AFAICS this patch
>>>>> basically reverts commit
>>>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>>>> still leaves the data structures like onenand_oob_128.
>>>>>
>>>>> So NACK for this patch - poor commit message, weird changes. I'm
>>>>> surprised to see this from kmpark.
>>>>
>>>>since we got some different OneNAND Spec. even though it has
>>>>same 4KiB pagesize.
>>>>
>>>>Thank you,
>>>>Kyungmin Park
>>>>>
>>>>> --
>>>>> Best Regards,
>>>>> Artem Bityutskiy (????? ????????)
>>>>>
>>>>>
>>>>
>>


From kmpark at infradead.org  Wed Jun  8 06:18:04 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 08 Jun 2011 19:18:04 +0900
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
Message-ID: <20110608101804.GA5527@july>

From: Kyungmin Park <kyungmin.park at samsung.com>

Implement the write DMA feature. It can reduce the CPU usage when write.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 3306b5b..f24cb6f 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -712,6 +712,74 @@ normal:
 	return 0;
 }
 
+static int s5pc110_write_bufferram(struct mtd_info *mtd, int area,
+		const unsigned char *buffer, int offset, size_t count)
+{
+	struct onenand_chip *this = mtd->priv;
+	struct device *dev = &onenand->pdev->dev;
+	void __iomem *p;
+	void *buf = (void *) buffer;
+	dma_addr_t dma_src, dma_dst;
+	int err, ofs, page_dma = 0;
+
+	p = this->base + area;
+	if (ONENAND_CURRENT_BUFFERRAM(this)) {
+		if (area == ONENAND_DATARAM)
+			p += this->writesize;
+		else
+			p += mtd->oobsize;
+	}
+
+	if (count != mtd->writesize || offset & 3 || (size_t) buf & 3)
+		goto normal;
+
+	/* Handle vmalloc address */
+	if (buf >= high_memory) {
+		struct page *page;
+
+		if (((size_t) buf & PAGE_MASK) !=
+		    ((size_t) (buf + count - 1) & PAGE_MASK))
+			goto normal;
+
+		page = vmalloc_to_page(buf);
+		if (unlikely(!page))
+			goto normal;
+
+		/* Page offset */
+		ofs = ((size_t) buf & ~PAGE_MASK);
+		page_dma = 1;
+
+		/* DMA routine */
+		dma_src = dma_map_page(dev, page, ofs, count, DMA_TO_DEVICE);
+		dma_dst = onenand->phys_base + (p - this->base);
+	} else {
+		/* DMA routine */
+		dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
+		dma_dst = onenand->phys_base + (p - this->base);
+	}
+
+	if (dma_mapping_error(dev, dma_src)) {
+		dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count);
+		goto normal;
+	}
+
+	err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
+			count, S5PC110_DMA_DIR_WRITE);
+
+	if (page_dma)
+		dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
+	else
+		dma_unmap_single(dev, dma_src, count, DMA_TO_DEVICE);
+
+	if (!err)
+		return 0;
+
+normal:
+	memcpy(p + offset, buffer, count);
+
+	return 0;
+}
+
 static int s5pc110_chip_probe(struct mtd_info *mtd)
 {
 	/* Now just return 0 */
@@ -844,6 +912,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
 	} else if (onenand->type == TYPE_S5PC110) {
 		/* Use generic onenand functions */
 		this->read_bufferram = s5pc110_read_bufferram;
+		this->write_bufferram = s5pc110_write_bufferram;
 		this->chip_probe = s5pc110_chip_probe;
 		return;
 	} else {


From jamie at jamieiles.com  Wed Jun  8 06:19:09 2011
From: jamie at jamieiles.com (Jamie Iles)
Date: Wed, 8 Jun 2011 11:19:09 +0100
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <1307461738-16811-1-git-send-email-dbaryshkov@gmail.com>
References: <20110607134429.GE21174@pulham.picochip.com>
	<1307461738-16811-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <20110608101909.GG21174@pulham.picochip.com>

On Tue, Jun 07, 2011 at 07:48:58PM +0400, Dmitry Eremin-Solenikov wrote:
> Lots (nearly all) mtd drivers contain nearly the similar code that
> calls parse_mtd_partitions, provides some platform-default values, if
> parsing fails, and registers  mtd device.
> 
> This is an aim to provide single implementation of this scenario:
> mtd_device_parse_register() which will handle all this parsing and
> defaults.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/mtdcore.c   |   47 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/mtd.h |    5 +++++
>  2 files changed, 52 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index c510aff..d538e0a 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -452,6 +452,53 @@ int mtd_device_register(struct mtd_info *master,
>  EXPORT_SYMBOL_GPL(mtd_device_register);
>  
>  /**
> + * mtd_device_parse_register - register an MTD device.
> + *
> + * @mtd: the MTD device to register
> + * @part_probe_types: the list of MTD partition probes to try
> + * @origin: start address of MTD device. =0 unless you are sure you need this.
> + * @defparts: default partition information to register. Only valid if
> + *		defnr_parts > 0
> + * @defnr_parts: the number of partitions in defparts.  If zero then the full
> + *		MTD device is registered if no partition info is found
> + *
> + * Extract partition info and register MTD device (partitions or a whole device)
> + * It calls parse_mtd_partitions(), checks the result. If there were no
> + * partitions found, it uses default info specified (via defparts/defnr_parts)
> + * and then registers either partitions, or (if no partitions were
> + * found/specified) the whow MTD.

s/whow/whole ?

> + */
> +int mtd_device_parse_register(struct mtd_info *mtd,
> +			      const char **part_probe_types,
> +			      unsigned long origin,
> +			      const struct mtd_partition *defparts,
> +			      int defnr_parts)
> +{
> +	int err;
> +	struct mtd_partition *parts;
> +
> +	err = parse_mtd_partitions(mtd, part_probe_types, &parts, origin);
> +	if (err <= 0 && defnr_parts) {
> +		parts = kmemdup(defparts, sizeof(*parts) * defnr_parts,
> +				GFP_KERNEL);
> +		if (!parts)
> +			err = -ENOMEM;
> +	}

I see that some of your patches for drivers (e.g. plat_nand) remove the 
kfree() of the partitions but this doesn't appear to be handled anywhere 
else afaict.  I don't think this can be done in mtd_device_unregister() 
as it doesn't have the mtd_partition array so probably needs to remain 
in the driver.

Jamie


From roman.tereshonkov at nokia.com  Wed Jun  8 06:20:23 2011
From: roman.tereshonkov at nokia.com (roman.tereshonkov at nokia.com)
Date: Wed, 8 Jun 2011 10:20:23 +0000
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <BANLkTikQqZ1oWOWRat8NkwuGt+0yqgV6MQ@mail.gmail.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD4B1D@008-AM1MPN1-042.mgdnok.nokia.com>
	<BANLkTikQqZ1oWOWRat8NkwuGt+0yqgV6MQ@mail.gmail.com>
Message-ID: <E942AFD653C85241BF3CCD5F471BEDA203FD4F44@008-AM1MPN1-042.mgdnok.nokia.com>

 

>-----Original Message-----
>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On 
>Behalf Of ext Kyungmin Park
>Sent: 08 June, 2011 13:04
>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org; 
>dwmw2 at infradead.org; m.szyprowski at samsung.com
>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 
>4KiB pagesize
>
>2011/6/8  <roman.tereshonkov at nokia.com>:
>>
>>
>>>-----Original Message-----
>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>Behalf Of ext Kyungmin Park
>>>Sent: 07 June, 2011 13:10
>>>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>>>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org;
>>>dwmw2 at infradead.org; m.szyprowski at samsung.com
>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>4KiB pagesize
>>>
>>>2011/6/7 ?<roman.tereshonkov at nokia.com>:
>>>>
>>>>
>>>>>-----Original Message-----
>>>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>>>Behalf Of ext Kyungmin Park
>>>>>Sent: 07 June, 2011 02:56
>>>>>To: dedekind1 at gmail.com
>>>>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>>>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>>>>m.szyprowski at samsung.com
>>>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>>>4KiB pagesize
>>>>>
>>>>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>>>>><dedekind1 at gmail.com> wrote:
>>>>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>>>>roman.tereshonkov at nokia.com wrote:
>>>>>>> > What do mean by "no case to use the subpage"?
>>>>>>> >
>>>>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>>>>Partial Program Cycles in the page (NOP)
>>>>>>> > is equal to 4 -> subpage_sft=2.
>>>>>
>>>>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>>>>say it has 1 NOP.
>>>>>
>>>>>Number of Partial Program Cycles in the page (Including main
>>>and spare
>>>>>area) NOP - - 1 cycles
>>>>>(KFM4G16Q5M-xEBx)
>>>>>
>>>>>that's reason I first set subpage_sft = 0 at original code.
>>>>>
>>>>>The different thing between you and me is the page architecture
>>>>>number. yes 4 is the correct number but 5 also has the 
>4KiB pagesize.
>>>>>I think it's mean the manufacturing difference. can you check the
>>>>>which XXnm manufacturing for your devices?
>>>>>In our case. it's 3Xnm. and previous is 4Xnm.
>>>>
>>>>
>>>>
>>>> It seems the spec does not specify the nm-technology used.
>>>>
>>>> Can we somehow use the DeviceID and VersionID registers to differ
>>>> our chips?
>>>> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
>>>> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>>>>
>>>> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.
>>>
>>>Here's my device register values.
>>>005000ec 0800013e 01010200 00000000
>>>DeviceID=0x0050, VersionID=0x013e
>>
>>
>> Our difference is in Stepping field of the VersionId register:
>> 0xe means "Version 1.0 (initial)", and 0x1 means "CS version 1.0".
>>
>> Does anybody know what does "CS" mean in this context? Is it 
>Customer SoC or something else?
>Consumer Sample.
>
>but 0x013e is shipped widely. Nexus S also uses this chip. so it
>should be fixed at mainline.
>
>Please see another patch. there's no way to detect the version ID even
>though it's ugly.


Yes. I looked the patch and it is ok for me. 
But the last word is for maintainer.


Thanks
Roman Tereshonkov

>
>Thank you,
>Kyungmin Park
>>
>> How do different Stepping versions differ from each other?
>>
>>
>> Regards
>> Roman Tereshonkov
>>
>>
>>>
>>>The lower 4 bits of VersionID is different. even though VersionID is
>>>different. it's dangerous to detect the NOP 4 or not.
>>>
>>>I sent the email to OneNAND person and share the result 
>soon. (he's on
>>>business trip and return at June 9).
>>>
>>>Thank you,
>>>Kyungmin Park
>>>
>>>
>>>>
>>>>
>>>>
>>>>>
>>>>>>>
>>>>>>> I thought this means "not supported by HW". But if this is
>>>>>supported,
>>>>>>> then I'm very surprised why would we remove it. I'm
>>>>>dropping this patch
>>>>>>> from my tree.
>>>>>>
>>>>>> OK, I actually did not put it to the l2 tree. And AFAICS 
>this patch
>>>>>> basically reverts commit
>>>>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>>>>> still leaves the data structures like onenand_oob_128.
>>>>>>
>>>>>> So NACK for this patch - poor commit message, weird changes. I'm
>>>>>> surprised to see this from kmpark.
>>>>>
>>>>>since we got some different OneNAND Spec. even though it has
>>>>>same 4KiB pagesize.
>>>>>
>>>>>Thank you,
>>>>>Kyungmin Park
>>>>>>
>>>>>> --
>>>>>> Best Regards,
>>>>>> Artem Bityutskiy (????? ????????)
>>>>>>
>>>>>>
>>>>>
>>>
>

From kmpark at infradead.org  Wed Jun  8 06:27:03 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 8 Jun 2011 19:27:03 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <E942AFD653C85241BF3CCD5F471BEDA203FD4F44@008-AM1MPN1-042.mgdnok.nokia.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD4B1D@008-AM1MPN1-042.mgdnok.nokia.com>
	<BANLkTikQqZ1oWOWRat8NkwuGt+0yqgV6MQ@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD4F44@008-AM1MPN1-042.mgdnok.nokia.com>
Message-ID: <BANLkTin1qX2deMOr_jv-W3+3uwdPHm0hkA@mail.gmail.com>

2011/6/8  <roman.tereshonkov at nokia.com>:
>
>
>>-----Original Message-----
>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>Behalf Of ext Kyungmin Park
>>Sent: 08 June, 2011 13:04
>>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org;
>>dwmw2 at infradead.org; m.szyprowski at samsung.com
>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>4KiB pagesize
>>
>>2011/6/8 ?<roman.tereshonkov at nokia.com>:
>>>
>>>
>>>>-----Original Message-----
>>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>>Behalf Of ext Kyungmin Park
>>>>Sent: 07 June, 2011 13:10
>>>>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>>>>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org;
>>>>dwmw2 at infradead.org; m.szyprowski at samsung.com
>>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>>4KiB pagesize
>>>>
>>>>2011/6/7 ?<roman.tereshonkov at nokia.com>:
>>>>>
>>>>>
>>>>>>-----Original Message-----
>>>>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>>>>Behalf Of ext Kyungmin Park
>>>>>>Sent: 07 June, 2011 02:56
>>>>>>To: dedekind1 at gmail.com
>>>>>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>>>>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>>>>>m.szyprowski at samsung.com
>>>>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>>>>4KiB pagesize
>>>>>>
>>>>>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>>>>>><dedekind1 at gmail.com> wrote:
>>>>>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>>>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>>>>>roman.tereshonkov at nokia.com wrote:
>>>>>>>> > What do mean by "no case to use the subpage"?
>>>>>>>> >
>>>>>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>>>>>Partial Program Cycles in the page (NOP)
>>>>>>>> > is equal to 4 -> subpage_sft=2.
>>>>>>
>>>>>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>>>>>say it has 1 NOP.
>>>>>>
>>>>>>Number of Partial Program Cycles in the page (Including main
>>>>and spare
>>>>>>area) NOP - - 1 cycles
>>>>>>(KFM4G16Q5M-xEBx)
>>>>>>
>>>>>>that's reason I first set subpage_sft = 0 at original code.
>>>>>>
>>>>>>The different thing between you and me is the page architecture
>>>>>>number. yes 4 is the correct number but 5 also has the
>>4KiB pagesize.
>>>>>>I think it's mean the manufacturing difference. can you check the
>>>>>>which XXnm manufacturing for your devices?
>>>>>>In our case. it's 3Xnm. and previous is 4Xnm.
>>>>>
>>>>>
>>>>>
>>>>> It seems the spec does not specify the nm-technology used.
>>>>>
>>>>> Can we somehow use the DeviceID and VersionID registers to differ
>>>>> our chips?
>>>>> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
>>>>> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>>>>>
>>>>> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.
>>>>
>>>>Here's my device register values.
>>>>005000ec 0800013e 01010200 00000000
>>>>DeviceID=0x0050, VersionID=0x013e
>>>
>>>
>>> Our difference is in Stepping field of the VersionId register:
>>> 0xe means "Version 1.0 (initial)", and 0x1 means "CS version 1.0".
>>>
>>> Does anybody know what does "CS" mean in this context? Is it
>>Customer SoC or something else?
>>Consumer Sample.
>>
>>but 0x013e is shipped widely. Nexus S also uses this chip. so it
>>should be fixed at mainline.
>>
>>Please see another patch. there's no way to detect the version ID even
>>though it's ugly.
>
>
> Yes. I looked the patch and it is ok for me.
> But the last word is for maintainer.
Me(?) or Artem(?).
I heard the H/W engineer and there's no difference between Q4M and Q5M
except the NOP.
and there's no way to detect. So uses the version ID as workaround.

Thank you,
Kyungmin Park
>
>
> Thanks
> Roman Tereshonkov
>
>>
>>Thank you,
>>Kyungmin Park
>>>
>>> How do different Stepping versions differ from each other?
>>>
>>>
>>> Regards
>>> Roman Tereshonkov
>>>
>>>
>>>>
>>>>The lower 4 bits of VersionID is different. even though VersionID is
>>>>different. it's dangerous to detect the NOP 4 or not.
>>>>
>>>>I sent the email to OneNAND person and share the result
>>soon. (he's on
>>>>business trip and return at June 9).
>>>>
>>>>Thank you,
>>>>Kyungmin Park
>>>>
>>>>
>>>>>
>>>>>
>>>>>
>>>>>>
>>>>>>>>
>>>>>>>> I thought this means "not supported by HW". But if this is
>>>>>>supported,
>>>>>>>> then I'm very surprised why would we remove it. I'm
>>>>>>dropping this patch
>>>>>>>> from my tree.
>>>>>>>
>>>>>>> OK, I actually did not put it to the l2 tree. And AFAICS
>>this patch
>>>>>>> basically reverts commit
>>>>>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>>>>>> still leaves the data structures like onenand_oob_128.
>>>>>>>
>>>>>>> So NACK for this patch - poor commit message, weird changes. I'm
>>>>>>> surprised to see this from kmpark.
>>>>>>
>>>>>>since we got some different OneNAND Spec. even though it has
>>>>>>same 4KiB pagesize.
>>>>>>
>>>>>>Thank you,
>>>>>>Kyungmin Park
>>>>>>>
>>>>>>> --
>>>>>>> Best Regards,
>>>>>>> Artem Bityutskiy (????? ????????)
>>>>>>>
>>>>>>>
>>>>>>
>>>>
>>


From roman.tereshonkov at nokia.com  Wed Jun  8 06:37:31 2011
From: roman.tereshonkov at nokia.com (roman.tereshonkov at nokia.com)
Date: Wed, 8 Jun 2011 10:37:31 +0000
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <BANLkTin1qX2deMOr_jv-W3+3uwdPHm0hkA@mail.gmail.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD4B1D@008-AM1MPN1-042.mgdnok.nokia.com>
	<BANLkTikQqZ1oWOWRat8NkwuGt+0yqgV6MQ@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD4F44@008-AM1MPN1-042.mgdnok.nokia.com>
	<BANLkTin1qX2deMOr_jv-W3+3uwdPHm0hkA@mail.gmail.com>
Message-ID: <E942AFD653C85241BF3CCD5F471BEDA203FD4F66@008-AM1MPN1-042.mgdnok.nokia.com>

 

>-----Original Message-----
>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On 
>Behalf Of ext Kyungmin Park
>Sent: 08 June, 2011 13:27
>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org; 
>dwmw2 at infradead.org; m.szyprowski at samsung.com
>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 
>4KiB pagesize
>
>2011/6/8  <roman.tereshonkov at nokia.com>:
>>
>>
>>>-----Original Message-----
>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>Behalf Of ext Kyungmin Park
>>>Sent: 08 June, 2011 13:04
>>>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>>>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org;
>>>dwmw2 at infradead.org; m.szyprowski at samsung.com
>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>4KiB pagesize
>>>
>>>2011/6/8 ?<roman.tereshonkov at nokia.com>:
>>>>
>>>>
>>>>>-----Original Message-----
>>>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>>>Behalf Of ext Kyungmin Park
>>>>>Sent: 07 June, 2011 13:10
>>>>>To: Tereshonkov Roman (Nokia-SD/Helsinki)
>>>>>Cc: dedekind1 at gmail.com; linux-mtd at lists.infradead.org;
>>>>>dwmw2 at infradead.org; m.szyprowski at samsung.com
>>>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>>>4KiB pagesize
>>>>>
>>>>>2011/6/7 ?<roman.tereshonkov at nokia.com>:
>>>>>>
>>>>>>
>>>>>>>-----Original Message-----
>>>>>>>From: kyungmin78 at gmail.com [mailto:kyungmin78 at gmail.com] On
>>>>>>>Behalf Of ext Kyungmin Park
>>>>>>>Sent: 07 June, 2011 02:56
>>>>>>>To: dedekind1 at gmail.com
>>>>>>>Cc: Tereshonkov Roman (Nokia-SD/Helsinki);
>>>>>>>linux-mtd at lists.infradead.org; dwmw2 at infradead.org;
>>>>>>>m.szyprowski at samsung.com
>>>>>>>Subject: Re: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at
>>>>>>>4KiB pagesize
>>>>>>>
>>>>>>>On Mon, Jun 6, 2011 at 7:06 PM, Artem Bityutskiy
>>>>>>><dedekind1 at gmail.com> wrote:
>>>>>>>> On Mon, 2011-06-06 at 13:02 +0300, Artem Bityutskiy wrote:
>>>>>>>>> On Mon, 2011-06-06 at 09:42 +0000,
>>>>>>>roman.tereshonkov at nokia.com wrote:
>>>>>>>>> > What do mean by "no case to use the subpage"?
>>>>>>>>> >
>>>>>>>>> > According to the spec KFM4G16Q4M-xEBx the Number of
>>>>>>>Partial Program Cycles in the page (NOP)
>>>>>>>>> > is equal to 4 -> subpage_sft=2.
>>>>>>>
>>>>>>>It's really strange. Two OneNAND spec which has 4KiB pagesize
>>>>>>>say it has 1 NOP.
>>>>>>>
>>>>>>>Number of Partial Program Cycles in the page (Including main
>>>>>and spare
>>>>>>>area) NOP - - 1 cycles
>>>>>>>(KFM4G16Q5M-xEBx)
>>>>>>>
>>>>>>>that's reason I first set subpage_sft = 0 at original code.
>>>>>>>
>>>>>>>The different thing between you and me is the page architecture
>>>>>>>number. yes 4 is the correct number but 5 also has the
>>>4KiB pagesize.
>>>>>>>I think it's mean the manufacturing difference. can you check the
>>>>>>>which XXnm manufacturing for your devices?
>>>>>>>In our case. it's 3Xnm. and previous is 4Xnm.
>>>>>>
>>>>>>
>>>>>>
>>>>>> It seems the spec does not specify the nm-technology used.
>>>>>>
>>>>>> Can we somehow use the DeviceID and VersionID registers to differ
>>>>>> our chips?
>>>>>> For my case KFM4G16Q4M DeviceID=0x0050, VersionID=0x0131,
>>>>>> and KFM8G16Q4M DeviceID=0x0068, VersionID=0x0131.
>>>>>>
>>>>>> BTW. Another spec KFM4G16Q4B also tells about NOP=4 cycles.
>>>>>
>>>>>Here's my device register values.
>>>>>005000ec 0800013e 01010200 00000000
>>>>>DeviceID=0x0050, VersionID=0x013e
>>>>
>>>>
>>>> Our difference is in Stepping field of the VersionId register:
>>>> 0xe means "Version 1.0 (initial)", and 0x1 means "CS version 1.0".
>>>>
>>>> Does anybody know what does "CS" mean in this context? Is it
>>>Customer SoC or something else?
>>>Consumer Sample.
>>>
>>>but 0x013e is shipped widely. Nexus S also uses this chip. so it
>>>should be fixed at mainline.
>>>
>>>Please see another patch. there's no way to detect the 
>version ID even
>>>though it's ugly.
>>
>>
>> Yes. I looked the patch and it is ok for me.
>> But the last word is for maintainer.
>Me(?) or Artem(?).
>I heard the H/W engineer and there's no difference between Q4M and Q5M
>except the NOP.
>and there's no way to detect. So uses the version ID as workaround.


If it is so what if we move the NOP definition to board specific domain.
The board configuration should know what chip is used.
And if NOP is set there then use it otherwise some safe default value.


The last word I meant for Artem.


Thanks
Roman Tereshonkov

>
>Thank you,
>Kyungmin Park
>>
>>
>> Thanks
>> Roman Tereshonkov
>>
>>>
>>>Thank you,
>>>Kyungmin Park
>>>>
>>>> How do different Stepping versions differ from each other?
>>>>
>>>>
>>>> Regards
>>>> Roman Tereshonkov
>>>>
>>>>
>>>>>
>>>>>The lower 4 bits of VersionID is different. even though 
>VersionID is
>>>>>different. it's dangerous to detect the NOP 4 or not.
>>>>>
>>>>>I sent the email to OneNAND person and share the result
>>>soon. (he's on
>>>>>business trip and return at June 9).
>>>>>
>>>>>Thank you,
>>>>>Kyungmin Park
>>>>>
>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>>>
>>>>>>>>>
>>>>>>>>> I thought this means "not supported by HW". But if this is
>>>>>>>supported,
>>>>>>>>> then I'm very surprised why would we remove it. I'm
>>>>>>>dropping this patch
>>>>>>>>> from my tree.
>>>>>>>>
>>>>>>>> OK, I actually did not put it to the l2 tree. And AFAICS
>>>this patch
>>>>>>>> basically reverts commit
>>>>>>>99b17c08bca2810f5910b3027f1b9d82edf7a576, but
>>>>>>>> still leaves the data structures like onenand_oob_128.
>>>>>>>>
>>>>>>>> So NACK for this patch - poor commit message, weird 
>changes. I'm
>>>>>>>> surprised to see this from kmpark.
>>>>>>>
>>>>>>>since we got some different OneNAND Spec. even though it has
>>>>>>>same 4KiB pagesize.
>>>>>>>
>>>>>>>Thank you,
>>>>>>>Kyungmin Park
>>>>>>>>
>>>>>>>> --
>>>>>>>> Best Regards,
>>>>>>>> Artem Bityutskiy (????? ????????)
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>
>>>
>

From dedekind1 at gmail.com  Wed Jun  8 06:53:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 13:53:17 +0300
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <BANLkTin3zBCy3MFHS0Q=L4uoRyG3YERE-g@mail.gmail.com>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
	<BANLkTin3zBCy3MFHS0Q=L4uoRyG3YERE-g@mail.gmail.com>
Message-ID: <1307530397.31223.40.camel@localhost>

Hi,

On Wed, 2011-06-08 at 09:59 +0900, Kyungmin Park wrote:
> then how to detect the NOP for similar chip? Using VersionID? or
> simply the minimum value?

You are from Samsung, could you use your channels and ask your HW guys
how to detect NOP? What is the proper way?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:03:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:03:14 +0300
Subject: [PATCH] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <20110608015625.GA27537@july>
References: <20110608015625.GA27537@july>
Message-ID: <1307530994.31223.46.camel@localhost>

On Wed, 2011-06-08 at 10:56 +0900, Kyungmin Park wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> There are two different 4KiB pagesize chips
> KFM4G16Q4M series have NOP 4 with version ID 0x0131
> But KFM4G16Q5M has NOP 1 with versoin ID 0x013e
> 
> Note that Q5M means that it has NOP 1.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
> diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
> index ac9e959..2adca63 100644
> --- a/drivers/mtd/onenand/onenand_base.c
> +++ b/drivers/mtd/onenand/onenand_base.c
> @@ -3429,6 +3429,13 @@ static void onenand_check_features(struct mtd_info *mtd)
>  		else if (numbufs == 1) {
>  			this->options |= ONENAND_HAS_4KB_PAGE;
>  			this->options |= ONENAND_HAS_CACHE_PROGRAM;
> +			/*
> +			 * There are two different 4KiB pagesize chips
> +			 * KFM4G16Q4M has NOP 4 with version ID 0x0131
> +			 * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
> +			 */

If you confirm that it is impossible to detect NOP and distinguish
between KFM4G16Q4M and KFM4G16Q5M, then can we take the following steps:

1. Add a comment that this is a hacky quirk to work around HW
   identification flaw, to make it clear for the people who read the
   code.
2. Make sure the default is NOP4 (you already do).
3. Compare _both_ device ID and version ID. This means that we'll end up
   with NOP1 only for your device, all the other will be NOP4. If then
   someone has issues, they'll have to reporte about them and add their
   device ID to this hack.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Wed Jun  8 07:08:55 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:08:55 +0300
Subject: [PATCH] mtd: ndfc: fix a memory leak in ndfc_remove
In-Reply-To: <1307458521.22584.1.camel@phoenix>
References: <1307458521.22584.1.camel@phoenix>
Message-ID: <1307531335.31223.47.camel@localhost>

On Tue, 2011-06-07 at 22:55 +0800, Axel Lin wrote:
> Signed-off-by: Axel Lin <axel.lin at gmail.com>
> ---
>  drivers/mtd/nand/ndfc.c |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:10:22 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:10:22 +0300
Subject: [PATCH 2/6] mtdinfo: send help/version info to stdout
In-Reply-To: <BANLkTikQzMtE6A=zNBU9ADjPKdOeTUzgtg@mail.gmail.com>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-2-git-send-email-vapier@gentoo.org>
	<1307428609.11104.39.camel@localhost>
	<BANLkTikQzMtE6A=zNBU9ADjPKdOeTUzgtg@mail.gmail.com>
Message-ID: <1307531422.31223.49.camel@localhost>

On Tue, 2011-06-07 at 11:00 -0400, Mike Frysinger wrote:
> On Tue, Jun 7, 2011 at 02:36, Artem Bityutskiy wrote:
> > On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> >> Usage/version information should go to stdout when it is expected behavior
> >> (i.e. the user requested it explicitly).  This info should go to stderr
> >> only when the usage info is being shown as a result of incorrect options.
> >
> > This is fine, but all other ubi utils need this change then as well. I
> > think this piece of code was copypasted in all ubi-utils, so you should
> > easily find it and change.
> 
> you just like making me work :p

It is difficult to not like this - you are doing very good job! :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:13:18 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:13:18 +0300
Subject: [PATCH v2] ubi-utils: send help/version info to stdout
In-Reply-To: <1307458922-1082-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-2-git-send-email-vapier@gentoo.org>
	<1307458922-1082-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307531598.31223.50.camel@localhost>

On Tue, 2011-06-07 at 11:02 -0400, Mike Frysinger wrote:
> Usage/version information should go to stdout when it is expected behavior
> (i.e. the user requested it explicitly).  This info should go to stderr
> only when the usage info is being shown as a result of incorrect options.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed to mtd-utils, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:15:50 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:15:50 +0300
Subject: [PATCH v2] flash_info: deprecate
In-Reply-To: <1307459497-2226-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-6-git-send-email-vapier@gentoo.org>
	<1307459497-2226-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307531750.31223.51.camel@localhost>

On Tue, 2011-06-07 at 11:11 -0400, Mike Frysinger wrote:
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
> v2
> 	- just deprecate for now rather than straight up removal
> 
>  feature-removal-schedule.txt |    7 +++++++
>  flash_info.c                 |    2 ++
>  2 files changed, 9 insertions(+), 0 deletions(-)

Pushed to mtd-utils.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:28:19 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:28:19 +0300
Subject: [PATCH 1/6] jffs2: make lzo optional at build time
In-Reply-To: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307532499.31223.60.camel@localhost>

On Tue, 2011-06-07 at 02:19 -0400, Mike Frysinger wrote:
> The external lzo dep can be a pain to deal with when cross-compiling,
> so make it optional for jffs2.  This is useful if people aren't even
> using the functionality, or for quicker development.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:47:15 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:47:15 +0300
Subject: [PATCH v3] libmtd: add helper funcs for getting regioninfo and
	locked info
In-Reply-To: <1307461925-6420-1-git-send-email-vapier@gentoo.org>
References: <1307460482-3745-1-git-send-email-vapier@gentoo.org>
	<1307461925-6420-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307533635.31223.63.camel@localhost>

On Tue, 2011-06-07 at 11:52 -0400, Mike Frysinger wrote:
> This extends the libmtd with the helper functions:
> 	mtd_regioninfo: interface to MEMGETREGIONINFO
> 	mtd_islocked: interface to MEMISLOCKED
> 
> Users of these functions will follow shortly ...
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
> v3
> 	- add a "islocked_supported" field to handle older kernels nicely

Umm, I meant a user-visible flag, so that the user could check it and
not even try to print the map. There does not seem to be much point
having this flag otherewise - we can just call the ioctl, and return
error if it fails, without printing any error message.

I'll stick with v2 of this patch, I think we better live without this
flag.


-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 07:52:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 14:52:46 +0300
Subject: [PATCH v2] libmtd: add helper funcs for getting regioninfo and
	locked info
In-Reply-To: <1307460482-3745-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-4-git-send-email-vapier@gentoo.org>
	<1307460482-3745-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307533966.31223.66.camel@localhost>

On Tue, 2011-06-07 at 11:28 -0400, Mike Frysinger wrote:
> This extends the libmtd with the helper functions:
> 	mtd_regioninfo: interface to MEMGETREGIONINFO
> 	mtd_islocked: interface to MEMISLOCKED
> 
> Users of these functions will follow shortly ...
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed with a small tweak, thanks!

> +int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
> +{
> +	int ret;
> +	erase_info_t ei;
> +
> +	ei.start = eb * mtd->eb_size;
> +	ei.length = mtd->eb_size;
> +
> +	ret = ioctl(fd, MEMISLOCKED, &ei);
> +	if (ret < 0)
> +		return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
> +

I've removed this error message - if we fail, better return an error
code silently. At least your next patch is built a way that it will keep
iterating and executing this function.

We might as well print an error message if (!ENOTTY && !ENOTSUPP), but I
did not do this. I expect you to send a correction patch if you do not
like this :-)

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Wed Jun  8 08:22:08 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 16:22:08 +0400
Subject: [PATCH 01/44] mtd: add new API for handling MTD registration
In-Reply-To: <20110608101909.GG21174@pulham.picochip.com>
References: <20110607134429.GE21174@pulham.picochip.com>
	<1307461738-16811-1-git-send-email-dbaryshkov@gmail.com>
	<20110608101909.GG21174@pulham.picochip.com>
Message-ID: <BANLkTikhuyQ3JN9EHLvoCtej6bMYtCZm8A@mail.gmail.com>

On 6/8/11, Jamie Iles <jamie at jamieiles.com> wrote:
> On Tue, Jun 07, 2011 at 07:48:58PM +0400, Dmitry Eremin-Solenikov wrote:
>> Lots (nearly all) mtd drivers contain nearly the similar code that
>> calls parse_mtd_partitions, provides some platform-default values, if
>> parsing fails, and registers  mtd device.
>>
>> This is an aim to provide single implementation of this scenario:
>> mtd_device_parse_register() which will handle all this parsing and
>> defaults.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>> ---
>>  drivers/mtd/mtdcore.c   |   47
>> +++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/mtd/mtd.h |    5 +++++
>>  2 files changed, 52 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
>> index c510aff..d538e0a 100644
>> --- a/drivers/mtd/mtdcore.c
>> +++ b/drivers/mtd/mtdcore.c
>> @@ -452,6 +452,53 @@ int mtd_device_register(struct mtd_info *master,
>>  EXPORT_SYMBOL_GPL(mtd_device_register);
>>
>>  /**
>> + * mtd_device_parse_register - register an MTD device.
>> + *
>> + * @mtd: the MTD device to register
>> + * @part_probe_types: the list of MTD partition probes to try
>> + * @origin: start address of MTD device. =0 unless you are sure you need
>> this.
>> + * @defparts: default partition information to register. Only valid if
>> + *		defnr_parts > 0
>> + * @defnr_parts: the number of partitions in defparts.  If zero then the
>> full
>> + *		MTD device is registered if no partition info is found
>> + *
>> + * Extract partition info and register MTD device (partitions or a whole
>> device)
>> + * It calls parse_mtd_partitions(), checks the result. If there were no
>> + * partitions found, it uses default info specified (via
>> defparts/defnr_parts)
>> + * and then registers either partitions, or (if no partitions were
>> + * found/specified) the whow MTD.
>
> s/whow/whole ?

Yup.

>> + */
>> +int mtd_device_parse_register(struct mtd_info *mtd,
>> +			      const char **part_probe_types,
>> +			      unsigned long origin,
>> +			      const struct mtd_partition *defparts,
>> +			      int defnr_parts)
>> +{
>> +	int err;
>> +	struct mtd_partition *parts;
>> +
>> +	err = parse_mtd_partitions(mtd, part_probe_types, &parts, origin);
>> +	if (err <= 0 && defnr_parts) {
>> +		parts = kmemdup(defparts, sizeof(*parts) * defnr_parts,
>> +				GFP_KERNEL);
>> +		if (!parts)
>> +			err = -ENOMEM;
>> +	}
>
> I see that some of your patches for drivers (e.g. plat_nand) remove the
> kfree() of the partitions but this doesn't appear to be handled anywhere
> else afaict.  I don't think this can be done in mtd_device_unregister()
> as it doesn't have the mtd_partition array so probably needs to remain
> in the driver.

It's handled by kfree right aftert add_mtd_partitions. No mtd partitions
information is exported out of mtd_device_parse_register(). In fact I'll have
to check if I can remove all <mtd/partitions.h> includes from drivers.

Anyway I'll post a V2 later after fixing issues identified by you and Artem.

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Wed Jun  8 08:27:43 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 15:27:43 +0300
Subject: [PATCH v2] libmtd: add helper funcs for getting regioninfo and
	locked info
In-Reply-To: <1307533966.31223.66.camel@localhost>
References: <1307427548-29306-4-git-send-email-vapier@gentoo.org>
	<1307460482-3745-1-git-send-email-vapier@gentoo.org>
	<1307533966.31223.66.camel@localhost>
Message-ID: <1307536063.31223.67.camel@localhost>

On Wed, 2011-06-08 at 14:52 +0300, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 11:28 -0400, Mike Frysinger wrote:
> > This extends the libmtd with the helper functions:
> > 	mtd_regioninfo: interface to MEMGETREGIONINFO
> > 	mtd_islocked: interface to MEMISLOCKED
> > 
> > Users of these functions will follow shortly ...
> > 
> > Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> 
> Pushed with a small tweak, thanks!
> 
> > +int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
> > +{
> > +	int ret;
> > +	erase_info_t ei;
> > +
> > +	ei.start = eb * mtd->eb_size;
> > +	ei.length = mtd->eb_size;
> > +
> > +	ret = ioctl(fd, MEMISLOCKED, &ei);
> > +	if (ret < 0)
> > +		return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
> > +
> 
> I've removed this error message - if we fail, better return an error
> code silently. At least your next patch is built a way that it will keep
> iterating and executing this function.
> 
> We might as well print an error message if (!ENOTTY && !ENOTSUPP), but I
> did not do this. I expect you to send a correction patch if you do not
> like this :-)

I've just pushed a correction patch on top of this:


From Artem.Bityutskiy at nokia.com  Wed Jun  8 08:30:14 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Wed, 8 Jun 2011 15:30:14 +0300
Subject: [PATCH] libmtd: improve mtd_islocked interface
Message-ID: <mailman.10.1307536333.24103.linux-mtd@lists.infradead.org>

This patch first of all, re-names 'mtd_islocked()' into 'mtd_is_locked()' since
this seems to be the name Mike wanted, and it looks a bit nicer.

This patch also makes 'mtd_is_locked()' print an error message if it fails. I'm
not sure if it is good idea for a library to do so, but all functions do this,
so it certainly _not_ a good idea to be inconsistent.

However, for the special case, when the the "is locked" ioctl is not supported
or is not valid for this device, we do not print an error message and return
ENOTSUPP error code.

Thus, the user can distinguish between real errors and non-fatal "not
supported" cases.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 include/libmtd.h |    8 +++++---
 lib/libmtd.c     |   13 +++++++++++--
 2 files changed, 16 insertions(+), 5 deletions(-)

diff --git a/include/libmtd.h b/include/libmtd.h
index 7275246..9efccbc 100644
--- a/include/libmtd.h
+++ b/include/libmtd.h
@@ -190,16 +190,18 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
 int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo);
 
 /**
- * mtd_islocked - see if the specified eraseblock is locked.
+ * mtd_is_locked - see if the specified eraseblock is locked.
  * @mtd: MTD device description object
  * @fd: MTD device node file descriptor
  * @eb: eraseblock to check
  *
  * This function checks to see if eraseblock @eb of MTD device described
  * by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and
- * %-1 in case of failure.
+ * %-1 in case of failure. If the ioctl is not supported (support was added in
+ * Linux kernel 2.6.36) or this particular device does not support it, errno is
+ * set to @ENOTSUPP.
  */
-int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb);
+int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb);
 
 /**
  * mtd_torture - torture an eraseblock.
diff --git a/lib/libmtd.c b/lib/libmtd.c
index 2573cc7..c34874e 100644
--- a/lib/libmtd.c
+++ b/lib/libmtd.c
@@ -900,14 +900,23 @@ int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
 	return 0;
 }
 
-int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
+int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb)
 {
+	int ret;
 	erase_info_t ei;
 
 	ei.start = eb * mtd->eb_size;
 	ei.length = mtd->eb_size;
 
-	return ioctl(fd, MEMISLOCKED, &ei);
+	ret = ioctl(fd, MEMISLOCKED, &ei);
+	if (ret < 0) {
+		if (errno != ENOTTY && errno != EOPNOTSUPP)
+			return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
+		else
+			errno = EOPNOTSUPP;
+	}
+
+	return ret;
 }
 
 /* Patterns to write to a physical eraseblock when torturing it */
-- 
1.7.2.3



-- 
Best Regards,
Artem Bityutskiy (?????????? ????????????????)



From axel.lin at gmail.com  Wed Jun  8 09:01:37 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Wed, 08 Jun 2011 21:01:37 +0800
Subject: [PATCH] mtd: davinci_nand: remove redundant mtd_device_unregister
	in nand_davinci_remove
Message-ID: <1307538097.17552.4.camel@phoenix>

mtd_device_unregister is done in nand_release(),
thus no need to call it in nand_davinci_remove().

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/davinci_nand.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 0c582ed..70c92a5 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -811,9 +811,6 @@ err_nomem:
 static int __exit nand_davinci_remove(struct platform_device *pdev)
 {
 	struct davinci_nand_info *info = platform_get_drvdata(pdev);
-	int status;
-
-	status = mtd_device_unregister(&info->mtd);
 
 	spin_lock_irq(&davinci_nand_lock);
 	if (info->chip.ecc.mode == NAND_ECC_HW_SYNDROME)
-- 
1.7.4.1





From kmpark at infradead.org  Wed Jun  8 09:21:17 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 8 Jun 2011 22:21:17 +0900
Subject: [PATCH] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <1307530994.31223.46.camel@localhost>
References: <20110608015625.GA27537@july> <1307530994.31223.46.camel@localhost>
Message-ID: <BANLkTinOBRUiaAGrbPcxve-EzZN3YdS__g@mail.gmail.com>

On Wed, Jun 8, 2011 at 8:03 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-08 at 10:56 +0900, Kyungmin Park wrote:
>> From: Kyungmin Park <kyungmin.park at samsung.com>
>>
>> There are two different 4KiB pagesize chips
>> KFM4G16Q4M series have NOP 4 with version ID 0x0131
>> But KFM4G16Q5M has NOP 1 with versoin ID 0x013e
>>
>> Note that Q5M means that it has NOP 1.
>>
>> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
>> ---
>> diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
>> index ac9e959..2adca63 100644
>> --- a/drivers/mtd/onenand/onenand_base.c
>> +++ b/drivers/mtd/onenand/onenand_base.c
>> @@ -3429,6 +3429,13 @@ static void onenand_check_features(struct mtd_info *mtd)
>> ? ? ? ? ? ? ? else if (numbufs == 1) {
>> ? ? ? ? ? ? ? ? ? ? ? this->options |= ONENAND_HAS_4KB_PAGE;
>> ? ? ? ? ? ? ? ? ? ? ? this->options |= ONENAND_HAS_CACHE_PROGRAM;
>> + ? ? ? ? ? ? ? ? ? ? /*
>> + ? ? ? ? ? ? ? ? ? ? ?* There are two different 4KiB pagesize chips
>> + ? ? ? ? ? ? ? ? ? ? ?* KFM4G16Q4M has NOP 4 with version ID 0x0131
>> + ? ? ? ? ? ? ? ? ? ? ?* KFM4G16Q5M has NOP 1 with versoin ID 0x013e
>> + ? ? ? ? ? ? ? ? ? ? ?*/
>
> If you confirm that it is impossible to detect NOP and distinguish
> between KFM4G16Q4M and KFM4G16Q5M, then can we take the following steps:
>
> 1. Add a comment that this is a hacky quirk to work around HW
> ? identification flaw, to make it clear for the people who read the
> ? code.

For the record, chip maker (memory) made different chips for each
vendor (Samsung Mobile, and Nokia)
with the design flaw, it made a workaround, not hacky quirk.

> 2. Make sure the default is NOP4 (you already do).
> 3. Compare _both_ device ID and version ID. This means that we'll end up
> ? with NOP1 only for your device, all the other will be NOP4. If then
> ? someone has issues, they'll have to reporte about them and add their
> ? device ID to this hack.

Okay no problem to compare the device ID.

Thank you,
Kyungmin Park
>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>


From dedekind1 at gmail.com  Wed Jun  8 09:19:16 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 16:19:16 +0300
Subject: [PATCH] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <BANLkTinOBRUiaAGrbPcxve-EzZN3YdS__g@mail.gmail.com>
References: <20110608015625.GA27537@july> <1307530994.31223.46.camel@localhost>
	<BANLkTinOBRUiaAGrbPcxve-EzZN3YdS__g@mail.gmail.com>
Message-ID: <1307539156.31223.69.camel@localhost>

On Wed, 2011-06-08 at 22:21 +0900, Kyungmin Park wrote:
> > 1. Add a comment that this is a hacky quirk to work around HW
> >   identification flaw, to make it clear for the people who read the
> >   code.
> 
> For the record, chip maker (memory) made different chips for each
> vendor (Samsung Mobile, and Nokia)
> with the design flaw, it made a workaround, not hacky quirk.

OK :-) Would you please send an updated patch ?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From kmpark at infradead.org  Wed Jun  8 09:26:40 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 8 Jun 2011 22:26:40 +0900
Subject: [PATCH] mtd: OneNAND: Fix wrong subpage_sft at 4KiB pagesize
In-Reply-To: <1307530397.31223.40.camel@localhost>
References: <20110602064832.GA7319@july> <1307115701.3069.20.camel@localhost>
	<E942AFD653C85241BF3CCD5F471BEDA203FC6E79@008-AM1MPN1-041.mgdnok.nokia.com>
	<1307354557.3112.21.camel@localhost>
	<1307354791.3112.24.camel@localhost>
	<BANLkTinPBum1WB=-tx833hj032mfs1TdVg@mail.gmail.com>
	<E942AFD653C85241BF3CCD5F471BEDA203FD21D7@008-AM1MPN1-041.mgdnok.nokia.com>
	<BANLkTi=aukCraGS1iOuemwuCvWrOaY0oxA@mail.gmail.com>
	<BANLkTin3zBCy3MFHS0Q=L4uoRyG3YERE-g@mail.gmail.com>
	<1307530397.31223.40.camel@localhost>
Message-ID: <BANLkTinqVRGEnvnoM9NApO_0aXZz6H6dPg@mail.gmail.com>

On Wed, Jun 8, 2011 at 7:53 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> Hi,
>
> On Wed, 2011-06-08 at 09:59 +0900, Kyungmin Park wrote:
>> then how to detect the NOP for similar chip? Using VersionID? or
>> simply the minimum value?
>
> You are from Samsung, could you use your channels and ask your HW guys
> how to detect NOP? What is the proper way?

I really surprised when talk with H/W guy. He don't understand why the
same codes are used for Samsung mobile and Nokia.
He said it can be distinguished from printed chip number at cover. not S/W.

That's reason. don't make a different version ID or others.

P.S., I'm working for Samsung Mobile.

>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>


From dedekind1 at gmail.com  Wed Jun  8 09:35:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 16:35:51 +0300
Subject: [PATCH v2] mtdinfo: add regioninfo/eraseblock map display
In-Reply-To: <1307461999-6483-1-git-send-email-vapier@gentoo.org>
References: <1307427548-29306-5-git-send-email-vapier@gentoo.org>
	<1307461999-6483-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307540151.31223.85.camel@localhost>

On Tue, 2011-06-07 at 11:53 -0400, Mike Frysinger wrote:
> This brings the mtdinfo utility in line with the functionality
> of the flash_info utility.  It dumps the erase regioninfo (if
> the devices has it) as well as showing a handy eraseblock map
> (if the user has requested it).  The eraseblock map also shows
> which blocks are locked and which ones are bad.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
> v2
> 	- rename sector map to eraseblock map
> 	- include bad block info in map
> 	- update libmtd api calls

Sorry, but I still have some nit-picks.

> @@ -110,6 +114,10 @@ static int parse_opt(int argc, char * const argv[])
>  			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
>  			break;
>  
> +		case 'M':
> +			args.map = 1;
> +			break;
> +
>  		case 'h':
>  			printf("%s\n\n", doc);
>  			printf("%s\n\n", usage);

Would you also please add the following code near the end of the
'parse_opt()' function:

+       if (args.map && !args.node)
+               return errmsg("-M requires MTD device node name");

This will anyway be true when we remove -m, a the checks like "if
(args.node)" will be not needed.

> +static void print_map(libmtd_t libmtd, const struct mtd_dev_info *mtd,
> +		      int fd, const region_info_t *reginfo)
> +{
> +	unsigned long start;
> +	int i, width;
> +
> +	printf("Eraseblock map:\n");
> +
> +	/* figure out the number of spaces to pad w/out libm */
> +	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
> +		continue;
> +
> +	for (i = 0; i < reginfo->numblocks; ++i) {
> +		start = reginfo->offset + i * reginfo->erasesize;
> +		printf(" %*i: %08lx ", width, i, start);
> +		if (mtd_is_locked(libmtd, mtd, fd, i) == 1)
> +			printf("RO ");
> +		else
> +			printf("   ");

I think this should be something like:

ret = mtd_is_locked()
if (ret < 0 && errno != ENOTSUPP)
	return;
if (ret == 1)
	printf("RO ");
else if (ret == 0)
	printf("   ");

> +		if (mtd_is_bad(mtd, fd, i) == 1)
> +			printf("BAD ");
> +		else
> +			printf("    ");

And similarly:

ret = mtd_is_bad()
if (ret < 0)
	return;
if (ret)
	printf("BAD ")l
else
	printf("    ");

> @@ -196,8 +235,26 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
>  	if (mtd.oob_size > 0)
>  		printf("OOB size:                       %d bytes\n",
>  		       mtd.oob_size);
> -	if (mtd.region_cnt > 0)
> +	if (mtd.region_cnt > 0) {
>  		printf("Additional erase regions:       %d\n", mtd.oob_size);
> +		if (args.node)
> +			fd = open(args.node, O_RDONLY | O_CLOEXEC);

We do want to print error message if open fails. E.g., I use -M and I do
not see any eraseblock map - because I am not root!

If open fails, we need to print something like "cannot fetch information
about regions - error blah (blah blah)". And may be we can just
continue.

> +		if (fd != -1) {
> +			int r;
> +
> +			for (r = 0; r < mtd.region_cnt; ++r) {
> +				printf(" region %i: ", r);
> +				if (mtd_regioninfo(fd, r, &reginfo) == 0) {
> +					printf(" offset: %#x size: %#x numblocks: %#x\n",
> +						reginfo.offset, reginfo.erasesize,
> +						reginfo.numblocks);
> +					if (args.map)
> +						print_map(libmtd, &mtd, fd, &reginfo);
> +				} else
> +					printf(" info is unavailable\n");
> +			}
> +		}
> +	}

OK, this is not very consistent. If we have more than one region and use
-M - we print sectors map _before_ things like "Bad blocks are allowed"
etc.

But if we have zero regions and use -M - we print the map at the very
end.

Not nice. Please, let's not call print_map here at all.


>  	if (mtd_info->sysfs_supported)
>  		printf("Character device major/minor:   %d:%d\n",
>  		       mtd.major, mtd.minor);
> @@ -225,6 +282,21 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
>  	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
>  
>  out:
> +	if (args.map && mtd.region_cnt == 0 && args.node) {
> +		if (fd == -1)
> +			fd = open(args.node, O_RDONLY | O_CLOEXEC);
> +		if (fd != -1) {
> +			reginfo.offset = 0;
> +			reginfo.erasesize = mtd.eb_size;
> +			reginfo.numblocks = mtd.eb_cnt;
> +			reginfo.regionindex = 0;
> +			print_map(libmtd, &mtd, fd, &reginfo);
> +		}
> +	}
> +
> +	if (fd != -1)
> +		close(fd);
> +

Let's print the map here for all situations, not only  mtd.region_cnt ==
0.

I'd created one functions:

int print_regions(mtd, map).

The 'map' parameter makes it also print the map. So you call this
function twice:

above:
if (mtd.region_cnt > 0
	print_regions(mtd, 0);

and here:
print_regions(mtd, 1);

Hide the file opening there. For -M if we cannot open the file - we have
to die. For just regions printing - we can continue if the file cannot
be opened.


-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 09:41:29 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 16:41:29 +0300
Subject: [PATCH 5/6] mtdinfo: add regioninfo/sectormap display
In-Reply-To: <BANLkTimY1DwxBBi=peQzqwoLktgVna-0KA@mail.gmail.com>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-5-git-send-email-vapier@gentoo.org>
	<1307432463.11104.65.camel@localhost>
	<BANLkTimY1DwxBBi=peQzqwoLktgVna-0KA@mail.gmail.com>
Message-ID: <1307540489.31223.87.camel@localhost>

I've just pushed this little patch to make sure the code is more
readable when you add your changes. Otherwise this "out:" label looks
ugly.


From Artem.Bityutskiy at nokia.com  Wed Jun  8 09:21:40 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Wed, 8 Jun 2011 16:21:40 +0300
Subject: [PATCH] mtdinfo: separate out ubi information printing
Message-ID: <mailman.11.1307540753.24103.linux-mtd@lists.infradead.org>

We are going to add some more code which prints eraseblocks map, so we need to
make 'print_dev_info()' a bit smaller to keep the code readable.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 ubi-utils/src/mtdinfo.c |   41 +++++++++++++++++++++++------------------
 1 files changed, 23 insertions(+), 18 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index 666d739..ca0ad71 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -160,6 +160,27 @@ static int translate_dev(libmtd_t libmtd, const char *node)
 	return 0;
 }
 
+static void print_ubi_info(const struct mtd_info *mtd_info,
+			   const struct mtd_dev_info *mtd)
+{
+	struct ubigen_info ui;
+
+	if (!mtd_info->sysfs_supported) {
+		errmsg("cannot provide UBI info, becasue sub-page size is "
+		       "not known");
+		return;
+	}
+
+	ubigen_info_init(&ui, mtd->eb_size, mtd->min_io_size, mtd->subpage_size,
+			 0, 1, 0);
+	printf("Default UBI VID header offset:  %d\n", ui.vid_hdr_offs);
+	printf("Default UBI data offset:        %d\n", ui.data_offs);
+	printf("Default UBI LEB size:           ");
+	ubiutils_print_bytes(ui.leb_size, 0);
+	printf("\n");
+	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
+}
+
 static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
 {
 	int err;
@@ -206,25 +227,9 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	printf("Device is writable:             %s\n",
 	      mtd.writable ? "true" : "false");
 
-	if (!args.ubinfo)
-		goto out;
-
-	if (!mtd_info->sysfs_supported) {
-		errmsg("cannot provide UBI info, becasue sub-page size is "
-		       "not known");
-		goto out;
-	}
-
-	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size,
-			 0, 1, 0);
-	printf("Default UBI VID header offset:  %d\n", ui.vid_hdr_offs);
-	printf("Default UBI data offset:        %d\n", ui.data_offs);
-	printf("Default UBI LEB size:           ");
-	ubiutils_print_bytes(ui.leb_size, 0);
-	printf("\n");
-	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
+	if (args.ubinfo)
+		print_ubi_info(mtd_info, &mtd);
 
-out:
 	printf("\n");
 	return 0;
 }
-- 
1.7.2.3


-- 
Best Regards,
Artem Bityutskiy (?????????? ????????????????)



From anemo at mba.ocn.ne.jp  Wed Jun  8 09:50:21 2011
From: anemo at mba.ocn.ne.jp (Atsushi Nemoto)
Date: Wed, 08 Jun 2011 22:50:21 +0900 (JST)
Subject: [PATCH 18/44] mtd: rbtx4939-flash.c: use mtd_device_parse_register
In-Reply-To: <1307453803-31950-19-git-send-email-dbaryshkov@gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-19-git-send-email-dbaryshkov@gmail.com>
Message-ID: <20110608.225021.214244518.anemo@mba.ocn.ne.jp>

On Tue,  7 Jun 2011 17:36:17 +0400, Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> wrote:
> @@ -106,18 +102,8 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
>  	info->mtd->owner = THIS_MODULE;
>  	if (err)
>  		goto err_out;
> -	err = parse_mtd_partitions(info->mtd, NULL, &info->parts, 0);
> -	if (err > 0) {
> -		mtd_device_register(info->mtd, info->parts, err);
> -		info->nr_parts = err;
> -		return 0;
> -	}
> -
> -	if (pdata->nr_parts) {
> -		pr_notice("Using rbtx4939 partition information\n");
> -		mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
> -		return 0;
> -	}
> +	err = mtd_device_parse_register(info->mtd, NULL, 0,
> +			pdata->parts, pdata->nr_parts);
>  
>  	mtd_device_register(info->mtd, NULL, 0);
>  	return 0;

The last mtd_device_register() call should be removed too?

---
Atsushi Nemoto


From dbaryshkov at gmail.com  Wed Jun  8 10:04:39 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 18:04:39 +0400
Subject: [PATCH 28/44] mtd: edb7312.c: use mtd_device_parse_register
In-Reply-To: <1307524810.31223.35.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-29-git-send-email-dbaryshkov@gmail.com>
	<1307524810.31223.35.camel@localhost>
Message-ID: <BANLkTikD6b7E0zK+y02NXu2me+e0du3N-w@mail.gmail.com>

On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
>> -	mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
>> +	mtd_device_register(ep7312_mtd, NULL, 0,
>> +			partition_info, NUM_PARTITIONS);
>
> And probably here?

82 syms

-- 
With best wishes
Dmitry


From dbaryshkov at gmail.com  Wed Jun  8 10:05:32 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 18:05:32 +0400
Subject: [PATCH 26/44] mtd: cs553x_nand.c: use mtd_device_parse_register
In-Reply-To: <1307524774.31223.34.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-27-git-send-email-dbaryshkov@gmail.com>
	<1307524774.31223.34.camel@localhost>
Message-ID: <BANLkTi=Fzn=FCK08xBG8HwpHuXdpRP_h4w@mail.gmail.com>

On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
>> +                       mtd_device_parse_register(cs553x_mtd[i], NULL,
>> 0,
>> +                                       NULL, 0);
>
> You do not need 2 lines here.

84 syms.

-- 
With best wishes
Dmitry


From dbaryshkov at gmail.com  Wed Jun  8 10:06:18 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 18:06:18 +0400
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <1307523765.31223.33.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
	<1307523682.31223.32.camel@localhost>
	<1307523765.31223.33.camel@localhost>
Message-ID: <BANLkTinZ_QVBpyB+PjcPDZ44obpBmOZpcA@mail.gmail.com>

On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-08 at 12:01 +0300, Artem Bityutskiy wrote:
>> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
>> > +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
>> > +                       pdata->parts, pdata->nr_parts);
>>
>> How about checking the return code? :-)
>
> Ok, you did not do it because the original function did not do it. Fair
> enough, this is a separate thing.

Nice idea. Making mtd_device_parse_register a __must_check function :)

-- 
With best wishes
Dmitry


From dbaryshkov at gmail.com  Wed Jun  8 10:07:40 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 18:07:40 +0400
Subject: [PATCH 18/44] mtd: rbtx4939-flash.c: use mtd_device_parse_register
In-Reply-To: <20110608.225021.214244518.anemo@mba.ocn.ne.jp>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-19-git-send-email-dbaryshkov@gmail.com>
	<20110608.225021.214244518.anemo@mba.ocn.ne.jp>
Message-ID: <BANLkTikhoyRZGxLo=VfxLBNEfwuHtQxuhA@mail.gmail.com>

On 6/8/11, Atsushi Nemoto <anemo at mba.ocn.ne.jp> wrote:
> On Tue,  7 Jun 2011 17:36:17 +0400, Dmitry Eremin-Solenikov
> <dbaryshkov at gmail.com> wrote:
>> @@ -106,18 +102,8 @@ static int rbtx4939_flash_probe(struct
>> platform_device *dev)
>>  	info->mtd->owner = THIS_MODULE;
>>  	if (err)
>>  		goto err_out;
>> -	err = parse_mtd_partitions(info->mtd, NULL, &info->parts, 0);
>> -	if (err > 0) {
>> -		mtd_device_register(info->mtd, info->parts, err);
>> -		info->nr_parts = err;
>> -		return 0;
>> -	}
>> -
>> -	if (pdata->nr_parts) {
>> -		pr_notice("Using rbtx4939 partition information\n");
>> -		mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
>> -		return 0;
>> -	}
>> +	err = mtd_device_parse_register(info->mtd, NULL, 0,
>> +			pdata->parts, pdata->nr_parts);
>>
>>  	mtd_device_register(info->mtd, NULL, 0);
>>  	return 0;
>
> The last mtd_device_register() call should be removed too?

Good catch, thanks!

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Wed Jun  8 10:11:05 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:11:05 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTikKVMQFxtE0S1VL4-SUPWNydgexLw@mail.gmail.com>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
	<1307421266.11104.10.camel@localhost>
	<BANLkTikKVMQFxtE0S1VL4-SUPWNydgexLw@mail.gmail.com>
Message-ID: <1307542265.31223.97.camel@localhost>

On Tue, 2011-06-07 at 16:41 -0400, Matthew L. Creech wrote:
> On Tue, Jun 7, 2011 at 12:34 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >
> > No, I have difficulties reading hexdumps. You have set of good nodes
> > following by one broken node. I wanted to see a human-readable dump of
> > the good nodes at the beginning of the LEB.
> >
> 
> Oh I see - sorry, I thought you wanted to debug the corrupted portion.
> 
> Here's the output for my corrupt flash:
> 
> http://mcreech.com/work/ubifs-2011-06-07.txt
> 
> I'll follow up with a patch.

Yes, it does look like this LEB might be garbage-collected. But it does
not have to be.

Anyway, what I can suggest you is to do several things.

1. If you have many occasions of such error, try to gather some
   information about how the device was used, and if it was uncleanly
   power-cut. Remember, I often saw that embedded devices have incorrect
   reboot. Whe users reboot it "normally" - it does not try to unmount
   the FS-es cleanly and just jumps to som HW reset function.

   You can verify this by rebooting normally and checking if UBIFS says
   "recovery needed" or not. If it does - the reboot was not normal.

2. This error may be due to memory corruptions in some driver (e.g.,
   wireless or video), due to issues in the mtd driver, etc. Try to
   stress your system with slub/slab full checks enabled, and other
   debugging features which you can find in the "hacking" section of
   make menuconfig.

3. If my theory is true, then what may help is adding a check it
   ubifs recovery function. The recovery ends with an ubifs_leb_change()
   call. You need to check the last node there - is it full and correct?
   If not, you should print a loud warning and information like leb dump
   _before_ the change, and dump of the buffer which we are going to
   write with ubifs_leb_change().

   You'd probably need to deploy this check to the field if this issue
   is not easy to reproduce. If you have then this info you may fix the
   bug.

4. Set-up power-cut emulation testing in your office.

P.S. I'm curious where you use UBIFS, if this is not a trade secret, of
course.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 10:12:09 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:12:09 +0300
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <BANLkTinZ_QVBpyB+PjcPDZ44obpBmOZpcA@mail.gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
	<1307523682.31223.32.camel@localhost>
	<1307523765.31223.33.camel@localhost>
	<BANLkTinZ_QVBpyB+PjcPDZ44obpBmOZpcA@mail.gmail.com>
Message-ID: <1307542329.31223.98.camel@localhost>

On Wed, 2011-06-08 at 18:06 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Wed, 2011-06-08 at 12:01 +0300, Artem Bityutskiy wrote:
> >> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> >> > +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
> >> > +                       pdata->parts, pdata->nr_parts);
> >>
> >> How about checking the return code? :-)
> >
> > Ok, you did not do it because the original function did not do it. Fair
> > enough, this is a separate thing.
> 
> Nice idea. Making mtd_device_parse_register a __must_check function :)

But please, do it as a separate patch.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 10:16:09 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:16:09 +0300
Subject: [PATCH] UBIFS: optionally return partial LEB scan results
In-Reply-To: <1307479967-3909-1-git-send-email-mlcreech@gmail.com>
References: <1307479967-3909-1-git-send-email-mlcreech@gmail.com>
Message-ID: <1307542569.31223.101.camel@localhost>

On Tue, 2011-06-07 at 16:52 -0400, Matthew L. Creech wrote:
> ubifs_scan() currently returns -EUCLEAN when it encounters corrupted data
> while scanning a LEB.  This is usually the right thing to do, but it prevents
> us from debugging certain kinds of corruption, since ubifs_scan() is called
> from dbg_dump_leb().
> 
> Add a flag which makes ubifs_scan() return partial node data when corruption
> is encountered, and use that flag in dbg_dump_leb().
> 
> Signed-off-by: Matthew L. Creech <mlcreech at gmail.com>
> ---
>  fs/ubifs/debug.c      |    2 +-
>  fs/ubifs/gc.c         |    2 +-
>  fs/ubifs/log.c        |    2 +-
>  fs/ubifs/lprops.c     |    2 +-
>  fs/ubifs/master.c     |    4 ++--
>  fs/ubifs/orphan.c     |    4 ++--
>  fs/ubifs/recovery.c   |    2 +-
>  fs/ubifs/replay.c     |    4 ++--
>  fs/ubifs/scan.c       |   16 ++++++++++++----
>  fs/ubifs/tnc_commit.c |    2 +-
>  fs/ubifs/ubifs.h      |    2 +-
>  11 files changed, 25 insertions(+), 17 deletions(-)

Thanks, but I think I'll do it differently. If the ubifs_scan() quiet
parameter is 0, then I can notice that this mean that the caller expects
corruptions and will fix it up. In which case current code will re-scan
the LEB. And I will make it so that if quiet == 0, then the scanned
buffer is not destroyed.

This will first of all make sure we do not read the same LEB 2 times
when recovering. And second of all - this is anyway needed to handle
unstable bits. So I'll be working on this change myself.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Wed Jun  8 10:22:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 18:22:01 +0400
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <1307542329.31223.98.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
	<1307523682.31223.32.camel@localhost>
	<1307523765.31223.33.camel@localhost>
	<BANLkTinZ_QVBpyB+PjcPDZ44obpBmOZpcA@mail.gmail.com>
	<1307542329.31223.98.camel@localhost>
Message-ID: <BANLkTinqjZJuAOfCvFjZGCcj8qQwTYB7dQ@mail.gmail.com>

On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-08 at 18:06 +0400, Dmitry Eremin-Solenikov wrote:
>> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> > On Wed, 2011-06-08 at 12:01 +0300, Artem Bityutskiy wrote:
>> >> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
>> >> > +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
>> >> > +                       pdata->parts, pdata->nr_parts);
>> >>
>> >> How about checking the return code? :-)
>> >
>> > Ok, you did not do it because the original function did not do it. Fair
>> > enough, this is a separate thing.
>>
>> Nice idea. Making mtd_device_parse_register a __must_check function :)
>
> But please, do it as a separate patch.

Why not make it a __must_check from the beginning? And fixup problematic
drivers later.

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Wed Jun  8 10:24:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:24:14 +0300
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <BANLkTinqjZJuAOfCvFjZGCcj8qQwTYB7dQ@mail.gmail.com>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
	<1307523682.31223.32.camel@localhost>
	<1307523765.31223.33.camel@localhost>
	<BANLkTinZ_QVBpyB+PjcPDZ44obpBmOZpcA@mail.gmail.com>
	<1307542329.31223.98.camel@localhost>
	<BANLkTinqjZJuAOfCvFjZGCcj8qQwTYB7dQ@mail.gmail.com>
Message-ID: <1307543054.31223.104.camel@localhost>

On Wed, 2011-06-08 at 18:22 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Wed, 2011-06-08 at 18:06 +0400, Dmitry Eremin-Solenikov wrote:
> >> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >> > On Wed, 2011-06-08 at 12:01 +0300, Artem Bityutskiy wrote:
> >> >> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
> >> >> > +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
> >> >> > +                       pdata->parts, pdata->nr_parts);
> >> >>
> >> >> How about checking the return code? :-)
> >> >
> >> > Ok, you did not do it because the original function did not do it. Fair
> >> > enough, this is a separate thing.
> >>
> >> Nice idea. Making mtd_device_parse_register a __must_check function :)
> >
> > But please, do it as a separate patch.
> 
> Why not make it a __must_check from the beginning? And fixup problematic
> drivers later.

Because it is a separate problem and separate set of patches is needed.
First, solve one problem, then start solving the other.

Secondly, if someone will later prove that __must_check was a mistake,
we can just revert that separate patch.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Wed Jun  8 10:31:37 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 8 Jun 2011 18:31:37 +0400
Subject: [PATCH 05/44] mtd: bfin-async-flash.c: use
	mtd_device_parse_register
In-Reply-To: <1307543054.31223.104.camel@localhost>
References: <1307453803-31950-1-git-send-email-dbaryshkov@gmail.com>
	<1307453803-31950-6-git-send-email-dbaryshkov@gmail.com>
	<1307523682.31223.32.camel@localhost>
	<1307523765.31223.33.camel@localhost>
	<BANLkTinZ_QVBpyB+PjcPDZ44obpBmOZpcA@mail.gmail.com>
	<1307542329.31223.98.camel@localhost>
	<BANLkTinqjZJuAOfCvFjZGCcj8qQwTYB7dQ@mail.gmail.com>
	<1307543054.31223.104.camel@localhost>
Message-ID: <BANLkTi=QOiwfBJJUMvKC+nxjVggMzzeESA@mail.gmail.com>

On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-08 at 18:22 +0400, Dmitry Eremin-Solenikov wrote:
>> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> > On Wed, 2011-06-08 at 18:06 +0400, Dmitry Eremin-Solenikov wrote:
>> >> On 6/8/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> >> > On Wed, 2011-06-08 at 12:01 +0300, Artem Bityutskiy wrote:
>> >> >> On Tue, 2011-06-07 at 17:36 +0400, Dmitry Eremin-Solenikov wrote:
>> >> >> > +       mtd_device_parse_register(state->mtd, part_probe_types, 0,
>> >> >> > +                       pdata->parts, pdata->nr_parts);
>> >> >>
>> >> >> How about checking the return code? :-)
>> >> >
>> >> > Ok, you did not do it because the original function did not do it.
>> >> > Fair
>> >> > enough, this is a separate thing.
>> >>
>> >> Nice idea. Making mtd_device_parse_register a __must_check function :)
>> >
>> > But please, do it as a separate patch.
>>
>> Why not make it a __must_check from the beginning? And fixup problematic
>> drivers later.
>
> Because it is a separate problem and separate set of patches is needed.
> First, solve one problem, then start solving the other.
>
> Secondly, if someone will later prove that __must_check was a mistake,
> we can just revert that separate patch.

Roger.

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Wed Jun  8 10:27:24 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:27:24 +0300
Subject: [PATCH 1/4] mtd: remove printk's for [kv][mz]alloc failures
In-Reply-To: <1307487717-25402-2-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
	<1307487717-25402-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307543244.31223.105.camel@localhost>

On Tue, 2011-06-07 at 16:01 -0700, Brian Norris wrote:
> When a memory allocation fails, the kernel will print out a backtrace
> automatically. These print statements are unnecessary.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  drivers/mtd/cmdlinepart.c         |    3 ---
>  drivers/mtd/inftlcore.c           |    4 +---
>  drivers/mtd/nand/nand_bbt.c       |   13 +++----------
>  drivers/mtd/nand/rtc_from4.c      |    1 -
>  drivers/mtd/nftlcore.c            |    4 +---
>  drivers/mtd/onenand/onenand_bbt.c |    4 +---
>  drivers/mtd/ssfdc.c               |   10 ++--------
>  7 files changed, 8 insertions(+), 31 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 10:43:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:43:47 +0300
Subject: [PATCH 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307487717-25402-3-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
	<1307487717-25402-3-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307544227.31223.115.camel@localhost>

Brian, thanks for the patch, it certainly makes the code nicer and a bit
more readable. But I have few requests.

On Tue, 2011-06-07 at 16:01 -0700, Brian Norris wrote:
> -		printk(KERN_NOTICE "%s: Attempt to write not "
> +		pr_notice("%s: Attempt to write not "
>  				"page aligned data\n", __func__);

OK, so with this change the string becomes shorter and you do not have
to split it any more. You should make it look like this:

               pr_notice("%s: attempt to write not page aligned data\n",
                          __func__);
 
This is more readable and preferable - no string split. Please, do this
for other messages too.

Also, while on it, may be you could unify the messages and make them:

1. start with small letter if there is a function name prerix -
   currently some start with small and some start with capital.
2. if there is a dot at the end - remove it.


> @@ -2561,7 +2561,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
>  		/* Heck if we have a bad block, we do not erase bad blocks! */
>  		if (nand_block_checkbad(mtd, ((loff_t) page) <<
>  					chip->page_shift, 0, allowbbt)) {
> -			printk(KERN_WARNING "%s: attempt to erase a bad block "
> +			pr_warning("%s: attempt to erase a bad block "
>  					"at page 0x%08x\n", __func__, page);

Since you now have more space, I think it is a bit better to re-wrap the
message, i.e., make it like this:

                       pr_warning("%s: attempt to erase a bad block at page "
                                  "0x%08x\n", __func__, page);

or, if you prefer, even like this:

                       pr_warning("%s: attempt to erase a bad block at page 0x%08x\n",
                                   __func__, page);
 
because the coding style does allow strings longer than 80 characters if
"exceeding 80 columns significantly increases readability".

Ditto for the rest. With this, your clean-up will make the code even
cleaner :-)

Thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 10:44:55 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:44:55 +0300
Subject: [PATCH 3/4] mtd: nand: replace DEBUG() with dev_dbg()
In-Reply-To: <1307487717-25402-4-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
	<1307487717-25402-4-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307544295.31223.116.camel@localhost>

On Tue, 2011-06-07 at 16:01 -0700, Brian Norris wrote:
> -		DEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
> +		dev_dbg(&mtd->dev, "%s: Length not block aligned\n",
>  					__func__);

Ditto for this patch.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Wed Jun  8 10:47:56 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:47:56 +0300
Subject: [PATCH 4/4] mtd: nand: define pr_fmt() to include __func__ in
	debug output
In-Reply-To: <1307487717-25402-5-git-send-email-computersforpeace@gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
	<1307487717-25402-5-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307544476.31223.119.camel@localhost>

On Tue, 2011-06-07 at 16:01 -0700, Brian Norris wrote:
> -				pr_info("nand_bbt: Error reading bad block table\n");
> +				pr_info("Error reading bad block table\n");

Compare:

read_bbt: Error reading bad block table
read_bbt: error reading bad block table

isn't the second version more correct? Or this depends on the country? I
prefer the latter, but as long as all messages are consistent, I do not
care much. What do you think?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From Artem.Bityutskiy at nokia.com  Wed Jun  8 10:52:37 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 17:52:37 +0300
Subject: [PATCH] mtd: davinci_nand: remove redundant
	mtd_device_unregister in nand_davinci_remove
In-Reply-To: <1307538097.17552.4.camel@phoenix>
References: <1307538097.17552.4.camel@phoenix>
Message-ID: <1307544757.31223.120.camel@localhost>

On Wed, 2011-06-08 at 21:01 +0800, Axel Lin wrote:
> mtd_device_unregister is done in nand_release(),
> thus no need to call it in nand_davinci_remove().
> 
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Wed Jun  8 11:59:49 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 19:59:49 +0400
Subject: [PATCH] mtd: lart.c: cleanup: drop HAVE_PARTITIONS
Message-ID: <1307548789-5733-1-git-send-email-dbaryshkov@gmail.com>

Consolidate knowledge about partitions in drivers/mtd/devices/lart.c.
Drop all HAVE_PARTITIONS conditionals. Always use partitioning.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/lart.c |   18 +-----------------
 1 files changed, 1 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/devices/lart.c b/drivers/mtd/devices/lart.c
index 772a0ff..3a11ea6 100644
--- a/drivers/mtd/devices/lart.c
+++ b/drivers/mtd/devices/lart.c
@@ -34,9 +34,6 @@
 /* debugging */
 //#define LART_DEBUG
 
-/* partition support */
-#define HAVE_PARTITIONS
-
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -44,9 +41,7 @@
 #include <linux/errno.h>
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
-#ifdef HAVE_PARTITIONS
 #include <linux/mtd/partitions.h>
-#endif
 
 #ifndef CONFIG_SA1100_LART
 #error This is for LART architecture only
@@ -598,7 +593,6 @@ static struct mtd_erase_region_info erase_regions[] = {
 	}
 };
 
-#ifdef HAVE_PARTITIONS
 static struct mtd_partition lart_partitions[] = {
 	/* blob */
 	{
@@ -619,7 +613,7 @@ static struct mtd_partition lart_partitions[] = {
 		.size	= INITRD_LEN,		/* MTDPART_SIZ_FULL */
 	}
 };
-#endif
+#define NUM_PARTITIONS ARRAY_SIZE(lart_partitions)
 
 static int __init lart_flash_init (void)
 {
@@ -668,7 +662,6 @@ static int __init lart_flash_init (void)
 			   result,mtd.eraseregions[result].erasesize,mtd.eraseregions[result].erasesize / 1024,
 			   result,mtd.eraseregions[result].numblocks);
 
-#ifdef HAVE_PARTITIONS
    printk ("\npartitions = %d\n", ARRAY_SIZE(lart_partitions));
 
    for (result = 0; result < ARRAY_SIZE(lart_partitions); result++)
@@ -681,25 +674,16 @@ static int __init lart_flash_init (void)
 			 result,lart_partitions[result].offset,
 			 result,lart_partitions[result].size,lart_partitions[result].size / 1024);
 #endif
-#endif
 
-#ifndef HAVE_PARTITIONS
-   result = mtd_device_register(&mtd, NULL, 0);
-#else
    result = mtd_device_register(&mtd, lart_partitions,
                                 ARRAY_SIZE(lart_partitions));
-#endif
 
    return (result);
 }
 
 static void __exit lart_flash_exit (void)
 {
-#ifndef HAVE_PARTITIONS
-   mtd_device_unregister(&mtd);
-#else
    mtd_device_unregister(&mtd);
-#endif
 }
 
 module_init (lart_flash_init);
-- 
1.7.4.4



From dedekind1 at gmail.com  Wed Jun  8 11:59:58 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 08 Jun 2011 18:59:58 +0300
Subject: [PATCH] mtd: lart.c: cleanup: drop HAVE_PARTITIONS
In-Reply-To: <1307548789-5733-1-git-send-email-dbaryshkov@gmail.com>
References: <1307548789-5733-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307548798.7374.0.camel@localhost>

On Wed, 2011-06-08 at 19:59 +0400, Dmitry Eremin-Solenikov wrote:
> Consolidate knowledge about partitions in drivers/mtd/devices/lart.c.
> Drop all HAVE_PARTITIONS conditionals. Always use partitioning.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/devices/lart.c |   18 +-----------------
>  1 files changed, 1 insertions(+), 17 deletions(-)

Looks good, thanks, pushed to l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Wed Jun  8 12:05:09 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:09 +0400
Subject: [PATCH 0/43 V2] mtd: simplify mtd partitions handling
Message-ID: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>

Lots of mtd drivers have more or less the same common logic:
parse partitions, then register them. Currently this ends up
with lots of code duplication, each copy having it's own features
and bugs. In this patch serie I create a special function
(mtd_device_parse_register) which handles all issues with acquiring
partition information, registering mtd device(s) and returning correct
error code.

Changes since V1:
- Added kerneldoc for mtd_device_parse_register
- removed lart.c patch (wrong commit message)
- dropped call to mtd_device_register from rbtx4939-flash
- small fixes within patches

The following changes since commit 1dc1d90aa53e6cec61f5369b6d1e185b3ef40c14:

  mtd: davinci_nand: remove redundant mtd_device_unregister (2011-06-08 18:00:41 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-parse-1st-2

Dmitry Eremin-Solenikov (43):
      mtd: add new API for handling MTD registration
      mtd: mtd_dataflash.c: use mtd_device_parse_register
      mtd: sst25l.c: use mtd_device_parse_register
      mtd: bfin-async-flash.c: use mtd_device_parse_register
      mtd: dc21285.c: use mtd_device_parse_register
      mtd: gpio-addr-flash.c: use mtd_device_parse_register
      mtd: h720x-flash.c: use mtd_device_parse_register
      mtd: impa7.c: use mtd_device_parse_register
      mtd: intel_vr_nor.c: use mtd_device_parse_register
      mtd: ixp2000.c: use mtd_device_parse_register
      mtd: ixp4xx.c: use mtd_device_parse_register
      mtd: lantiq-flash.c: use mtd_device_parse_register
      mtd: latch-addr-flash.c: use mtd_device_parse_register
      mtd: physmap.c: use mtd_device_parse_register
      mtd: plat-ram.c: use mtd_device_parse_register
      mtd: pxa2xx-flash.c: use mtd_device_parse_register
      mtd: rbtx4939-flash.c: use mtd_device_parse_register
      mtd: sa1100-flash.c: use mtd_device_parse_register
      mtd: solutionengine.c: use mtd_device_parse_register
      mtd: wr_sbc82xx_flash.c: use mtd_device_parse_register
      mtd: atmel_nand.c: use mtd_device_parse_register
      mtd: bcm_umi_nand.c: use mtd_device_parse_register
      mtd: cafe_nand.c: use mtd_device_parse_register
      mtd: cmx270_nand.c: use mtd_device_parse_register
      mtd: cs553x_nand.c: use mtd_device_parse_register
      mtd: davinci_nand.c: use mtd_device_parse_register
      mtd: edb7312.c: use mtd_device_parse_register
      mtd: fsmc_nand.c: use mtd_device_parse_register
      mtd: h1910.c: use mtd_device_parse_register
      mtd: jz4740_nand.c: use mtd_device_parse_register
      mtd: mxc_nand.c: use mtd_device_parse_register
      mtd: omap2.c: use mtd_device_parse_register
      mtd: orion_nand.c: use mtd_device_parse_register
      mtd: plat_nand.c: use mtd_device_parse_register
      mtd: ppchameleonevb.c: use mtd_device_parse_register
      mtd: pxa3xx_nand.c: use mtd_device_parse_register
      mtd: s3c2410.c: use mtd_device_parse_register
      mtd: sharpsl.c: use mtd_device_parse_register
      mtd: tmio_nand.c: use mtd_device_parse_register
      mtd: txx9ndfmc.c: use mtd_device_parse_register
      mtd: onenand/generic.c: use mtd_device_parse_register
      mtd: onenand/omap2.c: use mtd_device_parse_register
      mtd: onenand/samsung.c: use mtd_device_parse_register

 drivers/mtd/devices/mtd_dataflash.c |   21 ++---------
 drivers/mtd/devices/sst25l.c        |   33 ++---------------
 drivers/mtd/maps/bfin-async-flash.c |   16 +-------
 drivers/mtd/maps/dc21285.c          |    9 +----
 drivers/mtd/maps/gpio-addr-flash.c  |   16 +-------
 drivers/mtd/maps/h720x-flash.c      |   21 +----------
 drivers/mtd/maps/impa7.c            |   25 ++-----------
 drivers/mtd/maps/intel_vr_nor.c     |    6 +---
 drivers/mtd/maps/ixp2000.c          |   11 +-----
 drivers/mtd/maps/ixp4xx.c           |   29 ++-------------
 drivers/mtd/maps/lantiq-flash.c     |   14 +------
 drivers/mtd/maps/latch-addr-flash.c |   21 +----------
 drivers/mtd/maps/physmap.c          |   23 +-----------
 drivers/mtd/maps/plat-ram.c         |   23 +-----------
 drivers/mtd/maps/pxa2xx-flash.c     |   20 +----------
 drivers/mtd/maps/rbtx4939-flash.c   |   21 ++---------
 drivers/mtd/maps/sa1100-flash.c     |   30 ++--------------
 drivers/mtd/maps/solutionengine.c   |   30 ++++------------
 drivers/mtd/maps/wr_sbc82xx_flash.c |   30 ++++++----------
 drivers/mtd/mtdcore.c               |   60 +++++++++++++++++++++++++++++++
 drivers/mtd/nand/atmel_nand.c       |   19 +---------
 drivers/mtd/nand/bcm_umi_nand.c     |   19 +---------
 drivers/mtd/nand/cafe_nand.c        |   11 +-----
 drivers/mtd/nand/cmx270_nand.c      |   20 +---------
 drivers/mtd/nand/cs553x_nand.c      |    8 +---
 drivers/mtd/nand/davinci_nand.c     |   25 +------------
 drivers/mtd/nand/edb7312.c          |   17 +--------
 drivers/mtd/nand/fsmc_nand.c        |   66 +++++------------------------------
 drivers/mtd/nand/h1910.c            |   15 +-------
 drivers/mtd/nand/jz4740_nand.c      |   11 ++----
 drivers/mtd/nand/mxc_nand.c         |   15 ++------
 drivers/mtd/nand/omap2.c            |   10 +----
 drivers/mtd/nand/orion_nand.c       |   12 +-----
 drivers/mtd/nand/plat_nand.c        |   22 ++----------
 drivers/mtd/nand/ppchameleonevb.c   |   42 +++++-----------------
 drivers/mtd/nand/pxa3xx_nand.c      |   11 +-----
 drivers/mtd/nand/s3c2410.c          |   18 ++-------
 drivers/mtd/nand/sharpsl.c          |   11 +-----
 drivers/mtd/nand/tmio_nand.c        |   12 ++-----
 drivers/mtd/nand/txx9ndfmc.c        |    7 +---
 drivers/mtd/onenand/generic.c       |   11 ++----
 drivers/mtd/onenand/omap2.c         |   13 ++-----
 drivers/mtd/onenand/samsung.c       |   11 ++----
 include/linux/mtd/mtd.h             |    5 +++
 44 files changed, 191 insertions(+), 679 deletions(-)



From dbaryshkov at gmail.com  Wed Jun  8 12:05:10 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:10 +0400
Subject: [PATCH 01/43] mtd: add new API for handling MTD registration
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-2-git-send-email-dbaryshkov@gmail.com>

Lots (nearly all) mtd drivers contain nearly the similar code that
calls parse_mtd_partitions, provides some platform-default values, if
parsing fails, and registers  mtd device.

This is an aim to provide single implementation of this scenario:
mtd_device_parse_register() which will handle all this parsing and
defaults.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c   |   60 +++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/mtd/mtd.h |    5 ++++
 2 files changed, 65 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index c510aff..a0b41e3 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -452,6 +452,66 @@ int mtd_device_register(struct mtd_info *master,
 EXPORT_SYMBOL_GPL(mtd_device_register);
 
 /**
+ * mtd_device_parse_register - parse partitions and register an MTD device.
+ *
+ * @mtd: the MTD device to register
+ * @types: the list of MTD partition probes to try, see
+ *		'parse_mtd_partitions()' for more information
+ * @origin: start address of MTD device, %0 unless you are sure you need this.
+ * @parts: fallback partition information to register, if parsing fails;
+ *		only valid if %nr_parts > %0
+ * @nr_parts: the number of partitions in parts, if zero then the full
+ *		MTD device is registered if no partition info is found
+ *
+ * This function aggregates MTD partitions parsing (done by
+ * 'parse_mtd_partitions()') and MTD device and partitions registering. It
+ * basically follows the most common pattern found in many MTD drivers:
+ *
+ * * It first tries to probe partitions on MTD device @mtd using parsers
+ *   specified in @types (if @types is %NULL, then the default list of
+ *   parsers is used, see 'parse_mtd_partitions()' for more information).
+ * * If none are found this functions tries to fallback to information
+ *   specified in @parts/@nr_parts.
+ * * If any parititioning info was found, this function registers
+ *   the found partitions.
+ * * If no partitions were found this function just registers the MTD
+ *   device @mtd and exits.
+ *
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **types,
+			      unsigned long origin,
+			      const struct mtd_partition *parts,
+			      int nr_parts)
+{
+	int err;
+	struct mtd_partition *real_parts;
+
+	err = parse_mtd_partitions(mtd, types, &real_parts, origin);
+	if (err <= 0 && nr_parts) {
+		real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
+				GFP_KERNEL);
+		err = nr_parts;
+		if (!parts)
+			err = -ENOMEM;
+	}
+
+	if (err > 0) {
+		err = add_mtd_partitions(mtd, real_parts, err);
+		kfree(real_parts);
+	} else if (err == 0) {
+		err = add_mtd_device(mtd);
+		if (err == 1)
+			err = -ENODEV;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(mtd_device_parse_register);
+
+/**
  * mtd_device_unregister - unregister an existing MTD device.
  *
  * @master: the MTD device to unregister.  This will unregister both the master
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index 2541fb8..d28a241 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -327,6 +327,11 @@ struct mtd_partition;
 extern int mtd_device_register(struct mtd_info *master,
 			       const struct mtd_partition *parts,
 			       int nr_parts);
+extern int mtd_device_parse_register(struct mtd_info *mtd,
+			      const char **part_probe_types,
+			      unsigned long origin,
+			      const struct mtd_partition *defparts,
+			      int defnr_parts);
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:11 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:11 +0400
Subject: [PATCH 02/43] mtd: mtd_dataflash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-3-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/mtd_dataflash.c |   21 +++------------------
 1 files changed, 3 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c
index 4d4a9cd..8f6b02c 100644
--- a/drivers/mtd/devices/mtd_dataflash.c
+++ b/drivers/mtd/devices/mtd_dataflash.c
@@ -637,8 +637,6 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 	struct flash_platform_data	*pdata = spi->dev.platform_data;
 	char				*otp_tag = "";
 	int				err = 0;
-	struct mtd_partition		*parts;
-	int				nr_parts = 0;
 
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv)
@@ -677,23 +675,10 @@ add_dataflash_otp(struct spi_device *spi, char *name,
 			pagesize, otp_tag);
 	dev_set_drvdata(&spi->dev, priv);
 
-	nr_parts = parse_mtd_partitions(device, NULL, &parts, 0);
+	err = mtd_device_parse_register(device, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
-	if (nr_parts <= 0 && pdata && pdata->parts) {
-		parts = pdata->parts;
-		nr_parts = pdata->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		priv->partitioned = 1;
-		err = mtd_device_register(device, parts, nr_parts);
-		goto out;
-	}
-
-	if (mtd_device_register(device, NULL, 0) == 1)
-		err = -ENODEV;
-
-out:
 	if (!err)
 		return 0;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:12 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:12 +0400
Subject: [PATCH 03/43] mtd: sst25l.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-4-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/sst25l.c |   33 ++++-----------------------------
 1 files changed, 4 insertions(+), 29 deletions(-)

diff --git a/drivers/mtd/devices/sst25l.c b/drivers/mtd/devices/sst25l.c
index cd095af..eaae4e0 100644
--- a/drivers/mtd/devices/sst25l.c
+++ b/drivers/mtd/devices/sst25l.c
@@ -52,8 +52,6 @@ struct sst25l_flash {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-
-	int 			partitioned;
 };
 
 struct flash_info {
@@ -381,8 +379,6 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	struct sst25l_flash *flash;
 	struct flash_platform_data *data;
 	int ret, i;
-	struct mtd_partition *parts = NULL;
-	int nr_parts = 0;
 
 	flash_info = sst25l_match_device(spi);
 	if (!flash_info)
@@ -423,31 +419,10 @@ static int __devinit sst25l_probe(struct spi_device *spi)
 	      flash->mtd.numeraseregions);
 
 
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-
-		flash->partitioned = 1;
-		return mtd_device_register(&flash->mtd, parts,
-					   nr_parts);
-	}
-
-	ret = mtd_device_register(&flash->mtd, NULL, 0);
-	if (ret == 1) {
+	ret = mtd_device_parse_register(&flash->mtd, NULL, 0,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
+	if (ret) {
 		kfree(flash);
 		dev_set_drvdata(&spi->dev, NULL);
 		return -ENODEV;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:13 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:13 +0400
Subject: [PATCH 04/43] mtd: bfin-async-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-5-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/bfin-async-flash.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/maps/bfin-async-flash.c b/drivers/mtd/maps/bfin-async-flash.c
index d4297a9..246890e 100644
--- a/drivers/mtd/maps/bfin-async-flash.c
+++ b/drivers/mtd/maps/bfin-async-flash.c
@@ -41,7 +41,6 @@ struct async_state {
 	uint32_t flash_ambctl0, flash_ambctl1;
 	uint32_t save_ambctl0, save_ambctl1;
 	unsigned long irq_flags;
-	struct mtd_partition *parts;
 };
 
 static void switch_to_flash(struct async_state *state)
@@ -165,18 +164,8 @@ static int __devinit bfin_flash_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	ret = parse_mtd_partitions(state->mtd, part_probe_types, &pdata->parts, 0);
-	if (ret > 0) {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using commandline partition definition\n");
-		mtd_device_register(state->mtd, pdata->parts, ret);
-		state->parts = pdata->parts;
-	} else if (pdata->nr_parts) {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": Using board partition definition\n");
-		mtd_device_register(state->mtd, pdata->parts, pdata->nr_parts);
-	} else {
-		pr_devinit(KERN_NOTICE DRIVER_NAME ": no partition info available, registering whole flash at once\n");
-		mtd_device_register(state->mtd, NULL, 0);
-	}
+	mtd_device_parse_register(state->mtd, part_probe_types, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, state);
 
@@ -188,7 +177,6 @@ static int __devexit bfin_flash_remove(struct platform_device *pdev)
 	struct async_state *state = platform_get_drvdata(pdev);
 	gpio_free(state->enet_flash_pin);
 	mtd_device_unregister(state->mtd);
-	kfree(state->parts);
 	map_destroy(state->mtd);
 	kfree(state);
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:14 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:14 +0400
Subject: [PATCH 05/43] mtd: dc21285.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-6-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/dc21285.c |    9 +--------
 1 files changed, 1 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/maps/dc21285.c b/drivers/mtd/maps/dc21285.c
index 7a9e198..f43b365 100644
--- a/drivers/mtd/maps/dc21285.c
+++ b/drivers/mtd/maps/dc21285.c
@@ -145,14 +145,10 @@ static struct map_info dc21285_map = {
 
 
 /* Partition stuff */
-static struct mtd_partition *dc21285_parts;
 static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
 
 static int __init init_dc21285(void)
 {
-
-	int nrparts;
-
 	/* Determine bankwidth */
 	switch (*CSR_SA110_CNTL & (3<<14)) {
 		case SA110_CNTL_ROMWIDTH_8:
@@ -200,8 +196,7 @@ static int __init init_dc21285(void)
 
 	dc21285_mtd->owner = THIS_MODULE;
 
-	nrparts = parse_mtd_partitions(dc21285_mtd, probes, &dc21285_parts, 0);
-	mtd_device_register(dc21285_mtd, dc21285_parts, nrparts);
+	mtd_device_parse_register(dc21285_mtd, probes, 0, NULL, 0);
 
 	if(machine_is_ebsa285()) {
 		/*
@@ -224,8 +219,6 @@ static int __init init_dc21285(void)
 static void __exit cleanup_dc21285(void)
 {
 	mtd_device_unregister(dc21285_mtd);
-	if (dc21285_parts)
-		kfree(dc21285_parts);
 	map_destroy(dc21285_mtd);
 	iounmap(dc21285_map.virt);
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:15 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:15 +0400
Subject: [PATCH 06/43] mtd: gpio-addr-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-7-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/gpio-addr-flash.c |   16 ++--------------
 1 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 7568c5f..1ec66f0 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -187,7 +187,6 @@ static const char *part_probe_types[] = { "cmdlinepart", "RedBoot", NULL };
  */
 static int __devinit gpio_flash_probe(struct platform_device *pdev)
 {
-	int nr_parts;
 	size_t i, arr_size;
 	struct physmap_flash_data *pdata;
 	struct resource *memory;
@@ -252,20 +251,9 @@ static int __devinit gpio_flash_probe(struct platform_device *pdev)
 		return -ENXIO;
 	}
 
-	nr_parts = parse_mtd_partitions(state->mtd, part_probe_types,
-					&pdata->parts, 0);
-	if (nr_parts > 0) {
-		pr_devinit(KERN_NOTICE PFX "Using commandline partition definition\n");
-		kfree(pdata->parts);
-	} else if (pdata->nr_parts) {
-		pr_devinit(KERN_NOTICE PFX "Using board partition definition\n");
-		nr_parts = pdata->nr_parts;
-	} else {
-		pr_devinit(KERN_NOTICE PFX "no partition info available, registering whole flash at once\n");
-		nr_parts = 0;
-	}
 
-	mtd_device_register(state->mtd, pdata->parts, nr_parts);
+	mtd_device_parse_register(state->mtd, part_probe_types, 0,
+			pdata->parts, pdata->nr_parts);
 
 	return 0;
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:16 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:16 +0400
Subject: [PATCH 07/43] mtd: h720x-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-8-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/h720x-flash.c |   21 ++-------------------
 1 files changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/h720x-flash.c b/drivers/mtd/maps/h720x-flash.c
index f331a2c..49c1418 100644
--- a/drivers/mtd/maps/h720x-flash.c
+++ b/drivers/mtd/maps/h720x-flash.c
@@ -58,16 +58,11 @@ static struct mtd_partition h720x_partitions[] = {
 
 #define NUM_PARTITIONS ARRAY_SIZE(h720x_partitions)
 
-static int                   nr_mtd_parts;
-static struct mtd_partition *mtd_parts;
 /*
  * Initialize FLASH support
  */
 static int __init h720x_mtd_init(void)
 {
-
-	char	*part_type = NULL;
-
 	h720x_map.virt = ioremap(h720x_map.phys, h720x_map.size);
 
 	if (!h720x_map.virt) {
@@ -90,16 +85,8 @@ static int __init h720x_mtd_init(void)
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
 
-		nr_mtd_parts = parse_mtd_partitions(mymtd, NULL, &mtd_parts, 0);
-		if (nr_mtd_parts > 0)
-			part_type = "command line";
-		if (nr_mtd_parts <= 0) {
-			mtd_parts = h720x_partitions;
-			nr_mtd_parts = NUM_PARTITIONS;
-			part_type = "builtin";
-		}
-		printk(KERN_INFO "Using %s partition table\n", part_type);
-		mtd_device_register(mymtd, mtd_parts, nr_mtd_parts);
+		mtd_device_parse_register(mymtd, NULL, 0,
+				h720x_partitions, NUM_PARTITIONS);
 		return 0;
 	}
 
@@ -118,10 +105,6 @@ static void __exit h720x_mtd_cleanup(void)
 		map_destroy(mymtd);
 	}
 
-	/* Free partition info, if commandline partition was used */
-	if (mtd_parts && (mtd_parts != h720x_partitions))
-		kfree (mtd_parts);
-
 	if (h720x_map.virt) {
 		iounmap((void *)h720x_map.virt);
 		h720x_map.virt = 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:18 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:18 +0400
Subject: [PATCH 09/43] mtd: intel_vr_nor.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-10-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/intel_vr_nor.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/maps/intel_vr_nor.c b/drivers/mtd/maps/intel_vr_nor.c
index fd612c7..08c2396 100644
--- a/drivers/mtd/maps/intel_vr_nor.c
+++ b/drivers/mtd/maps/intel_vr_nor.c
@@ -44,7 +44,6 @@ struct vr_nor_mtd {
 	void __iomem *csr_base;
 	struct map_info map;
 	struct mtd_info *info;
-	int nr_parts;
 	struct pci_dev *dev;
 };
 
@@ -71,12 +70,9 @@ static void __devexit vr_nor_destroy_partitions(struct vr_nor_mtd *p)
 
 static int __devinit vr_nor_init_partitions(struct vr_nor_mtd *p)
 {
-	struct mtd_partition *parts;
-
 	/* register the flash bank */
 	/* partition the flash bank */
-	p->nr_parts = parse_mtd_partitions(p->info, NULL, &parts, 0);
-	return mtd_device_register(p->info, parts, p->nr_parts);
+	return mtd_device_parse_register(p->info, NULL, 0, NULL, 0);
 }
 
 static void __devexit vr_nor_destroy_mtd_setup(struct vr_nor_mtd *p)
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:17 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:17 +0400
Subject: [PATCH 08/43] mtd: impa7.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-9-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/impa7.c |   25 +++----------------------
 1 files changed, 3 insertions(+), 22 deletions(-)

diff --git a/drivers/mtd/maps/impa7.c b/drivers/mtd/maps/impa7.c
index 2d45a48..7b8b5d8 100644
--- a/drivers/mtd/maps/impa7.c
+++ b/drivers/mtd/maps/impa7.c
@@ -58,15 +58,10 @@ static struct mtd_partition static_partitions[] =
 	},
 };
 
-static int mtd_parts_nb[NUM_FLASHBANKS];
-static struct mtd_partition *mtd_parts[NUM_FLASHBANKS];
-
-
 static int __init init_impa7(void)
 {
 	static const char *rom_probe_types[] = PROBETYPES;
 	const char **type;
-	const char *part_type = 0;
 	int i;
 	static struct { u_long addr; u_long size; } pt[NUM_FLASHBANKS] = {
 	  { WINDOW_ADDR0, WINDOW_SIZE0 },
@@ -96,23 +91,9 @@ static int __init init_impa7(void)
 		if (impa7_mtd[i]) {
 			impa7_mtd[i]->owner = THIS_MODULE;
 			devicesfound++;
-			mtd_parts_nb[i] = parse_mtd_partitions(impa7_mtd[i],
-							       NULL,
-							       &mtd_parts[i],
-							       0);
-			if (mtd_parts_nb[i] > 0) {
-				part_type = "command line";
-			} else {
-				mtd_parts[i] = static_partitions;
-				mtd_parts_nb[i] = ARRAY_SIZE(static_partitions);
-				part_type = "static";
-			}
-
-			printk(KERN_NOTICE MSG_PREFIX
-			       "using %s partition definition\n",
-			       part_type);
-			mtd_device_register(impa7_mtd[i],
-					    mtd_parts[i], mtd_parts_nb[i]);
+			mtd_device_parse_register(impa7_mtd[i], NULL, 0,
+					static_partitions,
+					ARRAY_SIZE(static_partitions));
 		}
 		else
 			iounmap((void *)impa7_map[i].virt);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:20 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:20 +0400
Subject: [PATCH 11/43] mtd: ixp4xx.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-12-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/ixp4xx.c |   29 ++++-------------------------
 1 files changed, 4 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/maps/ixp4xx.c b/drivers/mtd/maps/ixp4xx.c
index 155b219..3040901 100644
--- a/drivers/mtd/maps/ixp4xx.c
+++ b/drivers/mtd/maps/ixp4xx.c
@@ -145,7 +145,6 @@ static void ixp4xx_write16(struct map_info *map, map_word d, unsigned long adr)
 struct ixp4xx_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-	struct mtd_partition *partitions;
 	struct resource *res;
 };
 
@@ -168,8 +167,6 @@ static int ixp4xx_flash_remove(struct platform_device *dev)
 	if (info->map.virt)
 		iounmap(info->map.virt);
 
-	kfree(info->partitions);
-
 	if (info->res) {
 		release_resource(info->res);
 		kfree(info->res);
@@ -185,8 +182,6 @@ 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)
@@ -252,28 +247,12 @@ static int ixp4xx_flash_probe(struct platform_device *dev)
 	/* Use the fast version */
 	info->map.write = ixp4xx_write16;
 
-	nr_parts = parse_mtd_partitions(info->mtd, probes, &info->partitions,
-					dev->resource->start);
-	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");
-	else
-		printk(KERN_NOTICE "IXP4xx flash: using %s partition "
-			"definition\n", part_type);
-
-	err = mtd_device_register(info->mtd, info->partitions, nr_parts);
-	if (err)
+	err = mtd_device_parse_register(info->mtd, probes, dev->resource->start,
+			plat->parts, plat->nr_parts);
+	if (err) {
 		printk(KERN_ERR "Could not parse partitions\n");
-
-	if (err)
 		goto Error;
+	}
 
 	return 0;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:19 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:19 +0400
Subject: [PATCH 10/43] mtd: ixp2000.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-11-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/ixp2000.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/maps/ixp2000.c b/drivers/mtd/maps/ixp2000.c
index c00b917..93bf83d 100644
--- a/drivers/mtd/maps/ixp2000.c
+++ b/drivers/mtd/maps/ixp2000.c
@@ -38,7 +38,6 @@
 struct ixp2000_flash_info {
 	struct		mtd_info *mtd;
 	struct		map_info map;
-	struct		mtd_partition *partitions;
 	struct		resource *res;
 };
 
@@ -125,8 +124,6 @@ static int ixp2000_flash_remove(struct platform_device *dev)
 	if (info->map.map_priv_1)
 		iounmap((void *) info->map.map_priv_1);
 
-	kfree(info->partitions);
-
 	if (info->res) {
 		release_resource(info->res);
 		kfree(info->res);
@@ -228,13 +225,7 @@ static int ixp2000_flash_probe(struct platform_device *dev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, probes, &info->partitions, 0);
-	if (err > 0) {
-		err = mtd_device_register(info->mtd, info->partitions, err);
-		if(err)
-			dev_err(&dev->dev, "Could not parse partitions\n");
-	}
-
+	err = mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
 	if (err)
 		goto Error;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:21 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:21 +0400
Subject: [PATCH 12/43] mtd: lantiq-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-13-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/lantiq-flash.c |   14 ++------------
 1 files changed, 2 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/maps/lantiq-flash.c b/drivers/mtd/maps/lantiq-flash.c
index 57ea3fe..f750784 100644
--- a/drivers/mtd/maps/lantiq-flash.c
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -112,9 +112,7 @@ ltq_mtd_probe(struct platform_device *pdev)
 {
 	struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
 	struct ltq_mtd *ltq_mtd;
-	struct mtd_partition *parts;
 	struct resource *res;
-	int nr_parts = 0;
 	struct cfi_private *cfi;
 	int err;
 
@@ -170,16 +168,8 @@ ltq_mtd_probe(struct platform_device *pdev)
 	cfi->addr_unlock1 ^= 1;
 	cfi->addr_unlock2 ^= 1;
 
-	nr_parts = parse_mtd_partitions(ltq_mtd->mtd, NULL, &parts, 0);
-	if (nr_parts > 0) {
-		dev_info(&pdev->dev,
-			"using %d partitions from cmdline", nr_parts);
-	} else {
-		nr_parts = ltq_mtd_data->nr_parts;
-		parts = ltq_mtd_data->parts;
-	}
-
-	err = add_mtd_partitions(ltq_mtd->mtd, parts, nr_parts);
+	err = mtd_device_parse_register(ltq_mtd->mtd, NULL, 0,
+			ltq_mtd_data->parts, ltq_mtd_data->nr_parts);
 	if (err) {
 		dev_err(&pdev->dev, "failed to add partitions\n");
 		goto err_destroy;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:22 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:22 +0400
Subject: [PATCH 13/43] mtd: latch-addr-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-14-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/latch-addr-flash.c |   21 ++-------------------
 1 files changed, 2 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/latch-addr-flash.c b/drivers/mtd/maps/latch-addr-flash.c
index 09cf704..119baa7 100644
--- a/drivers/mtd/maps/latch-addr-flash.c
+++ b/drivers/mtd/maps/latch-addr-flash.c
@@ -33,9 +33,6 @@ struct latch_addr_flash_info {
 	/* cache; could be found out of res */
 	unsigned long		win_mask;
 
-	int			nr_parts;
-	struct mtd_partition	*parts;
-
 	spinlock_t		lock;
 };
 
@@ -110,8 +107,6 @@ static int latch_addr_flash_remove(struct platform_device *dev)
 	latch_addr_data = dev->dev.platform_data;
 
 	if (info->mtd != NULL) {
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
@@ -204,20 +199,8 @@ static int __devinit latch_addr_flash_probe(struct platform_device *dev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	err = parse_mtd_partitions(info->mtd, NULL, &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->mtd, info->parts, err);
-		return 0;
-	}
-	if (latch_addr_data->nr_parts) {
-		pr_notice("Using latch-addr-flash partition information\n");
-		mtd_device_register(info->mtd,
-				    latch_addr_data->parts,
-				    latch_addr_data->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->mtd, NULL, 0);
+	mtd_device_parse_register(info->mtd, NULL, 0,
+			latch_addr_data->parts, latch_addr_data->nr_parts);
 	return 0;
 
 iounmap:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:23 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:23 +0400
Subject: [PATCH 14/43] mtd: physmap.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-15-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap.c |   23 ++---------------------
 1 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c
index 2174d10..256f787 100644
--- a/drivers/mtd/maps/physmap.c
+++ b/drivers/mtd/maps/physmap.c
@@ -27,8 +27,6 @@ struct physmap_flash_info {
 	struct mtd_info		*mtd[MAX_RESOURCES];
 	struct mtd_info		*cmtd;
 	struct map_info		map[MAX_RESOURCES];
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 
 static int physmap_flash_remove(struct platform_device *dev)
@@ -46,8 +44,6 @@ static int physmap_flash_remove(struct platform_device *dev)
 
 	if (info->cmtd) {
 		mtd_device_unregister(info->cmtd);
-		if (info->nr_parts)
-			kfree(info->parts);
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
 	}
@@ -175,23 +171,8 @@ static int physmap_flash_probe(struct platform_device *dev)
 	if (err)
 		goto err_out;
 
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->cmtd, info->parts, err);
-		info->nr_parts = err;
-		return 0;
-	}
-
-	if (physmap_data->nr_parts) {
-		printk(KERN_NOTICE "Using physmap partition information\n");
-		mtd_device_register(info->cmtd, physmap_data->parts,
-				    physmap_data->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->cmtd, NULL, 0);
-
+	mtd_device_parse_register(info->cmtd, part_probe_types, 0,
+			physmap_data->parts, physmap_data->nr_parts);
 	return 0;
 
 err_out:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:24 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:24 +0400
Subject: [PATCH 15/43] mtd: plat-ram.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-16-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/plat-ram.c |   23 ++---------------------
 1 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/maps/plat-ram.c b/drivers/mtd/maps/plat-ram.c
index 9ca1ecc..94f5534 100644
--- a/drivers/mtd/maps/plat-ram.c
+++ b/drivers/mtd/maps/plat-ram.c
@@ -44,8 +44,6 @@ struct platram_info {
 	struct device		*dev;
 	struct mtd_info		*mtd;
 	struct map_info		 map;
-	struct mtd_partition	*partitions;
-	bool			free_partitions;
 	struct resource		*area;
 	struct platdata_mtd_ram	*pdata;
 };
@@ -95,10 +93,6 @@ static int platram_remove(struct platform_device *pdev)
 
 	if (info->mtd) {
 		mtd_device_unregister(info->mtd);
-		if (info->partitions) {
-			if (info->free_partitions)
-				kfree(info->partitions);
-		}
 		map_destroy(info->mtd);
 	}
 
@@ -228,21 +222,8 @@ static int platram_probe(struct platform_device *pdev)
 	/* check to see if there are any available partitions, or wether
 	 * to add this device whole */
 
-	if (!pdata->nr_partitions) {
-		/* try to probe using the supplied probe type */
-		if (pdata->probes) {
-			err = parse_mtd_partitions(info->mtd, pdata->probes,
-					   &info->partitions, 0);
-			info->free_partitions = 1;
-			if (err > 0)
-				err = mtd_device_register(info->mtd,
-					info->partitions, err);
-		}
-	}
-	/* use the static mapping */
-	else
-		err = mtd_device_register(info->mtd, pdata->partitions,
-					  pdata->nr_partitions);
+	err = mtd_device_parse_register(info->mtd, pdata->probes, 0,
+			pdata->partitions, pdata->nr_partitions);
 	if (!err)
 		dev_info(&pdev->dev, "registered mtd device\n");
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:25 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:25 +0400
Subject: [PATCH 16/43] mtd: pxa2xx-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-17-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/pxa2xx-flash.c |   20 +-------------------
 1 files changed, 1 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c
index f59d62f..8fb8198 100644
--- a/drivers/mtd/maps/pxa2xx-flash.c
+++ b/drivers/mtd/maps/pxa2xx-flash.c
@@ -41,8 +41,6 @@ static void pxa2xx_map_inval_cache(struct map_info *map, unsigned long from,
 }
 
 struct pxa2xx_flash_info {
-	struct mtd_partition	*parts;
-	int			nr_parts;
 	struct mtd_info		*mtd;
 	struct map_info		map;
 };
@@ -55,9 +53,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *flash = pdev->dev.platform_data;
 	struct pxa2xx_flash_info *info;
-	struct mtd_partition *parts;
 	struct resource *res;
-	int ret = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -71,8 +67,6 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	info->map.bankwidth = flash->width;
 	info->map.phys = res->start;
 	info->map.size = res->end - res->start + 1;
-	info->parts = flash->parts;
-	info->nr_parts = flash->nr_parts;
 
 	info->map.virt = ioremap(info->map.phys, info->map.size);
 	if (!info->map.virt) {
@@ -104,18 +98,7 @@ static int __devinit pxa2xx_flash_probe(struct platform_device *pdev)
 	}
 	info->mtd->owner = THIS_MODULE;
 
-	ret = parse_mtd_partitions(info->mtd, probes, &parts, 0);
-
-	if (ret > 0) {
-		info->nr_parts = ret;
-		info->parts = parts;
-	}
-
-	if (!info->nr_parts)
-		printk("Registering %s as whole device\n",
-		       info->map.name);
-
-	mtd_device_register(info->mtd, info->parts, info->nr_parts);
+	mtd_device_parse_register(info->mtd, probes, 0, NULL, 0);
 
 	platform_set_drvdata(pdev, info);
 	return 0;
@@ -133,7 +116,6 @@ static int __devexit pxa2xx_flash_remove(struct platform_device *dev)
 	iounmap(info->map.virt);
 	if (info->map.cached)
 		iounmap(info->map.cached);
-	kfree(info->parts);
 	kfree(info);
 	return 0;
 }
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:26 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:26 +0400
Subject: [PATCH 17/43] mtd: rbtx4939-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-18-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/rbtx4939-flash.c |   21 ++++-----------------
 1 files changed, 4 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/maps/rbtx4939-flash.c b/drivers/mtd/maps/rbtx4939-flash.c
index 5d15b6b..0237f19 100644
--- a/drivers/mtd/maps/rbtx4939-flash.c
+++ b/drivers/mtd/maps/rbtx4939-flash.c
@@ -25,8 +25,6 @@
 struct rbtx4939_flash_info {
 	struct mtd_info *mtd;
 	struct map_info map;
-	int nr_parts;
-	struct mtd_partition *parts;
 };
 
 static int rbtx4939_flash_remove(struct platform_device *dev)
@@ -41,8 +39,6 @@ static int rbtx4939_flash_remove(struct platform_device *dev)
 	if (info->mtd) {
 		struct rbtx4939_flash_data *pdata = dev->dev.platform_data;
 
-		if (info->nr_parts)
-			kfree(info->parts);
 		mtd_device_unregister(info->mtd);
 		map_destroy(info->mtd);
 	}
@@ -106,20 +102,11 @@ static int rbtx4939_flash_probe(struct platform_device *dev)
 	info->mtd->owner = THIS_MODULE;
 	if (err)
 		goto err_out;
-	err = parse_mtd_partitions(info->mtd, NULL, &info->parts, 0);
-	if (err > 0) {
-		mtd_device_register(info->mtd, info->parts, err);
-		info->nr_parts = err;
-		return 0;
-	}
+	err = mtd_device_parse_register(info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
-	if (pdata->nr_parts) {
-		pr_notice("Using rbtx4939 partition information\n");
-		mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
-		return 0;
-	}
-
-	mtd_device_register(info->mtd, NULL, 0);
+	if (err)
+		goto err_out;
 	return 0;
 
 err_out:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:27 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:27 +0400
Subject: [PATCH 18/43] mtd: sa1100-flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-19-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/sa1100-flash.c |   30 +++---------------------------
 1 files changed, 3 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/maps/sa1100-flash.c b/drivers/mtd/maps/sa1100-flash.c
index a9b5e0e..fa9c0a9 100644
--- a/drivers/mtd/maps/sa1100-flash.c
+++ b/drivers/mtd/maps/sa1100-flash.c
@@ -131,10 +131,8 @@ struct sa_subdev_info {
 };
 
 struct sa_info {
-	struct mtd_partition	*parts;
 	struct mtd_info		*mtd;
 	int			num_subdev;
-	unsigned int		nr_parts;
 	struct sa_subdev_info	subdev[0];
 };
 
@@ -231,8 +229,6 @@ static void sa1100_destroy(struct sa_info *info, struct flash_platform_data *pla
 			mtd_concat_destroy(info->mtd);
 	}
 
-	kfree(info->parts);
-
 	for (i = info->num_subdev - 1; i >= 0; i--)
 		sa1100_destroy_subdev(&info->subdev[i]);
 	kfree(info);
@@ -341,10 +337,8 @@ static const char *part_probes[] = { "cmdlinepart", "RedBoot", NULL };
 static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 {
 	struct flash_platform_data *plat = pdev->dev.platform_data;
-	struct mtd_partition *parts;
-	const char *part_type = NULL;
 	struct sa_info *info;
-	int err, nr_parts = 0;
+	int err;
 
 	if (!plat)
 		return -ENODEV;
@@ -358,26 +352,8 @@ static int __devinit sa1100_mtd_probe(struct platform_device *pdev)
 	/*
 	 * Partition selection stuff.
 	 */
-	nr_parts = parse_mtd_partitions(info->mtd, part_probes, &parts, 0);
-	if (nr_parts > 0) {
-		info->parts = parts;
-		part_type = "dynamic";
-	} else {
-		parts = plat->parts;
-		nr_parts = plat->nr_parts;
-		part_type = "static";
-	}
-
-	if (nr_parts == 0)
-		printk(KERN_NOTICE "SA1100 flash: no partition info "
-			"available, registering whole flash\n");
-	else
-		printk(KERN_NOTICE "SA1100 flash: using %s partition "
-			"definition\n", part_type);
-
-	mtd_device_register(info->mtd, parts, nr_parts);
-
-	info->nr_parts = nr_parts;
+	mtd_device_parse_register(info->mtd, part_probes, 0,
+			plat->parts, plat->nr_parts);
 
 	platform_set_drvdata(pdev, info);
 	err = 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:28 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:28 +0400
Subject: [PATCH 19/43] mtd: solutionengine.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-20-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/solutionengine.c |   30 +++++++-----------------------
 1 files changed, 7 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/maps/solutionengine.c b/drivers/mtd/maps/solutionengine.c
index cbf6bad..496c407 100644
--- a/drivers/mtd/maps/solutionengine.c
+++ b/drivers/mtd/maps/solutionengine.c
@@ -19,8 +19,6 @@
 static struct mtd_info *flash_mtd;
 static struct mtd_info *eprom_mtd;
 
-static struct mtd_partition *parsed_parts;
-
 struct map_info soleng_eprom_map = {
 	.name = "Solution Engine EPROM",
 	.size = 0x400000,
@@ -51,12 +49,14 @@ static struct mtd_partition superh_se_partitions[] = {
 		.size = MTDPART_SIZ_FULL,
 	}
 };
+#define NUM_PARTITIONS ARRAY_SIZE(superh_se_partitions)
+#else
+#define superh_se_partitions NULL
+#define NUM_PARTITIONS 0
 #endif /* CONFIG_MTD_SUPERH_RESERVE */
 
 static int __init init_soleng_maps(void)
 {
-	int nr_parts = 0;
-
 	/* First probe at offset 0 */
 	soleng_flash_map.phys = 0;
 	soleng_flash_map.virt = (void __iomem *)P2SEGADDR(0);
@@ -92,21 +92,8 @@ static int __init init_soleng_maps(void)
 		mtd_device_register(eprom_mtd, NULL, 0);
 	}
 
-	nr_parts = parse_mtd_partitions(flash_mtd, probes, &parsed_parts, 0);
-
-#ifdef CONFIG_MTD_SUPERH_RESERVE
-	if (nr_parts <= 0) {
-		printk(KERN_NOTICE "Using configured partition at 0x%08x.\n",
-		       CONFIG_MTD_SUPERH_RESERVE);
-		parsed_parts = superh_se_partitions;
-		nr_parts = sizeof(superh_se_partitions)/sizeof(*parsed_parts);
-	}
-#endif /* CONFIG_MTD_SUPERH_RESERVE */
-
-	if (nr_parts > 0)
-		mtd_device_register(flash_mtd, parsed_parts, nr_parts);
-	else
-		mtd_device_register(flash_mtd, NULL, 0);
+	mtd_device_parse_register(flash_mtd, probes, 0,
+			superh_se_partitions, NUM_PARTITIONS);
 
 	return 0;
 }
@@ -118,10 +105,7 @@ static void __exit cleanup_soleng_maps(void)
 		map_destroy(eprom_mtd);
 	}
 
-	if (parsed_parts)
-		mtd_device_unregister(flash_mtd);
-	else
-		mtd_device_unregister(flash_mtd);
+	mtd_device_unregister(flash_mtd);
 	map_destroy(flash_mtd);
 }
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:32 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:32 +0400
Subject: [PATCH 23/43] mtd: cafe_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-24-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cafe_nand.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index 88ac4b5..db3bfac 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -57,7 +57,6 @@
 
 struct cafe_priv {
 	struct nand_chip nand;
-	struct mtd_partition *parts;
 	struct pci_dev *pdev;
 	void __iomem *mmio;
 	struct rs_control *rs;
@@ -630,8 +629,6 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	struct cafe_priv *cafe;
 	uint32_t ctrl;
 	int err = 0;
-	struct mtd_partition *parts;
-	int nr_parts;
 
 	/* Very old versions shared the same PCI ident for all three
 	   functions on the chip. Verify the class too... */
@@ -804,12 +801,8 @@ static int __devinit cafe_nand_probe(struct pci_dev *pdev,
 	mtd_device_register(mtd, NULL, 0);
 
 	mtd->name = "cafe_nand";
-	nr_parts = parse_mtd_partitions(mtd, part_probes, &parts, 0);
-	if (nr_parts > 0) {
-		cafe->parts = parts;
-		dev_info(&cafe->pdev->dev, "%d partitions found\n", nr_parts);
-		mtd_device_register(mtd, parts, nr_parts);
-	}
+	mtd_device_parse_register(mtd, part_probes, 0, NULL, 0);
+
 	goto out;
 
  out_irq:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:33 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:33 +0400
Subject: [PATCH 24/43] mtd: cmx270_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-25-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cmx270_nand.c |   20 ++------------------
 1 files changed, 2 insertions(+), 18 deletions(-)

diff --git a/drivers/mtd/nand/cmx270_nand.c b/drivers/mtd/nand/cmx270_nand.c
index f8f5b7c..8305692 100644
--- a/drivers/mtd/nand/cmx270_nand.c
+++ b/drivers/mtd/nand/cmx270_nand.c
@@ -149,9 +149,6 @@ static int cmx270_device_ready(struct mtd_info *mtd)
 static int __init cmx270_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type;
-	struct mtd_partition *mtd_parts;
-	int mtd_parts_nb = 0;
 	int ret;
 
 	if (!(machine_is_armcore() && cpu_is_pxa27x()))
@@ -220,22 +217,9 @@ static int __init cmx270_init(void)
 		goto err_scan;
 	}
 
-	mtd_parts_nb = parse_mtd_partitions(cmx270_nand_mtd, NULL,
-					    &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (!mtd_parts_nb) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
-
 	/* Register the partitions */
-	pr_notice("Using %s partition definition\n", part_type);
-	ret = mtd_device_register(cmx270_nand_mtd, mtd_parts, mtd_parts_nb);
+	ret = mtd_device_parse_register(cmx270_nand_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 	if (ret)
 		goto err_scan;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:34 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:34 +0400
Subject: [PATCH 25/43] mtd: cs553x_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-26-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/cs553x_nand.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/cs553x_nand.c b/drivers/mtd/nand/cs553x_nand.c
index b2bdf72..a60ae39 100644
--- a/drivers/mtd/nand/cs553x_nand.c
+++ b/drivers/mtd/nand/cs553x_nand.c
@@ -283,8 +283,6 @@ static int __init cs553x_init(void)
 	int err = -ENXIO;
 	int i;
 	uint64_t val;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = NULL;
 
 	/* If the CPU isn't a Geode GX or LX, abort */
 	if (!is_geode())
@@ -314,11 +312,9 @@ static int __init cs553x_init(void)
 	   do mtdconcat etc. if we want to. */
 	for (i = 0; i < NR_CS553X_CONTROLLERS; i++) {
 		if (cs553x_mtd[i]) {
-
 			/* If any devices registered, return success. Else the last error. */
-			mtd_parts_nb = parse_mtd_partitions(cs553x_mtd[i], NULL, &mtd_parts, 0);
-			mtd_device_register(cs553x_mtd[i], mtd_parts,
-					    mtd_parts_nb);
+			mtd_device_parse_register(cs553x_mtd[i], NULL, 0,
+					NULL, 0);
 			err = 0;
 		}
 	}
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:29 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:29 +0400
Subject: [PATCH 20/43] mtd: wr_sbc82xx_flash.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-21-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/wr_sbc82xx_flash.c |   30 +++++++++++-------------------
 1 files changed, 11 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/maps/wr_sbc82xx_flash.c b/drivers/mtd/maps/wr_sbc82xx_flash.c
index 901ce96..aaec902 100644
--- a/drivers/mtd/maps/wr_sbc82xx_flash.c
+++ b/drivers/mtd/maps/wr_sbc82xx_flash.c
@@ -20,7 +20,6 @@
 #include <asm/immap_cpm2.h>
 
 static struct mtd_info *sbcmtd[3];
-static struct mtd_partition *sbcmtd_parts[3];
 
 struct map_info sbc82xx_flash_map[3] = {
 	{.name = "Boot flash"},
@@ -101,6 +100,7 @@ static int __init init_sbc82xx_flash(void)
 	for (i=0; i<3; i++) {
 		int8_t flashcs[3] = { 0, 6, 1 };
 		int nr_parts;
+		struct mtd_partition *defparts;
 
 		printk(KERN_NOTICE "PowerQUICC II %s (%ld MiB on CS%d",
 		       sbc82xx_flash_map[i].name,
@@ -129,24 +129,20 @@ static int __init init_sbc82xx_flash(void)
 
 		sbcmtd[i]->owner = THIS_MODULE;
 
-		nr_parts = parse_mtd_partitions(sbcmtd[i], part_probes,
-						&sbcmtd_parts[i], 0);
-		if (nr_parts > 0) {
-			mtd_device_register(sbcmtd[i], sbcmtd_parts[i],
-					    nr_parts);
-			continue;
-		}
-
 		/* No partitioning detected. Use default */
 		if (i == 2) {
-			mtd_device_register(sbcmtd[i], NULL, 0);
+			defparts = NULL;
+			nr_parts = 0;
 		} else if (i == bigflash) {
-			mtd_device_register(sbcmtd[i], bigflash_parts,
-					    ARRAY_SIZE(bigflash_parts));
+			defparts = bigflash_parts;
+			nr_parts = ARRAY_SIZE(bigflash_parts);
 		} else {
-			mtd_device_register(sbcmtd[i], smallflash_parts,
-					    ARRAY_SIZE(smallflash_parts));
+			defparts = smallflash_parts;
+			nr_parts = ARRAY_SIZE(smallflash_parts);
 		}
+
+		mtd_device_parse_register(sbcmtd[i], part_probes, 0,
+				defparts, nr_parts);
 	}
 	return 0;
 }
@@ -159,12 +155,8 @@ static void __exit cleanup_sbc82xx_flash(void)
 		if (!sbcmtd[i])
 			continue;
 
-		if (i<2 || sbcmtd_parts[i])
-			mtd_device_unregister(sbcmtd[i]);
-		else
-			mtd_device_unregister(sbcmtd[i]);
+		mtd_device_unregister(sbcmtd[i]);
 
-		kfree(sbcmtd_parts[i]);
 		map_destroy(sbcmtd[i]);
 
 		iounmap((void *)sbc82xx_flash_map[i].virt);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:30 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:30 +0400
Subject: [PATCH 21/43] mtd: atmel_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-22-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/atmel_nand.c |   19 ++-----------------
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index a19a112..6702208 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -491,8 +491,6 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	struct resource *regs;
 	struct resource *mem;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
 
 	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!mem) {
@@ -651,24 +649,11 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 	}
 
 	mtd->name = "atmel_nand";
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, 0);
-	if (num_partitions <= 0 && host->board->parts) {
-		partitions = host->board->parts;
-		num_partitions = host->board->num_parts;
-	}
-
-	if ((!partitions) || (num_partitions == 0)) {
-		printk(KERN_ERR "atmel_nand: No partitions defined, or unsupported device.\n");
-		res = -ENXIO;
-		goto err_no_partitions;
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, 0,
+			host->board->parts, host->board->num_parts);
 	if (!res)
 		return res;
 
-err_no_partitions:
-	nand_release(mtd);
 err_scan_tail:
 err_scan_ident:
 err_no_card:
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:31 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:31 +0400
Subject: [PATCH 22/43] mtd: bcm_umi_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-23-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/bcm_umi_nand.c |   19 ++-----------------
 1 files changed, 2 insertions(+), 17 deletions(-)

diff --git a/drivers/mtd/nand/bcm_umi_nand.c b/drivers/mtd/nand/bcm_umi_nand.c
index e0230c5..d98bc48 100644
--- a/drivers/mtd/nand/bcm_umi_nand.c
+++ b/drivers/mtd/nand/bcm_umi_nand.c
@@ -489,23 +489,8 @@ static int __devinit bcm_umi_nand_probe(struct platform_device *pdev)
 	}
 
 	/* Register the partitions */
-	{
-		int nr_partitions;
-		struct mtd_partition *partition_info;
-
-		board_mtd->name = "bcm_umi-nand";
-		nr_partitions = parse_mtd_partitions(board_mtd, NULL,
-						     &partition_info, 0);
-
-		if (nr_partitions <= 0) {
-			printk(KERN_ERR "BCM UMI NAND: Too few partitions - %d\n",
-			       nr_partitions);
-			iounmap(bcm_umi_io_base);
-			kfree(board_mtd);
-			return -EIO;
-		}
-		mtd_device_register(board_mtd, partition_info, nr_partitions);
-	}
+	board_mtd->name = "bcm_umi-nand";
+	mtd_device_parse_register(board_mtd, NULL, 0, NULL, 0);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:35 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:35 +0400
Subject: [PATCH 26/43] mtd: davinci_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-27-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/davinci_nand.c |   25 ++-----------------------
 1 files changed, 2 insertions(+), 23 deletions(-)

diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c
index 70c92a5..c153e1f 100644
--- a/drivers/mtd/nand/davinci_nand.c
+++ b/drivers/mtd/nand/davinci_nand.c
@@ -57,7 +57,6 @@ struct davinci_nand_info {
 
 	struct device		*dev;
 	struct clk		*clk;
-	bool			partitioned;
 
 	bool			is_readmode;
 
@@ -530,8 +529,6 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
 	int				ret;
 	uint32_t			val;
 	nand_ecc_modes_t		ecc_mode;
-	struct mtd_partition		*mtd_parts = NULL;
-	int				mtd_parts_nb = 0;
 
 	/* insist on board-specific configuration */
 	if (!pdata)
@@ -753,26 +750,8 @@ syndrome_done:
 	if (ret < 0)
 		goto err_scan;
 
-	mtd_parts_nb = parse_mtd_partitions(&info->mtd, NULL, &mtd_parts, 0);
-
-	if (mtd_parts_nb <= 0) {
-		mtd_parts = pdata->parts;
-		mtd_parts_nb = pdata->nr_parts;
-	}
-
-	/* Register any partitions */
-	if (mtd_parts_nb > 0) {
-		ret = mtd_device_register(&info->mtd, mtd_parts,
-					  mtd_parts_nb);
-		if (ret == 0)
-			info->partitioned = true;
-	}
-
-	/* If there's no partition info, just package the whole chip
-	 * as a single MTD device.
-	 */
-	if (!info->partitioned)
-		ret = mtd_device_register(&info->mtd, NULL, 0) ? -ENODEV : 0;
+	ret = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	if (ret < 0)
 		goto err_scan;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:36 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:36 +0400
Subject: [PATCH 27/43] mtd: edb7312.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-28-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/edb7312.c |   17 ++---------------
 1 files changed, 2 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
index 2f9374b..0b1bb91 100644
--- a/drivers/mtd/nand/edb7312.c
+++ b/drivers/mtd/nand/edb7312.c
@@ -104,9 +104,6 @@ static int ep7312_device_ready(struct mtd_info *mtd)
 static int __init ep7312_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *ep7312_fio_base;
 
 	/* Allocate memory for MTD device structure and private data */
@@ -156,20 +153,10 @@ static int __init ep7312_init(void)
 		return -ENXIO;
 	}
 	ep7312_mtd->name = "edb7312-nand";
-	mtd_parts_nb = parse_mtd_partitions(ep7312_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ep7312_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_register(ep7312_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:37 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:37 +0400
Subject: [PATCH 28/43] mtd: fsmc_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-29-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsmc_nand.c |   66 ++++++------------------------------------
 1 files changed, 9 insertions(+), 57 deletions(-)

diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index a39c224..8cc8065 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -146,7 +146,7 @@ static struct mtd_partition partition_info_16KB_blk[] = {
 	{
 		.name = "Root File System",
 		.offset = 0x460000,
-		.size = 0,
+		.size = MTDPART_SIZ_FULL,
 	},
 };
 
@@ -173,7 +173,7 @@ static struct mtd_partition partition_info_128KB_blk[] = {
 	{
 		.name = "Root File System",
 		.offset = 0x800000,
-		.size = 0,
+		.size = MTDPART_SIZ_FULL,
 	},
 };
 
@@ -184,8 +184,6 @@ static struct mtd_partition partition_info_128KB_blk[] = {
  * @pid:		Part ID on the AMBA PrimeCell format
  * @mtd:		MTD info for a NAND flash.
  * @nand:		Chip related info for a NAND flash.
- * @partitions:		Partition info for a NAND Flash.
- * @nr_partitions:	Total number of partition of a NAND flash.
  *
  * @ecc_place:		ECC placing locations in oobfree type format.
  * @bank:		Bank number for probed device.
@@ -200,8 +198,6 @@ struct fsmc_nand_data {
 	u32			pid;
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
-	struct mtd_partition	*partitions;
-	unsigned int		nr_partitions;
 
 	struct fsmc_eccplace	*ecc_place;
 	unsigned int		bank;
@@ -717,57 +713,13 @@ static int __init fsmc_nand_probe(struct platform_device *pdev)
 	 * Check for partition info passed
 	 */
 	host->mtd.name = "nand";
-	host->nr_partitions = parse_mtd_partitions(&host->mtd, NULL,
-			&host->partitions, 0);
-	if (host->nr_partitions <= 0) {
-		/*
-		 * Check if partition info passed via command line
-		 */
-		if (pdata->partitions) {
-			host->partitions = pdata->partitions;
-			host->nr_partitions = pdata->nr_partitions;
-		} else {
-			struct mtd_partition *partition;
-			int i;
-
-			/* Select the default partitions info */
-			switch (host->mtd.size) {
-			case 0x01000000:
-			case 0x02000000:
-			case 0x04000000:
-				host->partitions = partition_info_16KB_blk;
-				host->nr_partitions =
-					sizeof(partition_info_16KB_blk) /
-					sizeof(struct mtd_partition);
-				break;
-			case 0x08000000:
-			case 0x10000000:
-			case 0x20000000:
-			case 0x40000000:
-				host->partitions = partition_info_128KB_blk;
-				host->nr_partitions =
-					sizeof(partition_info_128KB_blk) /
-					sizeof(struct mtd_partition);
-				break;
-			default:
-				ret = -ENXIO;
-				pr_err("Unsupported NAND size\n");
-				goto err_probe;
-			}
-
-			partition = host->partitions;
-			for (i = 0; i < host->nr_partitions; i++, partition++) {
-				if (partition->size == 0) {
-					partition->size = host->mtd.size -
-						partition->offset;
-					break;
-				}
-			}
-		}
-	}
-
-	ret = mtd_device_register(&host->mtd, host->partitions,
-				  host->nr_partitions);
+	ret = mtd_device_parse_register(&host->mtd, NULL, 0,
+			host->mtd.size <= 0x04000000 ?
+				partition_info_16KB_blk :
+				partition_info_128KB_blk,
+			host->mtd.size <= 0x04000000 ?
+				ARRAY_SIZE(partition_info_16KB_blk) :
+				ARRAY_SIZE(partition_info_128KB_blk),
 	if (ret)
 		goto err_probe;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:38 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:38 +0400
Subject: [PATCH 29/43] mtd: h1910.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-30-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/h1910.c |   15 ++-------------
 1 files changed, 2 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/h1910.c b/drivers/mtd/nand/h1910.c
index 42f9177..5dc6f0d 100644
--- a/drivers/mtd/nand/h1910.c
+++ b/drivers/mtd/nand/h1910.c
@@ -81,9 +81,6 @@ static int h1910_device_ready(struct mtd_info *mtd)
 static int __init h1910_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *nandaddr;
 
 	if (!machine_is_h1900())
@@ -136,18 +133,10 @@ static int __init h1910_init(void)
 		iounmap((void *)nandaddr);
 		return -ENXIO;
 	}
-	mtd_parts_nb = parse_mtd_partitions(h1910_nand_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else {
-		mtd_parts = partition_info;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(h1910_nand_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(h1910_nand_mtd, NULL, 0,
+			partition_info, NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:39 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:39 +0400
Subject: [PATCH 30/43] mtd: jz4740_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-31-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/jz4740_nand.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/jz4740_nand.c b/drivers/mtd/nand/jz4740_nand.c
index 920719c..e266407 100644
--- a/drivers/mtd/nand/jz4740_nand.c
+++ b/drivers/mtd/nand/jz4740_nand.c
@@ -295,8 +295,6 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
-	struct mtd_partition *partition_info;
-	int num_partitions = 0;
 
 	nand = kzalloc(sizeof(*nand), GFP_KERNEL);
 	if (!nand) {
@@ -369,12 +367,9 @@ static int __devinit jz_nand_probe(struct platform_device *pdev)
 		goto err_gpio_free;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partition_info, 0);
-	if (num_partitions <= 0 && pdata) {
-		num_partitions = pdata->num_partitions;
-		partition_info = pdata->partitions;
-	}
-	ret = mtd_device_register(mtd, partition_info, num_partitions);
+	ret = mtd_device_parse_register(mtd, NULL, 0,
+			pdata ? pdata->partitions : NULL,
+			pdata ? pdata->num_partitions : 0);
 
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to add mtd device\n");
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:40 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:40 +0400
Subject: [PATCH 31/43] mtd: mxc_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-32-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mxc_nand.c |   15 +++------------
 1 files changed, 3 insertions(+), 12 deletions(-)

diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index ca42c8f..4c2bb4a 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -143,7 +143,6 @@
 struct mxc_nand_host {
 	struct mtd_info		mtd;
 	struct nand_chip	nand;
-	struct mtd_partition	*parts;
 	struct device		*dev;
 
 	void			*spare0;
@@ -1044,7 +1043,7 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	struct mxc_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct mxc_nand_host *host;
 	struct resource *res;
-	int err = 0, __maybe_unused nr_parts = 0;
+	int err = 0;
 	struct nand_ecclayout *oob_smallpage, *oob_largepage;
 
 	/* Allocate memory for MTD device structure and private data */
@@ -1231,16 +1230,8 @@ static int __init mxcnd_probe(struct platform_device *pdev)
 	}
 
 	/* Register the partitions */
-	nr_parts =
-	    parse_mtd_partitions(mtd, part_probes, &host->parts, 0);
-	if (nr_parts > 0)
-		mtd_device_register(mtd, host->parts, nr_parts);
-	else if (pdata->parts)
-		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-	else {
-		pr_info("Registering %s as whole device\n", mtd->name);
-		mtd_device_register(mtd, NULL, 0);
-	}
+	mtd_device_parse_register(mtd, part_probes, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, host);
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:41 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:41 +0400
Subject: [PATCH 32/43] mtd: omap2.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-33-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/omap2.c |   10 ++--------
 1 files changed, 2 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 8783c08..c5e33fd 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -112,7 +112,6 @@ struct omap_nand_info {
 	struct nand_hw_control		controller;
 	struct omap_nand_platform_data	*pdata;
 	struct mtd_info			mtd;
-	struct mtd_partition		*parts;
 	struct nand_chip		nand;
 	struct platform_device		*pdev;
 
@@ -1101,13 +1100,8 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
 		goto out_release_mem_region;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, NULL, &info->parts, 0);
-	if (err > 0)
-		mtd_device_register(&info->mtd, info->parts, err);
-	else if (pdata->parts)
-		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-	else
-		mtd_device_register(&info->mtd, NULL, 0);
+	mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 
 	platform_set_drvdata(pdev, &info->mtd);
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:42 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:42 +0400
Subject: [PATCH 33/43] mtd: orion_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-34-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/orion_nand.c |   12 ++----------
 1 files changed, 2 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index 5c55981..29f505a 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -79,8 +79,6 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 	struct resource *res;
 	void __iomem *io_base;
 	int ret = 0;
-	struct mtd_partition *partitions = NULL;
-	int num_part = 0;
 
 	nc = kzalloc(sizeof(struct nand_chip) + sizeof(struct mtd_info), GFP_KERNEL);
 	if (!nc) {
@@ -131,14 +129,8 @@ static int __init orion_nand_probe(struct platform_device *pdev)
 	}
 
 	mtd->name = "orion_nand";
-	num_part = parse_mtd_partitions(mtd, NULL, &partitions, 0);
-	/* If cmdline partitions have been passed, let them be used */
-	if (num_part <= 0) {
-		num_part = board->nr_parts;
-		partitions = board->parts;
-	}
-
-	ret = mtd_device_register(mtd, partitions, num_part);
+	ret = mtd_device_parse_register(mtd, NULL, 0,
+			board->parts, board->nr_parts);
 	if (ret) {
 		nand_release(mtd);
 		goto no_dev;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:43 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:43 +0400
Subject: [PATCH 34/43] mtd: plat_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-35-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/plat_nand.c |   22 +++-------------------
 1 files changed, 3 insertions(+), 19 deletions(-)

diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 1339fa8..e62468b 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -21,8 +21,6 @@ struct plat_nand_data {
 	struct nand_chip	chip;
 	struct mtd_info		mtd;
 	void __iomem		*io_base;
-	int			nr_parts;
-	struct mtd_partition	*parts;
 };
 
 /*
@@ -99,21 +97,9 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
 		goto out;
 	}
 
-	if (pdata->chip.part_probe_types) {
-		err = parse_mtd_partitions(&data->mtd,
-					pdata->chip.part_probe_types,
-					&data->parts, 0);
-		if (err > 0) {
-			mtd_device_register(&data->mtd, data->parts, err);
-			return 0;
-		}
-	}
-	if (pdata->chip.partitions) {
-		data->parts = pdata->chip.partitions;
-		err = mtd_device_register(&data->mtd, data->parts,
-			pdata->chip.nr_partitions);
-	} else
-		err = mtd_device_register(&data->mtd, NULL, 0);
+	err = mtd_device_parse_register(&data->mtd,
+			pdata->chip.part_probe_types, 0,
+			pdata->chip.partitions, pdata->chip.nr_partitions);
 
 	if (!err)
 		return err;
@@ -143,8 +129,6 @@ static int __devexit plat_nand_remove(struct platform_device *pdev)
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 
 	nand_release(&data->mtd);
-	if (data->parts && data->parts != pdata->chip.partitions)
-		kfree(data->parts);
 	if (pdata->ctrl.remove)
 		pdata->ctrl.remove(pdev);
 	iounmap(data->io_base);
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:44 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:44 +0400
Subject: [PATCH 35/43] mtd: ppchameleonevb.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-36-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ppchameleonevb.c |   42 ++++++++----------------------------
 1 files changed, 10 insertions(+), 32 deletions(-)

diff --git a/drivers/mtd/nand/ppchameleonevb.c b/drivers/mtd/nand/ppchameleonevb.c
index 9376633..7e52af5 100644
--- a/drivers/mtd/nand/ppchameleonevb.c
+++ b/drivers/mtd/nand/ppchameleonevb.c
@@ -191,9 +191,6 @@ static int ppchameleonevb_device_ready(struct mtd_info *minfo)
 static int __init ppchameleonevb_init(void)
 {
 	struct nand_chip *this;
-	const char *part_type = 0;
-	int mtd_parts_nb = 0;
-	struct mtd_partition *mtd_parts = 0;
 	void __iomem *ppchameleon_fio_base;
 	void __iomem *ppchameleonevb_fio_base;
 
@@ -276,24 +273,13 @@ static int __init ppchameleonevb_init(void)
 #endif
 
 	ppchameleon_mtd->name = "ppchameleon-nand";
-	mtd_parts_nb = parse_mtd_partitions(ppchameleon_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (mtd_parts_nb == 0) {
-		if (ppchameleon_mtd->size == NAND_SMALL_SIZE)
-			mtd_parts = partition_info_me;
-		else
-			mtd_parts = partition_info_hi;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ppchameleon_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(ppchameleon_mtd, NULL, 0,
+			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+				partition_info_me :
+				partition_info_hi,
+			NUM_PARTITIONS);
 
  nand_evb_init:
 	/****************************
@@ -377,21 +363,13 @@ static int __init ppchameleonevb_init(void)
 	}
 
 	ppchameleonevb_mtd->name = NAND_EVB_MTD_NAME;
-	mtd_parts_nb = parse_mtd_partitions(ppchameleonevb_mtd, NULL, &mtd_parts, 0);
-	if (mtd_parts_nb > 0)
-		part_type = "command line";
-	else
-		mtd_parts_nb = 0;
-
-	if (mtd_parts_nb == 0) {
-		mtd_parts = partition_info_evb;
-		mtd_parts_nb = NUM_PARTITIONS;
-		part_type = "static";
-	}
 
 	/* Register the partitions */
-	printk(KERN_NOTICE "Using %s partition definition\n", part_type);
-	mtd_device_register(ppchameleonevb_mtd, mtd_parts, mtd_parts_nb);
+	mtd_device_parse_register(ppchameleonevb_mtd, NULL, 0,
+			ppchameleon_mtd->size == NAND_SMALL_SIZE ?
+				partition_info_me :
+				partition_info_hi,
+			NUM_PARTITIONS);
 
 	/* Return happy */
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:45 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:45 +0400
Subject: [PATCH 36/43] mtd: pxa3xx_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-37-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 5c3af2f..b7db1b2 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -1133,8 +1133,6 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-	struct mtd_partition *parts;
-	int nr_parts;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1152,13 +1150,8 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-
-	nr_parts = parse_mtd_partitions(info->mtd, NULL, &parts, 0);
-
-	if (nr_parts)
-		return mtd_device_register(info->mtd, parts, nr_parts);
-
-	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
+	return mtd_device_parse_register(info->mtd, NULL, 0,
+			pdata->parts, pdata->nr_parts);
 }
 
 #ifdef CONFIG_PM
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:46 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:46 +0400
Subject: [PATCH 37/43] mtd: s3c2410.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-38-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/s3c2410.c |   18 ++++--------------
 1 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c
index 17954ba..b0f8e77 100644
--- a/drivers/mtd/nand/s3c2410.c
+++ b/drivers/mtd/nand/s3c2410.c
@@ -748,21 +748,11 @@ static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
 				      struct s3c2410_nand_mtd *mtd,
 				      struct s3c2410_nand_set *set)
 {
-	struct mtd_partition *part_info;
-	int nr_part = 0;
+	if (set)
+		mtd->mtd.name = set->name;
 
-	if (set == NULL)
-		return mtd_device_register(&mtd->mtd, NULL, 0);
-
-	mtd->mtd.name = set->name;
-	nr_part = parse_mtd_partitions(&mtd->mtd, NULL, &part_info, 0);
-
-	if (nr_part <= 0 && set->nr_partitions > 0) {
-		nr_part = set->nr_partitions;
-		part_info = set->partitions;
-	}
-
-	return mtd_device_register(&mtd->mtd, part_info, nr_part);
+	return mtd_device_parse_register(&mtd->mtd, NULL, 0,
+			set->partitions, set->nr_partitions);
 }
 
 /**
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:47 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:47 +0400
Subject: [PATCH 38/43] mtd: sharpsl.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-39-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/sharpsl.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/sharpsl.c b/drivers/mtd/nand/sharpsl.c
index b3377f8..619d2a5 100644
--- a/drivers/mtd/nand/sharpsl.c
+++ b/drivers/mtd/nand/sharpsl.c
@@ -109,8 +109,6 @@ static int sharpsl_nand_calculate_ecc(struct mtd_info *mtd, const u_char * dat,
 static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 {
 	struct nand_chip *this;
-	struct mtd_partition *sharpsl_partition_info;
-	int nr_partitions;
 	struct resource *r;
 	int err = 0;
 	struct sharpsl_nand *sharpsl;
@@ -182,14 +180,9 @@ static int __devinit sharpsl_nand_probe(struct platform_device *pdev)
 
 	/* Register the partitions */
 	sharpsl->mtd.name = "sharpsl-nand";
-	nr_partitions = parse_mtd_partitions(&sharpsl->mtd, NULL, &sharpsl_partition_info, 0);
-	if (nr_partitions <= 0) {
-		nr_partitions = data->nr_partitions;
-		sharpsl_partition_info = data->partitions;
-	}
 
-	err = mtd_device_register(&sharpsl->mtd, sharpsl_partition_info,
-				  nr_partitions);
+	err = mtd_device_parse_register(&sharpsl->mtd, NULL, 0,
+			data->partitions, data->nr_partitions);
 	if (err)
 		goto err_add;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:48 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:48 +0400
Subject: [PATCH 39/43] mtd: tmio_nand.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-40-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/tmio_nand.c |   12 +++---------
 1 files changed, 3 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index b6ffad6..d476857 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -378,8 +378,6 @@ static int tmio_probe(struct platform_device *dev)
 	struct tmio_nand *tmio;
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
-	struct mtd_partition *parts;
-	int nbparts = 0;
 	int retval;
 
 	if (data == NULL)
@@ -458,13 +456,9 @@ static int tmio_probe(struct platform_device *dev)
 		goto err_scan;
 	}
 	/* Register the partitions */
-	nbparts = parse_mtd_partitions(mtd, NULL, &parts, 0);
-	if (nbparts <= 0 && data) {
-		parts = data->partition;
-		nbparts = data->num_partitions;
-	}
-
-	retval = mtd_device_register(mtd, parts, nbparts);
+	retval = mtd_device_register(mtd, NULL, 0,
+			data ? data->partition : NULL,
+			data ? data->num_partitions : 0);
 	if (!retval)
 		return retval;
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:49 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:49 +0400
Subject: [PATCH 40/43] mtd: txx9ndfmc.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-41-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/txx9ndfmc.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/txx9ndfmc.c b/drivers/mtd/nand/txx9ndfmc.c
index 91b05b9..ace46fd 100644
--- a/drivers/mtd/nand/txx9ndfmc.c
+++ b/drivers/mtd/nand/txx9ndfmc.c
@@ -74,7 +74,6 @@ struct txx9ndfmc_drvdata {
 	unsigned char hold;	/* in gbusclock */
 	unsigned char spw;	/* in gbusclock */
 	struct nand_hw_control hw_control;
-	struct mtd_partition *parts[MAX_TXX9NDFMC_DEV];
 };
 
 static struct platform_device *mtd_to_platdev(struct mtd_info *mtd)
@@ -332,7 +331,6 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		struct txx9ndfmc_priv *txx9_priv;
 		struct nand_chip *chip;
 		struct mtd_info *mtd;
-		int nr_parts;
 
 		if (!(plat->ch_mask & (1 << i)))
 			continue;
@@ -392,9 +390,7 @@ static int __init txx9ndfmc_probe(struct platform_device *dev)
 		}
 		mtd->name = txx9_priv->mtdname;
 
-		nr_parts = parse_mtd_partitions(mtd, NULL,
-						&drvdata->parts[i], 0);
-		mtd_device_register(mtd, drvdata->parts[i], nr_parts);
+		mtd_device_parse_register(mtd, NULL, 0, NULL, 0);
 		drvdata->mtds[i] = mtd;
 	}
 
@@ -420,7 +416,6 @@ static int __exit txx9ndfmc_remove(struct platform_device *dev)
 		txx9_priv = chip->priv;
 
 		nand_release(mtd);
-		kfree(drvdata->parts[i]);
 		kfree(txx9_priv->mtdname);
 		kfree(txx9_priv);
 	}
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:50 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:50 +0400
Subject: [PATCH 41/43] mtd: onenand/generic.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-42-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/generic.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index bca1c49..8152a31 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -32,7 +32,6 @@
 
 struct onenand_info {
 	struct mtd_info		mtd;
-	struct mtd_partition	*parts;
 	struct onenand_chip	onenand;
 };
 
@@ -71,13 +70,9 @@ static int __devinit generic_onenand_probe(struct platform_device *pdev)
 		goto out_iounmap;
 	}
 
-	err = parse_mtd_partitions(&info->mtd, NULL, &info->parts, 0);
-	if (err > 0)
-		mtd_device_register(&info->mtd, info->parts, err);
-	else if (err <= 0 && pdata && pdata->parts)
-		mtd_device_register(&info->mtd, pdata->parts, pdata->nr_parts);
-	else
-		err = mtd_device_register(&info->mtd, NULL, 0);
+	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
 	platform_set_drvdata(pdev, info);
 
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:51 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:51 +0400
Subject: [PATCH 42/43] mtd: onenand/omap2.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-43-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/omap2.c |   13 +++----------
 1 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index 5ca2053..eb9cbd9 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -57,7 +57,6 @@ struct omap2_onenand {
 	unsigned long phys_base;
 	int gpio_irq;
 	struct mtd_info mtd;
-	struct mtd_partition *parts;
 	struct onenand_chip onenand;
 	struct completion irq_done;
 	struct completion dma_done;
@@ -752,13 +751,9 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	r = parse_mtd_partitions(&c->mtd, NULL, &c->parts, 0);
-	if (r > 0)
-		r = mtd_device_register(&c->mtd, c->parts, r);
-	else if (pdata->parts != NULL)
-		r = mtd_device_register(&c->mtd, pdata->parts, pdata->nr_parts);
-	else
-		r = mtd_device_register(&c->mtd, NULL, 0);
+	r = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 	if (r)
 		goto err_release_onenand;
 
@@ -785,7 +780,6 @@ err_release_mem_region:
 err_free_cs:
 	gpmc_cs_free(c->gpmc_cs);
 err_kfree:
-	kfree(c->parts);
 	kfree(c);
 
 	return r;
@@ -808,7 +802,6 @@ static int __devexit omap2_onenand_remove(struct platform_device *pdev)
 	iounmap(c->onenand.base);
 	release_mem_region(c->phys_base, ONENAND_IO_SIZE);
 	gpmc_cs_free(c->gpmc_cs);
-	kfree(c->parts);
 	kfree(c);
 
 	return 0;
-- 
1.7.4.4



From dbaryshkov at gmail.com  Wed Jun  8 12:05:52 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed,  8 Jun 2011 20:05:52 +0400
Subject: [PATCH 43/43] mtd: onenand/samsung.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307549152-7085-44-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/onenand/samsung.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 78a08ea..597dffc 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -147,7 +147,6 @@ struct s3c_onenand {
 	struct resource *dma_res;
 	unsigned long	phys_base;
 	struct completion	complete;
-	struct mtd_partition *parts;
 };
 
 #define CMD_MAP_00(dev, addr)		(dev->cmd_map(MAP_00, ((addr) << 1)))
@@ -1015,13 +1014,9 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-	err = parse_mtd_partitions(mtd, NULL, &onenand->parts, 0);
-	if (err > 0)
-		mtd_device_register(mtd, onenand->parts, err);
-	else if (err <= 0 && pdata && pdata->parts)
-		mtd_device_register(mtd, pdata->parts, pdata->nr_parts);
-	else
-		err = mtd_device_register(mtd, NULL, 0);
+	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+			pdata ? pdata->parts : NULL,
+			pdata ? pdata->nr_parts : 0);
 
 	platform_set_drvdata(pdev, mtd);
 
-- 
1.7.4.4



From mlcreech at gmail.com  Wed Jun  8 13:50:24 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Wed, 8 Jun 2011 13:50:24 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307542265.31223.97.camel@localhost>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
	<1307421266.11104.10.camel@localhost>
	<BANLkTikKVMQFxtE0S1VL4-SUPWNydgexLw@mail.gmail.com>
	<1307542265.31223.97.camel@localhost>
Message-ID: <BANLkTimXGmANdV663BP2CLKZTJyzD+QLhQ@mail.gmail.com>

On Wed, Jun 8, 2011 at 10:11 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> Yes, it does look like this LEB might be garbage-collected. But it does
> not have to be.
>
> Anyway, what I can suggest you is to do several things.
>
> 1. If you have many occasions of such error, try to gather some
> ? information about how the device was used, and if it was uncleanly
> ? power-cut. Remember, I often saw that embedded devices have incorrect
> ? reboot. Whe users reboot it "normally" - it does not try to unmount
> ? the FS-es cleanly and just jumps to som HW reset function.
>
> ? You can verify this by rebooting normally and checking if UBIFS says
> ? "recovery needed" or not. If it does - the reboot was not normal.
>

Yes, it currently reboots uncleanly (though it does do a "sync"
first).  I noticed this a while back, and the next release firmware
will have it fixed.  However, it doesn't make a huge difference to us,
because these devices are probably more likely to experience power
loss than a software reboot, in the field at least.

> 2. This error may be due to memory corruptions in some driver (e.g.,
> ? wireless or video), due to issues in the mtd driver, etc. Try to
> ? stress your system with slub/slab full checks enabled, and other
> ? debugging features which you can find in the "hacking" section of
> ? make menuconfig.
>

Will do.

> 3. If my theory is true, then what may help is adding a check it
> ? ubifs recovery function. The recovery ends with an ubifs_leb_change()
> ? call. You need to check the last node there - is it full and correct?
> ? If not, you should print a loud warning and information like leb dump
> ? _before_ the change, and dump of the buffer which we are going to
> ? write with ubifs_leb_change().
>
> ? You'd probably need to deploy this check to the field if this issue
> ? is not easy to reproduce. If you have then this info you may fix the
> ? bug.
>

Great, I'll add this check and see if we get any hits.  Even if it
takes a while to hit it in the field, this would at least give us a
way to make some progress in finding the issue.

> 4. Set-up power-cut emulation testing in your office.
>

I did this at one point - I have a programmable UPS, so I was able to
automate a test to turn outlet power off & on repeatedly while having
the device do some work.  It didn't seem to help reproduce the
problem, but it's worth trying again on a long-term basis (especially
with the change above to try & catch the corruption in the act).

Thanks again Artem.

-- 
Matthew L. Creech


From vapier at gentoo.org  Wed Jun  8 14:10:27 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed, 8 Jun 2011 14:10:27 -0400
Subject: [PATCH v3] libmtd: add helper funcs for getting regioninfo and
	locked info
In-Reply-To: <1307533635.31223.63.camel@localhost>
References: <1307460482-3745-1-git-send-email-vapier@gentoo.org>
	<1307461925-6420-1-git-send-email-vapier@gentoo.org>
	<1307533635.31223.63.camel@localhost>
Message-ID: <BANLkTik4QVDOePb1xXZEQi=Zhq90ewoT=A@mail.gmail.com>

On Wed, Jun 8, 2011 at 07:47, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 11:52 -0400, Mike Frysinger wrote:
>> This extends the libmtd with the helper functions:
>> ? ? ? mtd_regioninfo: interface to MEMGETREGIONINFO
>> ? ? ? mtd_islocked: interface to MEMISLOCKED
>>
>> Users of these functions will follow shortly ...
>>
>> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>> ---
>> v3
>> ? ? ? - add a "islocked_supported" field to handle older kernels nicely
>
> Umm, I meant a user-visible flag, so that the user could check it and
> not even try to print the map.

there is an option to not print the map ... "-M --map".  not sure what
you mean other than that.

> There does not seem to be much point having this flag otherewise
> - we can just call the ioctl, and return
> error if it fails, without printing any error message.

built-in optimization.  no point in doing the ioctl() over and over if
you know it's going to fail.

although thinking about it a bit more, i think the optimization is
incorrect.  it binds the status to the libmtd_t handle which is
per-library, not per-mtd.  so using it on different mtd devices would
result in misbehavior.
-mike


From vapier at gentoo.org  Wed Jun  8 14:12:39 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed, 8 Jun 2011 14:12:39 -0400
Subject: [PATCH v2] libmtd: add helper funcs for getting regioninfo and
	locked info
In-Reply-To: <1307536063.31223.67.camel@localhost>
References: <1307427548-29306-4-git-send-email-vapier@gentoo.org>
	<1307460482-3745-1-git-send-email-vapier@gentoo.org>
	<1307533966.31223.66.camel@localhost>
	<1307536063.31223.67.camel@localhost>
Message-ID: <BANLkTi=dFc4gh26QV67Gp4ijOo8-nPhc4Q@mail.gmail.com>

On Wed, Jun 8, 2011 at 08:27, Artem Bityutskiy wrote:
> On Wed, 2011-06-08 at 14:52 +0300, Artem Bityutskiy wrote:
>> On Tue, 2011-06-07 at 11:28 -0400, Mike Frysinger wrote:
>> > This extends the libmtd with the helper functions:
>> > ? ? mtd_regioninfo: interface to MEMGETREGIONINFO
>> > ? ? mtd_islocked: interface to MEMISLOCKED
>> >
>> > Users of these functions will follow shortly ...
>> >
>> > Signed-off-by: Mike Frysinger <vapier at gentoo.org>
>>
>> Pushed with a small tweak, thanks!
>>
>> > +int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
>> > +{
>> > + ? int ret;
>> > + ? erase_info_t ei;
>> > +
>> > + ? ei.start = eb * mtd->eb_size;
>> > + ? ei.length = mtd->eb_size;
>> > +
>> > + ? ret = ioctl(fd, MEMISLOCKED, &ei);
>> > + ? if (ret < 0)
>> > + ? ? ? ? ? return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
>> > +
>>
>> I've removed this error message - if we fail, better return an error
>> code silently. At least your next patch is built a way that it will keep
>> iterating and executing this function.
>>
>> We might as well print an error message if (!ENOTTY && !ENOTSUPP), but I
>> did not do this. I expect you to send a correction patch if you do not
>> like this :-)
>
> I've just pushed a correction patch on top of this:
>
> From 92a06994b7c3f146cbdb770b30780e32f021118f Mon Sep 17 00:00:00 2001
> From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> Date: Wed, 8 Jun 2011 15:30:14 +0300
> Subject: [PATCH] libmtd: improve mtd_islocked interface
>
> This patch first of all, re-names 'mtd_islocked()' into 'mtd_is_locked()' since
> this seems to be the name Mike wanted, and it looks a bit nicer.
>
> This patch also makes 'mtd_is_locked()' print an error message if it fails. I'm
> not sure if it is good idea for a library to do so, but all functions do this,
> so it certainly _not_ a good idea to be inconsistent.
>
> However, for the special case, when the the "is locked" ioctl is not supported
> or is not valid for this device, we do not print an error message and return
> ENOTSUPP error code.
>
> Thus, the user can distinguish between real errors and non-fatal "not
> supported" cases.
>
> Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> ---
> ?include/libmtd.h | ? ?8 +++++---
> ?lib/libmtd.c ? ? | ? 13 +++++++++++--
> ?2 files changed, 16 insertions(+), 5 deletions(-)
>
> diff --git a/include/libmtd.h b/include/libmtd.h
> index 7275246..9efccbc 100644
> --- a/include/libmtd.h
> +++ b/include/libmtd.h
> @@ -190,16 +190,18 @@ int mtd_erase(libmtd_t desc, const struct mtd_dev_info *mtd, int fd, int eb);
> ?int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo);
>
> ?/**
> - * mtd_islocked - see if the specified eraseblock is locked.
> + * mtd_is_locked - see if the specified eraseblock is locked.
> ?* @mtd: MTD device description object
> ?* @fd: MTD device node file descriptor
> ?* @eb: eraseblock to check
> ?*
> ?* This function checks to see if eraseblock @eb of MTD device described
> ?* by @fd is locked. Returns %0 if it is unlocked, %1 if it is locked, and
> - * %-1 in case of failure.
> + * %-1 in case of failure. If the ioctl is not supported (support was added in
> + * Linux kernel 2.6.36) or this particular device does not support it, errno is
> + * set to @ENOTSUPP.
> ?*/
> -int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb);
> +int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb);
>
> ?/**
> ?* mtd_torture - torture an eraseblock.
> diff --git a/lib/libmtd.c b/lib/libmtd.c
> index 2573cc7..c34874e 100644
> --- a/lib/libmtd.c
> +++ b/lib/libmtd.c
> @@ -900,14 +900,23 @@ int mtd_regioninfo(int fd, int regidx, struct region_info_user *reginfo)
> ? ? ? ?return 0;
> ?}
>
> -int mtd_islocked(const struct mtd_dev_info *mtd, int fd, int eb)
> +int mtd_is_locked(const struct mtd_dev_info *mtd, int fd, int eb)
> ?{
> + ? ? ? int ret;
> ? ? ? ?erase_info_t ei;
>
> ? ? ? ?ei.start = eb * mtd->eb_size;
> ? ? ? ?ei.length = mtd->eb_size;
>
> - ? ? ? return ioctl(fd, MEMISLOCKED, &ei);
> + ? ? ? ret = ioctl(fd, MEMISLOCKED, &ei);
> + ? ? ? if (ret < 0) {
> + ? ? ? ? ? ? ? if (errno != ENOTTY && errno != EOPNOTSUPP)
> + ? ? ? ? ? ? ? ? ? ? ? return mtd_ioctl_error(mtd, eb, "MEMISLOCKED");
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? errno = EOPNOTSUPP;
> + ? ? ? }
> +
> + ? ? ? return ret;
> ?}

if you remove the new "islocked_supported" flag from my v3, this is
almost what i had already.  so i'll drop any further work here (and
focus on `mtdinfo`) since we've come to feature parity.
-mike


From vapier at gentoo.org  Wed Jun  8 14:14:12 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed, 8 Jun 2011 14:14:12 -0400
Subject: [PATCH 5/6] mtdinfo: add regioninfo/sectormap display
In-Reply-To: <1307540489.31223.87.camel@localhost>
References: <1307427548-29306-1-git-send-email-vapier@gentoo.org>
	<1307427548-29306-5-git-send-email-vapier@gentoo.org>
	<1307432463.11104.65.camel@localhost>
	<BANLkTimY1DwxBBi=peQzqwoLktgVna-0KA@mail.gmail.com>
	<1307540489.31223.87.camel@localhost>
Message-ID: <BANLkTi=T-3AF8oQNKtYGeeVwVOiYoJmWpA@mail.gmail.com>

On Wed, Jun 8, 2011 at 09:41, Artem Bityutskiy wrote:
> I've just pushed this little patch to make sure the code is more
> readable when you add your changes. Otherwise this "out:" label looks
> ugly.

np; i probably should have done this myself
-mike


From computersforpeace at gmail.com  Wed Jun  8 14:23:25 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 8 Jun 2011 11:23:25 -0700
Subject: [PATCH 4/4] mtd: nand: define pr_fmt() to include __func__ in
	debug output
In-Reply-To: <1307544476.31223.119.camel@localhost>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
	<1307487717-25402-5-git-send-email-computersforpeace@gmail.com>
	<1307544476.31223.119.camel@localhost>
Message-ID: <BANLkTi=7Xivud_V=uMadL1BA-1ZC7V9RYw@mail.gmail.com>

On Wed, Jun 8, 2011 at 7:47 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> Compare:
>
> read_bbt: Error reading bad block table
> read_bbt: error reading bad block table
>
> isn't the second version more correct? Or this depends on the country? I
> prefer the latter, but as long as all messages are consistent, I do not
> care much. What do you think?

I'm not sure it's not so much language-related here, since these type
of messages are just fragments anyway. I think the lowercase version
is more consistent.

Brian


From computersforpeace at gmail.com  Wed Jun  8 14:25:19 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 8 Jun 2011 11:25:19 -0700
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307544227.31223.115.camel@localhost>
References: <1307544227.31223.115.camel@localhost>
Message-ID: <1307557519-31269-1-git-send-email-computersforpeace@gmail.com>

Also fix some punctuation, indentation, and capitalization that went
along with the affected lines.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_base.c |   65 ++++++++++++++++++++----------------------
 drivers/mtd/nand/nand_bbt.c  |   39 ++++++++++++-------------
 2 files changed, 50 insertions(+), 54 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 019187b..7550cea 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2167,8 +2167,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
 	/* Reject writes, which are not page aligned */
 	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
-		printk(KERN_NOTICE "%s: Attempt to write not "
-				"page aligned data\n", __func__);
+		pr_notice("%s: attempt to write non page aligned data\n",
+			   __func__);
 		return -EINVAL;
 	}
 
@@ -2561,8 +2561,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 		/* Heck if we have a bad block, we do not erase bad blocks! */
 		if (nand_block_checkbad(mtd, ((loff_t) page) <<
 					chip->page_shift, 0, allowbbt)) {
-			printk(KERN_WARNING "%s: attempt to erase a bad block "
-					"at page 0x%08x\n", __func__, page);
+			pr_warning("%s: attempt to erase a bad block at page 0x%08x\n",
+				    __func__, page);
 			instr->state = MTD_ERASE_FAILED;
 			goto erase_exit;
 		}
@@ -2735,8 +2735,8 @@ static void nand_resume(struct mtd_info *mtd)
 	if (chip->state == FL_PM_SUSPENDED)
 		nand_release_device(mtd);
 	else
-		printk(KERN_ERR "%s called for a chip which is not "
-		       "in suspended state\n", __func__);
+		pr_err("%s called for a chip which is not in suspended state\n",
+			__func__);
 }
 
 /* Set default functions */
@@ -2827,13 +2827,13 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
 		return 0;
 
-	printk(KERN_INFO "ONFI flash detected\n");
+	pr_info("ONFI flash detected\n");
 	chip->cmdfunc(mtd, NAND_CMD_PARAM, 0, -1);
 	for (i = 0; i < 3; i++) {
 		chip->read_buf(mtd, (uint8_t *)p, sizeof(*p));
 		if (onfi_crc16(ONFI_CRC_BASE, (uint8_t *)p, 254) ==
 				le16_to_cpu(p->crc)) {
-			printk(KERN_INFO "ONFI param page %d valid\n", i);
+			pr_info("ONFI param page %d valid\n", i);
 			break;
 		}
 	}
@@ -2857,8 +2857,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->onfi_version = 0;
 
 	if (!chip->onfi_version) {
-		printk(KERN_INFO "%s: unsupported ONFI version: %d\n",
-								__func__, val);
+		pr_info("%s: unsupported ONFI version: %d\n", __func__, val);
 		return 0;
 	}
 
@@ -2923,7 +2922,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 		id_data[i] = chip->read_byte(mtd);
 
 	if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
-		printk(KERN_INFO "%s: second ID read did not match "
+		pr_info("%s: second ID read did not match "
 		       "%02x,%02x against %02x,%02x\n", __func__,
 		       *maf_id, *dev_id, id_data[0], id_data[1]);
 		return ERR_PTR(-ENODEV);
@@ -3068,10 +3067,10 @@ ident_done:
 	 * chip correct!
 	 */
 	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
-		printk(KERN_INFO "NAND device: Manufacturer ID:"
+		pr_info("NAND device: Manufacturer ID:"
 		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
 		       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
-		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
+		pr_warning("NAND bus width %d instead %d bit\n",
 		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
 		       busw ? 16 : 8);
 		return ERR_PTR(-EINVAL);
@@ -3129,7 +3128,7 @@ ident_done:
 	if (mtd->writesize > 512 && chip->cmdfunc == nand_command)
 		chip->cmdfunc = nand_command_lp;
 
-	printk(KERN_INFO "NAND device: Manufacturer ID:"
+	pr_info("NAND device: Manufacturer ID:"
 		" 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id, *dev_id,
 		nand_manuf_ids[maf_idx].name,
 		chip->onfi_version ? chip->onfi_params.model : type->name);
@@ -3166,7 +3165,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 
 	if (IS_ERR(type)) {
 		if (!(chip->options & NAND_SCAN_SILENT_NODEV))
-			printk(KERN_WARNING "No NAND device found.\n");
+			pr_warning("No NAND device found\n");
 		chip->select_chip(mtd, -1);
 		return PTR_ERR(type);
 	}
@@ -3184,7 +3183,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
 			break;
 	}
 	if (i > 1)
-		printk(KERN_INFO "%d NAND chips detected\n", i);
+		pr_info("%d NAND chips detected\n", i);
 
 	/* Store the number of chips and calc total size for mtd */
 	chip->numchips = i;
@@ -3234,8 +3233,8 @@ int nand_scan_tail(struct mtd_info *mtd)
 			chip->ecc.layout = &nand_oob_128;
 			break;
 		default:
-			printk(KERN_WARNING "No oob scheme defined for "
-			       "oobsize %d\n", mtd->oobsize);
+			pr_warning("No oob scheme defined for oobsize %d\n",
+				   mtd->oobsize);
 			BUG();
 		}
 	}
@@ -3253,8 +3252,8 @@ int nand_scan_tail(struct mtd_info *mtd)
 		/* Similar to NAND_ECC_HW, but a separate read_page handle */
 		if (!chip->ecc.calculate || !chip->ecc.correct ||
 		     !chip->ecc.hwctl) {
-			printk(KERN_WARNING "No ECC functions supplied; "
-			       "Hardware ECC not possible\n");
+			pr_warning("No ECC functions supplied; "
+				   "hardware ECC not possible\n");
 			BUG();
 		}
 		if (!chip->ecc.read_page)
@@ -3282,8 +3281,8 @@ int nand_scan_tail(struct mtd_info *mtd)
 		     chip->ecc.read_page == nand_read_page_hwecc ||
 		     !chip->ecc.write_page ||
 		     chip->ecc.write_page == nand_write_page_hwecc)) {
-			printk(KERN_WARNING "No ECC functions supplied; "
-			       "Hardware ECC not possible\n");
+			pr_warning("No ECC functions supplied; "
+				   "hardware ECC not possible\n");
 			BUG();
 		}
 		/* Use standard syndrome read/write page function? */
@@ -3302,9 +3301,9 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 		if (mtd->writesize >= chip->ecc.size)
 			break;
-		printk(KERN_WARNING "%d byte HW ECC not possible on "
-		       "%d byte page size, fallback to SW ECC\n",
-		       chip->ecc.size, mtd->writesize);
+		pr_warning("%d byte HW ECC not possible on "
+			   "%d byte page size, fallback to SW ECC\n",
+			   chip->ecc.size, mtd->writesize);
 		chip->ecc.mode = NAND_ECC_SOFT;
 
 	case NAND_ECC_SOFT:
@@ -3324,7 +3323,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 
 	case NAND_ECC_SOFT_BCH:
 		if (!mtd_nand_has_bch()) {
-			printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n");
+			pr_warning("CONFIG_MTD_ECC_BCH not enabled\n");
 			BUG();
 		}
 		chip->ecc.calculate = nand_bch_calculate_ecc;
@@ -3351,14 +3350,14 @@ int nand_scan_tail(struct mtd_info *mtd)
 					       chip->ecc.bytes,
 					       &chip->ecc.layout);
 		if (!chip->ecc.priv) {
-			printk(KERN_WARNING "BCH ECC initialization failed!\n");
+			pr_warning("BCH ECC initialization failed!\n");
 			BUG();
 		}
 		break;
 
 	case NAND_ECC_NONE:
-		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
-		       "This is not recommended !!\n");
+		pr_warning("NAND_ECC_NONE selected by board driver. "
+			   "This is not recommended!\n");
 		chip->ecc.read_page = nand_read_page_raw;
 		chip->ecc.write_page = nand_write_page_raw;
 		chip->ecc.read_oob = nand_read_oob_std;
@@ -3370,8 +3369,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 		break;
 
 	default:
-		printk(KERN_WARNING "Invalid NAND_ECC_MODE %d\n",
-		       chip->ecc.mode);
+		pr_warning("Invalid NAND_ECC_MODE %d\n", chip->ecc.mode);
 		BUG();
 	}
 
@@ -3392,7 +3390,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	 */
 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
 	if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
-		printk(KERN_WARNING "Invalid ecc parameters\n");
+		pr_warning("Invalid ecc parameters\n");
 		BUG();
 	}
 	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
@@ -3483,8 +3481,7 @@ int nand_scan(struct mtd_info *mtd, int maxchips)
 
 	/* Many callers got this wrong, so check for it for a while... */
 	if (!mtd->owner && caller_is_module()) {
-		printk(KERN_CRIT "%s called with NULL mtd->owner!\n",
-				__func__);
+		pr_crit("%s called with NULL mtd->owner!\n", __func__);
 		BUG();
 	}
 
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 8875d6d..d7221df 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -205,10 +205,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		res = mtd->read(mtd, from, len, &retlen, buf);
 		if (res < 0) {
 			if (retlen != len) {
-				printk(KERN_INFO "nand_bbt: Error reading bad block table\n");
+				pr_info("nand_bbt: Error reading bad block table\n");
 				return res;
 			}
-			printk(KERN_WARNING "nand_bbt: ECC error while reading bad block table\n");
+			pr_warn("nand_bbt: ECC error while reading bad block table\n");
 		}
 
 		/* Analyse data */
@@ -219,7 +219,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
-					printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
+					pr_debug("nand_read_bbt: Reserved block at 0x%012llx\n",
 					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
 					mtd->ecc_stats.bbtblocks++;
@@ -229,7 +229,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				 * Leave it for now, if it's matured we can
 				 * move this message to MTD_DEBUG_LEVEL0.
 				 */
-				printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
+				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
 				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
@@ -383,7 +383,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
-		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+		pr_debug("Bad block table at page %d, version 0x%02X\n",
 		       td->pages[0], td->version[0]);
 	}
 
@@ -392,7 +392,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
-		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
+		pr_debug("Bad block table at page %d, version 0x%02X\n",
 		       md->pages[0], md->version[0]);
 	}
 	return 1;
@@ -466,7 +466,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	loff_t from;
 	size_t readlen;
 
-	printk(KERN_INFO "Scanning device for bad blocks\n");
+	pr_info("Scanning device for bad blocks\n");
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -495,7 +495,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = 0;
 	} else {
 		if (chip >= this->numchips) {
-			printk(KERN_WARNING "create_bbt(): chipnr (%d) > available chips (%d)\n",
+			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
@@ -524,7 +524,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 		if (ret) {
 			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-			printk(KERN_WARNING "Bad eraseblock %d at 0x%012llx\n",
+			pr_warn("Bad eraseblock %d at 0x%012llx\n",
 			       i >> 1, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
@@ -607,10 +607,10 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 	/* Check, if we found a bbt for each requested chip */
 	for (i = 0; i < chips; i++) {
 		if (td->pages[i] == -1)
-			printk(KERN_WARNING "Bad block table not found for chip %d\n", i);
+			pr_warn("Bad block table not found for chip %d\n", i);
 		else
-			printk(KERN_DEBUG "Bad block table found at page %d, version 0x%02X\n", td->pages[i],
-			       td->version[i]);
+			pr_debug("Bad block table found at page %d, version "
+				 "0x%02X\n", td->pages[i], td->version[i]);
 	}
 	return 0;
 }
@@ -723,7 +723,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			if (!md || md->pages[chip] != page)
 				goto write;
 		}
-		printk(KERN_ERR "No space left to write bad block table\n");
+		pr_err("No space left to write bad block table\n");
 		return -ENOSPC;
 	write:
 
@@ -758,12 +758,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			res = mtd->read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
-					printk(KERN_INFO "nand_bbt: Error "
+					pr_info("nand_bbt: Error "
 					       "reading block for writing "
 					       "the bad block table\n");
 					return res;
 				}
-				printk(KERN_WARNING "nand_bbt: ECC error "
+				pr_warn("nand_bbt: ECC error "
 				       "while reading block for writing "
 				       "bad block table\n");
 			}
@@ -840,7 +840,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		if (res < 0)
 			goto outerr;
 
-		printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
+		pr_debug("Bad block table written to 0x%012llx, version "
 		       "0x%02X\n", (unsigned long long)to, td->version[chip]);
 
 		/* Mark it as used */
@@ -849,8 +849,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	return 0;
 
  outerr:
-	printk(KERN_WARNING
-	       "nand_bbt: Error while writing bad block table %d\n", res);
+	pr_warning("nand_bbt: Error while writing bad block table %d\n", res);
 	return res;
 }
 
@@ -1130,7 +1129,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	 */
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
-			printk(KERN_ERR "nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			pr_err("nand_bbt: Can't scan flash and build the RAM-based BBT\n");
 			kfree(this->bbt);
 			this->bbt = NULL;
 		}
@@ -1298,7 +1297,7 @@ static int nand_create_default_bbt_descr(struct nand_chip *this)
 {
 	struct nand_bbt_descr *bd;
 	if (this->badblock_pattern) {
-		printk(KERN_WARNING "BBT descr already allocated; not replacing.\n");
+		pr_warn("BBT descr already allocated; not replacing\n");
 		return -EINVAL;
 	}
 	bd = kzalloc(sizeof(*bd), GFP_KERNEL);
-- 
1.7.0.4




From vapier at gentoo.org  Wed Jun  8 14:26:01 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed, 8 Jun 2011 14:26:01 -0400
Subject: [PATCH v2] mtdinfo: add regioninfo/eraseblock map display
In-Reply-To: <1307540151.31223.85.camel@localhost>
References: <1307427548-29306-5-git-send-email-vapier@gentoo.org>
	<1307461999-6483-1-git-send-email-vapier@gentoo.org>
	<1307540151.31223.85.camel@localhost>
Message-ID: <BANLkTinQMzCWy+1nWf5ev4VJW-2kOfoQ7g@mail.gmail.com>

On Wed, Jun 8, 2011 at 09:35, Artem Bityutskiy wrote:
> On Tue, 2011-06-07 at 11:53 -0400, Mike Frysinger wrote:
>> @@ -110,6 +114,10 @@ static int parse_opt(int argc, char * const argv[])
>> ? ? ? ? ? ? ? ? ? ? ? warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
>> ? ? ? ? ? ? ? ? ? ? ? break;
>>
>> + ? ? ? ? ? ? case 'M':
>> + ? ? ? ? ? ? ? ? ? ? args.map = 1;
>> + ? ? ? ? ? ? ? ? ? ? break;
>> +
>> ? ? ? ? ? ? ? case 'h':
>> ? ? ? ? ? ? ? ? ? ? ? printf("%s\n\n", doc);
>> ? ? ? ? ? ? ? ? ? ? ? printf("%s\n\n", usage);
>
> Would you also please add the following code near the end of the
> 'parse_opt()' function:
>
> + ? ? ? if (args.map && !args.node)
> + ? ? ? ? ? ? ? return errmsg("-M requires MTD device node name");
>
> This will anyway be true when we remove -m, a the checks like "if
> (args.node)" will be not needed.

the -a/--all option will need reworking, but that'll have to happen
anyways once we punt -m

>> @@ -196,8 +235,26 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
>> ? ? ? if (mtd.oob_size > 0)
>> ? ? ? ? ? ? ? printf("OOB size: ? ? ? ? ? ? ? ? ? ? ? %d bytes\n",
>> ? ? ? ? ? ? ? ? ? ? ?mtd.oob_size);
>> - ? ? if (mtd.region_cnt > 0)
>> + ? ? if (mtd.region_cnt > 0) {
>> ? ? ? ? ? ? ? printf("Additional erase regions: ? ? ? %d\n", mtd.oob_size);
>> + ? ? ? ? ? ? if (args.node)
>> + ? ? ? ? ? ? ? ? ? ? fd = open(args.node, O_RDONLY | O_CLOEXEC);
>
> We do want to print error message if open fails. E.g., I use -M and I do
> not see any eraseblock map - because I am not root!
>
> If open fails, we need to print something like "cannot fetch information
> about regions - error blah (blah blah)". And may be we can just
> continue.

i can add a warning when the open() fails

i have some ideas for the rest, so i'll just send a new patch which
should make us both happy i think
-mike


From computersforpeace at gmail.com  Wed Jun  8 14:27:30 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 8 Jun 2011 11:27:30 -0700
Subject: [PATCH v2 3/4] mtd: nand: replace DEBUG() with dev_dbg()
In-Reply-To: <1307544295.31223.116.camel@localhost>
References: <1307544295.31223.116.camel@localhost>
Message-ID: <1307557650-31323-1-git-send-email-computersforpeace@gmail.com>

Start moving away from the MTD_DEBUG_LEVEL messages. The dynamic
debugging feature is a generic kernel feature that provides more
flexibility.

(See Documentation/dynamic-debug-howto.txt)

Also fix some punctuation, indentation, and capitalization that went
along with the affected lines.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_base.c |   74 ++++++++++++++++++++---------------------
 drivers/mtd/nand/nand_bbt.c  |    9 ++---
 2 files changed, 39 insertions(+), 44 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 7550cea..e124498 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -113,21 +113,19 @@ static int check_offs_len(struct mtd_info *mtd,
 
 	/* Start address must align on block boundary */
 	if (ofs & ((1 << chip->phys_erase_shift) - 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Unaligned address\n", __func__);
+		dev_dbg(&mtd->dev, "%s: unaligned address\n", __func__);
 		ret = -EINVAL;
 	}
 
 	/* Length must align on block boundary */
 	if (len & ((1 << chip->phys_erase_shift) - 1)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Length not block aligned\n",
-					__func__);
+		dev_dbg(&mtd->dev, "%s: length not block aligned\n", __func__);
 		ret = -EINVAL;
 	}
 
 	/* Do not allow past end of device */
 	if (ofs + len > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Past end of device\n",
-					__func__);
+		dev_dbg(&mtd->dev, "%s: past end of device\n", __func__);
 		ret = -EINVAL;
 	}
 
@@ -912,7 +910,7 @@ static int __nand_unlock(struct mtd_info *mtd, loff_t ofs,
 	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+		dev_dbg(&mtd->dev, "%s: error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
 	}
@@ -934,7 +932,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	int chipnr;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	dev_dbg(&mtd->dev, "%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
 
 	if (check_offs_len(mtd, ofs, len))
@@ -953,7 +951,7 @@ int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		dev_dbg(&mtd->dev, "%s: device is write protected!\n",
 					__func__);
 		ret = -EIO;
 		goto out;
@@ -987,7 +985,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	int chipnr, status, page;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
+	dev_dbg(&mtd->dev, "%s: start = 0x%012llx, len = %llu\n",
 			__func__, (unsigned long long)ofs, len);
 
 	if (check_offs_len(mtd, ofs, len))
@@ -1002,7 +1000,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
+		dev_dbg(&mtd->dev, "%s: device is write protected!\n",
 					__func__);
 		status = MTD_ERASE_FAILED;
 		ret = -EIO;
@@ -1018,7 +1016,7 @@ int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len)
 	udelay(1000);
 	/* See if device thinks it succeeded */
 	if (status & 0x01) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Error status = 0x%08x\n",
+		dev_dbg(&mtd->dev, "%s: error status = 0x%08x\n",
 					__func__, status);
 		ret = -EIO;
 		goto out;
@@ -1757,7 +1755,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 	int len;
 	uint8_t *buf = ops->oobbuf;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
+	dev_dbg(&mtd->dev, "%s: from = 0x%08Lx, len = %i\n",
 			__func__, (unsigned long long)from, readlen);
 
 	if (ops->mode == MTD_OOB_AUTO)
@@ -1766,8 +1764,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 		len = mtd->oobsize;
 
 	if (unlikely(ops->ooboffs >= len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start read "
-					"outside oob\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to start read outside oob\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -1775,8 +1773,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 	if (unlikely(from >= mtd->size ||
 		     ops->ooboffs + readlen > ((mtd->size >> chip->page_shift) -
 					(from >> chip->page_shift)) * len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read beyond end "
-					"of device\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to read beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -1851,8 +1849,8 @@ static int nand_read_oob(struct mtd_info *mtd, loff_t from,
 
 	/* Do not allow reads past end of device */
 	if (ops->datbuf && (from + ops->len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt read "
-				"beyond end of device\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to read beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -2341,7 +2339,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 	int chipnr, page, status, len;
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: to = 0x%08x, len = %i\n",
+	dev_dbg(&mtd->dev, "%s: to = 0x%08x, len = %i\n",
 			 __func__, (unsigned int)to, (int)ops->ooblen);
 
 	if (ops->mode == MTD_OOB_AUTO)
@@ -2351,14 +2349,14 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 
 	/* Do not allow write past end of page */
 	if ((ops->ooboffs + ops->ooblen) > len) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to write "
-				"past end of page\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to write past end of page\n",
+				__func__);
 		return -EINVAL;
 	}
 
 	if (unlikely(ops->ooboffs >= len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt to start "
-				"write outside oob\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to start write outside oob\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -2367,8 +2365,8 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 		     ops->ooboffs + ops->ooblen >
 			((mtd->size >> chip->page_shift) -
 			 (to >> chip->page_shift)) * len)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
-				"end of device\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to write beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -2423,8 +2421,8 @@ static int nand_write_oob(struct mtd_info *mtd, loff_t to,
 
 	/* Do not allow writes past end of device */
 	if (ops->datbuf && (to + ops->len) > mtd->size) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Attempt write beyond "
-				"end of device\n", __func__);
+		dev_dbg(&mtd->dev, "%s: attempt to write beyond end of device\n",
+				__func__);
 		return -EINVAL;
 	}
 
@@ -2513,9 +2511,9 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 	unsigned int bbt_masked_page = 0xffffffff;
 	loff_t len;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: start = 0x%012llx, len = %llu\n",
-				__func__, (unsigned long long)instr->addr,
-				(unsigned long long)instr->len);
+	dev_dbg(&mtd->dev, "%s: start = 0x%012llx, len = %llu\n",
+			__func__, (unsigned long long)instr->addr,
+			(unsigned long long)instr->len);
 
 	if (check_offs_len(mtd, instr->addr, instr->len))
 		return -EINVAL;
@@ -2537,8 +2535,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
 	/* Check, if it is write protected */
 	if (nand_check_wp(mtd)) {
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: Device is write protected!!!\n",
-					__func__);
+		dev_dbg(&mtd->dev, "%s: device is write protected!\n",
+				__func__);
 		instr->state = MTD_ERASE_FAILED;
 		goto erase_exit;
 	}
@@ -2589,8 +2587,8 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 
 		/* See if block erase succeeded */
 		if (status & NAND_STATUS_FAIL) {
-			DEBUG(MTD_DEBUG_LEVEL0, "%s: Failed erase, "
-					"page 0x%08x\n", __func__, page);
+			dev_dbg(&mtd->dev, "%s: failed erase, page 0x%08x\n",
+					__func__, page);
 			instr->state = MTD_ERASE_FAILED;
 			instr->fail_addr =
 				((loff_t)page << chip->page_shift);
@@ -2650,9 +2648,9 @@ erase_exit:
 		if (!rewrite_bbt[chipnr])
 			continue;
 		/* Update the BBT for chip */
-		DEBUG(MTD_DEBUG_LEVEL0, "%s: nand_update_bbt "
-			"(%d:0x%0llx 0x%0x)\n", __func__, chipnr,
-			rewrite_bbt[chipnr], chip->bbt_td->pages[chipnr]);
+		dev_dbg(&mtd->dev, "%s: nand_update_bbt (%d:0x%0llx 0x%0x)\n",
+				__func__, chipnr, rewrite_bbt[chipnr],
+				chip->bbt_td->pages[chipnr]);
 		nand_update_bbt(mtd, rewrite_bbt[chipnr]);
 	}
 
@@ -2670,7 +2668,7 @@ static void nand_sync(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
 
-	DEBUG(MTD_DEBUG_LEVEL3, "%s: called\n", __func__);
+	dev_dbg(&mtd->dev, "%s: called\n", __func__);
 
 	/* Grab the lock and see if the device is available */
 	nand_get_device(chip, mtd, FL_SYNCING);
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index d7221df..5835404 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -225,10 +225,6 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
-				/*
-				 * Leave it for now, if it's matured we can
-				 * move this message to MTD_DEBUG_LEVEL0.
-				 */
 				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
 				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
@@ -1378,8 +1374,9 @@ int nand_isbad_bbt(struct mtd_info *mtd, loff_t offs, int allowbbt)
 	block = (int)(offs >> (this->bbt_erase_shift - 1));
 	res = (this->bbt[block >> 3] >> (block & 0x06)) & 0x03;
 
-	DEBUG(MTD_DEBUG_LEVEL2, "nand_isbad_bbt(): bbt info for offs 0x%08x: (block %d) 0x%02x\n",
-	      (unsigned int)offs, block >> 1, res);
+	dev_dbg(&mtd->dev, "nand_isbad_bbt(): bbt info for offs 0x%08x: "
+			   "(block %d) 0x%02x\n",
+			   (unsigned int)offs, block >> 1, res);
 
 	switch ((int)res) {
 	case 0x00:
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun  8 14:28:28 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 8 Jun 2011 11:28:28 -0700
Subject: [PATCH v2 4/4] mtd: nand: define pr_fmt() to include __func__
	in debug output
In-Reply-To: <BANLkTi=7Xivud_V=uMadL1BA-1ZC7V9RYw@mail.gmail.com>
References: <BANLkTi=7Xivud_V=uMadL1BA-1ZC7V9RYw@mail.gmail.com>
Message-ID: <1307557708-31376-1-git-send-email-computersforpeace@gmail.com>

Also fix some capitalization that went along with the affected lines.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_bbt.c |   44 +++++++++++++++++++++---------------------
 1 files changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 5835404..3deced4 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -59,6 +59,8 @@
  *
  */
 
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/mtd/mtd.h>
@@ -205,10 +207,10 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 		res = mtd->read(mtd, from, len, &retlen, buf);
 		if (res < 0) {
 			if (retlen != len) {
-				pr_info("nand_bbt: Error reading bad block table\n");
+				pr_info("error reading bad block table\n");
 				return res;
 			}
-			pr_warn("nand_bbt: ECC error while reading bad block table\n");
+			pr_warn("ECC error while reading bad block table\n");
 		}
 
 		/* Analyse data */
@@ -219,13 +221,13 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
-					pr_debug("nand_read_bbt: Reserved block at 0x%012llx\n",
+					pr_debug("reserved block at 0x%012llx\n",
 					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
-				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
+				pr_debug("bad block at 0x%012llx\n",
 				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
@@ -379,7 +381,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
-		pr_debug("Bad block table at page %d, version 0x%02X\n",
+		pr_debug("bad block table at page %d, version 0x%02X\n",
 		       td->pages[0], td->version[0]);
 	}
 
@@ -388,7 +390,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
-		pr_debug("Bad block table at page %d, version 0x%02X\n",
+		pr_debug("bad block table at page %d, version 0x%02X\n",
 		       md->pages[0], md->version[0]);
 	}
 	return 1;
@@ -462,7 +464,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	loff_t from;
 	size_t readlen;
 
-	pr_info("Scanning device for bad blocks\n");
+	pr_info("scanning device for bad blocks\n");
 
 	if (bd->options & NAND_BBT_SCANALLPAGES)
 		len = 1 << (this->bbt_erase_shift - this->page_shift);
@@ -491,7 +493,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 		from = 0;
 	} else {
 		if (chip >= this->numchips) {
-			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
+			pr_warn("chipnr (%d) > available chips (%d)\n",
 			       chip + 1, this->numchips);
 			return -EINVAL;
 		}
@@ -520,7 +522,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 
 		if (ret) {
 			this->bbt[i >> 3] |= 0x03 << (i & 0x6);
-			pr_warn("Bad eraseblock %d at 0x%012llx\n",
+			pr_warn("bad eraseblock %d at 0x%012llx\n",
 			       i >> 1, (unsigned long long)from);
 			mtd->ecc_stats.badblocks++;
 		}
@@ -603,9 +605,9 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 	/* Check, if we found a bbt for each requested chip */
 	for (i = 0; i < chips; i++) {
 		if (td->pages[i] == -1)
-			pr_warn("Bad block table not found for chip %d\n", i);
+			pr_warn("bad block table not found for chip %d\n", i);
 		else
-			pr_debug("Bad block table found at page %d, version "
+			pr_debug("bad block table found at page %d, version "
 				 "0x%02X\n", td->pages[i], td->version[i]);
 	}
 	return 0;
@@ -719,7 +721,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			if (!md || md->pages[chip] != page)
 				goto write;
 		}
-		pr_err("No space left to write bad block table\n");
+		pr_err("no space left to write bad block table\n");
 		return -ENOSPC;
 	write:
 
@@ -754,14 +756,12 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 			res = mtd->read(mtd, to, len, &retlen, buf);
 			if (res < 0) {
 				if (retlen != len) {
-					pr_info("nand_bbt: Error "
-					       "reading block for writing "
-					       "the bad block table\n");
+					pr_info("error reading block for writing"
+						" the bad block table\n");
 					return res;
 				}
-				pr_warn("nand_bbt: ECC error "
-				       "while reading block for writing "
-				       "bad block table\n");
+				pr_warn("ECC error while reading block for "
+					"writing bad block table\n");
 			}
 			/* Read oob data */
 			ops.ooblen = (len >> this->page_shift) * mtd->oobsize;
@@ -836,8 +836,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		if (res < 0)
 			goto outerr;
 
-		pr_debug("Bad block table written to 0x%012llx, version "
-		       "0x%02X\n", (unsigned long long)to, td->version[chip]);
+		pr_debug("bad block table written to 0x%012llx, version "
+			 "0x%02X\n", (unsigned long long)to, td->version[chip]);
 
 		/* Mark it as used */
 		td->pages[chip] = page;
@@ -845,7 +845,7 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 	return 0;
 
  outerr:
-	pr_warning("nand_bbt: Error while writing bad block table %d\n", res);
+	pr_warning("error while writing bad block table %d\n", res);
 	return res;
 }
 
@@ -1125,7 +1125,7 @@ int nand_scan_bbt(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 	 */
 	if (!td) {
 		if ((res = nand_memory_bbt(mtd, bd))) {
-			pr_err("nand_bbt: Can't scan flash and build the RAM-based BBT\n");
+			pr_err("can't scan flash and build the RAM-based BBT\n");
 			kfree(this->bbt);
 			this->bbt = NULL;
 		}
-- 
1.7.0.4




From vapier at gentoo.org  Wed Jun  8 14:52:28 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed,  8 Jun 2011 14:52:28 -0400
Subject: [PATCH] mtdinfo: remove now unused ubigen info
Message-ID: <1307559148-28483-1-git-send-email-vapier@gentoo.org>

A previous commit moved the code using this var into a diff func.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 ubi-utils/src/mtdinfo.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index ca0ad71..38b63ca 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -185,7 +185,6 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 {
 	int err;
 	struct mtd_dev_info mtd;
-	struct ubigen_info ui;
 
 	err = mtd_get_dev_info1(libmtd, mtdn, &mtd);
 	if (err) {
-- 
1.7.5.3



From geert at linux-m68k.org  Wed Jun  8 14:53:23 2011
From: geert at linux-m68k.org (Geert Uytterhoeven)
Date: Wed, 8 Jun 2011 20:53:23 +0200
Subject: ARM: 6910/1: MTD: physmap: let set_vpp() pass a platform_device
	instead of a map_info
In-Reply-To: <201105240059.p4O0xPfN009516@hera.kernel.org>
References: <201105240059.p4O0xPfN009516@hera.kernel.org>
Message-ID: <BANLkTim1=DBd1AvPw1VuPfGi_Z5ktAhyPg@mail.gmail.com>

On Tue, May 24, 2011 at 02:59, Linux Kernel Mailing List
<linux-kernel at vger.kernel.org> wrote:
> ? ?ARM: 6910/1: MTD: physmap: let set_vpp() pass a platform_device instead of a map_info
>
> ? ?The set_vpp() method provided by physmap passes a map_info back to
> ? ?the platform code, which has little relevance as far as the platform
> ? ?is concerned (this parameter is completely unused).
>
> ? ?Instead, pass the platform_device, which can be used in the pismo
> ? ?driver to retrieve some important information in a nicer way, instead
> ? ?of the hack that was in place.
>
> ? ?The empty set_vpp function in board-at572d940hf_ek.c is left untouched,
> ? ?as the board/SoC is scheduled for removal.
>
> ? ?Cc: Andrew Victor <linux at maxim.org.za>
> ? ?Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
> ? ?Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
> ? ?Cc: Philipp Zabel <philipp.zabel at gmail.com>
> ? ?Cc: Eric Miao <eric.y.miao at gmail.com>
> ? ?Cc: Ben Dooks <ben-linux at fluff.org>
> ? ?Acked-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
> ? ?Acked-by: David Woodhouse <dwmw2 at infradead.org>
> ? ?Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ? ?Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>

> --- a/include/linux/mtd/physmap.h
> +++ b/include/linux/mtd/physmap.h
> @@ -24,7 +24,7 @@ struct physmap_flash_data {
> ? ? ? ?unsigned int ? ? ? ? ? ?width;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? (*init)(struct platform_device *);
> ? ? ? ?void ? ? ? ? ? ? ? ? ? ?(*exit)(struct platform_device *);
> - ? ? ? void ? ? ? ? ? ? ? ? ? ?(*set_vpp)(struct map_info *, int);
> + ? ? ? void ? ? ? ? ? ? ? ? ? ?(*set_vpp)(struct platform_device *, int);
> ? ? ? ?unsigned int ? ? ? ? ? ?nr_parts;
> ? ? ? ?unsigned int ? ? ? ? ? ?pfow_base;
> ? ? ? ?char ? ? ? ? ? ? ? ? ? ?*probe_type;

You forgot to update the set_vpp parameter of physmap_configure():

void physmap_configure(unsigned long addr, unsigned long size,
                int bankwidth, void (*set_vpp)(struct map_info *, int) );

causing

drivers/mtd/maps/physmap.c: In function ?physmap_configure?:
drivers/mtd/maps/physmap.c:255: warning: assignment from incompatible
pointer type

Interestingly, there are no (in-tree) users of physmap_configure()?

Gr{oetje,eeting}s,

? ? ? ? ? ? ? ? ? ? ? ? Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
? ? ? ? ? ? ? ? ? ? ? ? ? ?? ?? -- Linus Torvalds


From vapier at gentoo.org  Wed Jun  8 15:02:22 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed,  8 Jun 2011 15:02:22 -0400
Subject: [PATCH v3] mtdinfo: add regioninfo/eraseblock map display
In-Reply-To: <1307461999-6483-1-git-send-email-vapier@gentoo.org>
References: <1307461999-6483-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307559742-29134-1-git-send-email-vapier@gentoo.org>

This brings the mtdinfo utility in line with the functionality
of the flash_info utility.  It dumps the erase regioninfo (if
the devices has it) as well as showing a handy eraseblock map
(if the user has requested it).  The eraseblock map also shows
which blocks are locked and which ones are bad.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v3
	- unify region and map printing

 ubi-utils/src/mtdinfo.c |  119 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 116 insertions(+), 3 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index 38b63ca..045f5c9 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -29,6 +29,7 @@
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <mtd/mtd-user.h>
 
 #include <libubigen.h>
@@ -41,6 +42,7 @@ struct args {
 	int mtdn;
 	unsigned int all:1;
 	unsigned int ubinfo:1;
+	unsigned int map:1;
 	const char *node;
 };
 
@@ -59,14 +61,15 @@ static const char optionsstr[] =
 "                                (deprecated option, will be removed, do not use)\n"
 "-u, --ubi-info                  print what would UBI layout be if it was put\n"
 "                                on this MTD device\n"
+"-M, --map                       print eraseblock map\n"
 "-a, --all                       print information about all MTD devices\n"
 "-h, --help                      print help message\n"
 "-V, --version                   print program version";
 
 static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-h] [-V] [--mtdn <MTD device number>]\n"
+"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n"
 "\t\t[--ubi-info] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-h] [-V] [--ubi-info] [--help]\n"
+"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
 "\t\t[--version]\n"
 "Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
 "Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
@@ -79,6 +82,7 @@ static const char usage[] =
 static const struct option long_options[] = {
 	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
 	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
+	{ .name = "map",       .has_arg = 0, .flag = NULL, .val = 'M' },
 	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
 	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
 	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
@@ -90,7 +94,7 @@ static int parse_opt(int argc, char * const argv[])
 	while (1) {
 		int key, error = 0;
 
-		key = getopt_long(argc, argv, "am:uhV", long_options, NULL);
+		key = getopt_long(argc, argv, "am:uMhV", long_options, NULL);
 		if (key == -1)
 			break;
 
@@ -110,6 +114,10 @@ static int parse_opt(int argc, char * const argv[])
 			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
 			break;
 
+		case 'M':
+			args.map = 1;
+			break;
+
 		case 'h':
 			printf("%s\n\n", doc);
 			printf("%s\n\n", usage);
@@ -139,6 +147,9 @@ static int parse_opt(int argc, char * const argv[])
 		args.node = NULL;
 	}
 
+	if (args.map && !args.node)
+		return errmsg("-M requires MTD device node name");
+
 	return 0;
 }
 
@@ -181,6 +192,105 @@ static void print_ubi_info(const struct mtd_info *mtd_info,
 	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
 }
 
+static void print_region_map(const struct mtd_dev_info *mtd, int fd,
+			     const region_info_t *reginfo)
+{
+	unsigned long start;
+	int i, width;
+	int ret_locked, errno_locked, ret_bad, errno_bad;
+
+	printf("Eraseblock map:\n");
+
+	/* figure out the number of spaces to pad w/out libm */
+	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
+		continue;
+
+	/* if we don't have a fd to query, just show the bare map */
+	if (fd == -1) {
+		ret_locked = ret_bad = -1;
+		errno_locked = errno_bad = ENODEV;
+	} else
+		ret_locked = ret_bad = errno_locked = errno_bad = 0;
+
+	for (i = 0; i < reginfo->numblocks; ++i) {
+		start = reginfo->offset + i * reginfo->erasesize;
+		printf(" %*i: %08lx ", width, i, start);
+
+		if (ret_locked != -1) {
+			ret_locked = mtd_is_locked(mtd, fd, i);
+			if (ret_locked == 1)
+				printf("RO ");
+			else
+				errno_locked = errno;
+		}
+		if (ret_locked != 1)
+			printf("   ");
+
+		if (ret_bad != -1) {
+			ret_bad = mtd_is_bad(mtd, fd, i);
+			if (ret_bad == 1)
+				printf("BAD ");
+			else
+				errno_bad = errno;
+		}
+		if (ret_bad != 1)
+			printf("    ");
+
+		if (((i + 1) % 4) == 0)
+			printf("\n");
+	}
+	if (i % 4)
+		printf("\n");
+
+	if (ret_locked == -1 && errno_locked != EOPNOTSUPP) {
+		errno = errno_locked;
+		sys_errmsg("could not read locked block info");
+	}
+
+	if (mtd->bb_allowed && ret_bad == -1 && errno_bad != EOPNOTSUPP) {
+		errno = errno_bad;
+		sys_errmsg("could not read bad block info");
+	}
+}
+
+static void print_region_info(const struct mtd_dev_info *mtd)
+{
+	region_info_t reginfo;
+	int r, fd;
+
+	/* First open the device so we can query it */
+	fd = open(args.node, O_RDONLY | O_CLOEXEC);
+	if (fd == -1) {
+		sys_errmsg("couldn't open MTD dev: %s", args.node);
+		if (mtd->region_cnt)
+			return;
+	}
+
+	/* walk all the regions and show the map for them */
+	if (mtd->region_cnt) {
+		for (r = 0; r < mtd->region_cnt; ++r) {
+			printf("Eraseblock region %i: ", r);
+			if (mtd_regioninfo(fd, r, &reginfo) == 0) {
+				printf(" offset: %#x size: %#x numblocks: %#x\n",
+					reginfo.offset, reginfo.erasesize,
+					reginfo.numblocks);
+				if (args.map)
+					print_region_map(mtd, fd, &reginfo);
+			} else
+				printf(" info is unavailable\n");
+		}
+	} else {
+		reginfo.offset = 0;
+		reginfo.erasesize = mtd->eb_size;
+		reginfo.numblocks = mtd->eb_cnt;
+		reginfo.regionindex = 0;
+		print_region_map(mtd, fd, &reginfo);
+	}
+
+	if (fd != -1)
+		close(fd);
+}
+
 static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
 {
 	int err;
@@ -229,6 +339,9 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	if (args.ubinfo)
 		print_ubi_info(mtd_info, &mtd);
 
+	if (args.map)
+		print_region_info(&mtd);
+
 	printf("\n");
 	return 0;
 }
-- 
1.7.5.3



From vapier.adi at gmail.com  Wed Jun  8 15:03:10 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Wed, 8 Jun 2011 15:03:10 -0400
Subject: [PATCH 4/4] mtd: nand: define pr_fmt() to include __func__ in
	debug output
In-Reply-To: <BANLkTi=7Xivud_V=uMadL1BA-1ZC7V9RYw@mail.gmail.com>
References: <1307487717-25402-1-git-send-email-computersforpeace@gmail.com>
	<1307487717-25402-5-git-send-email-computersforpeace@gmail.com>
	<1307544476.31223.119.camel@localhost>
	<BANLkTi=7Xivud_V=uMadL1BA-1ZC7V9RYw@mail.gmail.com>
Message-ID: <BANLkTinFZL-ybdZxqdDthEZLAmXtKCCCSA@mail.gmail.com>

On Wed, Jun 8, 2011 at 14:23, Brian Norris wrote:
> On Wed, Jun 8, 2011 at 7:47 AM, Artem Bityutskiy wrote:
>> Compare:
>>
>> read_bbt: Error reading bad block table
>> read_bbt: error reading bad block table
>>
>> isn't the second version more correct? Or this depends on the country? I
>> prefer the latter, but as long as all messages are consistent, I do not
>> care much. What do you think?
>
> I'm not sure it's not so much language-related here, since these type
> of messages are just fragments anyway. I think the lowercase version
> is more consistent.

+1 to both
-mike


From vapier at gentoo.org  Wed Jun  8 15:11:32 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Wed,  8 Jun 2011 15:11:32 -0400
Subject: [PATCH v4] mtdinfo: add regioninfo/eraseblock map display
In-Reply-To: <1307559742-29134-1-git-send-email-vapier@gentoo.org>
References: <1307559742-29134-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307560292-29595-1-git-send-email-vapier@gentoo.org>

This brings the mtdinfo utility in line with the functionality
of the flash_info utility.  It dumps the erase regioninfo (if
the devices has it) as well as showing a handy eraseblock map
(if the user has requested it).  The eraseblock map also shows
which blocks are locked and which ones are bad.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v4
	- still show region info when map isn't requested

 ubi-utils/src/mtdinfo.c |  122 +++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index 38b63ca..e4b9f70 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -29,6 +29,7 @@
 #include <getopt.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 #include <mtd/mtd-user.h>
 
 #include <libubigen.h>
@@ -41,6 +42,7 @@ struct args {
 	int mtdn;
 	unsigned int all:1;
 	unsigned int ubinfo:1;
+	unsigned int map:1;
 	const char *node;
 };
 
@@ -59,14 +61,15 @@ static const char optionsstr[] =
 "                                (deprecated option, will be removed, do not use)\n"
 "-u, --ubi-info                  print what would UBI layout be if it was put\n"
 "                                on this MTD device\n"
+"-M, --map                       print eraseblock map\n"
 "-a, --all                       print information about all MTD devices\n"
 "-h, --help                      print help message\n"
 "-V, --version                   print program version";
 
 static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-h] [-V] [--mtdn <MTD device number>]\n"
+"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n"
 "\t\t[--ubi-info] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-h] [-V] [--ubi-info] [--help]\n"
+"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
 "\t\t[--version]\n"
 "Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
 "Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
@@ -79,6 +82,7 @@ static const char usage[] =
 static const struct option long_options[] = {
 	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
 	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
+	{ .name = "map",       .has_arg = 0, .flag = NULL, .val = 'M' },
 	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
 	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
 	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
@@ -90,7 +94,7 @@ static int parse_opt(int argc, char * const argv[])
 	while (1) {
 		int key, error = 0;
 
-		key = getopt_long(argc, argv, "am:uhV", long_options, NULL);
+		key = getopt_long(argc, argv, "am:uMhV", long_options, NULL);
 		if (key == -1)
 			break;
 
@@ -110,6 +114,10 @@ static int parse_opt(int argc, char * const argv[])
 			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
 			break;
 
+		case 'M':
+			args.map = 1;
+			break;
+
 		case 'h':
 			printf("%s\n\n", doc);
 			printf("%s\n\n", usage);
@@ -139,6 +147,9 @@ static int parse_opt(int argc, char * const argv[])
 		args.node = NULL;
 	}
 
+	if (args.map && !args.node)
+		return errmsg("-M requires MTD device node name");
+
 	return 0;
 }
 
@@ -181,6 +192,109 @@ static void print_ubi_info(const struct mtd_info *mtd_info,
 	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
 }
 
+static void print_region_map(const struct mtd_dev_info *mtd, int fd,
+			     const region_info_t *reginfo)
+{
+	unsigned long start;
+	int i, width;
+	int ret_locked, errno_locked, ret_bad, errno_bad;
+
+	printf("Eraseblock map:\n");
+
+	/* figure out the number of spaces to pad w/out libm */
+	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
+		continue;
+
+	/* if we don't have a fd to query, just show the bare map */
+	if (fd == -1) {
+		ret_locked = ret_bad = -1;
+		errno_locked = errno_bad = ENODEV;
+	} else
+		ret_locked = ret_bad = errno_locked = errno_bad = 0;
+
+	for (i = 0; i < reginfo->numblocks; ++i) {
+		start = reginfo->offset + i * reginfo->erasesize;
+		printf(" %*i: %08lx ", width, i, start);
+
+		if (ret_locked != -1) {
+			ret_locked = mtd_is_locked(mtd, fd, i);
+			if (ret_locked == 1)
+				printf("RO ");
+			else
+				errno_locked = errno;
+		}
+		if (ret_locked != 1)
+			printf("   ");
+
+		if (ret_bad != -1) {
+			ret_bad = mtd_is_bad(mtd, fd, i);
+			if (ret_bad == 1)
+				printf("BAD ");
+			else
+				errno_bad = errno;
+		}
+		if (ret_bad != 1)
+			printf("    ");
+
+		if (((i + 1) % 4) == 0)
+			printf("\n");
+	}
+	if (i % 4)
+		printf("\n");
+
+	if (ret_locked == -1 && errno_locked != EOPNOTSUPP) {
+		errno = errno_locked;
+		sys_errmsg("could not read locked block info");
+	}
+
+	if (mtd->bb_allowed && ret_bad == -1 && errno_bad != EOPNOTSUPP) {
+		errno = errno_bad;
+		sys_errmsg("could not read bad block info");
+	}
+}
+
+static void print_region_info(const struct mtd_dev_info *mtd)
+{
+	region_info_t reginfo;
+	int r, fd;
+
+	/* If we don't have any region info, just return */
+	if (!args.map && mtd->region_cnt == 0)
+		return;
+
+	/* First open the device so we can query it */
+	fd = open(args.node, O_RDONLY | O_CLOEXEC);
+	if (fd == -1) {
+		sys_errmsg("couldn't open MTD dev: %s", args.node);
+		if (mtd->region_cnt)
+			return;
+	}
+
+	/* Walk all the regions and show the map for them */
+	if (mtd->region_cnt) {
+		for (r = 0; r < mtd->region_cnt; ++r) {
+			printf("Eraseblock region %i: ", r);
+			if (mtd_regioninfo(fd, r, &reginfo) == 0) {
+				printf(" offset: %#x size: %#x numblocks: %#x\n",
+					reginfo.offset, reginfo.erasesize,
+					reginfo.numblocks);
+				if (args.map)
+					print_region_map(mtd, fd, &reginfo);
+			} else
+				printf(" info is unavailable\n");
+		}
+	} else {
+		reginfo.offset = 0;
+		reginfo.erasesize = mtd->eb_size;
+		reginfo.numblocks = mtd->eb_cnt;
+		reginfo.regionindex = 0;
+		print_region_map(mtd, fd, &reginfo);
+	}
+
+	if (fd != -1)
+		close(fd);
+}
+
 static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
 {
 	int err;
@@ -229,6 +343,8 @@ static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int
 	if (args.ubinfo)
 		print_ubi_info(mtd_info, &mtd);
 
+	print_region_info(&mtd);
+
 	printf("\n");
 	return 0;
 }
-- 
1.7.5.3



From computersforpeace at gmail.com  Wed Jun  8 16:01:24 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 8 Jun 2011 13:01:24 -0700
Subject: nanddump badblock options
Message-ID: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>

Hello,

I have some ideas to implement in nanddump regarding the variety of bad block
handling options. I thought I'd at least get some feedback before working up a
full patch, so please comment on my ideas.

(1) The comments in nandwrite say that nandwrite is an "inverse operation" to
nanddump. However, take, for example, the following command:

   nandwrite --length=131072 /dev/mtd1 myfile

Then, if we consider that there may be bad blocks at the beginning of the
device, nandwrite may skip to the second block in order to write this data.
Now, the default behavior of nanddump does not at all fit the "inverse" of this
very simple nandwrite operation. While you might expect the following to be an
inverse:

   nanddump --length=131072 /dev/mtd1 --file=myfile.dump

you in fact will not get the same data that you wrote from the original file.
Instead, you will get all 0xFF since by default nanddump substitutes 0xFF for
all the data of the bad block. I call this (unwanted) behavior `padding'.

Thus, in short, I'm recommending that nanddump default to using --skipbad as
a default option, with a new `padbad' option to cover the original behavior.
Perhaps the "default" nanddump should have a warning over a period of time,
before changing the default operation? See (3), Deprecation schedule.

(2) There are now (with my addition of `skipbad', and the current default
`padbad') four methods used for handling bad blocks we come across when dumping
flash data. I think they'd be cleaner if they were all grouped under a single
option that would work something like:

   --bb=METHOD

where METHOD could be `padbad', `dumpbad', `skipbad', and `omitbad'. Notice the
renaming of --noskipbad to --bb=dumpbad, since --noskipbad seems like an
inverse to --skipbad, which it is not. See (5), Summary table.

I think eventually, we would just drop both the short and long options for the
--omitbad, --noskipbad, and --skipbad options.

(3) Deprecation schedule:

Assuming the above is agreeable to everyone, how soon can we:
   * drop the --noskipbad, --skipbad, --omitbad (pluse -b, -k, -N) flags in
     favor of --bb=METHOD?
   * change the default behavior from `padbad' to `skipbad'?

I was thinkig the old methods (--omitbad, --noskipbad, --skipbad) should remain
for the time being, with a warning to tell of their deprecation/removal in next
release.

Additionally, we could perhaps include a warning when nanddump is called
without an explicit BB handling option, alerting users that the default will be
changing to --bb=skipbad in the next release.

(4) Can Mike provide a good explanation for --bb=omitbad in the table below? I
personally don't understand it's exact use, nor do I know how to describe it
best (to provide contrast against the other options), but I understand that you
would like to keep the option. I would appreciate some help.

(5) Summary table:

-----------------------------------------------------------------------------------------------------------------
 Old option         New option                   Comment
-----------------------------------------------------------------------------------------------------------------
 <default>     =>   --bb=padbad                  dump flash data, substituting 0xFF for any bad blocks
 --noskipbad   =>   --bb=dumpbad                 dump flash data, including any bad blocks
 --skipbad     =>   --bb=skipbad, <default>      dump good data, completely skipping any bad blocks (new default)
 --omitbad     =>   --bb=omitbad                 (dump flash data, substituting nothing for any bad blocks?)

Thanks,
Brian



From kmpark at infradead.org  Thu Jun  9 02:12:56 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Thu, 9 Jun 2011 15:12:56 +0900
Subject: [PATCH] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <1307539156.31223.69.camel@localhost>
References: <20110608015625.GA27537@july> <1307530994.31223.46.camel@localhost>
	<BANLkTinOBRUiaAGrbPcxve-EzZN3YdS__g@mail.gmail.com>
	<1307539156.31223.69.camel@localhost>
Message-ID: <BANLkTi=LJJTTr=SGmyfh3wDAvdg4+0SN3w@mail.gmail.com>

On Wed, Jun 8, 2011 at 10:19 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-08 at 22:21 +0900, Kyungmin Park wrote:
>> > 1. Add a comment that this is a hacky quirk to work around HW
>> > ? identification flaw, to make it clear for the people who read the
>> > ? code.
>>
>> For the record, chip maker (memory) made different chips for each
>> vendor (Samsung Mobile, and Nokia)
>> with the design flaw, it made a workaround, not hacky quirk.
>
> OK :-) Would you please send an updated patch ?

BTW, as you mentioned, it's already checked. DeviceID is just
capacity, I mean size is already checked and 4KiB pagesize is also
checked by numbufs... So check the version ID is enough in this case?

How do you think?

>
> --
> Best Regards,
> Artem Bityutskiy (????? ????????)
>
>


From dedekind1 at gmail.com  Thu Jun  9 02:19:23 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 09:19:23 +0300
Subject: [PATCH] mtdinfo: remove now unused ubigen info
In-Reply-To: <1307559148-28483-1-git-send-email-vapier@gentoo.org>
References: <1307559148-28483-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307600363.7374.1.camel@localhost>

On Wed, 2011-06-08 at 14:52 -0400, Mike Frysinger wrote:
> A previous commit moved the code using this var into a diff func.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  ubi-utils/src/mtdinfo.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)

Pushed, thanks you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 02:25:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 09:25:17 +0300
Subject: [PATCH v4] mtdinfo: add regioninfo/eraseblock map display
In-Reply-To: <1307560292-29595-1-git-send-email-vapier@gentoo.org>
References: <1307559742-29134-1-git-send-email-vapier@gentoo.org>
	<1307560292-29595-1-git-send-email-vapier@gentoo.org>
Message-ID: <1307600717.7374.2.camel@localhost>

On Wed, 2011-06-08 at 15:11 -0400, Mike Frysinger wrote:
> This brings the mtdinfo utility in line with the functionality
> of the flash_info utility.  It dumps the erase regioninfo (if
> the devices has it) as well as showing a handy eraseblock map
> (if the user has requested it).  The eraseblock map also shows
> which blocks are locked and which ones are bad.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
> v4
> 	- still show region info when map isn't requested
> 

Looks good, quick test with nandsim also looks good, pushed, thanks a
lot!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 02:40:57 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 09:40:57 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307601657.7374.9.camel@localhost>

On Wed, 2011-06-08 at 11:25 -0700, Brian Norris wrote:
> Also fix some punctuation, indentation, and capitalization that went
> along with the affected lines.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  drivers/mtd/nand/nand_base.c |   65 ++++++++++++++++++++----------------------
>  drivers/mtd/nand/nand_bbt.c  |   39 ++++++++++++-------------
>  2 files changed, 50 insertions(+), 54 deletions(-)
> 

Pushed with few tweaks, thanks!

>  	if (id_data[0] != *maf_id || id_data[1] != *dev_id) {
> -		printk(KERN_INFO "%s: second ID read did not match "
> +		pr_info("%s: second ID read did not match "
>  		       "%02x,%02x against %02x,%02x\n", __func__,
>  		       *maf_id, *dev_id, id_data[0], id_data[1]);

This was not properly aligned - I've aligned it:

                pr_info("%s: second ID read did not match "
                        "%02x,%02x against %02x,%02x\n", __func__,
                        *maf_id, *dev_id, id_data[0], id_data[1]);


>  		return ERR_PTR(-ENODEV);
> @@ -3068,10 +3067,10 @@ ident_done:
>  	 * chip correct!
>  	 */
>  	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
> -		printk(KERN_INFO "NAND device: Manufacturer ID:"
> +		pr_info("NAND device: Manufacturer ID:"
>  		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
>  		       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
> -		printk(KERN_WARNING "NAND bus width %d instead %d bit\n",
> +		pr_warning("NAND bus width %d instead %d bit\n",
>  		       (chip->options & NAND_BUSWIDTH_16) ? 16 : 8,
>  		       busw ? 16 : 8);

And this, I've changed it:

                pr_info("NAND device: Manufacturer ID:"
                        " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
                        *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
                pr_warning("NAND bus width %d instead %d bit\n",
                           (chip->options & NAND_BUSWIDTH_16) ? 16 : 8, 
                           busw ? 16 : 8);


> -					printk(KERN_DEBUG "nand_read_bbt: Reserved block at 0x%012llx\n",
> +					pr_debug("nand_read_bbt: Reserved block at 0x%012llx\n",
>  					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
>  					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
>  					mtd->ecc_stats.bbtblocks++;
> @@ -229,7 +229,7 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
>  				 * Leave it for now, if it's matured we can
>  				 * move this message to MTD_DEBUG_LEVEL0.
>  				 */
> -				printk(KERN_DEBUG "nand_read_bbt: Bad block at 0x%012llx\n",
> +				pr_debug("nand_read_bbt: Bad block at 0x%012llx\n",
>  				       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);

Here I aligned lines too. They are also quite long, but that would need
to put this piece of code to a separate function, which is a different
story.

>  				/* Factory marked bad or worn out? */
>  				if (tmp == 0)
> @@ -383,7 +383,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
>  		scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
>  			      mtd->writesize, td);
>  		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
> -		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
> +		pr_debug("Bad block table at page %d, version 0x%02X\n",
>  		       td->pages[0], td->version[0]);

Was not aligned.

>  	}
>  
> @@ -392,7 +392,7 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
>  		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
>  			      mtd->writesize, td);
>  		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
> -		printk(KERN_DEBUG "Bad block table at page %d, version 0x%02X\n",
> +		pr_debug("Bad block table at page %d, version 0x%02X\n",
>  		       md->pages[0], md->version[0]);

Was not aligned.

> +			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
>  			       chip + 1, this->numchips);

And this and other, I amended them.


> +					pr_info("nand_bbt: Error "
>  					       "reading block for writing "
>  					       "the bad block table\n");
>  					return res;
>  				}
> -				printk(KERN_WARNING "nand_bbt: ECC error "
> +				pr_warn("nand_bbt: ECC error "
>  				       "while reading block for writing "
>  				       "bad block table\n");

Tweaked these 2.

Plus some other minor tweaks.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 02:46:37 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 09:46:37 +0300
Subject: [PATCH v2 3/4] mtd: nand: replace DEBUG() with dev_dbg()
In-Reply-To: <1307557650-31323-1-git-send-email-computersforpeace@gmail.com>
References: <1307544295.31223.116.camel@localhost>
	<1307557650-31323-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307601997.7374.10.camel@localhost>

On Wed, 2011-06-08 at 11:27 -0700, Brian Norris wrote:
> +               dev_dbg(&mtd->dev, "%s: error status = 0x%08x\n",
>                                         __func__, status); 

Aligned things like this and pushed, thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 02:53:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 09:53:08 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307602388.7374.13.camel@localhost>

On Wed, 2011-06-08 at 11:25 -0700, Brian Norris wrote:
> -		printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
> +		pr_debug("Bad block table written to 0x%012llx, version "
>  		       "0x%02X\n", (unsigned long long)to, td->version[chip]);

Hmm, the side effect of this change is this message will disappear if
DEBUG is undefined / dynamic debugging is disabled.

So I think we need to change all these pr_debug to pr_info, because this
is really just info.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 02:59:48 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 09:59:48 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307602388.7374.13.camel@localhost>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307602388.7374.13.camel@localhost>
Message-ID: <1307602788.7374.15.camel@localhost>

On Thu, 2011-06-09 at 09:53 +0300, Artem Bityutskiy wrote:
> On Wed, 2011-06-08 at 11:25 -0700, Brian Norris wrote:
> > -		printk(KERN_DEBUG "Bad block table written to 0x%012llx, version "
> > +		pr_debug("Bad block table written to 0x%012llx, version "
> >  		       "0x%02X\n", (unsigned long long)to, td->version[chip]);
> 
> Hmm, the side effect of this change is this message will disappear if
> DEBUG is undefined / dynamic debugging is disabled.
> 
> So I think we need to change all these pr_debug to pr_info, because this
> is really just info.

I've pushed the following patch on top, is this OK with you?


From Artem.Bityutskiy at nokia.com  Thu Jun  9 03:03:26 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Thu, 9 Jun 2011 10:03:26 +0300
Subject: [PATCH] mtd: nand_bbt: turn pr_debug into pr_info
Message-ID: <mailman.12.1307603051.24103.linux-mtd@lists.infradead.org>

In the previous patch we changed all "prink(KERN_DEBUG" messages with
"pr_debug()", which means that the messages will now disappear unless
they are explicitly enabled with DEBUG macro and dynamic debugging means.

But if you look at those messages, they are information messages like "bad
block table found or re-written", so we do want to see them. This patch turns
those messages into 'pr_info()'.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 drivers/mtd/nand/nand_bbt.c |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index a1e51dc..e3b0d62 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -219,14 +219,14 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
 				if (tmp == msk)
 					continue;
 				if (reserved_block_code && (tmp == reserved_block_code)) {
-					pr_debug("nand_read_bbt: reserved block at 0x%012llx\n",
-						 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+					pr_info("nand_read_bbt: reserved block at 0x%012llx\n",
+						(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 					this->bbt[offs + (act >> 3)] |= 0x2 << (act & 0x06);
 					mtd->ecc_stats.bbtblocks++;
 					continue;
 				}
-				pr_debug("nand_read_bbt: bad block at 0x%012llx\n",
-					 (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
+				pr_info("nand_read_bbt: bad block at 0x%012llx\n",
+					(loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);
 				/* Factory marked bad or worn out? */
 				if (tmp == 0)
 					this->bbt[offs + (act >> 3)] |= 0x3 << (act & 0x06);
@@ -379,8 +379,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)td->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		td->version[0] = buf[bbt_get_ver_offs(mtd, td)];
-		pr_debug("Bad block table at page %d, version 0x%02X\n",
-			 td->pages[0], td->version[0]);
+		pr_info("Bad block table at page %d, version 0x%02X\n",
+			td->pages[0], td->version[0]);
 	}
 
 	/* Read the mirror version, if available */
@@ -388,8 +388,8 @@ static int read_abs_bbts(struct mtd_info *mtd, uint8_t *buf,
 		scan_read_raw(mtd, buf, (loff_t)md->pages[0] << this->page_shift,
 			      mtd->writesize, td);
 		md->version[0] = buf[bbt_get_ver_offs(mtd, md)];
-		pr_debug("Bad block table at page %d, version 0x%02X\n",
-			 md->pages[0], md->version[0]);
+		pr_info("Bad block table at page %d, version 0x%02X\n",
+			md->pages[0], md->version[0]);
 	}
 	return 1;
 }
@@ -492,7 +492,7 @@ static int create_bbt(struct mtd_info *mtd, uint8_t *buf,
 	} else {
 		if (chip >= this->numchips) {
 			pr_warn("create_bbt(): chipnr (%d) > available chips (%d)\n",
-			       chip + 1, this->numchips);
+				chip + 1, this->numchips);
 			return -EINVAL;
 		}
 		numblocks = this->chipsize >> (this->bbt_erase_shift - 1);
@@ -605,8 +605,8 @@ static int search_bbt(struct mtd_info *mtd, uint8_t *buf, struct nand_bbt_descr
 		if (td->pages[i] == -1)
 			pr_warn("Bad block table not found for chip %d\n", i);
 		else
-			pr_debug("Bad block table found at page %d, version "
-				 "0x%02X\n", td->pages[i], td->version[i]);
+			pr_info("Bad block table found at page %d, version "
+				"0x%02X\n", td->pages[i], td->version[i]);
 	}
 	return 0;
 }
@@ -834,8 +834,8 @@ static int write_bbt(struct mtd_info *mtd, uint8_t *buf,
 		if (res < 0)
 			goto outerr;
 
-		pr_debug("Bad block table written to 0x%012llx, version 0x%02X\n",
-			 (unsigned long long)to, td->version[chip]);
+		pr_info("Bad block table written to 0x%012llx, version 0x%02X\n",
+			(unsigned long long)to, td->version[chip]);
 
 		/* Mark it as used */
 		td->pages[chip] = page;
-- 
1.7.2.3


-- 
Best Regards,
Artem Bityutskiy (?????????? ????????????????)



From dedekind1 at gmail.com  Thu Jun  9 03:10:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 10:10:49 +0300
Subject: [PATCH v2 4/4] mtd: nand: define pr_fmt() to include __func__
	in debug output
In-Reply-To: <1307557708-31376-1-git-send-email-computersforpeace@gmail.com>
References: <BANLkTi=7Xivud_V=uMadL1BA-1ZC7V9RYw@mail.gmail.com>
	<1307557708-31376-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307603449.7374.22.camel@localhost>

On Wed, 2011-06-08 at 11:28 -0700, Brian Norris wrote:
> Also fix some capitalization that went along with the affected lines.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

Thinking about this some more, I do not think it is good idea to
automatically prefix all messages with function name. In many cases this
just makes the kernel binary size larger without a real need.

> -				pr_info("nand_bbt: Error reading bad block table\n");
> +				pr_info("error reading bad block table\n");

Is nand_bbt: really needed here? May be this is not obvious, but isn't
this message unique anyway?

Well, this should be  pr_err(), because this is an error message :-) A
separate pass via all pr_* WRT this aspect would be nice.

>  				return res;
>  			}
> -			pr_warn("nand_bbt: ECC error while reading bad block table\n");
> +			pr_warn("ECC error while reading bad block table\n");

Is nand_bbt: really needed here?

>  		}
>  
>  		/* Analyse data */
> @@ -219,13 +221,13 @@ static int read_bbt(struct mtd_info *mtd, uint8_t *buf, int page, int num,
>  				if (tmp == msk)
>  					continue;
>  				if (reserved_block_code && (tmp == reserved_block_code)) {
> -					pr_debug("nand_read_bbt: Reserved block at 0x%012llx\n",
> +					pr_debug("reserved block at 0x%012llx\n",
>  					       (loff_t)((offs << 2) + (act >> 1)) << this->bbt_erase_shift);

OK, I turned this to pr_info, because this is not a debugging message.
And I do not think the function prefix is needed, I can grep the kernel
to find  it.

And really, in most places the function prefix is not needed.

In general, I think the function prefix is only needed in debugging
messages - dev_dbg() ones. All the other places should not require it in
most of the cases.

I'd do the following clean-ups instead:

1. Go through all messages and see if they are of proper level
(info/error/warning).
2. Go through all messages and thing if the function name prefix brings
   any value or only makes the kernel binary size larger.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 03:20:39 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 10:20:39 +0300
Subject: [PATCH 01/43] mtd: add new API for handling MTD registration
In-Reply-To: <1307549152-7085-2-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
	<1307549152-7085-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307604039.7374.30.camel@localhost>

On Wed, 2011-06-08 at 20:05 +0400, Dmitry Eremin-Solenikov wrote:
> Lots (nearly all) mtd drivers contain nearly the similar code that
> calls parse_mtd_partitions, provides some platform-default values, if
> parsing fails, and registers  mtd device.
> 
> This is an aim to provide single implementation of this scenario:
> mtd_device_parse_register() which will handle all this parsing and
> defaults.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/mtdcore.c   |   60 +++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mtd/mtd.h |    5 ++++
>  2 files changed, 65 insertions(+), 0 deletions(-)

I've re-formatted comments - removed no-so-nice-looking tabs, made lines
longer because (my vim can do this). And pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 03:24:22 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 10:24:22 +0300
Subject: [PATCH 08/43] mtd: impa7.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-9-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
	<1307549152-7085-9-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307604262.7374.33.camel@localhost>

On Wed, 2011-06-08 at 20:05 +0400, Dmitry Eremin-Solenikov wrote:
> -			mtd_device_register(impa7_mtd[i],
> -					    mtd_parts[i], mtd_parts_nb[i]);
> +			mtd_device_parse_register(impa7_mtd[i], NULL, 0,
> +					static_partitions,
> +					ARRAY_SIZE(static_partitions));
>  		}

Compare the alignment - original file is aligned with tabs and then few
spaces (the way I prefer), you use only tabs, which is not consistent
with this driver's style. But I'll amend this myself :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 03:32:32 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 10:32:32 +0300
Subject: [PATCH 14/43] mtd: physmap.c: use mtd_device_parse_register
In-Reply-To: <1307549152-7085-15-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
	<1307549152-7085-15-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307604752.7374.34.camel@localhost>

On Wed, 2011-06-08 at 20:05 +0400, Dmitry Eremin-Solenikov wrote:
> -	if (physmap_data->nr_parts) {
> -		printk(KERN_NOTICE "Using physmap partition information\n");
> -		mtd_device_register(info->cmtd, physmap_data->parts,
> -				    physmap_data->nr_parts);
> -		return 0;
> -	}
> -
> -	mtd_device_register(info->cmtd, NULL, 0);
> -
> +	mtd_device_parse_register(info->cmtd, part_probe_types, 0,
> +			physmap_data->parts, physmap_data->nr_parts);

Same here.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 03:44:16 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 10:44:16 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307605456.7374.35.camel@localhost>

On Wed, 2011-06-08 at 11:25 -0700, Brian Norris wrote:
> Also fix some punctuation, indentation, and capitalization that went
> along with the affected lines.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  drivers/mtd/nand/nand_base.c |   65 ++++++++++++++++++++----------------------
>  drivers/mtd/nand/nand_bbt.c  |   39 ++++++++++++-------------
>  2 files changed, 50 insertions(+), 54 deletions(-)
> 
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index 019187b..7550cea 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -2167,8 +2167,8 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
>  
>  	/* Reject writes, which are not page aligned */
>  	if (NOTALIGNED(to) || NOTALIGNED(ops->len)) {
> -		printk(KERN_NOTICE "%s: Attempt to write not "
> -				"page aligned data\n", __func__);
> +		pr_notice("%s: attempt to write non page aligned data\n",
> +			   __func__);
>  		return -EINVAL;

Wait, and why are we using pr_* while it is better to use dbg_* ? :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 03:56:27 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 10:56:27 +0300
Subject: [PATCH 0/43 V2] mtd: simplify mtd partitions handling
In-Reply-To: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307606187.7374.36.camel@localhost>

On Wed, 2011-06-08 at 20:05 +0400, Dmitry Eremin-Solenikov wrote:
> Lots of mtd drivers have more or less the same common logic:
> parse partitions, then register them. Currently this ends up
> with lots of code duplication, each copy having it's own features
> and bugs. In this patch serie I create a special function
> (mtd_device_parse_register) which handles all issues with acquiring
> partition information, registering mtd device(s) and returning correct
> error code.
> 
> Changes since V1:
> - Added kerneldoc for mtd_device_parse_register
> - removed lart.c patch (wrong commit message)
> - dropped call to mtd_device_register from rbtx4939-flash
> - small fixes within patches
> 
> The following changes since commit 1dc1d90aa53e6cec61f5369b6d1e185b3ef40c14:
> 
>   mtd: davinci_nand: remove redundant mtd_device_unregister (2011-06-08 18:00:41 +0300)
> 
> are available in the git repository at:
>   git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-parse-1st-2

Pushed the series with minor tweaks to l2-mtd-2.6.git, thank you!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From marc.zyngier at arm.com  Thu Jun  9 04:01:18 2011
From: marc.zyngier at arm.com (Marc Zyngier)
Date: Thu, 09 Jun 2011 09:01:18 +0100
Subject: ARM: 6910/1: MTD: physmap: let set_vpp() pass a platform_device
	instead of a map_info
In-Reply-To: <BANLkTim1=DBd1AvPw1VuPfGi_Z5ktAhyPg@mail.gmail.com>
References: <201105240059.p4O0xPfN009516@hera.kernel.org>
	<BANLkTim1=DBd1AvPw1VuPfGi_Z5ktAhyPg@mail.gmail.com>
Message-ID: <4DF07DCE.60707@arm.com>

On 08/06/11 19:53, Geert Uytterhoeven wrote:

Hi Geert,

> On Tue, May 24, 2011 at 02:59, Linux Kernel Mailing List
> <linux-kernel at vger.kernel.org> wrote:
>>    ARM: 6910/1: MTD: physmap: let set_vpp() pass a platform_device instead of a map_info
>>
>>    The set_vpp() method provided by physmap passes a map_info back to
>>    the platform code, which has little relevance as far as the platform
>>    is concerned (this parameter is completely unused).
>>
>>    Instead, pass the platform_device, which can be used in the pismo
>>    driver to retrieve some important information in a nicer way, instead
>>    of the hack that was in place.
>>
>>    The empty set_vpp function in board-at572d940hf_ek.c is left untouched,
>>    as the board/SoC is scheduled for removal.
>>
>>    Cc: Andrew Victor <linux at maxim.org.za>
>>    Cc: Nicolas Ferre <nicolas.ferre at atmel.com>
>>    Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>
>>    Cc: Philipp Zabel <philipp.zabel at gmail.com>
>>    Cc: Eric Miao <eric.y.miao at gmail.com>
>>    Cc: Ben Dooks <ben-linux at fluff.org>
>>    Acked-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
>>    Acked-by: David Woodhouse <dwmw2 at infradead.org>
>>    Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
>>    Signed-off-by: Russell King <rmk+kernel at arm.linux.org.uk>
> 
>> --- a/include/linux/mtd/physmap.h
>> +++ b/include/linux/mtd/physmap.h
>> @@ -24,7 +24,7 @@ struct physmap_flash_data {
>>        unsigned int            width;
>>        int                     (*init)(struct platform_device *);
>>        void                    (*exit)(struct platform_device *);
>> -       void                    (*set_vpp)(struct map_info *, int);
>> +       void                    (*set_vpp)(struct platform_device *, int);
>>        unsigned int            nr_parts;
>>        unsigned int            pfow_base;
>>        char                    *probe_type;
> 
> You forgot to update the set_vpp parameter of physmap_configure():
> 
> void physmap_configure(unsigned long addr, unsigned long size,
>                 int bankwidth, void (*set_vpp)(struct map_info *, int) );
> 
> causing
> 
> drivers/mtd/maps/physmap.c: In function ?physmap_configure?:
> drivers/mtd/maps/physmap.c:255: warning: assignment from incompatible
> pointer type
> 
> Interestingly, there are no (in-tree) users of physmap_configure()?

It's already been removed in -next:

commit 3b1b2b07088ed190090f0b1973416b6c8e49a2a1
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Thu Jun 2 18:51:14 2011 +0400

    mtd: drop physmap_configure

    physmap_configure() and physmap_set_partitions() have no users in
kernel.
    Out of kernel users should have been converted to regular platform
device
    long ago. Drop support for this obsolete API.

    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Maybe this should be merged to -rc3.

Thanks for the heads up.

	M.
-- 
Jazz is not dead. It just smells funny...



From dedekind1 at gmail.com  Thu Jun  9 04:13:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 11:13:14 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307607194.7374.49.camel@localhost>

Brian, would you please send a new series? I suggest you the following
order of things.

1. clean-up of non-DEBUG() messages.
   1.1. go through all printks and check if KERN_* is ok, fix. E.g.,
        I can see that all KERN_DEBUG should become KERN_INFO
   1.2. go through all printks and check if the function name prefix
        makes sense there - kill those which do not.

   Also, while doing this, keep in mind that messages will be later
   turned into dev_* (dev_info(), dev_err(), etc) so they will be
   automatically prefixed with the device name which is already some
   identification of the source of the message.

   1.3. turn messages to dev_*
   1.4. make another pass and do all the lines consolidations,
        alignments, punctuation, etc etc.

2. clean-up of DEBUG() cruft.
   2.1 change DEBUG() with dev_dbg()

   Kill all function name prefixes as well. The rationale is: dev_dbg()
   already adds function name prefixe (and process id) if dynamic
   debugging is enabled. In case of debugging with DEBUG macro, you
   anyway have to change the code (adding #define DEBUG) so you might
   easily defind pr_fmt at the same time for youself.

How does this sound to you?

FWIW: I've moved the patches I pushed from the master branch to the
"brian" branch of l2-mtd-2.6.git tree. But they will not be useful
for you, I guess.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 04:16:23 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 11:16:23 +0300
Subject: [PATCH] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <BANLkTi=LJJTTr=SGmyfh3wDAvdg4+0SN3w@mail.gmail.com>
References: <20110608015625.GA27537@july> <1307530994.31223.46.camel@localhost>
	<BANLkTinOBRUiaAGrbPcxve-EzZN3YdS__g@mail.gmail.com>
	<1307539156.31223.69.camel@localhost>
	<BANLkTi=LJJTTr=SGmyfh3wDAvdg4+0SN3w@mail.gmail.com>
Message-ID: <1307607383.7374.50.camel@localhost>

On Thu, 2011-06-09 at 15:12 +0900, Kyungmin Park wrote:
> BTW, as you mentioned, it's already checked. DeviceID is just
> capacity, I mean size is already checked and 4KiB pagesize is also
> checked by numbufs... So check the version ID is enough in this case?

Probably yes.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Thu Jun  9 04:23:28 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 9 Jun 2011 12:23:28 +0400
Subject: [PATCH 0/43 V2] mtd: simplify mtd partitions handling
In-Reply-To: <1307606187.7374.36.camel@localhost>
References: <1307549152-7085-1-git-send-email-dbaryshkov@gmail.com>
	<1307606187.7374.36.camel@localhost>
Message-ID: <BANLkTi=hTm8QTnRwfmxHasDjYCRjoPGt-Q@mail.gmail.com>

On 6/9/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-08 at 20:05 +0400, Dmitry Eremin-Solenikov wrote:
>> Lots of mtd drivers have more or less the same common logic:
>> parse partitions, then register them. Currently this ends up
>> with lots of code duplication, each copy having it's own features
>> and bugs. In this patch serie I create a special function
>> (mtd_device_parse_register) which handles all issues with acquiring
>> partition information, registering mtd device(s) and returning correct
>> error code.
>>
>> Changes since V1:
>> - Added kerneldoc for mtd_device_parse_register
>> - removed lart.c patch (wrong commit message)
>> - dropped call to mtd_device_register from rbtx4939-flash
>> - small fixes within patches
>>
>> The following changes since commit
>> 1dc1d90aa53e6cec61f5369b6d1e185b3ef40c14:
>>
>>   mtd: davinci_nand: remove redundant mtd_device_unregister (2011-06-08
>> 18:00:41 +0300)
>>
>> are available in the git repository at:
>>   git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-parse-1st-2
>
> Pushed the series with minor tweaks to l2-mtd-2.6.git, thank you!

Thank you!

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Thu Jun  9 04:26:44 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 11:26:44 +0300
Subject: nanddump badblock options
In-Reply-To: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1307608004.7374.56.camel@localhost>

Hi,

On Wed, 2011-06-08 at 13:01 -0700, Brian Norris wrote:
> I have some ideas to implement in nanddump regarding the variety of bad block
> handling options. I thought I'd at least get some feedback before working up a
> full patch, so please comment on my ideas.
> 
> (1) The comments in nandwrite say that nandwrite is an "inverse operation" to
> nanddump. However, take, for example, the following command:
> 
>    nandwrite --length=131072 /dev/mtd1 myfile
> 
> Then, if we consider that there may be bad blocks at the beginning of the
> device, nandwrite may skip to the second block in order to write this data.
> Now, the default behavior of nanddump does not at all fit the "inverse" of this
> very simple nandwrite operation. While you might expect the following to be an
> inverse:
> 
>    nanddump --length=131072 /dev/mtd1 --file=myfile.dump
> 
> you in fact will not get the same data that you wrote from the original file.
> Instead, you will get all 0xFF since by default nanddump substitutes 0xFF for
> all the data of the bad block. I call this (unwanted) behavior `padding'.
> 
> Thus, in short, I'm recommending that nanddump default to using --skipbad as
> a default option, with a new `padbad' option to cover the original behavior.
> Perhaps the "default" nanddump should have a warning over a period of time,
> before changing the default operation? See (3), Deprecation schedule.

Sounds good to me.

> (2) There are now (with my addition of `skipbad', and the current default
> `padbad') four methods used for handling bad blocks we come across when dumping
> flash data. I think they'd be cleaner if they were all grouped under a single
> option that would work something like:
> 
>    --bb=METHOD
> 
> where METHOD could be `padbad', `dumpbad', `skipbad', and `omitbad'. Notice the
> renaming of --noskipbad to --bb=dumpbad, since --noskipbad seems like an
> inverse to --skipbad, which it is not. See (5), Summary table.
> 
> I think eventually, we would just drop both the short and long options for the
> --omitbad, --noskipbad, and --skipbad options.
> 
> (3) Deprecation schedule:
> 
> Assuming the above is agreeable to everyone, how soon can we:
>    * drop the --noskipbad, --skipbad, --omitbad (pluse -b, -k, -N) flags in
>      favor of --bb=METHOD?
>    * change the default behavior from `padbad' to `skipbad'?

As soon as you implement this stuff and we push it, then one release
with warnings, next release we can remove that stuff. We already have
many changes, but I can wait for yours, then we release mtd-1.4.5, and
then we can kill the options next day.

> I was thinkig the old methods (--omitbad, --noskipbad, --skipbad) should remain
> for the time being, with a warning to tell of their deprecation/removal in next
> release.
> 
> Additionally, we could perhaps include a warning when nanddump is called
> without an explicit BB handling option, alerting users that the default will be
> changing to --bb=skipbad in the next release.

Yes.

> (4) Can Mike provide a good explanation for --bb=omitbad in the table below? I
> personally don't understand it's exact use, nor do I know how to describe it
> best (to provide contrast against the other options), but I understand that you
> would like to keep the option. I would appreciate some help.
> 
> (5) Summary table:
> 
> -----------------------------------------------------------------------------------------------------------------
>  Old option         New option                   Comment
> -----------------------------------------------------------------------------------------------------------------
>  <default>     =>   --bb=padbad                  dump flash data, substituting 0xFF for any bad blocks
>  --noskipbad   =>   --bb=dumpbad                 dump flash data, including any bad blocks
>  --skipbad     =>   --bb=skipbad, <default>      dump good data, completely skipping any bad blocks (new default)
>  --omitbad     =>   --bb=omitbad                 (dump flash data, substituting nothing for any bad blocks?)

Hmm...

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Thu Jun  9 04:34:19 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 9 Jun 2011 12:34:19 +0400
Subject: Question reg. parsing of mtd partitions
Message-ID: <20110609083419.GA23553@doriath.ww600.siemens.net>

Hello, colleagues,

While doing MTD partitions cleanup I noticed one strange thing.
parse_mtd_partitions function bears one extra argument (origin)
which isn't clearly described, set to non-zero only by ixp4xx.c
driver and then read by redboot partition table handling. I wander if we
can add some other way to handle this situation and drop this extra 0
argument from lots of drivers/handlers/etc.

Could you please check it?

-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Thu Jun  9 05:04:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:40 +0300
Subject: [PATCH 00/30] UBIFS: latest patches
Message-ID: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Hi,

here are latest UBIFS patches. Most of them are about cleaning up debugging
stuff and switching to debugfs knobs.

Artem.


From dedekind1 at gmail.com  Thu Jun  9 05:04:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:47 +0300
Subject: [PATCH 07/30] UBIFS: remove unnecessary brackets
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-8-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Remove unnecessary brackets in "inode->i_flags |= (S_NOCMTIME)" statement to
make the code not look silly.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/dir.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index ef5abd3..c6cbdd0 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -102,7 +102,7 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
 	 * UBIFS has to fully control "clean <-> dirty" transitions of inodes
 	 * to make budgeting work.
 	 */
-	inode->i_flags |= (S_NOCMTIME);
+	inode->i_flags |= S_NOCMTIME;
 
 	inode_init_owner(inode, dir, mode);
 	inode->i_mtime = inode->i_atime = inode->i_ctime =
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:49 +0300
Subject: [PATCH 09/30] UBIFS: harmonize znode flag helpers
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-10-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

We have 3 znode flags: cow, obsolete, dirty. For the last flag we have a
'ubifs_zn_dirty()' helper function, but for the other 2 flags we use
'test_bit()' directly.

This patch makes the situation more consistent and introduces helpers for the
other 2 flags: 'ubifs_zn_cow()' and 'ubifs_zn_obsolete()'.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/commit.c     |    2 +-
 fs/ubifs/misc.h       |   23 +++++++++++++++++++++++
 fs/ubifs/tnc.c        |   13 ++++++-------
 fs/ubifs/tnc_commit.c |    8 ++++----
 4 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 8ab03d1..637e076 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -78,7 +78,7 @@ static int nothing_to_commit(struct ubifs_info *c)
 	 * If the root TNC node is dirty, we definitely have something to
 	 * commit.
 	 */
-	if (c->zroot.znode && test_bit(DIRTY_ZNODE, &c->zroot.znode->flags))
+	if (c->zroot.znode && ubifs_zn_dirty(c->zroot.znode))
 		return 0;
 
 	/*
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 0b5296a..160cd90 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -39,6 +39,29 @@ static inline int ubifs_zn_dirty(const struct ubifs_znode *znode)
 }
 
 /**
+ * ubifs_zn_obsolete - check if znode is obsolete.
+ * @znode: znode to check
+ *
+ * This helper function returns %1 if @znode is obsolete and %0 otherwise.
+ */
+static inline int ubifs_zn_obsolete(const struct ubifs_znode *znode)
+{
+	return !!test_bit(OBSOLETE_ZNODE, &znode->flags);
+}
+
+/**
+ * ubifs_zn_cow - check if znode has to be copied on write.
+ * @znode: znode to check
+ *
+ * This helper function returns %1 if @znode is has COW flag set and %0
+ * otherwise.
+ */
+static inline int ubifs_zn_cow(const struct ubifs_znode *znode)
+{
+	return !!test_bit(COW_ZNODE, &znode->flags);
+}
+
+/**
  * ubifs_wake_up_bgt - wake up background thread.
  * @c: UBIFS file-system description object
  */
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 48b6ee6..b32a537 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -223,7 +223,7 @@ static struct ubifs_znode *copy_znode(struct ubifs_info *c,
 	__set_bit(DIRTY_ZNODE, &zn->flags);
 	__clear_bit(COW_ZNODE, &zn->flags);
 
-	ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+	ubifs_assert(!ubifs_zn_obsolete(znode));
 	__set_bit(OBSOLETE_ZNODE, &znode->flags);
 
 	if (znode->level != 0) {
@@ -271,7 +271,7 @@ static struct ubifs_znode *dirty_cow_znode(struct ubifs_info *c,
 	struct ubifs_znode *zn;
 	int err;
 
-	if (!test_bit(COW_ZNODE, &znode->flags)) {
+	if (!ubifs_zn_cow(znode)) {
 		/* znode is not being committed */
 		if (!test_and_set_bit(DIRTY_ZNODE, &znode->flags)) {
 			atomic_long_inc(&c->dirty_zn_cnt);
@@ -2423,7 +2423,7 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
 	 */
 
 	do {
-		ubifs_assert(!test_bit(OBSOLETE_ZNODE, &znode->flags));
+		ubifs_assert(!ubifs_zn_obsolete(znode));
 		ubifs_assert(ubifs_zn_dirty(znode));
 
 		zp = znode->parent;
@@ -2479,9 +2479,8 @@ static int tnc_delete(struct ubifs_info *c, struct ubifs_znode *znode, int n)
 			c->zroot.offs = zbr->offs;
 			c->zroot.len = zbr->len;
 			c->zroot.znode = znode;
-			ubifs_assert(!test_bit(OBSOLETE_ZNODE,
-				     &zp->flags));
-			ubifs_assert(test_bit(DIRTY_ZNODE, &zp->flags));
+			ubifs_assert(!ubifs_zn_obsolete(zp));
+			ubifs_assert(ubifs_zn_dirty(zp));
 			atomic_long_dec(&c->dirty_zn_cnt);
 
 			if (zp->cnext) {
@@ -2865,7 +2864,7 @@ static void tnc_destroy_cnext(struct ubifs_info *c)
 		struct ubifs_znode *znode = cnext;
 
 		cnext = cnext->cnext;
-		if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+		if (ubifs_zn_obsolete(znode))
 			kfree(znode);
 	} while (cnext && cnext != c->cnext);
 }
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index 8315387..f50c3e5 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -87,7 +87,7 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
 	atomic_long_dec(&c->dirty_zn_cnt);
 
 	ubifs_assert(ubifs_zn_dirty(znode));
-	ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
+	ubifs_assert(ubifs_zn_cow(znode));
 
 	__clear_bit(DIRTY_ZNODE, &znode->flags);
 	__clear_bit(COW_ZNODE, &znode->flags);
@@ -639,7 +639,7 @@ static int get_znodes_to_commit(struct ubifs_info *c)
 	}
 	cnt += 1;
 	while (1) {
-		ubifs_assert(!test_bit(COW_ZNODE, &znode->flags));
+		ubifs_assert(!ubifs_zn_cow(znode));
 		__set_bit(COW_ZNODE, &znode->flags);
 		znode->alt = 0;
 		cnext = find_next_dirty(znode);
@@ -888,7 +888,7 @@ static int write_index(struct ubifs_info *c)
 		cnext = znode->cnext;
 
 		ubifs_assert(ubifs_zn_dirty(znode));
-		ubifs_assert(test_bit(COW_ZNODE, &znode->flags));
+		ubifs_assert(ubifs_zn_cow(znode));
 
 		/*
 		 * It is important that other threads should see %DIRTY_ZNODE
@@ -983,7 +983,7 @@ static void free_obsolete_znodes(struct ubifs_info *c)
 	do {
 		znode = cnext;
 		cnext = znode->cnext;
-		if (test_bit(OBSOLETE_ZNODE, &znode->flags))
+		if (ubifs_zn_obsolete(znode))
 			kfree(znode);
 		else {
 			znode->cnext = NULL;
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:46 +0300
Subject: [PATCH 06/30] UBIFS: minor cleanup: use S_ISREG helper
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-7-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Instead of using long "(inode->i_mode & S_IFMT) != S_IFREG" expression, use
shorted "!S_ISREG(inode->i_mode)".

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/super.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 55161c6..70e8c92 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -85,7 +85,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
 	if (ui->data_len < 0 || ui->data_len > UBIFS_MAX_INO_DATA)
 		return 4;
 
-	if (ui->xattr && (inode->i_mode & S_IFMT) != S_IFREG)
+	if (ui->xattr && !S_ISREG(inode->i_mode))
 		return 5;
 
 	if (!ubifs_compr_present(ui->compr_type)) {
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:43 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:43 +0300
Subject: [PATCH 03/30] UBIFS: dump stack when pnode or nnode reading fails
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-4-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

When we fail to read a pnode or nnode - print stacktrace if debugging is enabled.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/lpt.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index ef5155e..04713cd 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1247,6 +1247,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 
 out:
 	ubifs_err("error %d reading nnode at %d:%d", err, lnum, offs);
+	dbg_dump_stack();
 	kfree(nnode);
 	return err;
 }
@@ -1312,6 +1313,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 out:
 	ubifs_err("error %d reading pnode at %d:%d", err, lnum, offs);
 	dbg_dump_pnode(c, pnode, parent, iip);
+	dbg_dump_stack();
 	dbg_msg("calc num: %d", calc_pnode_num_from_parent(c, parent, iip));
 	kfree(pnode);
 	return err;
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:41 +0300
Subject: [PATCH 01/30] UBIFS: return EROFS in case of broken commit
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-2-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

If commit failed and it is in broken state, UBIFS switches to R/O mode. Most
operations return -EROFS in this case, except of commit which returns -EINVAL.
Make it return -EROFS too for consistency. This is also important for our power
cut emulation testing.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/commit.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 87cd0ea..8ab03d1 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -418,7 +418,7 @@ int ubifs_run_commit(struct ubifs_info *c)
 
 	spin_lock(&c->cs_lock);
 	if (c->cmt_state == COMMIT_BROKEN) {
-		err = -EINVAL;
+		err = -EROFS;
 		goto out;
 	}
 
@@ -444,7 +444,7 @@ int ubifs_run_commit(struct ubifs_info *c)
 	 * re-check it.
 	 */
 	if (c->cmt_state == COMMIT_BROKEN) {
-		err = -EINVAL;
+		err = -EROFS;
 		goto out_cmt_unlock;
 	}
 
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:45 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:45 +0300
Subject: [PATCH 05/30] UBIFS: rename dbg_check_dir_size function
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-6-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Since this function is not only about size checking, rename it to
'dbg_check_dir()'.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |    2 +-
 fs/ubifs/debug.h |    4 ++--
 fs/ubifs/super.c |    2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 4a2170d..26d4c61 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -1177,7 +1177,7 @@ int dbg_check_synced_i_size(struct inode *inode)
  * Note, it is good idea to make sure the @dir->i_mutex is locked before
  * calling this function.
  */
-int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
+int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
 {
 	unsigned int nlink = 2;
 	union ubifs_key key;
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index c6ad9ea..a51c20b 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -248,7 +248,7 @@ int dbg_check_ltab(struct ubifs_info *c);
 int dbg_chk_lpt_free_spc(struct ubifs_info *c);
 int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len);
 int dbg_check_synced_i_size(struct inode *inode);
-int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir);
+int dbg_check_dir(struct ubifs_info *c, const struct inode *dir);
 int dbg_check_tnc(struct ubifs_info *c, int extra);
 int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
 int dbg_check_filesystem(struct ubifs_info *c);
@@ -417,7 +417,7 @@ static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c)      { return 0; }
 static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
 				 int action, int len)             { return 0; }
 static inline int dbg_check_synced_i_size(struct inode *inode)    { return 0; }
-static inline int dbg_check_dir_size(struct ubifs_info *c,
+static inline int dbg_check_dir(struct ubifs_info *c,
 				const struct inode *dir)          { return 0; }
 static inline int dbg_check_tnc(struct ubifs_info *c, int extra)  { return 0; }
 static inline int dbg_check_idx_size(struct ubifs_info *c,
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index b5aeb5a..55161c6 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -94,7 +94,7 @@ static int validate_inode(struct ubifs_info *c, const struct inode *inode)
 			   ubifs_compr_name(ui->compr_type));
 	}
 
-	err = dbg_check_dir_size(c, inode);
+	err = dbg_check_dir(c, inode);
 	return err;
 }
 
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:48 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:48 +0300
Subject: [PATCH 08/30] UBIFS: remove dead code
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-9-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Remove dead pieces of code under "if (c->min_io_size == 1)" statement -
we never execute it because in UBIFS 'c->min_io_size' is always at least 8.
This are leftovers from old pre-mainline prototype.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/tnc_commit.c |  106 ++++++++++++++-----------------------------------
 1 files changed, 30 insertions(+), 76 deletions(-)

diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index 41920f3..8315387 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -491,25 +491,6 @@ static int layout_in_empty_space(struct ubifs_info *c)
 		else
 			next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
 
-		if (c->min_io_size == 1) {
-			buf_offs += ALIGN(len, 8);
-			if (next_len) {
-				if (buf_offs + next_len <= c->leb_size)
-					continue;
-				err = ubifs_update_one_lp(c, lnum, 0,
-						c->leb_size - buf_offs, 0, 0);
-				if (err)
-					return err;
-				lnum = -1;
-				continue;
-			}
-			err = ubifs_update_one_lp(c, lnum,
-					c->leb_size - buf_offs, 0, 0, 0);
-			if (err)
-				return err;
-			break;
-		}
-
 		/* Update buffer positions */
 		wlen = used + len;
 		used += ALIGN(len, 8);
@@ -830,7 +811,7 @@ static int write_index(struct ubifs_info *c)
 	struct ubifs_idx_node *idx;
 	struct ubifs_znode *znode, *cnext;
 	int i, lnum, offs, len, next_len, buf_len, buf_offs, used;
-	int avail, wlen, err, lnum_pos = 0;
+	int avail, wlen, err, lnum_pos = 0, blen, nxt_offs;
 
 	cnext = c->enext;
 	if (!cnext)
@@ -938,65 +919,38 @@ static int write_index(struct ubifs_info *c)
 		else
 			next_len = ubifs_idx_node_sz(c, cnext->child_cnt);
 
-		if (c->min_io_size == 1) {
-			/*
-			 * Write the prepared index node immediately if there is
-			 * no minimum IO size
-			 */
-			err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
-					      wlen, UBI_SHORTTERM);
-			if (err)
-				return err;
-			buf_offs += ALIGN(wlen, 8);
-			if (next_len) {
-				used = 0;
-				avail = buf_len;
-				if (buf_offs + next_len > c->leb_size) {
-					err = ubifs_update_one_lp(c, lnum,
-						LPROPS_NC, 0, 0, LPROPS_TAKEN);
-					if (err)
-						return err;
-					lnum = -1;
-				}
+		nxt_offs = buf_offs + used + next_len;
+		if (next_len && nxt_offs <= c->leb_size) {
+			if (avail > 0)
 				continue;
-			}
+			else
+				blen = buf_len;
 		} else {
-			int blen, nxt_offs = buf_offs + used + next_len;
-
-			if (next_len && nxt_offs <= c->leb_size) {
-				if (avail > 0)
-					continue;
-				else
-					blen = buf_len;
-			} else {
-				wlen = ALIGN(wlen, 8);
-				blen = ALIGN(wlen, c->min_io_size);
-				ubifs_pad(c, c->cbuf + wlen, blen - wlen);
-			}
-			/*
-			 * The buffer is full or there are no more znodes
-			 * to do
-			 */
-			err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs,
-					      blen, UBI_SHORTTERM);
-			if (err)
-				return err;
-			buf_offs += blen;
-			if (next_len) {
-				if (nxt_offs > c->leb_size) {
-					err = ubifs_update_one_lp(c, lnum,
-						LPROPS_NC, 0, 0, LPROPS_TAKEN);
-					if (err)
-						return err;
-					lnum = -1;
-				}
-				used -= blen;
-				if (used < 0)
-					used = 0;
-				avail = buf_len - used;
-				memmove(c->cbuf, c->cbuf + blen, used);
-				continue;
+			wlen = ALIGN(wlen, 8);
+			blen = ALIGN(wlen, c->min_io_size);
+			ubifs_pad(c, c->cbuf + wlen, blen - wlen);
+		}
+
+		/* The buffer is full or there are no more znodes to do */
+		err = ubifs_leb_write(c, lnum, c->cbuf, buf_offs, blen,
+				      UBI_SHORTTERM);
+		if (err)
+			return err;
+		buf_offs += blen;
+		if (next_len) {
+			if (nxt_offs > c->leb_size) {
+				err = ubifs_update_one_lp(c, lnum, LPROPS_NC, 0,
+							  0, LPROPS_TAKEN);
+				if (err)
+					return err;
+				lnum = -1;
 			}
+			used -= blen;
+			if (used < 0)
+				used = 0;
+			avail = buf_len - used;
+			memmove(c->cbuf, c->cbuf + blen, used);
+			continue;
 		}
 		break;
 	}
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:50 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:50 +0300
Subject: [PATCH 10/30] UBIFS: use correct flags in lprops
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-11-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

The UBIFS lpt tree is in many aspects similar to the TNC tree, and we have
similar flags for these trees. And by mistake we use the COW_ZNODE flag for
LPT in some places, instead of the right flag COW_CNODE. And this works
only because these two constants have the same value.

This patch makes all the LPT code to use COW_CNODE and also changes COW_CNODE
constant value to make sure we do not misuse the flags any more.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/lprops.c     |    2 +-
 fs/ubifs/lpt_commit.c |    6 +++---
 fs/ubifs/ubifs.h      |    8 ++++----
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index 667884f..98b8e73 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -504,7 +504,7 @@ static int is_lprops_dirty(struct ubifs_info *c, struct ubifs_lprops *lprops)
 	pnode = (struct ubifs_pnode *)container_of(lprops - pos,
 						   struct ubifs_pnode,
 						   lprops[0]);
-	return !test_bit(COW_ZNODE, &pnode->flags) &&
+	return !test_bit(COW_CNODE, &pnode->flags) &&
 	       test_bit(DIRTY_CNODE, &pnode->flags);
 }
 
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index dfcb574..254e8d3 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -116,8 +116,8 @@ static int get_cnodes_to_commit(struct ubifs_info *c)
 		return 0;
 	cnt += 1;
 	while (1) {
-		ubifs_assert(!test_bit(COW_ZNODE, &cnode->flags));
-		__set_bit(COW_ZNODE, &cnode->flags);
+		ubifs_assert(!test_bit(COW_CNODE, &cnode->flags));
+		__set_bit(COW_CNODE, &cnode->flags);
 		cnext = next_dirty_cnode(cnode);
 		if (!cnext) {
 			cnode->cnext = c->lpt_cnext;
@@ -465,7 +465,7 @@ static int write_cnodes(struct ubifs_info *c)
 		 */
 		clear_bit(DIRTY_CNODE, &cnode->flags);
 		smp_mb__before_clear_bit();
-		clear_bit(COW_ZNODE, &cnode->flags);
+		clear_bit(COW_CNODE, &cnode->flags);
 		smp_mb__after_clear_bit();
 		offs += len;
 		dbg_chk_lpt_sz(c, 1, len);
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index f79983d..3304aad 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -230,14 +230,14 @@ enum {
  * LPT cnode flag bits.
  *
  * DIRTY_CNODE: cnode is dirty
- * COW_CNODE: cnode is being committed and must be copied before writing
  * OBSOLETE_CNODE: cnode is being committed and has been copied (or deleted),
- * so it can (and must) be freed when the commit is finished
+ *                 so it can (and must) be freed when the commit is finished
+ * COW_CNODE: cnode is being committed and must be copied before writing
  */
 enum {
 	DIRTY_CNODE    = 0,
-	COW_CNODE      = 1,
-	OBSOLETE_CNODE = 2,
+	OBSOLETE_CNODE = 1,
+	COW_CNODE      = 2,
 };
 
 /*
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:42 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:42 +0300
Subject: [PATCH 02/30] UBIFS: lessen the size of debugging info data structure
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-3-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This patch lessens the 'struct ubifs_debug_info' size by 90 bytes by
allocating less bytes for the debugfs root directory name. It introduces macros
for the name patter an length instead of hard-coding 100 bytes. It also makes
UBIFS use 'snprintf()' and teaches it to gracefully catch situations when the
name array is too short.

Additionally, this patch makes 2 unrelated changes - I just thought they do not
deserve separate commits: simplifies 'ubifs_assert()' for non-debugging case
and makes 'dbg_debugfs_init()' properly verify debugfs return code which may be
an error code or NULL, so we should you 'IS_ERR_OR_NULL()' instead of
'IS_ERR()'.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   18 +++++++++++++-----
 fs/ubifs/debug.h |   11 +++++++++--
 2 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 0bb2bce..c9609a6 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2815,8 +2815,8 @@ static struct dentry *dfs_rootdir;
 int dbg_debugfs_init(void)
 {
 	dfs_rootdir = debugfs_create_dir("ubifs", NULL);
-	if (IS_ERR(dfs_rootdir)) {
-		int err = PTR_ERR(dfs_rootdir);
+	if (IS_ERR_OR_NULL(dfs_rootdir)) {
+		int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;
 		ubifs_err("cannot create \"ubifs\" debugfs directory, "
 			  "error %d\n", err);
 		return err;
@@ -2880,12 +2880,20 @@ static const struct file_operations dfs_fops = {
  */
 int dbg_debugfs_init_fs(struct ubifs_info *c)
 {
-	int err;
+	int err, n;
 	const char *fname;
 	struct dentry *dent;
 	struct ubifs_debug_info *d = c->dbg;
 
-	sprintf(d->dfs_dir_name, "ubi%d_%d", c->vi.ubi_num, c->vi.vol_id);
+	n = snprintf(d->dfs_dir_name, UBIFS_DFS_DIR_LEN + 1, UBIFS_DFS_DIR_NAME,
+		     c->vi.ubi_num, c->vi.vol_id);
+	if (n == UBIFS_DFS_DIR_LEN) {
+		/* The array size is too small */
+		fname = UBIFS_DFS_DIR_NAME;
+		dent = ERR_PTR(-EINVAL);
+		goto out;
+	}
+
 	fname = d->dfs_dir_name;
 	dent = debugfs_create_dir(fname, dfs_rootdir);
 	if (IS_ERR_OR_NULL(dent))
@@ -2916,7 +2924,7 @@ out_remove:
 	debugfs_remove_recursive(d->dfs_dir);
 out:
 	err = dent ? PTR_ERR(dent) : -ENODEV;
-	ubifs_err("cannot create \"%s\" debugfs directory, error %d\n",
+	ubifs_err("cannot create \"%s\" debugfs filr or directory, error %d\n",
 		  fname, err);
 	return err;
 }
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index a811ac4..b59c43a 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -33,6 +33,13 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
 
 #include <linux/random.h>
 
+/*
+ * The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
+ * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
+ */
+#define UBIFS_DFS_DIR_NAME "ubi%d_%d"
+#define UBIFS_DFS_DIR_LEN  (3 + 1 + 2*2 + 1)
+
 /**
  * ubifs_debug_info - per-FS debugging information.
  * @old_zroot: old index root - used by 'dbg_check_old_index()'
@@ -84,7 +91,7 @@ struct ubifs_debug_info {
 	long long saved_free;
 	int saved_idx_gc_cnt;
 
-	char dfs_dir_name[100];
+	char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1];
 	struct dentry *dfs_dir;
 	struct dentry *dfs_dump_lprops;
 	struct dentry *dfs_dump_budg;
@@ -313,7 +320,7 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 
 /* Use "if (0)" to make compiler check arguments even if debugging is off */
 #define ubifs_assert(expr)  do {                                               \
-	if (0 && (expr))                                                       \
+	if (0)                                                                 \
 		printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
 		       __func__, __LINE__, current->pid);                      \
 } while (0)
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:44 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:44 +0300
Subject: [PATCH 04/30] UBIFS: improve inode dumping function
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-5-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Teach 'dbg_dump_inode()' dump directory entries for directory inodes.
This requires few additional changes:
1. The 'c' argument of 'dbg_dump_inode()' cannot be const any more.
2. Users of 'dbg_dump_inode()' should not have 'tnc_mutex' locked.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   56 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 fs/ubifs/debug.h |    6 ++--
 fs/ubifs/tnc.c   |    3 +-
 3 files changed, 60 insertions(+), 5 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index c9609a6..4a2170d 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -91,6 +91,28 @@ static const char *get_key_type(int type)
 	}
 }
 
+static const char *get_dent_type(int type)
+{
+	switch (type) {
+	case UBIFS_ITYPE_REG:
+		return "file";
+	case UBIFS_ITYPE_DIR:
+		return "dir";
+	case UBIFS_ITYPE_LNK:
+		return "symlink";
+	case UBIFS_ITYPE_BLK:
+		return "blkdev";
+	case UBIFS_ITYPE_CHR:
+		return "char dev";
+	case UBIFS_ITYPE_FIFO:
+		return "fifo";
+	case UBIFS_ITYPE_SOCK:
+		return "socket";
+	default:
+		return "unknown/invalid type";
+	}
+}
+
 static void sprintf_key(const struct ubifs_info *c, const union ubifs_key *key,
 			char *buffer)
 {
@@ -234,9 +256,13 @@ static void dump_ch(const struct ubifs_ch *ch)
 	printk(KERN_DEBUG "\tlen            %u\n", le32_to_cpu(ch->len));
 }
 
-void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
+void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode)
 {
 	const struct ubifs_inode *ui = ubifs_inode(inode);
+	struct qstr nm = { .name = NULL };
+	union ubifs_key key;
+	struct ubifs_dent_node *dent, *pdent = NULL;
+	int count = 2;
 
 	printk(KERN_DEBUG "Dump in-memory inode:");
 	printk(KERN_DEBUG "\tinode          %lu\n", inode->i_ino);
@@ -270,6 +296,32 @@ void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode)
 	printk(KERN_DEBUG "\tlast_page_read %lu\n", ui->last_page_read);
 	printk(KERN_DEBUG "\tread_in_a_row  %lu\n", ui->read_in_a_row);
 	printk(KERN_DEBUG "\tdata_len       %d\n", ui->data_len);
+
+	if (!S_ISDIR(inode->i_mode))
+		return;
+
+	printk(KERN_DEBUG "List of directory entries:\n");
+	ubifs_assert(!mutex_is_locked(&c->tnc_mutex));
+
+	lowest_dent_key(c, &key, inode->i_ino);
+	while (1) {
+		dent = ubifs_tnc_next_ent(c, &key, &nm);
+		if (IS_ERR(dent)) {
+			if (PTR_ERR(dent) != -ENOENT)
+				printk(KERN_DEBUG "error %ld\n", PTR_ERR(dent));
+			break;
+		}
+
+		printk(KERN_DEBUG "\t%d: %s (%s)\n",
+		       count++, dent->name, get_dent_type(dent->type));
+
+		nm.name = dent->name;
+		nm.len = le16_to_cpu(dent->nlen);
+		kfree(pdent);
+		pdent = dent;
+		key_read(c, &dent->key, &key);
+	}
+	kfree(pdent);
 }
 
 void dbg_dump_node(const struct ubifs_info *c, const void *node)
@@ -1167,12 +1219,14 @@ int dbg_check_dir_size(struct ubifs_info *c, const struct inode *dir)
 			  "but calculated size is %llu", dir->i_ino,
 			  (unsigned long long)i_size_read(dir),
 			  (unsigned long long)size);
+		dbg_dump_inode(c, dir);
 		dump_stack();
 		return -EINVAL;
 	}
 	if (dir->i_nlink != nlink) {
 		ubifs_err("directory inode %lu has nlink %u, but calculated "
 			  "nlink is %u", dir->i_ino, dir->i_nlink, nlink);
+		dbg_dump_inode(c, dir);
 		dump_stack();
 		return -EINVAL;
 	}
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index b59c43a..c6ad9ea 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -214,7 +214,7 @@ const char *dbg_cstate(int cmt_state);
 const char *dbg_jhead(int jhead);
 const char *dbg_get_key_dump(const struct ubifs_info *c,
 			     const union ubifs_key *key);
-void dbg_dump_inode(const struct ubifs_info *c, const struct inode *inode);
+void dbg_dump_inode(struct ubifs_info *c, const struct inode *inode);
 void dbg_dump_node(const struct ubifs_info *c, const void *node);
 void dbg_dump_lpt_node(const struct ubifs_info *c, void *node, int lnum,
 		       int offs);
@@ -364,7 +364,7 @@ static inline const char *dbg_jhead(int jhead)                    { return ""; }
 static inline const char *
 dbg_get_key_dump(const struct ubifs_info *c,
 		 const union ubifs_key *key)                      { return ""; }
-static inline void dbg_dump_inode(const struct ubifs_info *c,
+static inline void dbg_dump_inode(struct ubifs_info *c,
 				  const struct inode *inode)      { return; }
 static inline void dbg_dump_node(const struct ubifs_info *c,
 				 const void *node)                { return; }
@@ -418,7 +418,7 @@ static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
 				 int action, int len)             { return 0; }
 static inline int dbg_check_synced_i_size(struct inode *inode)    { return 0; }
 static inline int dbg_check_dir_size(struct ubifs_info *c,
-				     const struct inode *dir)     { return 0; }
+				const struct inode *dir)          { return 0; }
 static inline int dbg_check_tnc(struct ubifs_info *c, int extra)  { return 0; }
 static inline int dbg_check_idx_size(struct ubifs_info *c,
 				     long long idx_size)          { return 0; }
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 91b4213..48b6ee6 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -3337,9 +3337,10 @@ out_dump:
 	ubifs_err("inode %lu has size %lld, but there are data at offset %lld "
 		  "(data key %s)", (unsigned long)inode->i_ino, size,
 		  ((loff_t)block) << UBIFS_BLOCK_SHIFT, DBGKEY(key));
+	mutex_unlock(&c->tnc_mutex);
 	dbg_dump_inode(c, inode);
 	dbg_dump_stack();
-	err = -EINVAL;
+	return -EINVAL;
 
 out_unlock:
 	mutex_unlock(&c->tnc_mutex);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:51 +0300
Subject: [PATCH 11/30] UBIFS: add few commentaries about TNC
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-12-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Add a couple of comments - while looking into TNC I could not easily figure out
few facts, so it is a good idea to document them in the code.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/tnc_commit.c |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index f50c3e5..d6fab1a 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -89,6 +89,10 @@ static int make_idx_node(struct ubifs_info *c, struct ubifs_idx_node *idx,
 	ubifs_assert(ubifs_zn_dirty(znode));
 	ubifs_assert(ubifs_zn_cow(znode));
 
+	/*
+	 * Note, unlike 'write_index()' we do not add memory barriers here
+	 * because this function is called with @c->tnc_mutex locked.
+	 */
 	__clear_bit(DIRTY_ZNODE, &znode->flags);
 	__clear_bit(COW_ZNODE, &znode->flags);
 
@@ -903,6 +907,28 @@ static int write_index(struct ubifs_info *c)
 		clear_bit(COW_ZNODE, &znode->flags);
 		smp_mb__after_clear_bit();
 
+		/*
+		 * We have marked the znode as clean but have not updated the
+		 * @c->clean_zn_cnt counter. If this znode becomes dirty again
+		 * before 'free_obsolete_znodes()' is called, then
+		 * @c->clean_zn_cnt will be decremented before it gets
+		 * incremented (resulting in 2 decrements for the same znode).
+		 * This means that @c->clean_zn_cnt may become negative for a
+		 * while.
+		 *
+		 * Q: why we cannot increment @c->clean_zn_cnt?
+		 * A: because we do not have the @c->tnc_mutex locked, and the
+		 *    following code would be racy and buggy:
+		 *
+		 *    if (!ubifs_zn_obsolete(znode)) {
+		 *            atomic_long_inc(&c->clean_zn_cnt);
+		 *            atomic_long_inc(&ubifs_clean_zn_cnt);
+		 *    }
+		 *
+		 *    Thus, we just delay the @c->clean_zn_cnt update until we
+		 *    have the mutex locked.
+		 */
+
 		/* Do not access znode from this point on */
 
 		/* Update buffer positions */
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:52 +0300
Subject: [PATCH 12/30] UBIFS: amend debugging name check function prototype
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-13-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Add 'struct ubifs_info *c' parameter to the 'dbg_check_name()' debugging
function - it will be needed in one of the following commits where we switch to
debugfs. So this is just a preparation.

Mark parameters as 'const' while on it.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/dir.c |    8 +++++---
 1 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index c6cbdd0..d1725a9 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -172,7 +172,9 @@ struct inode *ubifs_new_inode(struct ubifs_info *c, const struct inode *dir,
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
-static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
+static int dbg_check_name(const struct ubifs_info *c,
+			  const struct ubifs_dent_node *dent,
+			  const struct qstr *nm)
 {
 	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
 		return 0;
@@ -185,7 +187,7 @@ static int dbg_check_name(struct ubifs_dent_node *dent, struct qstr *nm)
 
 #else
 
-#define dbg_check_name(dent, nm) 0
+#define dbg_check_name(c, dent, nm) 0
 
 #endif
 
@@ -219,7 +221,7 @@ static struct dentry *ubifs_lookup(struct inode *dir, struct dentry *dentry,
 		goto out;
 	}
 
-	if (dbg_check_name(dent, &dentry->d_name)) {
+	if (dbg_check_name(c, dent, &dentry->d_name)) {
 		err = -EINVAL;
 		goto out;
 	}
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:53 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:53 +0300
Subject: [PATCH 13/30] UBIFS: amend debugging inode size check function
	prototype
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-14-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Add 'const struct ubifs_info *c' parameter to 'dbg_check_synced_i_size()'
function because we'll need it in the next patch when we switch to debugfs.
So this patch is just a preparation.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |    3 ++-
 fs/ubifs/debug.h |    6 ++++--
 fs/ubifs/dir.c   |    4 ++--
 fs/ubifs/file.c  |    2 +-
 4 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 26d4c61..7adf9fe 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -1132,6 +1132,7 @@ out:
 
 /**
  * dbg_check_synced_i_size - check synchronized inode size.
+ * @c: UBIFS file-system description object
  * @inode: inode to check
  *
  * If inode is clean, synchronized inode size has to be equivalent to current
@@ -1139,7 +1140,7 @@ out:
  * has to be locked). Returns %0 if synchronized inode size if correct, and
  * %-EINVAL if not.
  */
-int dbg_check_synced_i_size(struct inode *inode)
+int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode)
 {
 	int err = 0;
 	struct ubifs_inode *ui = ubifs_inode(inode);
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index a51c20b..90805bd 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -247,7 +247,7 @@ int dbg_check_cats(struct ubifs_info *c);
 int dbg_check_ltab(struct ubifs_info *c);
 int dbg_chk_lpt_free_spc(struct ubifs_info *c);
 int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len);
-int dbg_check_synced_i_size(struct inode *inode);
+int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode);
 int dbg_check_dir(struct ubifs_info *c, const struct inode *dir);
 int dbg_check_tnc(struct ubifs_info *c, int extra);
 int dbg_check_idx_size(struct ubifs_info *c, long long idx_size);
@@ -416,7 +416,9 @@ static inline int dbg_check_ltab(struct ubifs_info *c)            { return 0; }
 static inline int dbg_chk_lpt_free_spc(struct ubifs_info *c)      { return 0; }
 static inline int dbg_chk_lpt_sz(struct ubifs_info *c,
 				 int action, int len)             { return 0; }
-static inline int dbg_check_synced_i_size(struct inode *inode)    { return 0; }
+static inline int
+dbg_check_synced_i_size(const struct ubifs_info *c,
+			struct inode *inode)                      { return 0; }
 static inline int dbg_check_dir(struct ubifs_info *c,
 				const struct inode *dir)          { return 0; }
 static inline int dbg_check_tnc(struct ubifs_info *c, int extra)  { return 0; }
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index d1725a9..98014bf 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -524,7 +524,7 @@ static int ubifs_link(struct dentry *old_dentry, struct inode *dir,
 	ubifs_assert(mutex_is_locked(&dir->i_mutex));
 	ubifs_assert(mutex_is_locked(&inode->i_mutex));
 
-	err = dbg_check_synced_i_size(inode);
+	err = dbg_check_synced_i_size(c, inode);
 	if (err)
 		return err;
 
@@ -579,7 +579,7 @@ static int ubifs_unlink(struct inode *dir, struct dentry *dentry)
 		inode->i_nlink, dir->i_ino);
 	ubifs_assert(mutex_is_locked(&dir->i_mutex));
 	ubifs_assert(mutex_is_locked(&inode->i_mutex));
-	err = dbg_check_synced_i_size(inode);
+	err = dbg_check_synced_i_size(c, inode);
 	if (err)
 		return err;
 
diff --git a/fs/ubifs/file.c b/fs/ubifs/file.c
index 5e7fccf..7cf738a 100644
--- a/fs/ubifs/file.c
+++ b/fs/ubifs/file.c
@@ -1263,7 +1263,7 @@ int ubifs_setattr(struct dentry *dentry, struct iattr *attr)
 	if (err)
 		return err;
 
-	err = dbg_check_synced_i_size(inode);
+	err = dbg_check_synced_i_size(c, inode);
 	if (err)
 		return err;
 
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:55 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:55 +0300
Subject: [PATCH 15/30] UBIFS: lessen amount of debugging check types
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-16-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

We have too many different debugging checks - lessen the amount by merging all
index-related checks into one. At the same time, move the "force in-the-gap"
test to the "index checks" class, because it is too heavy for the "general"
class.

This patch merges TNC, Old index, and Index size check and calles this just
"index checks".

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 Documentation/filesystems/ubifs.txt |    4 +---
 fs/ubifs/commit.c                   |    2 +-
 fs/ubifs/debug.c                    |    4 ++--
 fs/ubifs/debug.h                    |   24 +++++-------------------
 fs/ubifs/lpt_commit.c               |    1 +
 fs/ubifs/tnc_commit.c               |    6 +++---
 6 files changed, 13 insertions(+), 28 deletions(-)

diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index 8e4fab6..91ef076 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -123,10 +123,8 @@ debug_chks	Selects extra checks that UBIFS can do while running:
 		Check					Flag value
 
 		General checks				1
-		Check Tree Node Cache (TNC)		2
-		Check indexing tree size		4
+		Check the index				2
 		Check orphan area			8
-		Check old indexing tree			16
 		Check LEB properties (lprops)		32
 		Check leaf nodes and inodes		64
 
diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 63c4e44..fb3b5c8 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -576,7 +576,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
 	struct idx_node *i;
 	size_t sz;
 
-	if (!dbg_is_chk_old_idx(c))
+	if (!dbg_is_chk_index(c))
 		return 0;
 
 	INIT_LIST_HEAD(&list);
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 79d8924..a967d68 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -1544,7 +1544,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
 	long clean_cnt = 0, dirty_cnt = 0;
 	int err, last;
 
-	if (!dbg_is_chk_tnc(c))
+	if (!dbg_is_chk_index(c))
 		return 0;
 
 	ubifs_assert(mutex_is_locked(&c->tnc_mutex));
@@ -1791,7 +1791,7 @@ int dbg_check_idx_size(struct ubifs_info *c, long long idx_size)
 	int err;
 	long long calc = 0;
 
-	if (!dbg_is_chk_idx_sz(c))
+	if (!dbg_is_chk_index(c))
 		return 0;
 
 	err = dbg_walk_index(c, NULL, add_size, &calc);
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index c3d1ffd..44265a3 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -173,19 +173,15 @@ extern spinlock_t dbg_lock;
  * Debugging check flags.
  *
  * UBIFS_CHK_GEN: general checks
- * UBIFS_CHK_TNC: check TNC
- * UBIFS_CHK_IDX_SZ: check index size
+ * UBIFS_CHK_INDEX: check the index
  * UBIFS_CHK_ORPH: check orphans
- * UBIFS_CHK_OLD_IDX: check the old index
  * UBIFS_CHK_LPROPS: check lprops
  * UBIFS_CHK_FS: check the file-system
  */
 enum {
 	UBIFS_CHK_GEN     = 0x1,
-	UBIFS_CHK_TNC     = 0x2,
-	UBIFS_CHK_IDX_SZ  = 0x4,
+	UBIFS_CHK_INDEX   = 0x2,
 	UBIFS_CHK_ORPH    = 0x8,
-	UBIFS_CHK_OLD_IDX = 0x10,
 	UBIFS_CHK_LPROPS  = 0x20,
 	UBIFS_CHK_FS      = 0x40,
 };
@@ -207,22 +203,14 @@ static inline int dbg_is_chk_gen(const struct ubifs_info *c)
 {
 	return !!(ubifs_chk_flags & UBIFS_CHK_GEN);
 }
-static inline int dbg_is_chk_tnc(const struct ubifs_info *c)
+static inline int dbg_is_chk_index(const struct ubifs_info *c)
 {
-	return !!(ubifs_chk_flags & UBIFS_CHK_TNC);
-}
-static inline int dbg_is_chk_idx_sz(const struct ubifs_info *c)
-{
-	return !!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ);
+	return !!(ubifs_chk_flags & UBIFS_CHK_INDEX);
 }
 static inline int dbg_is_chk_orph(const struct ubifs_info *c)
 {
 	return !!(ubifs_chk_flags & UBIFS_CHK_ORPH);
 }
-static inline int dbg_is_chk_old_idx(const struct ubifs_info *c)
-{
-	return !!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX);
-}
 static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
 {
 	return !!(ubifs_chk_flags & UBIFS_CHK_LPROPS);
@@ -462,10 +450,8 @@ dbg_check_nondata_nodes_order(struct ubifs_info *c,
 			      struct list_head *head)             { return 0; }
 
 static inline int dbg_is_chk_gen(const struct ubifs_info *c)      { return 0; }
-static inline int dbg_is_chk_tnc(const struct ubifs_info *c)      { return 0; }
-static inline int dbg_is_chk_idx_sz(const struct ubifs_info *c)   { return 0; }
+static inline int dbg_is_chk_index(const struct ubifs_info *c)    { return 0; }
 static inline int dbg_is_chk_orph(const struct ubifs_info *c)     { return 0; }
-static inline int dbg_is_chk_old_idx(const struct ubifs_info *c)  { return 0; }
 static inline int dbg_is_chk_lprops(const struct ubifs_info *c)   { return 0; }
 static inline int dbg_is_chk_fs(const struct ubifs_info *c)       { return 0; }
 static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)    { return 0; }
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index f8e286b..f13addf 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -27,6 +27,7 @@
 
 #include <linux/crc16.h>
 #include <linux/slab.h>
+#include <linux/random.h>
 #include "ubifs.h"
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index 8959c72..4c15f07 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -22,8 +22,8 @@
 
 /* This file implements TNC functions for committing */
 
-#include "ubifs.h"
 #include <linux/random.h>
+#include "ubifs.h"
 
 /**
  * make_idx_node - make an index node for fill-the-gaps method of TNC commit.
@@ -382,7 +382,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
 				c->gap_lebs = NULL;
 				return err;
 			}
-			if (!dbg_is_chk_gen(c)) {
+			if (!dbg_is_chk_index(c)) {
 				/*
 				 * Do not print scary warnings if the debugging
 				 * option which forces in-the-gaps is enabled.
@@ -690,7 +690,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
 		c->ilebs[c->ileb_cnt++] = lnum;
 		dbg_cmt("LEB %d", lnum);
 	}
-	if (dbg_is_chk_gen(c) && !(random32() & 7))
+	if (dbg_is_chk_index(c) && !(random32() & 7))
 		return -ENOSPC;
 	return 0;
 }
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:57 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:57 +0300
Subject: [PATCH 17/30] UBIFS: be more informative in failure mode
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-18-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

When we are testing UBIFS recovery, it is better to print in which eraseblock
we are going to fail. Currently UBIFS prints it only if recovery debugging
messages are enabled, but this is not very practical. So change 'dbg_rcvry()'
messages to 'ubifs_warn()' messages.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   26 +++++++++++++-------------
 1 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index fdfa5de..05fae3f 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2631,11 +2631,11 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
 				d->fail_delay = 1;
 				d->fail_timeout = jiffies +
 						  msecs_to_jiffies(delay);
-				dbg_rcvry("failing after %ums", delay);
+				ubifs_warn("failing after %ums", delay);
 			} else {
 				d->fail_delay = 2;
 				d->fail_cnt_max = delay;
-				dbg_rcvry("failing after %u calls", delay);
+				ubifs_warn("failing after %u calls", delay);
 			}
 		}
 		d->fail_cnt += 1;
@@ -2653,56 +2653,56 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
 				return 0;
 		} else if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in super block LEB %d", lnum);
+		ubifs_warn("failing in super block LEB %d", lnum);
 	} else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
 		if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in master LEB %d", lnum);
+		ubifs_warn("failing in master LEB %d", lnum);
 	} else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
 		if (write) {
 			if (chance(99, 100))
 				return 0;
 		} else if (chance(399, 400))
 			return 0;
-		dbg_rcvry("failing in log LEB %d", lnum);
+		ubifs_warn("failing in log LEB %d", lnum);
 	} else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
 		if (write) {
 			if (chance(7, 8))
 				return 0;
 		} else if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in LPT LEB %d", lnum);
+		ubifs_warn("failing in LPT LEB %d", lnum);
 	} else if (lnum >= c->orph_first && lnum <= c->orph_last) {
 		if (write) {
 			if (chance(1, 2))
 				return 0;
 		} else if (chance(9, 10))
 			return 0;
-		dbg_rcvry("failing in orphan LEB %d", lnum);
+		ubifs_warn("failing in orphan LEB %d", lnum);
 	} else if (lnum == c->ihead_lnum) {
 		if (chance(99, 100))
 			return 0;
-		dbg_rcvry("failing in index head LEB %d", lnum);
+		ubifs_warn("failing in index head LEB %d", lnum);
 	} else if (c->jheads && lnum == c->jheads[GCHD].wbuf.lnum) {
 		if (chance(9, 10))
 			return 0;
-		dbg_rcvry("failing in GC head LEB %d", lnum);
+		ubifs_warn("failing in GC head LEB %d", lnum);
 	} else if (write && !RB_EMPTY_ROOT(&c->buds) &&
 		   !ubifs_search_bud(c, lnum)) {
 		if (chance(19, 20))
 			return 0;
-		dbg_rcvry("failing in non-bud LEB %d", lnum);
+		ubifs_warn("failing in non-bud LEB %d", lnum);
 	} else if (c->cmt_state == COMMIT_RUNNING_BACKGROUND ||
 		   c->cmt_state == COMMIT_RUNNING_REQUIRED) {
 		if (chance(999, 1000))
 			return 0;
-		dbg_rcvry("failing in bud LEB %d commit running", lnum);
+		ubifs_warn("failing in bud LEB %d commit running", lnum);
 	} else {
 		if (chance(9999, 10000))
 			return 0;
-		dbg_rcvry("failing in bud LEB %d commit not running", lnum);
+		ubifs_warn("failing in bud LEB %d commit not running", lnum);
 	}
-	ubifs_err("*** SETTING FAILURE MODE ON (LEB %d) ***", lnum);
+
 	d->failure_mode = 1;
 	dump_stack();
 	return 1;
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:59 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:59 +0300
Subject: [PATCH 19/30] UBIFS: introduce debugfs helpers
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-20-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Separate out pieces of code from the debugfs file read/write functions and
create separate 'interpret_user_input()'/'provide_user_output()' helpers. These
helpers will be needed in one of the following patches, so this is just a
preparational change.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   76 +++++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 515658c..91ac72c 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2820,13 +2820,39 @@ static int dfs_file_open(struct inode *inode, struct file *file)
 	return nonseekable_open(inode, file);
 }
 
+/**
+ * provide_user_output - provide output to the user reading a debugfs file.
+ * @val: boolean value for the answer
+ * @u: the buffer to store the answer at
+ * @count: size of the buffer
+ * @ppos: position in the @u output buffer
+ *
+ * This is a simple helper function which stores @val boolean value in the user
+ * buffer when the user reads one of UBIFS debugfs files. Returns amount of
+ * bytes written to @u in case of success and a negative error code in case of
+ * failure.
+ */
+static int provide_user_output(int val, char __user *u, size_t count,
+			       loff_t *ppos)
+{
+	char buf[3];
+
+	if (val)
+		buf[0] = '1';
+	else
+		buf[0] = '0';
+	buf[1] = '\n';
+	buf[2] = 0x00;
+
+	return simple_read_from_buffer(u, count, ppos, buf, 2);
+}
+
 static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
 			     loff_t *ppos)
 {
 	struct dentry *dent = file->f_path.dentry;
 	struct ubifs_info *c = file->private_data;
 	struct ubifs_debug_info *d = c->dbg;
-	char buf[3];
 	int val;
 
 	if (dent == d->dfs_chk_gen)
@@ -2844,14 +2870,33 @@ static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
 	else
 		return -EINVAL;
 
-	if (val)
-		buf[0] = '1';
-	else
-		buf[0] = '0';
-	buf[1] = '\n';
-	buf[2] = 0x00;
+	return provide_user_output(val, u, count, ppos);
+}
 
-	return simple_read_from_buffer(u, count, ppos, buf, 2);
+/**
+ * interpret_user_input - interpret user debugfs file input.
+ * @u: user-provided buffer with the input
+ * @count: buffer size
+ *
+ * This is a helper function which interpret user input to a boolean UBIFS
+ * debugfs file. Returns %0 or %1 in case of success and a negative error code
+ * in case of failure.
+ */
+static int interpret_user_input(const char __user *u, size_t count)
+{
+	size_t buf_size;
+	char buf[8];
+
+	buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, u, buf_size))
+		return -EFAULT;
+
+	if (buf[0] == '1')
+		return 1;
+	else if (buf[0] == '0')
+		return 0;
+
+	return -EINVAL;
 }
 
 static ssize_t dfs_file_write(struct file *file, const char __user *u,
@@ -2860,8 +2905,6 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
 	struct ubifs_info *c = file->private_data;
 	struct ubifs_debug_info *d = c->dbg;
 	struct dentry *dent = file->f_path.dentry;
-	size_t buf_size;
-	char buf[8];
 	int val;
 
 	/*
@@ -2883,16 +2926,9 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
 		return count;
 	}
 
-	buf_size = min_t(size_t, count, (sizeof(buf) - 1));
-	if (copy_from_user(buf, u, buf_size))
-		return -EFAULT;
-
-	if (buf[0] == '1')
-		val = 1;
-	else if (buf[0] == '0')
-		val = 0;
-	else
-		return -EINVAL;
+	val = interpret_user_input(u, count);
+	if (val < 0)
+		return val;
 
 	if (dent == d->dfs_chk_gen)
 		d->chk_gen = val;
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:54 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:54 +0300
Subject: [PATCH 14/30] UBIFS: introduce helper functions for debugging checks
	and tests
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-15-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This patch introduces helper functions for all debugging checks, so instead of
doing

if (!(ubifs_chk_flags & UBIFS_CHK_GEN))

we now do

if (!dbg_is_chk_gen(c))

This is a preparation to further changes where the flags will go away, and
we'll need to only change the helper functions, but the code which utilizes
them won't be touched.

At the same time this patch removes 'dbg_force_in_the_gaps()',
'dbg_force_in_the_gaps_enabled()', and dbg_failure_mode helpers for
consistency.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/commit.c     |    2 +-
 fs/ubifs/debug.c      |   30 ++++++++--------------
 fs/ubifs/debug.h      |   66 ++++++++++++++++++++++++++++++++++---------------
 fs/ubifs/dir.c        |    2 +-
 fs/ubifs/log.c        |    2 +-
 fs/ubifs/lprops.c     |    6 ++--
 fs/ubifs/lpt.c        |    2 +-
 fs/ubifs/lpt_commit.c |   10 +++---
 fs/ubifs/orphan.c     |    2 +-
 fs/ubifs/scan.c       |    2 +-
 fs/ubifs/tnc.c        |    2 +-
 fs/ubifs/tnc_commit.c |    5 ++-
 12 files changed, 75 insertions(+), 56 deletions(-)

diff --git a/fs/ubifs/commit.c b/fs/ubifs/commit.c
index 637e076..63c4e44 100644
--- a/fs/ubifs/commit.c
+++ b/fs/ubifs/commit.c
@@ -576,7 +576,7 @@ int dbg_check_old_index(struct ubifs_info *c, struct ubifs_zbranch *zroot)
 	struct idx_node *i;
 	size_t sz;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX))
+	if (!dbg_is_chk_old_idx(c))
 		return 0;
 
 	INIT_LIST_HEAD(&list);
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 7adf9fe..79d8924 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -330,7 +330,7 @@ void dbg_dump_node(const struct ubifs_info *c, const void *node)
 	union ubifs_key key;
 	const struct ubifs_ch *ch = node;
 
-	if (dbg_failure_mode)
+	if (dbg_is_tst_rcvry(c))
 		return;
 
 	/* If the magic is incorrect, just hexdump the first bytes */
@@ -886,7 +886,7 @@ void dbg_dump_leb(const struct ubifs_info *c, int lnum)
 	struct ubifs_scan_node *snod;
 	void *buf;
 
-	if (dbg_failure_mode)
+	if (dbg_is_tst_rcvry(c))
 		return;
 
 	printk(KERN_DEBUG "(pid %d) start dumping LEB %d\n",
@@ -1145,7 +1145,7 @@ int dbg_check_synced_i_size(const struct ubifs_info *c, struct inode *inode)
 	int err = 0;
 	struct ubifs_inode *ui = ubifs_inode(inode);
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 	if (!S_ISREG(inode->i_mode))
 		return 0;
@@ -1186,7 +1186,7 @@ int dbg_check_dir(struct ubifs_info *c, const struct inode *dir)
 	struct qstr nm = { .name = NULL };
 	loff_t size = UBIFS_INO_NODE_SZ;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	if (!S_ISDIR(dir->i_mode))
@@ -1544,7 +1544,7 @@ int dbg_check_tnc(struct ubifs_info *c, int extra)
 	long clean_cnt = 0, dirty_cnt = 0;
 	int err, last;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_TNC))
+	if (!dbg_is_chk_tnc(c))
 		return 0;
 
 	ubifs_assert(mutex_is_locked(&c->tnc_mutex));
@@ -1791,7 +1791,7 @@ int dbg_check_idx_size(struct ubifs_info *c, long long idx_size)
 	int err;
 	long long calc = 0;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ))
+	if (!dbg_is_chk_idx_sz(c))
 		return 0;
 
 	err = dbg_walk_index(c, NULL, add_size, &calc);
@@ -2367,7 +2367,7 @@ int dbg_check_filesystem(struct ubifs_info *c)
 	int err;
 	struct fsck_data fsckd;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_FS))
+	if (!dbg_is_chk_fs(c))
 		return 0;
 
 	fsckd.inodes = RB_ROOT;
@@ -2402,7 +2402,7 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head)
 	struct list_head *cur;
 	struct ubifs_scan_node *sa, *sb;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	for (cur = head->next; cur->next != head; cur = cur->next) {
@@ -2469,7 +2469,7 @@ int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head)
 	struct list_head *cur;
 	struct ubifs_scan_node *sa, *sb;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	for (cur = head->next; cur->next != head; cur = cur->next) {
@@ -2546,14 +2546,6 @@ error_dump:
 	return 0;
 }
 
-int dbg_force_in_the_gaps(void)
-{
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
-		return 0;
-
-	return !(random32() & 7);
-}
-
 /* Failure mode for recovery testing */
 
 #define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
@@ -2624,7 +2616,7 @@ static int in_failure_mode(struct ubi_volume_desc *desc)
 {
 	struct ubifs_info *c = dbg_find_info(desc);
 
-	if (c && dbg_failure_mode)
+	if (c && dbg_is_tst_rcvry(c))
 		return c->dbg->failure_mode;
 	return 0;
 }
@@ -2634,7 +2626,7 @@ static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
 	struct ubifs_info *c = dbg_find_info(desc);
 	struct ubifs_debug_info *d;
 
-	if (!c || !dbg_failure_mode)
+	if (!c || !dbg_is_tst_rcvry(c))
 		return 0;
 	d = c->dbg;
 	if (d->failure_mode)
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 90805bd..c3d1ffd 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -31,8 +31,6 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
-#include <linux/random.h>
-
 /*
  * The UBIFS debugfs directory name pattern and maximum name length (3 for "ubi"
  * + 1 for "_" and plus 2x2 for 2 UBI numbers and 1 for the trailing zero byte.
@@ -169,6 +167,8 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 /* Additional recovery messages */
 #define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__)
 
+extern spinlock_t dbg_lock;
+
 /*
  * Debugging check flags.
  *
@@ -199,12 +199,43 @@ enum {
 	UBIFS_TST_RCVRY             = 0x4,
 };
 
-extern spinlock_t dbg_lock;
-
 extern unsigned int ubifs_msg_flags;
 extern unsigned int ubifs_chk_flags;
 extern unsigned int ubifs_tst_flags;
 
+static inline int dbg_is_chk_gen(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_GEN);
+}
+static inline int dbg_is_chk_tnc(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_TNC);
+}
+static inline int dbg_is_chk_idx_sz(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_IDX_SZ);
+}
+static inline int dbg_is_chk_orph(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_ORPH);
+}
+static inline int dbg_is_chk_old_idx(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_OLD_IDX);
+}
+static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_LPROPS);
+}
+static inline int dbg_is_chk_fs(const struct ubifs_info *c)
+{
+	return !!(ubifs_chk_flags & UBIFS_CHK_FS);
+}
+static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
+{
+	return !!(ubifs_tst_flags & UBIFS_TST_RCVRY);
+}
+
 int ubifs_debugging_init(struct ubifs_info *c);
 void ubifs_debugging_exit(struct ubifs_info *c);
 
@@ -261,16 +292,6 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
 int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
-/* Force the use of in-the-gaps method for testing */
-static inline int dbg_force_in_the_gaps_enabled(void)
-{
-	return ubifs_chk_flags & UBIFS_CHK_GEN;
-}
-int dbg_force_in_the_gaps(void);
-
-/* Failure mode for recovery testing */
-#define dbg_failure_mode (ubifs_tst_flags & UBIFS_TST_RCVRY)
-
 #ifndef UBIFS_DBG_PRESERVE_UBI
 #define ubi_leb_read   dbg_leb_read
 #define ubi_leb_write  dbg_leb_write
@@ -330,6 +351,9 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 		ubifs_err(fmt, ##__VA_ARGS__);     \
 } while (0)
 
+#define DBGKEY(key)  ((char *)(key))
+#define DBGKEY1(key) ((char *)(key))
+
 #define ubifs_dbg_msg(fmt, ...) do {               \
 	if (0)                                     \
 		pr_debug(fmt "\n", ##__VA_ARGS__); \
@@ -353,9 +377,6 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c);
 #define dbg_scan(fmt, ...)  ubifs_dbg_msg(fmt, ##__VA_ARGS__)
 #define dbg_rcvry(fmt, ...) ubifs_dbg_msg(fmt, ##__VA_ARGS__)
 
-#define DBGKEY(key)  ((char *)(key))
-#define DBGKEY1(key) ((char *)(key))
-
 static inline int ubifs_debugging_init(struct ubifs_info *c)      { return 0; }
 static inline void ubifs_debugging_exit(struct ubifs_info *c)     { return; }
 static inline const char *dbg_ntype(int type)                     { return ""; }
@@ -440,9 +461,14 @@ static inline int
 dbg_check_nondata_nodes_order(struct ubifs_info *c,
 			      struct list_head *head)             { return 0; }
 
-static inline int dbg_force_in_the_gaps(void)                     { return 0; }
-#define dbg_force_in_the_gaps_enabled() 0
-#define dbg_failure_mode                0
+static inline int dbg_is_chk_gen(const struct ubifs_info *c)      { return 0; }
+static inline int dbg_is_chk_tnc(const struct ubifs_info *c)      { return 0; }
+static inline int dbg_is_chk_idx_sz(const struct ubifs_info *c)   { return 0; }
+static inline int dbg_is_chk_orph(const struct ubifs_info *c)     { return 0; }
+static inline int dbg_is_chk_old_idx(const struct ubifs_info *c)  { return 0; }
+static inline int dbg_is_chk_lprops(const struct ubifs_info *c)   { return 0; }
+static inline int dbg_is_chk_fs(const struct ubifs_info *c)       { return 0; }
+static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)    { return 0; }
 
 static inline int dbg_debugfs_init(void)                          { return 0; }
 static inline void dbg_debugfs_exit(void)                         { return; }
diff --git a/fs/ubifs/dir.c b/fs/ubifs/dir.c
index 98014bf..6834920 100644
--- a/fs/ubifs/dir.c
+++ b/fs/ubifs/dir.c
@@ -176,7 +176,7 @@ static int dbg_check_name(const struct ubifs_info *c,
 			  const struct ubifs_dent_node *dent,
 			  const struct qstr *nm)
 {
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 	if (le16_to_cpu(dent->nlen) != nm->len)
 		return -EINVAL;
diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index affea94..fabfb53 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -752,7 +752,7 @@ static int dbg_check_bud_bytes(struct ubifs_info *c)
 	struct ubifs_bud *bud;
 	long long bud_bytes = 0;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	spin_lock(&c->buds_lock);
diff --git a/fs/ubifs/lprops.c b/fs/ubifs/lprops.c
index 98b8e73..f8a181e 100644
--- a/fs/ubifs/lprops.c
+++ b/fs/ubifs/lprops.c
@@ -860,7 +860,7 @@ int dbg_check_cats(struct ubifs_info *c)
 	struct list_head *pos;
 	int i, cat;
 
-	if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
+	if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
 		return 0;
 
 	list_for_each_entry(lprops, &c->empty_list, list) {
@@ -958,7 +958,7 @@ void dbg_check_heap(struct ubifs_info *c, struct ubifs_lpt_heap *heap, int cat,
 {
 	int i = 0, j, err = 0;
 
-	if (!(ubifs_chk_flags & (UBIFS_CHK_GEN | UBIFS_CHK_LPROPS)))
+	if (!dbg_is_chk_gen(c) && !dbg_is_chk_lprops(c))
 		return;
 
 	for (i = 0; i < heap->cnt; i++) {
@@ -1262,7 +1262,7 @@ int dbg_check_lprops(struct ubifs_info *c)
 	int i, err;
 	struct ubifs_lp_stats lst;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	/*
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 04713cd..ab91ca6 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -2226,7 +2226,7 @@ int dbg_check_lpt_nodes(struct ubifs_info *c, struct ubifs_cnode *cnode,
 	struct ubifs_cnode *cn;
 	int num, iip = 0, err;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	while (cnode) {
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index 254e8d3..f8e286b 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -1640,7 +1640,7 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 	int ret;
 	void *buf, *p;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	buf = p = __vmalloc(c->leb_size, GFP_NOFS, PAGE_KERNEL);
@@ -1711,7 +1711,7 @@ int dbg_check_ltab(struct ubifs_info *c)
 {
 	int lnum, err, i, cnt;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	/* Bring the entire tree into memory */
@@ -1754,7 +1754,7 @@ int dbg_chk_lpt_free_spc(struct ubifs_info *c)
 	long long free = 0;
 	int i;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	for (i = 0; i < c->lpt_lebs; i++) {
@@ -1796,7 +1796,7 @@ int dbg_chk_lpt_sz(struct ubifs_info *c, int action, int len)
 	long long chk_lpt_sz, lpt_sz;
 	int err = 0;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_LPROPS))
+	if (!dbg_is_chk_lprops(c))
 		return 0;
 
 	switch (action) {
@@ -2019,7 +2019,7 @@ static int dbg_populate_lsave(struct ubifs_info *c)
 	struct ubifs_lpt_heap *heap;
 	int i;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 	if (random32() & 3)
 		return 0;
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index a5422ff..c542c73 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -929,7 +929,7 @@ static int dbg_check_orphans(struct ubifs_info *c)
 	struct check_info ci;
 	int err;
 
-	if (!(ubifs_chk_flags & UBIFS_CHK_ORPH))
+	if (!dbg_is_chk_orph(c))
 		return 0;
 
 	ci.last_ino = 0;
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index 36216b4..c7df916 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -240,7 +240,7 @@ void ubifs_scanned_corruption(const struct ubifs_info *c, int lnum, int offs,
 	int len;
 
 	ubifs_err("corruption at LEB %d:%d", lnum, offs);
-	if (dbg_failure_mode)
+	if (dbg_is_tst_rcvry(c))
 		return;
 	len = c->leb_size - offs;
 	if (len > 8192)
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index b32a537..526b63c 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -3300,7 +3300,7 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 
 	if (!S_ISREG(inode->i_mode))
 		return 0;
-	if (!(ubifs_chk_flags & UBIFS_CHK_GEN))
+	if (!dbg_is_chk_gen(c))
 		return 0;
 
 	block = (size + UBIFS_BLOCK_SIZE - 1) >> UBIFS_BLOCK_SHIFT;
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index d6fab1a..8959c72 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -23,6 +23,7 @@
 /* This file implements TNC functions for committing */
 
 #include "ubifs.h"
+#include <linux/random.h>
 
 /**
  * make_idx_node - make an index node for fill-the-gaps method of TNC commit.
@@ -381,7 +382,7 @@ static int layout_in_gaps(struct ubifs_info *c, int cnt)
 				c->gap_lebs = NULL;
 				return err;
 			}
-			if (dbg_force_in_the_gaps_enabled()) {
+			if (!dbg_is_chk_gen(c)) {
 				/*
 				 * Do not print scary warnings if the debugging
 				 * option which forces in-the-gaps is enabled.
@@ -689,7 +690,7 @@ static int alloc_idx_lebs(struct ubifs_info *c, int cnt)
 		c->ilebs[c->ileb_cnt++] = lnum;
 		dbg_cmt("LEB %d", lnum);
 	}
-	if (dbg_force_in_the_gaps())
+	if (dbg_is_chk_gen(c) && !(random32() & 7))
 		return -ENOSPC;
 	return 0;
 }
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:56 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:56 +0300
Subject: [PATCH 16/30] UBIFS: switch self-check knobs to debugfs
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-17-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

UBIFS has many built-in self-check functions which can be enabled using the
debug_chks module parameter or the corresponding sysfs file
(/sys/module/ubifs/parameters/debug_chks). However, this is not flexible enough
because it is not per-filesystem. This patch moves this to debugfs interfaces.

We already have debugfs support, so this patch just adds more debugfs files.
While looking at debugfs support I've noticed that it is racy WRT file-system
unmount, and added a TODO entry for that. This problem has been there for long
time and it is quite standard debugfs PITA. The plan is to fix this later.

This patch is simple, but it is large because it changes many places where we
check if a particular type of checks is enabled or disabled.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 Documentation/filesystems/ubifs.txt |   26 -------
 fs/ubifs/debug.c                    |  140 ++++++++++++++++++++++++++++++----
 fs/ubifs/debug.h                    |   72 +++++++++---------
 3 files changed, 159 insertions(+), 79 deletions(-)

diff --git a/Documentation/filesystems/ubifs.txt b/Documentation/filesystems/ubifs.txt
index 91ef076..a0a61d2 100644
--- a/Documentation/filesystems/ubifs.txt
+++ b/Documentation/filesystems/ubifs.txt
@@ -111,32 +111,6 @@ The following is an example of the kernel boot arguments to attach mtd0
 to UBI and mount volume "rootfs":
 ubi.mtd=0 root=ubi0:rootfs rootfstype=ubifs
 
-
-Module Parameters for Debugging
-===============================
-
-When UBIFS has been compiled with debugging enabled, there are 2 module
-parameters that are available to control aspects of testing and debugging.
-
-debug_chks	Selects extra checks that UBIFS can do while running:
-
-		Check					Flag value
-
-		General checks				1
-		Check the index				2
-		Check orphan area			8
-		Check LEB properties (lprops)		32
-		Check leaf nodes and inodes		64
-
-debug_tsts	Selects a mode of testing, as follows:
-
-		Test mode				Flag value
-
-		Failure mode for recovery testing	4
-
-For example, set debug_chks to 3 to enable general and TNC checks.
-
-
 References
 ==========
 
diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index a967d68..fdfa5de 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -31,9 +31,9 @@
 
 #include "ubifs.h"
 #include <linux/module.h>
-#include <linux/moduleparam.h>
 #include <linux/debugfs.h>
 #include <linux/math64.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
@@ -42,15 +42,6 @@ DEFINE_SPINLOCK(dbg_lock);
 static char dbg_key_buf0[128];
 static char dbg_key_buf1[128];
 
-unsigned int ubifs_chk_flags;
-unsigned int ubifs_tst_flags;
-
-module_param_named(debug_chks, ubifs_chk_flags, uint, S_IRUGO | S_IWUSR);
-module_param_named(debug_tsts, ubifs_tst_flags, uint, S_IRUGO | S_IWUSR);
-
-MODULE_PARM_DESC(debug_chks, "Debug check flags");
-MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
-
 static const char *get_key_fmt(int fmt)
 {
 	switch (fmt) {
@@ -2886,21 +2877,93 @@ static int open_debugfs_file(struct inode *inode, struct file *file)
 	return nonseekable_open(inode, file);
 }
 
-static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
-				  size_t count, loff_t *ppos)
+static ssize_t dfs_file_read(struct file *file, char __user *u, size_t count,
+			     loff_t *ppos)
+{
+	struct dentry *dent = file->f_path.dentry;
+	struct ubifs_info *c = file->private_data;
+	struct ubifs_debug_info *d = c->dbg;
+	char buf[3];
+	int val;
+
+	if (dent == d->dfs_chk_gen)
+		val = d->chk_gen;
+	else if (dent == d->dfs_chk_index)
+		val = d->chk_index;
+	else if (dent == d->dfs_chk_orph)
+		val = d->chk_orph;
+	else if (dent == d->dfs_chk_lprops)
+		val = d->chk_lprops;
+	else if (dent == d->dfs_chk_fs)
+		val = d->chk_fs;
+	else if (dent == d->dfs_tst_rcvry)
+		val = d->tst_rcvry;
+	else
+		return -EINVAL;
+
+	if (val)
+		buf[0] = '1';
+	else
+		buf[0] = '0';
+	buf[1] = '\n';
+	buf[2] = 0x00;
+
+	return simple_read_from_buffer(u, count, ppos, buf, 2);
+}
+
+static ssize_t dfs_file_write(struct file *file, const char __user *u,
+			      size_t count, loff_t *ppos)
 {
 	struct ubifs_info *c = file->private_data;
 	struct ubifs_debug_info *d = c->dbg;
+	struct dentry *dent = file->f_path.dentry;
+	size_t buf_size;
+	char buf[8];
+	int val;
 
-	if (file->f_path.dentry == d->dfs_dump_lprops)
+	/*
+	 * FIXME: this is racy - the file-system might have already been
+	 * unmounted and we'd oops in this case.
+	 */
+	if (file->f_path.dentry == d->dfs_dump_lprops) {
 		dbg_dump_lprops(c);
-	else if (file->f_path.dentry == d->dfs_dump_budg)
+		return count;
+	}
+	if (file->f_path.dentry == d->dfs_dump_budg) {
 		dbg_dump_budg(c, &c->bi);
-	else if (file->f_path.dentry == d->dfs_dump_tnc) {
+		return count;
+	}
+	if (file->f_path.dentry == d->dfs_dump_tnc) {
 		mutex_lock(&c->tnc_mutex);
 		dbg_dump_tnc(c);
 		mutex_unlock(&c->tnc_mutex);
-	} else
+		return count;
+	}
+
+	buf_size = min_t(size_t, count, (sizeof(buf) - 1));
+	if (copy_from_user(buf, u, buf_size))
+		return -EFAULT;
+
+	if (buf[0] == '1')
+		val = 1;
+	else if (buf[0] == '0')
+		val = 0;
+	else
+		return -EINVAL;
+
+	if (dent == d->dfs_chk_gen)
+		d->chk_gen = val;
+	else if (dent == d->dfs_chk_index)
+		d->chk_index = val;
+	else if (dent == d->dfs_chk_orph)
+		d->chk_orph = val;
+	else if (dent == d->dfs_chk_lprops)
+		d->chk_lprops = val;
+	else if (dent == d->dfs_chk_fs)
+		d->chk_fs = val;
+	else if (dent == d->dfs_tst_rcvry)
+		d->tst_rcvry = val;
+	else
 		return -EINVAL;
 
 	return count;
@@ -2908,7 +2971,8 @@ static ssize_t write_debugfs_file(struct file *file, const char __user *buf,
 
 static const struct file_operations dfs_fops = {
 	.open = open_debugfs_file,
-	.write = write_debugfs_file,
+	.read = dfs_file_read,
+	.write = dfs_file_write,
 	.owner = THIS_MODULE,
 	.llseek = no_llseek,
 };
@@ -2965,6 +3029,48 @@ int dbg_debugfs_init_fs(struct ubifs_info *c)
 		goto out_remove;
 	d->dfs_dump_tnc = dent;
 
+	fname = "chk_general";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_gen = dent;
+
+	fname = "chk_index";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_index = dent;
+
+	fname = "chk_orphans";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_orph = dent;
+
+	fname = "chk_lprops";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_lprops = dent;
+
+	fname = "chk_fs";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_chk_fs = dent;
+
+	fname = "tst_recovery";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, d->dfs_dir, c,
+				   &dfs_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	d->dfs_tst_rcvry = dent;
+
 	return 0;
 
 out_remove:
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 44265a3..8c3bdd3 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -43,11 +43,13 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
  * @old_zroot: old index root - used by 'dbg_check_old_index()'
  * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
  * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
+ *
  * @failure_mode: failure mode for recovery testing
  * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
  * @fail_timeout: time in jiffies when delay of failure mode expires
  * @fail_cnt: current number of calls to failure mode I/O functions
  * @fail_cnt_max: number of calls by which to delay failure mode
+ *
  * @chk_lpt_sz: used by LPT tree size checker
  * @chk_lpt_sz2: used by LPT tree size checker
  * @chk_lpt_wastage: used by LPT tree size checker
@@ -61,21 +63,36 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
  * @saved_free: saved amount of free space
  * @saved_idx_gc_cnt: saved value of @c->idx_gc_cnt
  *
+ * @chk_gen: if general extra checks are enabled
+ * @chk_index: if index xtra checks are enabled
+ * @chk_orph: if orphans extra checks are enabled
+ * @chk_lprops: if lprops extra checks are enabled
+ * @chk_fs: if UBIFS contents extra checks are enabled
+ * @tst_rcvry: if UBIFS recovery testing mode enabled
+ *
  * @dfs_dir_name: name of debugfs directory containing this file-system's files
  * @dfs_dir: direntry object of the file-system debugfs directory
  * @dfs_dump_lprops: "dump lprops" debugfs knob
  * @dfs_dump_budg: "dump budgeting information" debugfs knob
  * @dfs_dump_tnc: "dump TNC" debugfs knob
+ * @dfs_chk_gen: debugfs knob to enable UBIFS general extra checks
+ * @dfs_chk_index: debugfs knob to enable UBIFS index extra checks
+ * @dfs_chk_orph: debugfs knob to enable UBIFS orphans extra checks
+ * @dfs_chk_lprops: debugfs knob to enable UBIFS LEP properties extra checks
+ * @dfs_chk_fs: debugfs knob to enable UBIFS contents extra checks
+ * @dfs_tst_rcvry: debugfs knob to enable UBIFS recovery testing
  */
 struct ubifs_debug_info {
 	struct ubifs_zbranch old_zroot;
 	int old_zroot_level;
 	unsigned long long old_zroot_sqnum;
+
 	int failure_mode;
 	int fail_delay;
 	unsigned long fail_timeout;
 	unsigned int fail_cnt;
 	unsigned int fail_cnt_max;
+
 	long long chk_lpt_sz;
 	long long chk_lpt_sz2;
 	long long chk_lpt_wastage;
@@ -89,11 +106,24 @@ struct ubifs_debug_info {
 	long long saved_free;
 	int saved_idx_gc_cnt;
 
+	unsigned int chk_gen:1;
+	unsigned int chk_index:1;
+	unsigned int chk_orph:1;
+	unsigned int chk_lprops:1;
+	unsigned int chk_fs:1;
+	unsigned int tst_rcvry:1;
+
 	char dfs_dir_name[UBIFS_DFS_DIR_LEN + 1];
 	struct dentry *dfs_dir;
 	struct dentry *dfs_dump_lprops;
 	struct dentry *dfs_dump_budg;
 	struct dentry *dfs_dump_tnc;
+	struct dentry *dfs_chk_gen;
+	struct dentry *dfs_chk_index;
+	struct dentry *dfs_chk_orph;
+	struct dentry *dfs_chk_lprops;
+	struct dentry *dfs_chk_fs;
+	struct dentry *dfs_tst_rcvry;
 };
 
 #define ubifs_assert(expr) do {                                                \
@@ -169,59 +199,29 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 
 extern spinlock_t dbg_lock;
 
-/*
- * Debugging check flags.
- *
- * UBIFS_CHK_GEN: general checks
- * UBIFS_CHK_INDEX: check the index
- * UBIFS_CHK_ORPH: check orphans
- * UBIFS_CHK_LPROPS: check lprops
- * UBIFS_CHK_FS: check the file-system
- */
-enum {
-	UBIFS_CHK_GEN     = 0x1,
-	UBIFS_CHK_INDEX   = 0x2,
-	UBIFS_CHK_ORPH    = 0x8,
-	UBIFS_CHK_LPROPS  = 0x20,
-	UBIFS_CHK_FS      = 0x40,
-};
-
-/*
- * Special testing flags.
- *
- * UBIFS_TST_RCVRY: failure mode for recovery testing
- */
-enum {
-	UBIFS_TST_RCVRY             = 0x4,
-};
-
-extern unsigned int ubifs_msg_flags;
-extern unsigned int ubifs_chk_flags;
-extern unsigned int ubifs_tst_flags;
-
 static inline int dbg_is_chk_gen(const struct ubifs_info *c)
 {
-	return !!(ubifs_chk_flags & UBIFS_CHK_GEN);
+	return c->dbg->chk_gen;
 }
 static inline int dbg_is_chk_index(const struct ubifs_info *c)
 {
-	return !!(ubifs_chk_flags & UBIFS_CHK_INDEX);
+	return c->dbg->chk_index;
 }
 static inline int dbg_is_chk_orph(const struct ubifs_info *c)
 {
-	return !!(ubifs_chk_flags & UBIFS_CHK_ORPH);
+	return c->dbg->chk_orph;
 }
 static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
 {
-	return !!(ubifs_chk_flags & UBIFS_CHK_LPROPS);
+	return c->dbg->chk_lprops;
 }
 static inline int dbg_is_chk_fs(const struct ubifs_info *c)
 {
-	return !!(ubifs_chk_flags & UBIFS_CHK_FS);
+	return c->dbg->chk_fs;
 }
 static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
 {
-	return !!(ubifs_tst_flags & UBIFS_TST_RCVRY);
+	return c->dbg->tst_rcvry;
 }
 
 int ubifs_debugging_init(struct ubifs_info *c);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:05 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:05 +0300
Subject: [PATCH 25/30] UBIFS: switch to ubifs_leb_write
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-26-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Stop using 'ubi_leb_write()' directly and switch to the 'ubifs_leb_write()'
helper.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/io.c |   36 ++++++++++++++----------------------
 1 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index f58f11b..a0c5fb4 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -523,14 +523,10 @@ int ubifs_wbuf_sync_nolock(struct ubifs_wbuf *wbuf)
 	dirt = sync_len - wbuf->used;
 	if (dirt)
 		ubifs_pad(c, wbuf->buf + wbuf->used, dirt);
-	err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-			    sync_len, wbuf->dtype);
-	if (err) {
-		ubifs_err("cannot write %d bytes to LEB %d:%d",
-			  sync_len, wbuf->lnum, wbuf->offs);
-		dbg_dump_stack();
+	err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs, sync_len,
+			      wbuf->dtype);
+	if (err)
 		return err;
-	}
 
 	spin_lock(&wbuf->lock);
 	wbuf->offs += sync_len;
@@ -722,9 +718,9 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		if (aligned_len == wbuf->avail) {
 			dbg_io("flush jhead %s wbuf to LEB %d:%d",
 			       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
-			err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf,
-					    wbuf->offs, wbuf->size,
-					    wbuf->dtype);
+			err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf,
+					      wbuf->offs, wbuf->size,
+					      wbuf->dtype);
 			if (err)
 				goto out;
 
@@ -759,8 +755,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		dbg_io("flush jhead %s wbuf to LEB %d:%d",
 		       dbg_jhead(wbuf->jhead), wbuf->lnum, wbuf->offs);
 		memcpy(wbuf->buf + wbuf->used, buf, wbuf->avail);
-		err = ubi_leb_write(c->ubi, wbuf->lnum, wbuf->buf, wbuf->offs,
-				    wbuf->size, wbuf->dtype);
+		err = ubifs_leb_write(c, wbuf->lnum, wbuf->buf, wbuf->offs,
+				      wbuf->size, wbuf->dtype);
 		if (err)
 			goto out;
 
@@ -778,8 +774,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		 */
 		dbg_io("write %d bytes to LEB %d:%d",
 		       wbuf->size, wbuf->lnum, wbuf->offs);
-		err = ubi_leb_write(c->ubi, wbuf->lnum, buf, wbuf->offs,
-				    wbuf->size, wbuf->dtype);
+		err = ubifs_leb_write(c, wbuf->lnum, buf, wbuf->offs,
+				      wbuf->size, wbuf->dtype);
 		if (err)
 			goto out;
 
@@ -800,8 +796,8 @@ int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len)
 		n <<= c->max_write_shift;
 		dbg_io("write %d bytes to LEB %d:%d", n, wbuf->lnum,
 		       wbuf->offs);
-		err = ubi_leb_write(c->ubi, wbuf->lnum, buf + written,
-				    wbuf->offs, n, wbuf->dtype);
+		err = ubifs_leb_write(c, wbuf->lnum, buf + written,
+				      wbuf->offs, n, wbuf->dtype);
 		if (err)
 			goto out;
 		wbuf->offs += n;
@@ -883,13 +879,9 @@ int ubifs_write_node(struct ubifs_info *c, void *buf, int len, int lnum,
 		return -EROFS;
 
 	ubifs_prepare_node(c, buf, len, 1);
-	err = ubi_leb_write(c->ubi, lnum, buf, offs, buf_len, dtype);
-	if (err) {
-		ubifs_err("cannot write %d bytes to LEB %d:%d, error %d",
-			  buf_len, lnum, offs, err);
+	err = ubifs_leb_write(c, lnum, buf, offs, buf_len, dtype);
+	if (err)
 		dbg_dump_node(c, buf);
-		dbg_dump_stack();
-	}
 
 	return err;
 }
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:04 +0300
Subject: [PATCH 24/30] UBIFS: switch to ubifs_leb_read
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-25-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Instead of using 'ubi_read()' function directly, used the 'ubifs_leb_read()'
helper function instead. This allows to get rid of several redundant error
messages and make sure that we always have a stack dump on read errors.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/io.c         |   15 ++++-----------
 fs/ubifs/lpt.c        |   17 +++++++++--------
 fs/ubifs/lpt_commit.c |   23 +++++++++++------------
 fs/ubifs/recovery.c   |   17 +++++++++--------
 fs/ubifs/replay.c     |    3 +--
 fs/ubifs/sb.c         |    2 +-
 fs/ubifs/scan.c       |    2 +-
 fs/ubifs/tnc.c        |    8 ++++----
 8 files changed, 40 insertions(+), 47 deletions(-)

diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 239899d..f58f11b 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -941,13 +941,9 @@ int ubifs_read_node_wbuf(struct ubifs_wbuf *wbuf, void *buf, int type, int len,
 
 	if (rlen > 0) {
 		/* Read everything that goes before write-buffer */
-		err = ubi_read(c->ubi, lnum, buf, offs, rlen);
-		if (err && err != -EBADMSG) {
-			ubifs_err("failed to read node %d from LEB %d:%d, "
-				  "error %d", type, lnum, offs, err);
-			dbg_dump_stack();
+		err = ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
+		if (err && err != -EBADMSG)
 			return err;
-		}
 	}
 
 	if (type != ch->node_type) {
@@ -1002,12 +998,9 @@ int ubifs_read_node(const struct ubifs_info *c, void *buf, int type, int len,
 	ubifs_assert(!(offs & 7) && offs < c->leb_size);
 	ubifs_assert(type >= 0 && type < UBIFS_NODE_TYPES_CNT);
 
-	err = ubi_read(c->ubi, lnum, buf, offs, len);
-	if (err && err != -EBADMSG) {
-		ubifs_err("cannot read node %d from LEB %d:%d, error %d",
-			  type, lnum, offs, err);
+	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
+	if (err && err != -EBADMSG)
 		return err;
-	}
 
 	if (type != ch->node_type) {
 		ubifs_err("bad node type (%d but expected %d)",
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index ab91ca6..8b9ee9f 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -1222,7 +1222,7 @@ int ubifs_read_nnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 		if (c->big_lpt)
 			nnode->num = calc_nnode_num_from_parent(c, parent, iip);
 	} else {
-		err = ubi_read(c->ubi, lnum, buf, offs, c->nnode_sz);
+		err = ubifs_leb_read(c, lnum, buf, offs, c->nnode_sz, 1);
 		if (err)
 			goto out;
 		err = ubifs_unpack_nnode(c, buf, nnode);
@@ -1291,7 +1291,7 @@ static int read_pnode(struct ubifs_info *c, struct ubifs_nnode *parent, int iip)
 			lprops->flags = ubifs_categorize_lprops(c, lprops);
 		}
 	} else {
-		err = ubi_read(c->ubi, lnum, buf, offs, c->pnode_sz);
+		err = ubifs_leb_read(c, lnum, buf, offs, c->pnode_sz, 1);
 		if (err)
 			goto out;
 		err = unpack_pnode(c, buf, pnode);
@@ -1333,7 +1333,7 @@ static int read_ltab(struct ubifs_info *c)
 	buf = vmalloc(c->ltab_sz);
 	if (!buf)
 		return -ENOMEM;
-	err = ubi_read(c->ubi, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz);
+	err = ubifs_leb_read(c, c->ltab_lnum, buf, c->ltab_offs, c->ltab_sz, 1);
 	if (err)
 		goto out;
 	err = unpack_ltab(c, buf);
@@ -1356,7 +1356,8 @@ static int read_lsave(struct ubifs_info *c)
 	buf = vmalloc(c->lsave_sz);
 	if (!buf)
 		return -ENOMEM;
-	err = ubi_read(c->ubi, c->lsave_lnum, buf, c->lsave_offs, c->lsave_sz);
+	err = ubifs_leb_read(c, c->lsave_lnum, buf, c->lsave_offs,
+			     c->lsave_sz, 1);
 	if (err)
 		goto out;
 	err = unpack_lsave(c, buf);
@@ -1816,8 +1817,8 @@ static struct ubifs_nnode *scan_get_nnode(struct ubifs_info *c,
 		if (c->big_lpt)
 			nnode->num = calc_nnode_num_from_parent(c, parent, iip);
 	} else {
-		err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
-			       c->nnode_sz);
+		err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
+				     c->nnode_sz, 1);
 		if (err)
 			return ERR_PTR(err);
 		err = ubifs_unpack_nnode(c, buf, nnode);
@@ -1885,8 +1886,8 @@ static struct ubifs_pnode *scan_get_pnode(struct ubifs_info *c,
 		ubifs_assert(branch->lnum >= c->lpt_first &&
 			     branch->lnum <= c->lpt_last);
 		ubifs_assert(branch->offs >= 0 && branch->offs < c->leb_size);
-		err = ubi_read(c->ubi, branch->lnum, buf, branch->offs,
-			       c->pnode_sz);
+		err = ubifs_leb_read(c, branch->lnum, buf, branch->offs,
+				     c->pnode_sz, 1);
 		if (err)
 			return ERR_PTR(err);
 		err = unpack_pnode(c, buf, pnode);
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index f13addf..cddd6bd 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -1161,11 +1161,11 @@ static int lpt_gc_lnum(struct ubifs_info *c, int lnum)
 	void *buf = c->lpt_buf;
 
 	dbg_lp("LEB %d", lnum);
-	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-	if (err) {
-		ubifs_err("cannot read LEB %d, error %d", lnum, err);
+
+	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+	if (err)
 		return err;
-	}
+
 	while (1) {
 		if (!is_a_node(c, buf, len)) {
 			int pad_len;
@@ -1651,11 +1651,11 @@ static int dbg_check_ltab_lnum(struct ubifs_info *c, int lnum)
 	}
 
 	dbg_lp("LEB %d", lnum);
-	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-	if (err) {
-		dbg_msg("ubi_read failed, LEB %d, error %d", lnum, err);
+
+	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+	if (err)
 		goto out;
-	}
+
 	while (1) {
 		if (!is_a_node(c, p, len)) {
 			int i, pad_len;
@@ -1902,11 +1902,10 @@ static void dump_lpt_leb(const struct ubifs_info *c, int lnum)
 		return;
 	}
 
-	err = ubi_read(c->ubi, lnum, buf, 0, c->leb_size);
-	if (err) {
-		ubifs_err("cannot read LEB %d, error %d", lnum, err);
+	err = ubifs_leb_read(c, lnum, buf, 0, c->leb_size, 1);
+	if (err)
 		goto out;
-	}
+
 	while (1) {
 		offs = c->leb_size - len;
 		if (!is_a_node(c, p, len)) {
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index c591549..f28070c 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -117,7 +117,7 @@ static int get_master_node(const struct ubifs_info *c, int lnum, void **pbuf,
 	if (!sbuf)
 		return -ENOMEM;
 
-	err = ubi_read(c->ubi, lnum, sbuf, 0, c->leb_size);
+	err = ubifs_leb_read(c, lnum, sbuf, 0, c->leb_size, 0);
 	if (err && err != -EBADMSG)
 		goto out_free;
 
@@ -539,8 +539,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 			int len = ALIGN(endpt, c->min_io_size);
 
 			if (start) {
-				err = ubi_read(c->ubi, lnum, sleb->buf, 0,
-					       start);
+				err = ubifs_leb_read(c, lnum, sleb->buf, 0,
+						     start, 1);
 				if (err)
 					return err;
 			}
@@ -819,7 +819,8 @@ static int get_cs_sqnum(struct ubifs_info *c, int lnum, int offs,
 		return -ENOMEM;
 	if (c->leb_size - offs < UBIFS_CS_NODE_SZ)
 		goto out_err;
-	err = ubi_read(c->ubi, lnum, (void *)cs_node, offs, UBIFS_CS_NODE_SZ);
+	err = ubifs_leb_read(c, lnum, (void *)cs_node, offs,
+			     UBIFS_CS_NODE_SZ, 0);
 	if (err && err != -EBADMSG)
 		goto out_free;
 	ret = ubifs_scan_a_node(c, cs_node, UBIFS_CS_NODE_SZ, lnum, offs, 0);
@@ -930,12 +931,12 @@ static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 		return 0;
 
 	/* Read at the head location and check it is empty flash */
-	err = ubi_read(c->ubi, lnum, sbuf, offs, len);
+	err = ubifs_leb_read(c, lnum, sbuf, offs, len, 1);
 	if (err || !is_empty(sbuf, len)) {
 		dbg_rcvry("cleaning head at %d:%d", lnum, offs);
 		if (offs == 0)
 			return ubifs_leb_unmap(c, lnum);
-		err = ubi_read(c->ubi, lnum, sbuf, 0, offs);
+		err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
 		if (err)
 			return err;
 		return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN);
@@ -1008,7 +1009,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c,
 		return 0;
 	}
 
-	err = ubi_read(c->ubi, lnum, buf, offs, len);
+	err = ubifs_leb_read(c, lnum, buf, offs, len, 0);
 	if (err && err != -EBADMSG)
 		return err;
 
@@ -1453,7 +1454,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
 	if (i_size >= e->d_size)
 		return 0;
 	/* Read the LEB */
-	err = ubi_read(c->ubi, lnum, c->sbuf, 0, c->leb_size);
+	err = ubifs_leb_read(c, lnum, c->sbuf, 0, c->leb_size, 1);
 	if (err)
 		goto out;
 	/* Change the size field and recalculate the CRC */
diff --git a/fs/ubifs/replay.c b/fs/ubifs/replay.c
index 5e97161..ccabaf1 100644
--- a/fs/ubifs/replay.c
+++ b/fs/ubifs/replay.c
@@ -523,8 +523,7 @@ static int is_last_bud(struct ubifs_info *c, struct ubifs_bud *bud)
 	if (!list_is_last(&next->list, &jh->buds_list))
 		return 0;
 
-	err = ubi_read(c->ubi, next->lnum, (char *)&data,
-		       next->start, 4);
+	err = ubifs_leb_read(c, next->lnum, (char *)&data, next->start, 4, 1);
 	if (err)
 		return 0;
 
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index c606f01..701dccc 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -678,7 +678,7 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
 	}
 
 	dbg_mnt("fixup LEB %d, data len %d", lnum, len);
-	err = ubi_read(c->ubi, lnum, c->sbuf, 0, len);
+	err = ubifs_leb_read(c, lnum, c->sbuf, 0, len, 1);
 	if (err)
 		return err;
 
diff --git a/fs/ubifs/scan.c b/fs/ubifs/scan.c
index c7df916..37383e8 100644
--- a/fs/ubifs/scan.c
+++ b/fs/ubifs/scan.c
@@ -148,7 +148,7 @@ struct ubifs_scan_leb *ubifs_start_scan(const struct ubifs_info *c, int lnum,
 	INIT_LIST_HEAD(&sleb->nodes);
 	sleb->buf = sbuf;
 
-	err = ubi_read(c->ubi, lnum, sbuf + offs, offs, c->leb_size - offs);
+	err = ubifs_leb_read(c, lnum, sbuf + offs, offs, c->leb_size - offs, 0);
 	if (err && err != -EBADMSG) {
 		ubifs_err("cannot read %d bytes from LEB %d:%d,"
 			  " error %d", c->leb_size - offs, lnum, offs, err);
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 526b63c..0667386 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -462,7 +462,7 @@ static int try_read_node(const struct ubifs_info *c, void *buf, int type,
 
 	dbg_io("LEB %d:%d, %s, length %d", lnum, offs, dbg_ntype(type), len);
 
-	err = ubi_read(c->ubi, lnum, buf, offs, len);
+	err = ubifs_leb_read(c, lnum, buf, offs, len, 1);
 	if (err) {
 		ubifs_err("cannot read node type %d from LEB %d:%d, error %d",
 			  type, lnum, offs, err);
@@ -1666,7 +1666,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
 	if (!overlap) {
 		/* We may safely unlock the write-buffer and read the data */
 		spin_unlock(&wbuf->lock);
-		return ubi_read(c->ubi, lnum, buf, offs, len);
+		return ubifs_leb_read(c, lnum, buf, offs, len, 0);
 	}
 
 	/* Don't read under wbuf */
@@ -1680,7 +1680,7 @@ static int read_wbuf(struct ubifs_wbuf *wbuf, void *buf, int len, int lnum,
 
 	if (rlen > 0)
 		/* Read everything that goes before write-buffer */
-		return ubi_read(c->ubi, lnum, buf, offs, rlen);
+		return ubifs_leb_read(c, lnum, buf, offs, rlen, 0);
 
 	return 0;
 }
@@ -1767,7 +1767,7 @@ int ubifs_tnc_bulk_read(struct ubifs_info *c, struct bu_info *bu)
 	if (wbuf)
 		err = read_wbuf(wbuf, bu->buf, len, lnum, offs);
 	else
-		err = ubi_read(c->ubi, lnum, bu->buf, offs, len);
+		err = ubifs_leb_read(c, lnum, bu->buf, offs, len, 0);
 
 	/* Check for a race with GC */
 	if (maybe_leb_gced(c, lnum, bu->gc_seq))
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:03 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:03 +0300
Subject: [PATCH 23/30] UBIFS: introduce more I/O helpers
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-24-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Introduce the following I/O helper functions: 'ubifs_leb_read()',
'ubifs_leb_write()', 'ubifs_leb_change()', 'ubifs_leb_unmap()',
'ubifs_leb_map()', 'ubifs_is_mapped().

The idea is to wrap all UBI I/O functions in order to encapsulate various
assertions and error path handling (error message, stack dump, switching to R/O
mode). And there are some other benefits of this which will be used in the
following patches.

This patch does not switch whole UBIFS to use these functions yet.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.h    |   16 +++++++
 fs/ubifs/io.c       |  117 +++++++++++++++++++++++++++++++++++++++++++++++++++
 fs/ubifs/misc.h     |   80 -----------------------------------
 fs/ubifs/recovery.c |    9 ++--
 fs/ubifs/ubifs.h    |   13 +++++-
 5 files changed, 148 insertions(+), 87 deletions(-)

diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index e1dcfd2..b0b005b 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -244,6 +244,10 @@ static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
 {
 	return !!(ubifs_dbg.tst_rcvry || c->dbg->tst_rcvry);
 }
+static inline int dbg_is_power_cut(const struct ubifs_info *c)
+{
+	return !!c->dbg->failure_mode;
+}
 
 int ubifs_debugging_init(struct ubifs_info *c);
 void ubifs_debugging_exit(struct ubifs_info *c);
@@ -445,12 +449,24 @@ static inline int
 dbg_check_nondata_nodes_order(struct ubifs_info *c,
 			      struct list_head *head)             { return 0; }
 
+static inline int dbg_leb_write(struct ubi_volume_desc *desc,
+				int lnum, const void *buf,
+				int offset, int len, int dtype)   { return 0; }
+static inline int dbg_leb_change(struct ubi_volume_desc *desc,
+				 int lnum, const void *buf,
+				 int len, int dtype)              { return 0; }
+static inline int dbg_leb_unmap(struct ubi_volume_desc *desc,
+				int lnum)                         { return 0; }
+static inline int dbg_leb_map(struct ubi_volume_desc *desc,
+			      int lnum, int dtype)                { return 0; }
+
 static inline int dbg_is_chk_gen(const struct ubifs_info *c)      { return 0; }
 static inline int dbg_is_chk_index(const struct ubifs_info *c)    { return 0; }
 static inline int dbg_is_chk_orph(const struct ubifs_info *c)     { return 0; }
 static inline int dbg_is_chk_lprops(const struct ubifs_info *c)   { return 0; }
 static inline int dbg_is_chk_fs(const struct ubifs_info *c)       { return 0; }
 static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)    { return 0; }
+static inline int dbg_is_power_cut(const struct ubifs_info *c)    { return 0; }
 
 static inline int dbg_debugfs_init(void)                          { return 0; }
 static inline void dbg_debugfs_exit(void)                         { return; }
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 48e1680..239899d 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -90,6 +90,123 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
 	}
 }
 
+/*
+ * Below are simple wrappers over UBI I/O functions which include some
+ * additional checks and UBIFS debugging stuff. See corresponding UBI function
+ * for more information.
+ */
+
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+		   int len, int even_ebadmsg)
+{
+	int err;
+
+	err = ubi_read(c->ubi, lnum, buf, offs, len);
+	/*
+	 * In case of %-EBADMSG print the error message only if the
+	 * @even_ebadmsg is true.
+	 */
+	if (err && (err != -EBADMSG || even_ebadmsg)) {
+		ubifs_err("reading %d bytes from LEB %d:%d failed, error %d",
+			  len, lnum, offs, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+		    int len, int dtype)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+	else
+		err = dbg_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+	if (err) {
+		ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
+			  len, lnum, offs, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+		     int dtype)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
+	else
+		err = dbg_leb_change(c->ubi, lnum, buf, len, dtype);
+	if (err) {
+		ubifs_err("changing %d bytes in LEB %d failed, error %d",
+			  len, lnum, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_unmap(c->ubi, lnum);
+	else
+		err = dbg_leb_unmap(c->ubi, lnum);
+	if (err) {
+		ubifs_err("unmap LEB %d failed, error %d", lnum, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
+{
+	int err;
+
+	ubifs_assert(!c->ro_media && !c->ro_mount);
+	if (c->ro_error)
+		return -EROFS;
+	if (!dbg_is_tst_rcvry(c))
+		err = ubi_leb_map(c->ubi, lnum, dtype);
+	else
+		err = dbg_leb_map(c->ubi, lnum, dtype);
+	if (err) {
+		ubifs_err("mapping LEB %d failed, error %d", lnum, err);
+		ubifs_ro_mode(c, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum)
+{
+	int err;
+
+	err = ubi_is_mapped(c->ubi, lnum);
+	if (err < 0) {
+		ubifs_err("ubi_is_mapped failed for LEB %d, error %d",
+			  lnum, err);
+		dbg_dump_stack();
+	}
+	return err;
+}
+
 /**
  * ubifs_check_node - check node.
  * @c: UBIFS file-system description object
diff --git a/fs/ubifs/misc.h b/fs/ubifs/misc.h
index 160cd90..ee7cb5e 100644
--- a/fs/ubifs/misc.h
+++ b/fs/ubifs/misc.h
@@ -145,86 +145,6 @@ static inline int ubifs_wbuf_sync(struct ubifs_wbuf *wbuf)
 }
 
 /**
- * ubifs_leb_unmap - unmap an LEB.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to unmap
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_unmap(const struct ubifs_info *c, int lnum)
-{
-	int err;
-
-	ubifs_assert(!c->ro_media && !c->ro_mount);
-	if (c->ro_error)
-		return -EROFS;
-	err = ubi_leb_unmap(c->ubi, lnum);
-	if (err) {
-		ubifs_err("unmap LEB %d failed, error %d", lnum, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
- * ubifs_leb_write - write to a LEB.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to write
- * @buf: buffer to write from
- * @offs: offset within LEB to write to
- * @len: length to write
- * @dtype: data type
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_write(const struct ubifs_info *c, int lnum,
-				  const void *buf, int offs, int len, int dtype)
-{
-	int err;
-
-	ubifs_assert(!c->ro_media && !c->ro_mount);
-	if (c->ro_error)
-		return -EROFS;
-	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
-	if (err) {
-		ubifs_err("writing %d bytes at %d:%d, error %d",
-			  len, lnum, offs, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
- * ubifs_leb_change - atomic LEB change.
- * @c: UBIFS file-system description object
- * @lnum: LEB number to write
- * @buf: buffer to write from
- * @len: length to write
- * @dtype: data type
- *
- * This function returns %0 on success and a negative error code on failure.
- */
-static inline int ubifs_leb_change(const struct ubifs_info *c, int lnum,
-				   const void *buf, int len, int dtype)
-{
-	int err;
-
-	ubifs_assert(!c->ro_media && !c->ro_mount);
-	if (c->ro_error)
-		return -EROFS;
-	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
-	if (err) {
-		ubifs_err("changing %d bytes in LEB %d, error %d",
-			  len, lnum, err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
  * ubifs_encode_dev - encode device node IDs.
  * @dev: UBIFS device node information
  * @rdev: device IDs to encode
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index 783d8e0..c591549 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -919,8 +919,7 @@ struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int recover_head(const struct ubifs_info *c, int lnum, int offs,
-			void *sbuf)
+static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 {
 	int len = c->max_write_size, err;
 
@@ -962,7 +961,7 @@ static int recover_head(const struct ubifs_info *c, int lnum, int offs,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
+int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf)
 {
 	int err;
 
@@ -993,7 +992,7 @@ int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf)
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-static int clean_an_unclean_leb(const struct ubifs_info *c,
+static int clean_an_unclean_leb(struct ubifs_info *c,
 				struct ubifs_unclean_leb *ucleb, void *sbuf)
 {
 	int err, lnum = ucleb->lnum, offs = 0, len = ucleb->endpt, quiet = 1;
@@ -1089,7 +1088,7 @@ static int clean_an_unclean_leb(const struct ubifs_info *c,
  *
  * This function returns %0 on success and a negative error code on failure.
  */
-int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf)
+int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf)
 {
 	dbg_rcvry("recovery");
 	while (!list_empty(&c->unclean_leb_list)) {
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index 3304aad..702b792 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -1468,6 +1468,15 @@ extern struct ubifs_compressor *ubifs_compressors[UBIFS_COMPR_TYPES_CNT];
 
 /* io.c */
 void ubifs_ro_mode(struct ubifs_info *c, int err);
+int ubifs_leb_read(const struct ubifs_info *c, int lnum, void *buf, int offs,
+		   int len, int even_ebadmsg);
+int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+		    int len, int dtype);
+int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+		     int dtype);
+int ubifs_leb_unmap(struct ubifs_info *c, int lnum);
+int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype);
+int ubifs_is_mapped(const struct ubifs_info *c, int lnum);
 int ubifs_wbuf_write_nolock(struct ubifs_wbuf *wbuf, void *buf, int len);
 int ubifs_wbuf_seek_nolock(struct ubifs_wbuf *wbuf, int lnum, int offs,
 			   int dtype);
@@ -1747,8 +1756,8 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 					 int offs, void *sbuf, int jhead);
 struct ubifs_scan_leb *ubifs_recover_log_leb(struct ubifs_info *c, int lnum,
 					     int offs, void *sbuf);
-int ubifs_recover_inl_heads(const struct ubifs_info *c, void *sbuf);
-int ubifs_clean_lebs(const struct ubifs_info *c, void *sbuf);
+int ubifs_recover_inl_heads(struct ubifs_info *c, void *sbuf);
+int ubifs_clean_lebs(struct ubifs_info *c, void *sbuf);
 int ubifs_rcvry_gc_commit(struct ubifs_info *c);
 int ubifs_recover_size_accum(struct ubifs_info *c, union ubifs_key *key,
 			     int deletion, loff_t new_size);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:06 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:06 +0300
Subject: [PATCH 26/30] UBIFS: switch to I/O helpers
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-27-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Switch the rest of direct UBI calls to UBIFS helper functions.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/log.c      |    4 +---
 fs/ubifs/lpt.c      |   16 ++++++++--------
 fs/ubifs/recovery.c |   14 +++++++-------
 fs/ubifs/sb.c       |    4 ++--
 fs/ubifs/super.c    |    2 +-
 5 files changed, 19 insertions(+), 21 deletions(-)

diff --git a/fs/ubifs/log.c b/fs/ubifs/log.c
index fabfb53..f9fd068 100644
--- a/fs/ubifs/log.c
+++ b/fs/ubifs/log.c
@@ -262,7 +262,7 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
 		 * an unclean reboot, because the target LEB might have been
 		 * unmapped, but not yet physically erased.
 		 */
-		err = ubi_leb_map(c->ubi, bud->lnum, UBI_SHORTTERM);
+		err = ubifs_leb_map(c, bud->lnum, UBI_SHORTTERM);
 		if (err)
 			goto out_unlock;
 	}
@@ -283,8 +283,6 @@ int ubifs_add_bud_to_log(struct ubifs_info *c, int jhead, int lnum, int offs)
 	return 0;
 
 out_unlock:
-	if (err != -EAGAIN)
-		ubifs_ro_mode(c, err);
 	mutex_unlock(&c->log_mutex);
 	kfree(ref);
 	kfree(bud);
diff --git a/fs/ubifs/lpt.c b/fs/ubifs/lpt.c
index 8b9ee9f..6189c74 100644
--- a/fs/ubifs/lpt.c
+++ b/fs/ubifs/lpt.c
@@ -701,8 +701,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
 			memset(p, 0xff, alen - len);
-			err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-					     UBI_SHORTTERM);
+			err = ubifs_leb_change(c, lnum++, buf, alen,
+					       UBI_SHORTTERM);
 			if (err)
 				goto out;
 			p = buf;
@@ -732,8 +732,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 				set_ltab(c, lnum, c->leb_size - alen,
 					    alen - len);
 				memset(p, 0xff, alen - len);
-				err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-						     UBI_SHORTTERM);
+				err = ubifs_leb_change(c, lnum++, buf, alen,
+						       UBI_SHORTTERM);
 				if (err)
 					goto out;
 				p = buf;
@@ -780,8 +780,8 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 			alen = ALIGN(len, c->min_io_size);
 			set_ltab(c, lnum, c->leb_size - alen, alen - len);
 			memset(p, 0xff, alen - len);
-			err = ubi_leb_change(c->ubi, lnum++, buf, alen,
-					     UBI_SHORTTERM);
+			err = ubifs_leb_change(c, lnum++, buf, alen,
+					       UBI_SHORTTERM);
 			if (err)
 				goto out;
 			p = buf;
@@ -806,7 +806,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 		alen = ALIGN(len, c->min_io_size);
 		set_ltab(c, lnum, c->leb_size - alen, alen - len);
 		memset(p, 0xff, alen - len);
-		err = ubi_leb_change(c->ubi, lnum++, buf, alen, UBI_SHORTTERM);
+		err = ubifs_leb_change(c, lnum++, buf, alen, UBI_SHORTTERM);
 		if (err)
 			goto out;
 		p = buf;
@@ -826,7 +826,7 @@ int ubifs_create_dflt_lpt(struct ubifs_info *c, int *main_lebs, int lpt_first,
 
 	/* Write remaining buffer */
 	memset(p, 0xff, alen - len);
-	err = ubi_leb_change(c->ubi, lnum, buf, alen, UBI_SHORTTERM);
+	err = ubifs_leb_change(c, lnum, buf, alen, UBI_SHORTTERM);
 	if (err)
 		goto out;
 
diff --git a/fs/ubifs/recovery.c b/fs/ubifs/recovery.c
index f28070c..51bcf42 100644
--- a/fs/ubifs/recovery.c
+++ b/fs/ubifs/recovery.c
@@ -213,10 +213,10 @@ static int write_rcvrd_mst_node(struct ubifs_info *c,
 	mst->flags |= cpu_to_le32(UBIFS_MST_RCVRY);
 
 	ubifs_prepare_node(c, mst, UBIFS_MST_NODE_SZ, 1);
-	err = ubi_leb_change(c->ubi, lnum, mst, sz, UBI_SHORTTERM);
+	err = ubifs_leb_change(c, lnum, mst, sz, UBI_SHORTTERM);
 	if (err)
 		goto out;
-	err = ubi_leb_change(c->ubi, lnum + 1, mst, sz, UBI_SHORTTERM);
+	err = ubifs_leb_change(c, lnum + 1, mst, sz, UBI_SHORTTERM);
 	if (err)
 		goto out;
 out:
@@ -554,8 +554,8 @@ static int fix_unclean_leb(struct ubifs_info *c, struct ubifs_scan_leb *sleb,
 					ubifs_pad(c, buf, pad_len);
 				}
 			}
-			err = ubi_leb_change(c->ubi, lnum, sleb->buf, len,
-					     UBI_UNKNOWN);
+			err = ubifs_leb_change(c, lnum, sleb->buf, len,
+					       UBI_UNKNOWN);
 			if (err)
 				return err;
 		}
@@ -939,7 +939,7 @@ static int recover_head(struct ubifs_info *c, int lnum, int offs, void *sbuf)
 		err = ubifs_leb_read(c, lnum, sbuf, 0, offs, 1);
 		if (err)
 			return err;
-		return ubi_leb_change(c->ubi, lnum, sbuf, offs, UBI_UNKNOWN);
+		return ubifs_leb_change(c, lnum, sbuf, offs, UBI_UNKNOWN);
 	}
 
 	return 0;
@@ -1069,7 +1069,7 @@ static int clean_an_unclean_leb(struct ubifs_info *c,
 	}
 
 	/* Write back the LEB atomically */
-	err = ubi_leb_change(c->ubi, lnum, sbuf, len, UBI_UNKNOWN);
+	err = ubifs_leb_change(c, lnum, sbuf, len, UBI_UNKNOWN);
 	if (err)
 		return err;
 
@@ -1470,7 +1470,7 @@ static int fix_size_in_place(struct ubifs_info *c, struct size_entry *e)
 		len -= 1;
 	len = ALIGN(len + 1, c->min_io_size);
 	/* Atomically write the fixed LEB back again */
-	err = ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
+	err = ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
 	if (err)
 		goto out;
 	dbg_rcvry("inode %lu at %d:%d size %lld -> %lld",
diff --git a/fs/ubifs/sb.c b/fs/ubifs/sb.c
index 701dccc..93d938a 100644
--- a/fs/ubifs/sb.c
+++ b/fs/ubifs/sb.c
@@ -674,7 +674,7 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
 
 	if (len == 0) {
 		dbg_mnt("unmap empty LEB %d", lnum);
-		return ubi_leb_unmap(c->ubi, lnum);
+		return ubifs_leb_unmap(c, lnum);
 	}
 
 	dbg_mnt("fixup LEB %d, data len %d", lnum, len);
@@ -682,7 +682,7 @@ static int fixup_leb(struct ubifs_info *c, int lnum, int len)
 	if (err)
 		return err;
 
-	return ubi_leb_change(c->ubi, lnum, c->sbuf, len, UBI_UNKNOWN);
+	return ubifs_leb_change(c, lnum, c->sbuf, len, UBI_UNKNOWN);
 }
 
 /**
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 70e8c92..9b2bc56 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -914,7 +914,7 @@ static int check_volume_empty(struct ubifs_info *c)
 
 	c->empty = 1;
 	for (lnum = 0; lnum < c->leb_cnt; lnum++) {
-		err = ubi_is_mapped(c->ubi, lnum);
+		err = ubifs_is_mapped(c, lnum);
 		if (unlikely(err < 0))
 			return err;
 		if (err == 1) {
-- 
1.7.2.3



From dbaryshkov at gmail.com  Thu Jun  9 05:08:09 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 09 Jun 2011 13:08:09 +0400
Subject: Question reg. parsing of mtd partitions
In-Reply-To: <20110609083419.GA23553@doriath.ww600.siemens.net>
References: <20110609083419.GA23553@doriath.ww600.siemens.net>
Message-ID: <4DF08D79.9090707@gmail.com>

On 09.06.2011 12:34, Dmitry Eremin-Solenikov wrote:
> Hello, colleagues,
>
> While doing MTD partitions cleanup I noticed one strange thing.
> parse_mtd_partitions function bears one extra argument (origin)
> which isn't clearly described, set to non-zero only by ixp4xx.c
> driver and then read by redboot partition table handling. I wander if we
> can add some other way to handle this situation and drop this extra 0
> argument from lots of drivers/handlers/etc.
>
> Could you please check it?

At least the ixp4xx part was added by commit f40a6f1cc7fe522,
back in 2006:

If the amount of flash is not divisible by 2 then the mask in
parse_mtd_partitions would fail to work as designed.  Passing in the 
base address corrects this problem.


-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Thu Jun  9 05:05:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:08 +0300
Subject: [PATCH 28/30] UBIFS: remove custom list of superblocks
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-29-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This is a clean-up of the power-cut emulation code - remove the custom list of
superblocks which we maintained to find the superblock by the UBI volume
descriptor. We do not need that crud any longer, because now we can get the
superblock as a function argument.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |  105 ++++++++++-------------------------------------------
 fs/ubifs/debug.h |   31 ++++++++--------
 fs/ubifs/io.c    |    8 ++--
 3 files changed, 39 insertions(+), 105 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 6502657..a0e0c95 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2539,16 +2539,7 @@ error_dump:
 
 #define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
 
-struct failure_mode_info {
-	struct list_head list;
-	struct ubifs_info *c;
-};
-
-static LIST_HEAD(fmi_list);
-static DEFINE_SPINLOCK(fmi_lock);
-
 static unsigned int next;
-
 static int simple_rand(void)
 {
 	if (next == 0)
@@ -2557,69 +2548,15 @@ static int simple_rand(void)
 	return (next >> 16) & 32767;
 }
 
-static void failure_mode_init(struct ubifs_info *c)
-{
-	struct failure_mode_info *fmi;
-
-	fmi = kmalloc(sizeof(struct failure_mode_info), GFP_NOFS);
-	if (!fmi) {
-		ubifs_err("Failed to register failure mode - no memory");
-		return;
-	}
-	fmi->c = c;
-	spin_lock(&fmi_lock);
-	list_add_tail(&fmi->list, &fmi_list);
-	spin_unlock(&fmi_lock);
-}
-
-static void failure_mode_exit(struct ubifs_info *c)
-{
-	struct failure_mode_info *fmi, *tmp;
-
-	spin_lock(&fmi_lock);
-	list_for_each_entry_safe(fmi, tmp, &fmi_list, list)
-		if (fmi->c == c) {
-			list_del(&fmi->list);
-			kfree(fmi);
-		}
-	spin_unlock(&fmi_lock);
-}
-
-static struct ubifs_info *dbg_find_info(struct ubi_volume_desc *desc)
+static int do_fail(struct ubifs_info *c, int lnum, int write)
 {
-	struct failure_mode_info *fmi;
-
-	spin_lock(&fmi_lock);
-	list_for_each_entry(fmi, &fmi_list, list)
-		if (fmi->c->ubi == desc) {
-			struct ubifs_info *c = fmi->c;
-
-			spin_unlock(&fmi_lock);
-			return c;
-		}
-	spin_unlock(&fmi_lock);
-	return NULL;
-}
-
-static int in_failure_mode(struct ubi_volume_desc *desc)
-{
-	struct ubifs_info *c = dbg_find_info(desc);
+	struct ubifs_debug_info *d = c->dbg;
 
-	if (c && dbg_is_tst_rcvry(c))
-		return c->dbg->failure_mode;
-	return 0;
-}
+	ubifs_assert(dbg_is_tst_rcvry(c));
 
-static int do_fail(struct ubi_volume_desc *desc, int lnum, int write)
-{
-	struct ubifs_info *c = dbg_find_info(desc);
-	struct ubifs_debug_info *d;
-
-	if (!c || !dbg_is_tst_rcvry(c))
-		return 0;
-	d = c->dbg;
 	if (d->failure_mode)
 		return 1;
+
 	if (!d->fail_cnt) {
 		/* First call - decide delay to failure */
 		if (chance(1, 2)) {
@@ -2716,17 +2653,17 @@ static void cut_data(const void *buf, int len)
 		p[i] = 0xff;
 }
 
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
 		  int offs, int len, int dtype)
 {
 	int err, failing;
 
-	if (in_failure_mode(desc))
+	if (c->dbg->failure_mode)
 		return -EROFS;
-	failing = do_fail(desc, lnum, 1);
+	failing = do_fail(c, lnum, 1);
 	if (failing)
 		cut_data(buf, len);
-	err = ubi_leb_write(desc, lnum, buf, offs, len, dtype);
+	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
 	if (err)
 		return err;
 	if (failing)
@@ -2734,45 +2671,45 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
 	return 0;
 }
 
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
 		   int len, int dtype)
 {
 	int err;
 
-	if (do_fail(desc, lnum, 1))
+	if (do_fail(c, lnum, 1))
 		return -EROFS;
-	err = ubi_leb_change(desc, lnum, buf, len, dtype);
+	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
 	if (err)
 		return err;
-	if (do_fail(desc, lnum, 1))
+	if (do_fail(c, lnum, 1))
 		return -EROFS;
 	return 0;
 }
 
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
+int dbg_leb_unmap(struct ubifs_info *c, int lnum)
 {
 	int err;
 
-	if (do_fail(desc, lnum, 0))
+	if (do_fail(c, lnum, 0))
 		return -EROFS;
-	err = ubi_leb_unmap(desc, lnum);
+	err = ubi_leb_unmap(c->ubi, lnum);
 	if (err)
 		return err;
-	if (do_fail(desc, lnum, 0))
+	if (do_fail(c, lnum, 0))
 		return -EROFS;
 	return 0;
 }
 
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
+int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
 {
 	int err;
 
-	if (do_fail(desc, lnum, 0))
+	if (do_fail(c, lnum, 0))
 		return -EROFS;
-	err = ubi_leb_map(desc, lnum, dtype);
+	err = ubi_leb_map(c->ubi, lnum, dtype);
 	if (err)
 		return err;
-	if (do_fail(desc, lnum, 0))
+	if (do_fail(c, lnum, 0))
 		return -EROFS;
 	return 0;
 }
@@ -3202,7 +3139,6 @@ int ubifs_debugging_init(struct ubifs_info *c)
 	if (!c->dbg)
 		return -ENOMEM;
 
-	failure_mode_init(c);
 	return 0;
 }
 
@@ -3212,7 +3148,6 @@ int ubifs_debugging_init(struct ubifs_info *c)
  */
 void ubifs_debugging_exit(struct ubifs_info *c)
 {
-	failure_mode_exit(c);
 	kfree(c->dbg);
 }
 
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index b5bc09d..0ab3757 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -305,12 +305,12 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
 int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
-int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		  int offs, int len, int dtype);
-int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		   int len, int dtype);
-int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
+int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
+		  int len, int dtype);
+int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
+		   int dtype);
+int dbg_leb_unmap(struct ubifs_info *c, int lnum);
+int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype);
 
 /* Debugfs-related stuff */
 int dbg_debugfs_init(void);
@@ -442,16 +442,15 @@ static inline int
 dbg_check_nondata_nodes_order(struct ubifs_info *c,
 			      struct list_head *head)             { return 0; }
 
-static inline int dbg_leb_write(struct ubi_volume_desc *desc,
-				int lnum, const void *buf,
-				int offset, int len, int dtype)   { return 0; }
-static inline int dbg_leb_change(struct ubi_volume_desc *desc,
-				 int lnum, const void *buf,
-				 int len, int dtype)              { return 0; }
-static inline int dbg_leb_unmap(struct ubi_volume_desc *desc,
-				int lnum)                         { return 0; }
-static inline int dbg_leb_map(struct ubi_volume_desc *desc,
-			      int lnum, int dtype)                { return 0; }
+static inline int dbg_leb_write(struct ubifs_info *c, int lnum,
+				const void *buf, int offset,
+				int len, int dtype)               { return 0; }
+static inline int dbg_leb_change(struct ubifs_info *c, int lnum,
+				 const void *buf, int len,
+				 int dtype)                       { return 0; }
+static inline int dbg_leb_unmap(struct ubifs_info *c, int lnum)   { return 0; }
+static inline int dbg_leb_map(struct ubifs_info *c, int lnum,
+			      int dtype)                          { return 0; }
 
 static inline int dbg_is_chk_gen(const struct ubifs_info *c)      { return 0; }
 static inline int dbg_is_chk_index(const struct ubifs_info *c)    { return 0; }
diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index a0c5fb4..9228950 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -125,7 +125,7 @@ int ubifs_leb_write(struct ubifs_info *c, int lnum, const void *buf, int offs,
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
 	else
-		err = dbg_leb_write(c->ubi, lnum, buf, offs, len, dtype);
+		err = dbg_leb_write(c, lnum, buf, offs, len, dtype);
 	if (err) {
 		ubifs_err("writing %d bytes to LEB %d:%d failed, error %d",
 			  len, lnum, offs, err);
@@ -146,7 +146,7 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
 	else
-		err = dbg_leb_change(c->ubi, lnum, buf, len, dtype);
+		err = dbg_leb_change(c, lnum, buf, len, dtype);
 	if (err) {
 		ubifs_err("changing %d bytes in LEB %d failed, error %d",
 			  len, lnum, err);
@@ -166,7 +166,7 @@ int ubifs_leb_unmap(struct ubifs_info *c, int lnum)
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_unmap(c->ubi, lnum);
 	else
-		err = dbg_leb_unmap(c->ubi, lnum);
+		err = dbg_leb_unmap(c, lnum);
 	if (err) {
 		ubifs_err("unmap LEB %d failed, error %d", lnum, err);
 		ubifs_ro_mode(c, err);
@@ -185,7 +185,7 @@ int ubifs_leb_map(struct ubifs_info *c, int lnum, int dtype)
 	if (!dbg_is_tst_rcvry(c))
 		err = ubi_leb_map(c->ubi, lnum, dtype);
 	else
-		err = dbg_leb_map(c->ubi, lnum, dtype);
+		err = dbg_leb_map(c, lnum, dtype);
 	if (err) {
 		ubifs_err("mapping LEB %d failed, error %d", lnum, err);
 		ubifs_ro_mode(c, err);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:07 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:07 +0300
Subject: [PATCH 27/30] UBIFS: stop re-defining UBI operations
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-28-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Now when we use UBIFS helpers for all the I/O, we can remove the horrible hack
of re-defining UBI I/O functions.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |    2 --
 fs/ubifs/debug.h |    7 -------
 2 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index a159cfd..6502657 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -27,8 +27,6 @@
  * various local functions of those subsystems.
  */
 
-#define UBIFS_DBG_PRESERVE_UBI
-
 #include "ubifs.h"
 #include <linux/module.h>
 #include <linux/debugfs.h>
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index b0b005b..b5bc09d 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -305,13 +305,6 @@ int dbg_check_inode_size(struct ubifs_info *c, const struct inode *inode,
 int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
 int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
-#ifndef UBIFS_DBG_PRESERVE_UBI
-#define ubi_leb_write  dbg_leb_write
-#define ubi_leb_change dbg_leb_change
-#define ubi_leb_unmap  dbg_leb_unmap
-#define ubi_leb_map    dbg_leb_map
-#endif
-
 int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
 		  int offs, int len, int dtype);
 int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:02 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:02 +0300
Subject: [PATCH 22/30] UBIFS: always print stacktrace when switching to R/O
	mode
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-23-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

When switching to R/O mode due to an I/O error, always dump the stack, not only
when debugging is enabled.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/io.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 3be645e..48e1680 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -86,7 +86,7 @@ void ubifs_ro_mode(struct ubifs_info *c, int err)
 		c->no_chk_data_crc = 0;
 		c->vfs_sb->s_flags |= MS_RDONLY;
 		ubifs_warn("switched to read-only mode, error %d", err);
-		dbg_dump_stack();
+		dump_stack();
 	}
 }
 
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:10 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:10 +0300
Subject: [PATCH 30/30] UBIFS: improve power cut emulation testing
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-31-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This patch cleans-up and improves the power cut testing:

1. Kill custom 'simple_random()' function and use 'random32()' instead.
2. Make timeout larger
3. When cutting the buffer - fill the end with random data sometimes, not
   only with 0xFFs.
4. Some times cut in the middle of the buffer, not always at the end.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   91 +++++++++++++++++++++++++++++------------------------
 1 files changed, 50 insertions(+), 41 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index be45d62..48b6369 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -27,11 +27,12 @@
  * various local functions of those subsystems.
  */
 
-#include "ubifs.h"
 #include <linux/module.h>
 #include <linux/debugfs.h>
 #include <linux/math64.h>
 #include <linux/uaccess.h>
+#include <linux/random.h>
+#include "ubifs.h"
 
 #ifdef CONFIG_UBIFS_FS_DEBUG
 
@@ -2535,17 +2536,10 @@ error_dump:
 	return 0;
 }
 
-/* Failure mode for recovery testing */
-
-#define chance(n, d) (simple_rand() <= (n) * 32768LL / (d))
-
-static unsigned int next;
-static int simple_rand(void)
+static inline int chance(unsigned int n, unsigned int out_of)
 {
-	if (next == 0)
-		next = current->pid;
-	next = next * 1103515245 + 12345;
-	return (next >> 16) & 32767;
+	return !!((random32() % out_of) + 1 <= n);
+
 }
 
 static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
@@ -2557,33 +2551,37 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 	if (!d->pc_cnt) {
 		/* First call - decide delay to the power cut */
 		if (chance(1, 2)) {
-			unsigned int delay = 1 << (simple_rand() >> 11);
+			unsigned long delay;
 
 			if (chance(1, 2)) {
 				d->pc_delay = 1;
-				d->pc_timeout = jiffies +
-						  msecs_to_jiffies(delay);
-				ubifs_warn("failing after %ums", delay);
+				/* Fail withing 1 minute */
+				delay = random32() % 60000;
+				d->pc_timeout = jiffies;
+				d->pc_timeout += msecs_to_jiffies(delay);
+				ubifs_warn("failing after %lums", delay);
 			} else {
 				d->pc_delay = 2;
+				delay = random32() % 10000;
+				/* Fail within 10000 operations */
 				d->pc_cnt_max = delay;
-				ubifs_warn("failing after %u calls", delay);
+				ubifs_warn("failing after %lu calls", delay);
 			}
 		}
+
 		d->pc_cnt += 1;
 	}
+
 	/* Determine if failure delay has expired */
-	if (d->pc_delay == 1) {
-		if (time_before(jiffies, d->pc_timeout))
+	if (d->pc_delay == 1 && time_before(jiffies, d->pc_timeout))
 			return 0;
-	} else if (d->pc_delay == 2)
-		if (d->pc_cnt++ < d->pc_cnt_max)
+	if (d->pc_delay == 2 && d->pc_cnt++ < d->pc_cnt_max)
 			return 0;
+
 	if (lnum == UBIFS_SB_LNUM) {
-		if (write) {
-			if (chance(1, 2))
-				return 0;
-		} else if (chance(19, 20))
+		if (write && chance(1, 2))
+			return 0;
+		if (chance(19, 20))
 			return 0;
 		ubifs_warn("failing in super block LEB %d", lnum);
 	} else if (lnum == UBIFS_MST_LNUM || lnum == UBIFS_MST_LNUM + 1) {
@@ -2591,24 +2589,21 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 			return 0;
 		ubifs_warn("failing in master LEB %d", lnum);
 	} else if (lnum >= UBIFS_LOG_LNUM && lnum <= c->log_last) {
-		if (write) {
-			if (chance(99, 100))
-				return 0;
-		} else if (chance(399, 400))
+		if (write && chance(99, 100))
+			return 0;
+		if (chance(399, 400))
 			return 0;
 		ubifs_warn("failing in log LEB %d", lnum);
 	} else if (lnum >= c->lpt_first && lnum <= c->lpt_last) {
-		if (write) {
-			if (chance(7, 8))
-				return 0;
-		} else if (chance(19, 20))
+		if (write && chance(7, 8))
+			return 0;
+		if (chance(19, 20))
 			return 0;
 		ubifs_warn("failing in LPT LEB %d", lnum);
 	} else if (lnum >= c->orph_first && lnum <= c->orph_last) {
-		if (write) {
-			if (chance(1, 2))
-				return 0;
-		} else if (chance(9, 10))
+		if (write && chance(1, 2))
+			return 0;
+		if (chance(9, 10))
 			return 0;
 		ubifs_warn("failing in orphan LEB %d", lnum);
 	} else if (lnum == c->ihead_lnum) {
@@ -2636,18 +2631,32 @@ static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 	}
 
 	d->pc_happened = 1;
+	ubifs_warn("========== Power cut emulated ==========");
 	dump_stack();
 	return 1;
 }
 
-static void cut_data(const void *buf, int len)
+static void cut_data(const void *buf, unsigned int len)
 {
-	int flen, i;
+	unsigned int from, to, i, ffs = chance(1, 2);
 	unsigned char *p = (void *)buf;
 
-	flen = (len * (long long)simple_rand()) >> 15;
-	for (i = flen; i < len; i++)
-		p[i] = 0xff;
+	from = random32() % (len + 1);
+	if (chance(1, 2))
+		to = random32() % (len - from + 1);
+	else
+		to = len;
+
+	if (from < to)
+		ubifs_warn("filled bytes %u-%u with %s", from, to - 1,
+			   ffs ? "0xFFs" : "random data");
+
+	if (ffs)
+		for (i = from; i < to; i++)
+			p[i] = 0xFF;
+	else
+		for (i = from; i < to; i++)
+			p[i] = random32() % 0x100;
 }
 
 int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:09 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:09 +0300
Subject: [PATCH 29/30] UBIFS: rename recovery testing variables
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-30-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Since the recovery testing is effectively about emulating power cuts by UBIFS,
use "power cut" as the base term for all the related variables and name them
correspondingly. This is just a minor clean-up for the sake of readability.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   52 ++++++++++++++++++++++++++++------------------------
 fs/ubifs/debug.h |   22 +++++++++++-----------
 2 files changed, 39 insertions(+), 35 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index a0e0c95..be45d62 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2548,39 +2548,36 @@ static int simple_rand(void)
 	return (next >> 16) & 32767;
 }
 
-static int do_fail(struct ubifs_info *c, int lnum, int write)
+static int power_cut_emulated(struct ubifs_info *c, int lnum, int write)
 {
 	struct ubifs_debug_info *d = c->dbg;
 
 	ubifs_assert(dbg_is_tst_rcvry(c));
 
-	if (d->failure_mode)
-		return 1;
-
-	if (!d->fail_cnt) {
-		/* First call - decide delay to failure */
+	if (!d->pc_cnt) {
+		/* First call - decide delay to the power cut */
 		if (chance(1, 2)) {
 			unsigned int delay = 1 << (simple_rand() >> 11);
 
 			if (chance(1, 2)) {
-				d->fail_delay = 1;
-				d->fail_timeout = jiffies +
+				d->pc_delay = 1;
+				d->pc_timeout = jiffies +
 						  msecs_to_jiffies(delay);
 				ubifs_warn("failing after %ums", delay);
 			} else {
-				d->fail_delay = 2;
-				d->fail_cnt_max = delay;
+				d->pc_delay = 2;
+				d->pc_cnt_max = delay;
 				ubifs_warn("failing after %u calls", delay);
 			}
 		}
-		d->fail_cnt += 1;
+		d->pc_cnt += 1;
 	}
 	/* Determine if failure delay has expired */
-	if (d->fail_delay == 1) {
-		if (time_before(jiffies, d->fail_timeout))
+	if (d->pc_delay == 1) {
+		if (time_before(jiffies, d->pc_timeout))
 			return 0;
-	} else if (d->fail_delay == 2)
-		if (d->fail_cnt++ < d->fail_cnt_max)
+	} else if (d->pc_delay == 2)
+		if (d->pc_cnt++ < d->pc_cnt_max)
 			return 0;
 	if (lnum == UBIFS_SB_LNUM) {
 		if (write) {
@@ -2638,7 +2635,7 @@ static int do_fail(struct ubifs_info *c, int lnum, int write)
 		ubifs_warn("failing in bud LEB %d commit not running", lnum);
 	}
 
-	d->failure_mode = 1;
+	d->pc_happened = 1;
 	dump_stack();
 	return 1;
 }
@@ -2658,9 +2655,10 @@ int dbg_leb_write(struct ubifs_info *c, int lnum, const void *buf,
 {
 	int err, failing;
 
-	if (c->dbg->failure_mode)
+	if (c->dbg->pc_happened)
 		return -EROFS;
-	failing = do_fail(c, lnum, 1);
+
+	failing = power_cut_emulated(c, lnum, 1);
 	if (failing)
 		cut_data(buf, len);
 	err = ubi_leb_write(c->ubi, lnum, buf, offs, len, dtype);
@@ -2676,12 +2674,14 @@ int dbg_leb_change(struct ubifs_info *c, int lnum, const void *buf,
 {
 	int err;
 
-	if (do_fail(c, lnum, 1))
+	if (c->dbg->pc_happened)
+		return -EROFS;
+	if (power_cut_emulated(c, lnum, 1))
 		return -EROFS;
 	err = ubi_leb_change(c->ubi, lnum, buf, len, dtype);
 	if (err)
 		return err;
-	if (do_fail(c, lnum, 1))
+	if (power_cut_emulated(c, lnum, 1))
 		return -EROFS;
 	return 0;
 }
@@ -2690,12 +2690,14 @@ int dbg_leb_unmap(struct ubifs_info *c, int lnum)
 {
 	int err;
 
-	if (do_fail(c, lnum, 0))
+	if (c->dbg->pc_happened)
+		return -EROFS;
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
 	err = ubi_leb_unmap(c->ubi, lnum);
 	if (err)
 		return err;
-	if (do_fail(c, lnum, 0))
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
 	return 0;
 }
@@ -2704,12 +2706,14 @@ int dbg_leb_map(struct ubifs_info *c, int lnum, int dtype)
 {
 	int err;
 
-	if (do_fail(c, lnum, 0))
+	if (c->dbg->pc_happened)
+		return -EROFS;
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
 	err = ubi_leb_map(c->ubi, lnum, dtype);
 	if (err)
 		return err;
-	if (do_fail(c, lnum, 0))
+	if (power_cut_emulated(c, lnum, 0))
 		return -EROFS;
 	return 0;
 }
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 0ab3757..45174b5 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -44,11 +44,11 @@ typedef int (*dbg_znode_callback)(struct ubifs_info *c,
  * @old_zroot_level: old index root level - used by 'dbg_check_old_index()'
  * @old_zroot_sqnum: old index root sqnum - used by 'dbg_check_old_index()'
  *
- * @failure_mode: failure mode for recovery testing
- * @fail_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
- * @fail_timeout: time in jiffies when delay of failure mode expires
- * @fail_cnt: current number of calls to failure mode I/O functions
- * @fail_cnt_max: number of calls by which to delay failure mode
+ * @pc_happened: non-zero if an emulated power cut happened
+ * @pc_delay: 0=>don't delay, 1=>delay a time, 2=>delay a number of calls
+ * @pc_timeout: time in jiffies when delay of failure mode expires
+ * @pc_cnt: current number of calls to failure mode I/O functions
+ * @pc_cnt_max: number of calls by which to delay failure mode
  *
  * @chk_lpt_sz: used by LPT tree size checker
  * @chk_lpt_sz2: used by LPT tree size checker
@@ -87,11 +87,11 @@ struct ubifs_debug_info {
 	int old_zroot_level;
 	unsigned long long old_zroot_sqnum;
 
-	int failure_mode;
-	int fail_delay;
-	unsigned long fail_timeout;
-	unsigned int fail_cnt;
-	unsigned int fail_cnt_max;
+	int pc_happened;
+	int pc_delay;
+	unsigned long pc_timeout;
+	unsigned int pc_cnt;
+	unsigned int pc_cnt_max;
 
 	long long chk_lpt_sz;
 	long long chk_lpt_sz2;
@@ -246,7 +246,7 @@ static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
 }
 static inline int dbg_is_power_cut(const struct ubifs_info *c)
 {
-	return !!c->dbg->failure_mode;
+	return !!c->dbg->pc_happened;
 }
 
 int ubifs_debugging_init(struct ubifs_info *c);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:01 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:01 +0300
Subject: [PATCH 21/30] UBIFS: remove unused and unneeded debugging function
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-22-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

This patch contains several minor clean-up and preparational cahnges.

1. Remove 'dbg_read()', 'dbg_write()', 'dbg_change()', and 'dbg_leb_erase()'
   functions as they are not used.
2. Remove 'dbg_leb_read()' and 'dbg_is_mapped()' as they are not really needed,
   it is fine to let reads go through in failure mode.
3. Rename 'offset' argument to 'offs' to be consistent with the rest of UBIFS
   code.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |   33 ++-------------------------------
 fs/ubifs/debug.h |   27 +--------------------------
 2 files changed, 3 insertions(+), 57 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 741f939..a159cfd 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2718,16 +2718,8 @@ static void cut_data(const void *buf, int len)
 		p[i] = 0xff;
 }
 
-int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
-		 int len, int check)
-{
-	if (in_failure_mode(desc))
-		return -EROFS;
-	return ubi_leb_read(desc, lnum, buf, offset, len, check);
-}
-
 int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		  int offset, int len, int dtype)
+		  int offs, int len, int dtype)
 {
 	int err, failing;
 
@@ -2736,7 +2728,7 @@ int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
 	failing = do_fail(desc, lnum, 1);
 	if (failing)
 		cut_data(buf, len);
-	err = ubi_leb_write(desc, lnum, buf, offset, len, dtype);
+	err = ubi_leb_write(desc, lnum, buf, offs, len, dtype);
 	if (err)
 		return err;
 	if (failing)
@@ -2759,20 +2751,6 @@ int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
 	return 0;
 }
 
-int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum)
-{
-	int err;
-
-	if (do_fail(desc, lnum, 0))
-		return -EROFS;
-	err = ubi_leb_erase(desc, lnum);
-	if (err)
-		return err;
-	if (do_fail(desc, lnum, 0))
-		return -EROFS;
-	return 0;
-}
-
 int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
 {
 	int err;
@@ -2787,13 +2765,6 @@ int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum)
 	return 0;
 }
 
-int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum)
-{
-	if (in_failure_mode(desc))
-		return -EROFS;
-	return ubi_is_mapped(desc, lnum);
-}
-
 int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
 {
 	int err;
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 43ec5d1..e1dcfd2 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -302,44 +302,19 @@ int dbg_check_data_nodes_order(struct ubifs_info *c, struct list_head *head);
 int dbg_check_nondata_nodes_order(struct ubifs_info *c, struct list_head *head);
 
 #ifndef UBIFS_DBG_PRESERVE_UBI
-#define ubi_leb_read   dbg_leb_read
 #define ubi_leb_write  dbg_leb_write
 #define ubi_leb_change dbg_leb_change
-#define ubi_leb_erase  dbg_leb_erase
 #define ubi_leb_unmap  dbg_leb_unmap
-#define ubi_is_mapped  dbg_is_mapped
 #define ubi_leb_map    dbg_leb_map
 #endif
 
-int dbg_leb_read(struct ubi_volume_desc *desc, int lnum, char *buf, int offset,
-		 int len, int check);
 int dbg_leb_write(struct ubi_volume_desc *desc, int lnum, const void *buf,
-		  int offset, int len, int dtype);
+		  int offs, int len, int dtype);
 int dbg_leb_change(struct ubi_volume_desc *desc, int lnum, const void *buf,
 		   int len, int dtype);
-int dbg_leb_erase(struct ubi_volume_desc *desc, int lnum);
 int dbg_leb_unmap(struct ubi_volume_desc *desc, int lnum);
-int dbg_is_mapped(struct ubi_volume_desc *desc, int lnum);
 int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype);
 
-static inline int dbg_read(struct ubi_volume_desc *desc, int lnum, char *buf,
-			   int offset, int len)
-{
-	return dbg_leb_read(desc, lnum, buf, offset, len, 0);
-}
-
-static inline int dbg_write(struct ubi_volume_desc *desc, int lnum,
-			    const void *buf, int offset, int len)
-{
-	return dbg_leb_write(desc, lnum, buf, offset, len, UBI_UNKNOWN);
-}
-
-static inline int dbg_change(struct ubi_volume_desc *desc, int lnum,
-				    const void *buf, int len)
-{
-	return dbg_leb_change(desc, lnum, buf, len, UBI_UNKNOWN);
-}
-
 /* Debugfs-related stuff */
 int dbg_debugfs_init(void);
 void dbg_debugfs_exit(void);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:05:00 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:05:00 +0300
Subject: [PATCH 20/30] UBIFS: add global debugfs knobs
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-21-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Now we have per-FS (superblock) debugfs knobs, but they have one drawback - you
have to first mount the FS and only after this you can switch self-checks
on/off. But often we want to have the checks enabled during the mount.
Introduce global debugging knobs for this purpose.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |  138 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 fs/ubifs/debug.h |   35 +++++++++++---
 2 files changed, 157 insertions(+), 16 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 91ac72c..741f939 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -3056,7 +3056,7 @@ out_remove:
 	debugfs_remove_recursive(d->dfs_dir);
 out:
 	err = dent ? PTR_ERR(dent) : -ENODEV;
-	ubifs_err("cannot create \"%s\" debugfs filr or directory, error %d\n",
+	ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
 		  fname, err);
 	return err;
 }
@@ -3070,6 +3070,74 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c)
 	debugfs_remove_recursive(c->dbg->dfs_dir);
 }
 
+struct ubifs_global_debug_info ubifs_dbg;
+
+static struct dentry *dfs_chk_gen;
+static struct dentry *dfs_chk_index;
+static struct dentry *dfs_chk_orph;
+static struct dentry *dfs_chk_lprops;
+static struct dentry *dfs_chk_fs;
+static struct dentry *dfs_tst_rcvry;
+
+static ssize_t dfs_global_file_read(struct file *file, char __user *u,
+				    size_t count, loff_t *ppos)
+{
+	struct dentry *dent = file->f_path.dentry;
+	int val;
+
+	if (dent == dfs_chk_gen)
+		val = ubifs_dbg.chk_gen;
+	else if (dent == dfs_chk_index)
+		val = ubifs_dbg.chk_index;
+	else if (dent == dfs_chk_orph)
+		val = ubifs_dbg.chk_orph;
+	else if (dent == dfs_chk_lprops)
+		val = ubifs_dbg.chk_lprops;
+	else if (dent == dfs_chk_fs)
+		val = ubifs_dbg.chk_fs;
+	else if (dent == dfs_tst_rcvry)
+		val = ubifs_dbg.tst_rcvry;
+	else
+		return -EINVAL;
+
+	return provide_user_output(val, u, count, ppos);
+}
+
+static ssize_t dfs_global_file_write(struct file *file, const char __user *u,
+				     size_t count, loff_t *ppos)
+{
+	struct dentry *dent = file->f_path.dentry;
+	int val;
+
+	val = interpret_user_input(u, count);
+	if (val < 0)
+		return val;
+
+	if (dent == dfs_chk_gen)
+		ubifs_dbg.chk_gen = val;
+	else if (dent == dfs_chk_index)
+		ubifs_dbg.chk_index = val;
+	else if (dent == dfs_chk_orph)
+		ubifs_dbg.chk_orph = val;
+	else if (dent == dfs_chk_lprops)
+		ubifs_dbg.chk_lprops = val;
+	else if (dent == dfs_chk_fs)
+		ubifs_dbg.chk_fs = val;
+	else if (dent == dfs_tst_rcvry)
+		ubifs_dbg.tst_rcvry = val;
+	else
+		return -EINVAL;
+
+	return count;
+}
+
+static const struct file_operations dfs_global_fops = {
+	.read = dfs_global_file_read,
+	.write = dfs_global_file_write,
+	.owner = THIS_MODULE,
+	.llseek = no_llseek,
+};
+
 /**
  * dbg_debugfs_init - initialize debugfs file-system.
  *
@@ -3080,15 +3148,67 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c)
  */
 int dbg_debugfs_init(void)
 {
-	dfs_rootdir = debugfs_create_dir("ubifs", NULL);
-	if (IS_ERR_OR_NULL(dfs_rootdir)) {
-		int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;
-		ubifs_err("cannot create \"ubifs\" debugfs directory, "
-			  "error %d\n", err);
-		return err;
-	}
+	int err;
+	const char *fname;
+	struct dentry *dent;
+
+	fname = "ubifs";
+	dent = debugfs_create_dir(fname, NULL);
+	if (IS_ERR_OR_NULL(dent))
+		goto out;
+	dfs_rootdir = dent;
+
+	fname = "chk_general";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_gen = dent;
+
+	fname = "chk_index";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_index = dent;
+
+	fname = "chk_orphans";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_orph = dent;
+
+	fname = "chk_lprops";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_lprops = dent;
+
+	fname = "chk_fs";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_chk_fs = dent;
+
+	fname = "tst_recovery";
+	dent = debugfs_create_file(fname, S_IRUSR | S_IWUSR, dfs_rootdir, NULL,
+				   &dfs_global_fops);
+	if (IS_ERR_OR_NULL(dent))
+		goto out_remove;
+	dfs_tst_rcvry = dent;
 
 	return 0;
+
+out_remove:
+	debugfs_remove_recursive(dfs_rootdir);
+out:
+	err = dent ? PTR_ERR(dent) : -ENODEV;
+	ubifs_err("cannot create \"%s\" debugfs file or directory, error %d\n",
+		  fname, err);
+	return err;
 }
 
 /**
@@ -3096,7 +3216,7 @@ int dbg_debugfs_init(void)
  */
 void dbg_debugfs_exit(void)
 {
-	debugfs_remove(dfs_rootdir);
+	debugfs_remove_recursive(dfs_rootdir);
 }
 
 /**
diff --git a/fs/ubifs/debug.h b/fs/ubifs/debug.h
index 8c3bdd3..43ec5d1 100644
--- a/fs/ubifs/debug.h
+++ b/fs/ubifs/debug.h
@@ -126,6 +126,25 @@ struct ubifs_debug_info {
 	struct dentry *dfs_tst_rcvry;
 };
 
+/**
+ * ubifs_global_debug_info - global (not per-FS) UBIFS debugging information.
+ *
+ * @chk_gen: if general extra checks are enabled
+ * @chk_index: if index xtra checks are enabled
+ * @chk_orph: if orphans extra checks are enabled
+ * @chk_lprops: if lprops extra checks are enabled
+ * @chk_fs: if UBIFS contents extra checks are enabled
+ * @tst_rcvry: if UBIFS recovery testing mode enabled
+ */
+struct ubifs_global_debug_info {
+	unsigned int chk_gen:1;
+	unsigned int chk_index:1;
+	unsigned int chk_orph:1;
+	unsigned int chk_lprops:1;
+	unsigned int chk_fs:1;
+	unsigned int tst_rcvry:1;
+};
+
 #define ubifs_assert(expr) do {                                                \
 	if (unlikely(!(expr))) {                                               \
 		printk(KERN_CRIT "UBIFS assert failed in %s at %u (pid %d)\n", \
@@ -162,6 +181,8 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 #define DBGKEY(key) dbg_key_str0(c, (key))
 #define DBGKEY1(key) dbg_key_str1(c, (key))
 
+extern spinlock_t dbg_lock;
+
 #define ubifs_dbg_msg(type, fmt, ...) do {                        \
 	spin_lock(&dbg_lock);                                     \
 	pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__); \
@@ -197,31 +218,31 @@ const char *dbg_key_str1(const struct ubifs_info *c,
 /* Additional recovery messages */
 #define dbg_rcvry(fmt, ...) ubifs_dbg_msg("rcvry", fmt, ##__VA_ARGS__)
 
-extern spinlock_t dbg_lock;
+extern struct ubifs_global_debug_info ubifs_dbg;
 
 static inline int dbg_is_chk_gen(const struct ubifs_info *c)
 {
-	return c->dbg->chk_gen;
+	return !!(ubifs_dbg.chk_gen || c->dbg->chk_gen);
 }
 static inline int dbg_is_chk_index(const struct ubifs_info *c)
 {
-	return c->dbg->chk_index;
+	return !!(ubifs_dbg.chk_index || c->dbg->chk_index);
 }
 static inline int dbg_is_chk_orph(const struct ubifs_info *c)
 {
-	return c->dbg->chk_orph;
+	return !!(ubifs_dbg.chk_orph || c->dbg->chk_orph);
 }
 static inline int dbg_is_chk_lprops(const struct ubifs_info *c)
 {
-	return c->dbg->chk_lprops;
+	return !!(ubifs_dbg.chk_lprops || c->dbg->chk_lprops);
 }
 static inline int dbg_is_chk_fs(const struct ubifs_info *c)
 {
-	return c->dbg->chk_fs;
+	return !!(ubifs_dbg.chk_fs || c->dbg->chk_fs);
 }
 static inline int dbg_is_tst_rcvry(const struct ubifs_info *c)
 {
-	return c->dbg->tst_rcvry;
+	return !!(ubifs_dbg.tst_rcvry || c->dbg->tst_rcvry);
 }
 
 int ubifs_debugging_init(struct ubifs_info *c);
-- 
1.7.2.3



From dedekind1 at gmail.com  Thu Jun  9 05:04:58 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu,  9 Jun 2011 12:04:58 +0300
Subject: [PATCH 18/30] UBIFS: re-arrange debugging code a bit
In-Reply-To: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
References: <1307610310-28691-1-git-send-email-dedekind1@gmail.com>
Message-ID: <1307610310-28691-19-git-send-email-dedekind1@gmail.com>

From: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>

Move 'dbg_debugfs_init()' and 'dbg_debugfs_exit()' functions which initialize
debugfs for whole UBIFS subsystem below the code which initializes debugfs for
a particular UBIFS instance. And do the same for 'ubifs_debugging_init()' and
'ubifs_debugging_exit()' functions. This layout is a bit better for the next
patches, so this is just a preparation.

Also, rename 'open_debugfs_file()' into 'dfs_file_open()' for consistency.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/debug.c |  118 +++++++++++++++++++++++++++---------------------------
 1 files changed, 59 insertions(+), 59 deletions(-)

diff --git a/fs/ubifs/debug.c b/fs/ubifs/debug.c
index 05fae3f..515658c 100644
--- a/fs/ubifs/debug.c
+++ b/fs/ubifs/debug.c
@@ -2808,70 +2808,13 @@ int dbg_leb_map(struct ubi_volume_desc *desc, int lnum, int dtype)
 	return 0;
 }
 
-/**
- * ubifs_debugging_init - initialize UBIFS debugging.
- * @c: UBIFS file-system description object
- *
- * This function initializes debugging-related data for the file system.
- * Returns zero in case of success and a negative error code in case of
- * failure.
- */
-int ubifs_debugging_init(struct ubifs_info *c)
-{
-	c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
-	if (!c->dbg)
-		return -ENOMEM;
-
-	failure_mode_init(c);
-	return 0;
-}
-
-/**
- * ubifs_debugging_exit - free debugging data.
- * @c: UBIFS file-system description object
- */
-void ubifs_debugging_exit(struct ubifs_info *c)
-{
-	failure_mode_exit(c);
-	kfree(c->dbg);
-}
-
 /*
  * Root directory for UBIFS stuff in debugfs. Contains sub-directories which
  * contain the stuff specific to particular file-system mounts.
  */
 static struct dentry *dfs_rootdir;
 
-/**
- * dbg_debugfs_init - initialize debugfs file-system.
- *
- * UBIFS uses debugfs file-system to expose various debugging knobs to
- * user-space. This function creates "ubifs" directory in the debugfs
- * file-system. Returns zero in case of success and a negative error code in
- * case of failure.
- */
-int dbg_debugfs_init(void)
-{
-	dfs_rootdir = debugfs_create_dir("ubifs", NULL);
-	if (IS_ERR_OR_NULL(dfs_rootdir)) {
-		int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;
-		ubifs_err("cannot create \"ubifs\" debugfs directory, "
-			  "error %d\n", err);
-		return err;
-	}
-
-	return 0;
-}
-
-/**
- * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
- */
-void dbg_debugfs_exit(void)
-{
-	debugfs_remove(dfs_rootdir);
-}
-
-static int open_debugfs_file(struct inode *inode, struct file *file)
+static int dfs_file_open(struct inode *inode, struct file *file)
 {
 	file->private_data = inode->i_private;
 	return nonseekable_open(inode, file);
@@ -2970,7 +2913,7 @@ static ssize_t dfs_file_write(struct file *file, const char __user *u,
 }
 
 static const struct file_operations dfs_fops = {
-	.open = open_debugfs_file,
+	.open = dfs_file_open,
 	.read = dfs_file_read,
 	.write = dfs_file_write,
 	.owner = THIS_MODULE,
@@ -3091,4 +3034,61 @@ void dbg_debugfs_exit_fs(struct ubifs_info *c)
 	debugfs_remove_recursive(c->dbg->dfs_dir);
 }
 
+/**
+ * dbg_debugfs_init - initialize debugfs file-system.
+ *
+ * UBIFS uses debugfs file-system to expose various debugging knobs to
+ * user-space. This function creates "ubifs" directory in the debugfs
+ * file-system. Returns zero in case of success and a negative error code in
+ * case of failure.
+ */
+int dbg_debugfs_init(void)
+{
+	dfs_rootdir = debugfs_create_dir("ubifs", NULL);
+	if (IS_ERR_OR_NULL(dfs_rootdir)) {
+		int err = dfs_rootdir ? PTR_ERR(dfs_rootdir) : -ENODEV;
+		ubifs_err("cannot create \"ubifs\" debugfs directory, "
+			  "error %d\n", err);
+		return err;
+	}
+
+	return 0;
+}
+
+/**
+ * dbg_debugfs_exit - remove the "ubifs" directory from debugfs file-system.
+ */
+void dbg_debugfs_exit(void)
+{
+	debugfs_remove(dfs_rootdir);
+}
+
+/**
+ * ubifs_debugging_init - initialize UBIFS debugging.
+ * @c: UBIFS file-system description object
+ *
+ * This function initializes debugging-related data for the file system.
+ * Returns zero in case of success and a negative error code in case of
+ * failure.
+ */
+int ubifs_debugging_init(struct ubifs_info *c)
+{
+	c->dbg = kzalloc(sizeof(struct ubifs_debug_info), GFP_KERNEL);
+	if (!c->dbg)
+		return -ENOMEM;
+
+	failure_mode_init(c);
+	return 0;
+}
+
+/**
+ * ubifs_debugging_exit - free debugging data.
+ * @c: UBIFS file-system description object
+ */
+void ubifs_debugging_exit(struct ubifs_info *c)
+{
+	failure_mode_exit(c);
+	kfree(c->dbg);
+}
+
 #endif /* CONFIG_UBIFS_FS_DEBUG */
-- 
1.7.2.3



From dbaryshkov at gmail.com  Thu Jun  9 05:23:31 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 9 Jun 2011 13:23:31 +0400
Subject: Question reg. parsing of mtd partitions
In-Reply-To: <4DF08D79.9090707@gmail.com>
References: <20110609083419.GA23553@doriath.ww600.siemens.net>
	<4DF08D79.9090707@gmail.com>
Message-ID: <BANLkTi=rBr0YS9vApbhTGJLEWAsfWWu8Fg@mail.gmail.com>

On 6/9/11, Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> wrote:
> On 09.06.2011 12:34, Dmitry Eremin-Solenikov wrote:
>> Hello, colleagues,
>>
>> While doing MTD partitions cleanup I noticed one strange thing.
>> parse_mtd_partitions function bears one extra argument (origin)
>> which isn't clearly described, set to non-zero only by ixp4xx.c
>> driver and then read by redboot partition table handling. I wander if we
>> can add some other way to handle this situation and drop this extra 0
>> argument from lots of drivers/handlers/etc.
>>
>> Could you please check it?
>
> At least the ixp4xx part was added by commit f40a6f1cc7fe522,
> back in 2006:
>
> If the amount of flash is not divisible by 2 then the mask in
> parse_mtd_partitions would fail to work as designed.  Passing in the
> base address corrects this problem.

Found the original patch/report at
http://thread.gmane.org/gmane.linux.ports.arm.kernel/24662

Awaiting for comments on this.

-- 
With best wishes
Dmitry


From gilles.ganault at free.fr  Thu Jun  9 06:24:22 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 09 Jun 2011 12:24:22 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
Message-ID: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>

Hello

	I went through the docs/FAQs on the site and elsewhere, and
proceeded to create a Ubifs root filesystem and flash a NAND partition
with it.
However, "ubiattach" fails, so I guess I didn't use the right settings
in mkfs.ubifs and/or ubinize and/or ubiformat for use with that NAND
partition.

Here are the steps I took:
==============
#First, get infos about NAND
appliance:/> mtdinfo /dev/mtd2 -u
mtd2
Name:                           filesystem_nand
Type:                           nand
Eraseblock size:                131072 bytes, 128.0 KiB
Amount of eraseblocks:          1984 (260046848 bytes, 248.0 MiB)
Minimum input/output unit size: 2048 bytes
Sub-page size:                  512 bytes
OOB size:                       64 bytes
Character device major/minor:   90:4
Bad blocks are allowed:         true
Device is writable:             true
Default UBI VID header offset:  512
Default UBI data offset:        2048
Default UBI LEB size:           129024 bytes, 126.0 KiB
Maximum UBI volumes count:      128
==============
#Create root filesystem
ubuntu:/> mkfs.ubifs --squash-uids -m 2048 -e 131072 -c 1984 -d
./romfs -D device_table-min.txt -o ./images/rootfs.ubifs

#ubinize image
ubuntu:/> cat ubi.cfg
[ubifs]
mode=ubi
image=./images/rootfs.ubifs
vol_id=0
vol_size=248MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

ubuntu:/> ubinize -o rootfs.ubi.img -m 2048 -p 128KiB -s 512 ./ubi.cfg
==============
appliance:/> ubiformat /dev/mtd2 -s 512 -f rootfs.ubi.img

appliance:/> ubiattach /dev/ubi_ctrl -m 2
UBI: attaching mtd2 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: vtbl_check: too large reserved_pebs 2016, good PEBs 1984
UBI error: vtbl_check: volume table check failed: record 0, error 9
UBI error: ubi_attach_mtd_dev: failed to attach by scanning, error -22
ubiattach: error!: cannot attach mtd2
           error 22 (Invalid argument)
==============

Any idea what I did wrong?

Thank you.



From dbaryshkov at gmail.com  Thu Jun  9 06:54:41 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 14:54:41 +0400
Subject: [PATCH] mtd: edb7312: correctly pass MTD name to parsers
Message-ID: <1307616881-13941-1-git-send-email-dbaryshkov@gmail.com>

cmdline partitions parser expects MTD name at mtd->name, instead of
origin, while edb7312 passes MTDID as origin. Fix that.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/edb7312.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
index fe42a21..b07acd6 100644
--- a/drivers/mtd/maps/edb7312.c
+++ b/drivers/mtd/maps/edb7312.c
@@ -88,8 +88,9 @@ static int __init init_edb7312nor(void)
 	}
 	if (mymtd) {
 		mymtd->owner = THIS_MODULE;
+		mymtd->name = MTDID;
 
-		mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, MTDID);
+		mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
 		if (mtd_parts_nb > 0)
 			part_type = "detected";
 
-- 
1.7.5.3



From dedekind1 at gmail.com  Thu Jun  9 08:10:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 15:10:34 +0300
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <BANLkTimXGmANdV663BP2CLKZTJyzD+QLhQ@mail.gmail.com>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
	<1307421266.11104.10.camel@localhost>
	<BANLkTikKVMQFxtE0S1VL4-SUPWNydgexLw@mail.gmail.com>
	<1307542265.31223.97.camel@localhost>
	<BANLkTimXGmANdV663BP2CLKZTJyzD+QLhQ@mail.gmail.com>
Message-ID: <1307621434.7374.78.camel@localhost>

On Wed, 2011-06-08 at 13:50 -0400, Matthew L. Creech wrote:
> On Wed, Jun 8, 2011 at 10:11 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >
> > Yes, it does look like this LEB might be garbage-collected. But it does
> > not have to be.
> >
> > Anyway, what I can suggest you is to do several things.
> >
> > 1. If you have many occasions of such error, try to gather some
> >   information about how the device was used, and if it was uncleanly
> >   power-cut. Remember, I often saw that embedded devices have incorrect
> >   reboot. Whe users reboot it "normally" - it does not try to unmount
> >   the FS-es cleanly and just jumps to som HW reset function.
> >
> >   You can verify this by rebooting normally and checking if UBIFS says
> >   "recovery needed" or not. If it does - the reboot was not normal.
> >
> 
> Yes, it currently reboots uncleanly (though it does do a "sync"
> first).  I noticed this a while back, and the next release firmware
> will have it fixed.  However, it doesn't make a huge difference to us,
> because these devices are probably more likely to experience power
> loss than a software reboot, in the field at least.
> 
> > 2. This error may be due to memory corruptions in some driver (e.g.,
> >   wireless or video), due to issues in the mtd driver, etc. Try to
> >   stress your system with slub/slab full checks enabled, and other
> >   debugging features which you can find in the "hacking" section of
> >   make menuconfig.
> >
> 
> Will do.
> 
> > 3. If my theory is true, then what may help is adding a check it
> >   ubifs recovery function. The recovery ends with an ubifs_leb_change()
> >   call. You need to check the last node there - is it full and correct?
> >   If not, you should print a loud warning and information like leb dump
> >   _before_ the change, and dump of the buffer which we are going to
> >   write with ubifs_leb_change().
> >
> >   You'd probably need to deploy this check to the field if this issue
> >   is not easy to reproduce. If you have then this info you may fix the
> >   bug.
> >
> 
> Great, I'll add this check and see if we get any hits.  Even if it
> takes a while to hit it in the field, this would at least give us a
> way to make some progress in finding the issue.

With my latest code-base, I am able to inject a hack into
ubifs_leb_change() - but this function does not exist in your code-base.
Anyway, I'm currently running power cut emulation testing with the
following hack:



From Artem.Bityutskiy at nokia.com  Thu Jun  9 08:08:59 2011
From: Artem.Bityutskiy at nokia.com (Artem Bityutskiy)
Date: Thu, 9 Jun 2011 15:08:59 +0300
Subject: [PATCH] UBIFS: temporary: hack to check recovery
Message-ID: <mailman.13.1307621700.24103.linux-mtd@lists.infradead.org>

We suspect that recovery cuts nodes sometimes. This is the hack which should
catch such things. We hack ubifs_change_leb and scan the leb right after
changing it - if we wrote corrupted data there, scan should fail.

Signed-off-by: Artem Bityutskiy <Artem.Bityutskiy at nokia.com>
---
 fs/ubifs/io.c |   24 ++++++++++++++++++++++++
 1 files changed, 24 insertions(+), 0 deletions(-)

diff --git a/fs/ubifs/io.c b/fs/ubifs/io.c
index 9228950..9f7dbbf 100644
--- a/fs/ubifs/io.c
+++ b/fs/ubifs/io.c
@@ -153,6 +153,30 @@ int ubifs_leb_change(struct ubifs_info *c, int lnum, const void *buf, int len,
 		ubifs_ro_mode(c, err);
 		dbg_dump_stack();
 	}
+
+	/* Temporary hack to catch incorrect recovery, if we have such */
+	if (!err && (lnum < c->lpt_first || lnum > c->lpt_last)) {
+		void *buf = vmalloc(c->leb_size);
+		struct ubifs_scan_leb *sleb;
+
+		if (!buf)
+			return 0;
+
+		sleb = ubifs_scan(c, lnum, 0, buf, 0);
+		if (!IS_ERR(sleb)) {
+			/* Scan succeeded */
+			vfree(buf);
+			return 0;
+		}
+
+		ubifs_err("scanning after LEB %d change failed, error %d!", lnum, err);
+		print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 32, 1,
+			       buf, c->leb_size, 1);
+		dump_stack();
+		vfree(buf);
+		return -EINVAL;
+	}
+
 	return err;
 }
 
-- 
1.7.2.3



-- 
Best Regards,
Artem Bityutskiy (?????????? ????????????????)



From dedekind1 at gmail.com  Thu Jun  9 08:20:37 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 15:20:37 +0300
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
In-Reply-To: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
Message-ID: <1307622037.7374.81.camel@localhost>

On Thu, 2011-06-09 at 12:24 +0200, Gilles wrote:
> Hello
> 
> 	I went through the docs/FAQs on the site and elsewhere, and
> proceeded to create a Ubifs root filesystem and flash a NAND partition
> with it.
> However, "ubiattach" fails, so I guess I didn't use the right settings
> in mkfs.ubifs and/or ubinize and/or ubiformat for use with that NAND
> partition.
> 
> Here are the steps I took:
> ==============
> #First, get infos about NAND
> appliance:/> mtdinfo /dev/mtd2 -u
> mtd2
> Name:                           filesystem_nand
> Type:                           nand
> Eraseblock size:                131072 bytes, 128.0 KiB
> Amount of eraseblocks:          1984 (260046848 bytes, 248.0 MiB)
> Minimum input/output unit size: 2048 bytes
> Sub-page size:                  512 bytes
> OOB size:                       64 bytes
> Character device major/minor:   90:4
> Bad blocks are allowed:         true
> Device is writable:             true
> Default UBI VID header offset:  512
> Default UBI data offset:        2048
> Default UBI LEB size:           129024 bytes, 126.0 KiB
> Maximum UBI volumes count:      128
> ==============
> #Create root filesystem
> ubuntu:/> mkfs.ubifs --squash-uids -m 2048 -e 131072 -c 1984 -d

Use  -e 129024

P.S. Yes, I realize the options are inconsistent, and will happily
accept a clean-up :-)

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 08:22:37 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 15:22:37 +0300
Subject: [PATCH] mtd: edb7312: correctly pass MTD name to parsers
In-Reply-To: <1307616881-13941-1-git-send-email-dbaryshkov@gmail.com>
References: <1307616881-13941-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307622157.7374.82.camel@localhost>

On Thu, 2011-06-09 at 14:54 +0400, Dmitry Eremin-Solenikov wrote:
> cmdline partitions parser expects MTD name at mtd->name, instead of
> origin, while edb7312 passes MTDID as origin. Fix that.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From gilles.ganault at free.fr  Thu Jun  9 08:31:46 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 09 Jun 2011 14:31:46 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<1307622037.7374.81.camel@localhost>
Message-ID: <m3f1v61in4l13ths5ibps1n3gvu159ia2k@4ax.com>

On Thu, 09 Jun 2011 15:20:37 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>> Default UBI LEB size:           129024 bytes, 126.0 KiB
>> Maximum UBI volumes count:      128
>> ==============
>> #Create root filesystem
>> ubuntu:/> mkfs.ubifs --squash-uids -m 2048 -e 131072 -c 1984 -d
>
>Use  -e 129024

Thanks Artem, but I'm still getting the error :-/

Here's what I did:
========================
ubuntu:/> mkfs.ubifs --squash-uids -m 2048 -e 129024 -c 1984 -d
./romfs -D device_table-min.txt -o ./images/rootfs.ubifs

ubuntu:/> cat ubi.cfg
[ubifs]
mode=ubi
image=./images/rootfs.ubifs
vol_id=0
;What size to use?
vol_size=248MiB
vol_type=dynamic
vol_name=rootfs
vol_flags=autoresize

ubuntu:/> ubinize -o rootfs.ubi.img -m 2048 -p 128KiB -s 512 ./ubi.cfg
ubuntu:/> mv rootfs.ubi.img /var/www

appliance:> cd /var/tmp ; wget -c http://192.168.0.3/rootfs.ubi.img

appliance:> ubiformat /dev/mtd2 -s 512 -f rootfs.ubi.img

appliance:> ubiattach /dev/ubi_ctrl -m 2
UBI: attaching mtd2 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: vtbl_check: too large reserved_pebs 2016, good PEBs 1984
UBI error: vtbl_check: volume table check failed: record 0, error 9
UBI error: ubi_attach_mtd_dev: failed to attach by scanning, error -22
ubiattach: error!: cannot attach mtd2
           error 22 (Invalid argument)
========================

According to some out-of-band information, "In most cases, the formula
for the offset boils down to: LEB_size = PEB_size - (((Subpage_size +
Page_size) * Page_size) / Page_size)".

So, using the infos provided by mtdinfo, I find this: 131.072 - (((
512 + 2.048) * 2.048 ) / 2.048 ) = 128.512

Should I use that number instead of 129024?

Also, I wonder if maybe I should leave some room in the NAND partition
for the Ubifs journal + error log? I used vol_size=248MiB in ubi.cfg,
but maybe this is too big?



From david.wagner at free-electrons.com  Thu Jun  9 08:42:08 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Thu, 09 Jun 2011 14:42:08 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
In-Reply-To: <7.0.1.0.2.20110609135430.06967d28@free.fr>
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<4DF0B36E.2020605@free-electrons.com>
	<7.0.1.0.2.20110609135430.06967d28@free.fr>
Message-ID: <4DF0BFA0.4030402@free-electrons.com>

On 06/09/2011 02:26 PM, Gilles Ganault wrote:
> Hello
> 
> At 13:50 09/06/2011, you wrote:
>> > Eraseblock size:                131072 bytes, 128.0 KiB
>> >  [...]
>> > Default UBI LEB size:           129024 bytes, 126.0 KiB
>> > Maximum UBI volumes count:      128
>> > ==============
>> > #Create root filesystem
>> > ubuntu:/> mkfs.ubifs --squash-uids -m 2048 -e 131072 -c 1984 -d
>> > ./romfs -D device_table-min.txt -o ./images/rootfs.ubifs
>> >
>>
>> The -e option of mkfs.ubifs takes the logical eraseblock size.
>> But you specified 131072, the physical eraseblock size.
>> So here, you should have -e 129024
>> The details for computing the LEB size are at
>> http://git.infradead.org/mtd-utils.git/blob/HEAD:/ubi-utils/src/libubigen.c#l40
>>
>> In most cases, the formula for the offset boils down to:
>> LEB_size = PEB_size - (((Subpage_size + Page_size) * Page_size) /
>> Page_size)
> 
> Thanks for the tip, but after recompiling a new root filesystem, I'm
> still getting the same error:
[...]
> BTW, using the formula above, I find this: 131.072 - ((( 512 + 2.048) *
> 2.048 ) / 2.048 ) = 128.512
> 
> I wonder if maybe I should leave some room in the NAND partition for the
> Ubifs journal + error log? I used vol_size=248MiB in ubi.cfg, but maybe
> this is toot big?

(I forgot to reply to all in my first answer)

Oops, sorry, the formula is
((Subpage_size + Page_size)) / Page_size) * Page_size
That is, subpage+page truncated to page.

Maybe you have to take the reserved LEBs into account: 1% of the PEBs.
I'm not sure if they are already included in what mtdinfo displays, though.

-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From david.wagner at free-electrons.com  Thu Jun  9 08:44:46 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Thu, 09 Jun 2011 14:44:46 +0200
Subject: impact of 2X_PROGRAM on read operations
In-Reply-To: <1307370761.3112.76.camel@localhost>
References: <4DECC41F.5060808@free-electrons.com>
	<1307370761.3112.76.camel@localhost>
Message-ID: <4DF0C03E.90909@free-electrons.com>

On 06/06/2011 04:32 PM, Artem Bityutskiy wrote:
> On Mon, 2011-06-06 at 14:12 +0200, David Wagner wrote:
>> Is there a way to safely read without 2X_PROGRAM enabled once it has
>> been flashed with a 2X_PROGRAM-enabled flasher (e.g. patched u-boot).
> 
> Not sure about u-boot, but AFAIK 2x is a completely separate mode which
> gives you I/O speed-up but makes things incompatible with "normal" mode.
> E.g., you can mount JFFS2 only in one of the modes.
> 

Ok, so I guess it doesn't make sense trying to address the issue of
incompatibilities.

I may have to check once again, but I'm pretty sure, however, that I
managed to flash a UBI image with a 2X_PROGRAM-enabled u-boot and read
it with a regular kernel. The u-boot code for 2X_PROGRAM handling seems
to basically be a copy-paste from the kernel.
If the diagram in my first mail is correct, that could not be possible.

Kyungmin, do you know what's wrong in my reasoning ?


Regards,
David Wagner.
-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From dedekind1 at gmail.com  Thu Jun  9 08:38:25 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 15:38:25 +0300
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
In-Reply-To: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
Message-ID: <1307623105.7374.91.camel@localhost>

On Thu, 2011-06-09 at 12:24 +0200, Gilles wrote:
> vol_size=248MiB

Put, say, 230MiB here. 248MiB is the total amount of space. UBI adds
some overhead, so your volume size will be smaller, see here:

http://www.linux-mtd.infradead.org/doc/ubi.html#L_overhead

The autoresize flag that you specified will make sure your volume will
be automatically re-sized to the maximum size when you first attach the
MTD device.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From kmpark at infradead.org  Thu Jun  9 09:01:14 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Thu, 9 Jun 2011 22:01:14 +0900
Subject: impact of 2X_PROGRAM on read operations
In-Reply-To: <4DF0C03E.90909@free-electrons.com>
References: <4DECC41F.5060808@free-electrons.com>
	<1307370761.3112.76.camel@localhost>
	<4DF0C03E.90909@free-electrons.com>
Message-ID: <BANLkTikOR5_XZoh7DWwvcqK2t_fy28=NyQ@mail.gmail.com>

On Thu, Jun 9, 2011 at 9:44 PM, David Wagner
<david.wagner at free-electrons.com> wrote:
> On 06/06/2011 04:32 PM, Artem Bityutskiy wrote:
>> On Mon, 2011-06-06 at 14:12 +0200, David Wagner wrote:
>>> Is there a way to safely read without 2X_PROGRAM enabled once it has
>>> been flashed with a 2X_PROGRAM-enabled flasher (e.g. patched u-boot).
>>
>> Not sure about u-boot, but AFAIK 2x is a completely separate mode which
>> gives you I/O speed-up but makes things incompatible with "normal" mode.
>> E.g., you can mount JFFS2 only in one of the modes.
>>
>
> Ok, so I guess it doesn't make sense trying to address the issue of
> incompatibilities.
>
> I may have to check once again, but I'm pretty sure, however, that I
> managed to flash a UBI image with a 2X_PROGRAM-enabled u-boot and read
> it with a regular kernel. The u-boot code for 2X_PROGRAM handling seems
> to basically be a copy-paste from the kernel.
> If the diagram in my first mail is correct, that could not be possible.
>
> Kyungmin, do you know what's wrong in my reasoning ?
Since we don't know how program hen 2x_program mode. even though
logically BufferRAM0 data will be located block even, BufferRAM1 will
be copied to block odd. but it's not clear.

Can you tried to program the sample 4KiB data when 2X_PROGRAM and read
(block even, page n) and read (block odd, page n) and compare it? then
you can find a difference.

I'm not tried to compare the compatible issue between normal and 2x mode.

Thank you,
Kyungmin Park
>
>
> Regards,
> David Wagner.
> --
> David Wagner, Free Electrons
> Kernel, drivers, real-time and embedded Linux
> development, consulting, training and support.
> http://free-electrons.com
>


From dbaryshkov at gmail.com  Thu Jun  9 10:22:49 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:49 +0400
Subject: [PATCH 00/17] mtd: last pile of MTD partition cleanup patches
Message-ID: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>

Here goes last serie of my current work on cleaning up the MTD partition
handling. Now my goal is to clean up OF partition handling.

The following changes since commit 3e1643b282542cf524d30cfab4cfe38f6b2afa99:

  mtd: edb7312: correctly pass MTD name to parsers (2011-06-09 15:30:44 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup

Dmitry Eremin-Solenikov (17):
      mtd: prepare to convert of_mtd_parse_partitions to partition parser
      mtd: physmap_of: use ofpart through generic parsing
      mtd: m25p80: use ofpart through generic parsing
      mtd: fsl_elbc_nand: use ofpart through generic parsing
      mtd: fsl_upm: use ofpart through generic parsing
      mtd: mpc5121_nfc: use ofpart through generic parsing
      mtd: ndfc: use ofpart through generic parsing
      mtd: socrates_nand: use ofpart through generic parsing
      mtd: drop of_mtd_parse_partitions()
      physmap_of: move parse_obsolete_partitions to become separate parser
      mtd: physmap_of.c: use mtd_device_parse_register
      mtd: m25p80.c: use mtd_device_parse_register
      mtd: fsl_elbc_nand.c: use mtd_device_parse_register
      mtd: fsl_upm.c: use mtd_device_parse_register
      mtd: mpc5121_nfc.c: use mtd_device_parse_register
      mtd: ndfc.c: use mtd_device_parse_register
      mtd: socrates_nand.c: use mtd_device_parse_register

 drivers/mtd/devices/m25p80.c     |   36 ++------------
 drivers/mtd/maps/physmap_of.c    |   79 ++----------------------------
 drivers/mtd/mtdcore.c            |   19 +++++++
 drivers/mtd/mtdpart.c            |    8 ++-
 drivers/mtd/nand/fsl_elbc_nand.c |   16 +-----
 drivers/mtd/nand/fsl_upm.c       |   12 +----
 drivers/mtd/nand/mpc5121_nfc.c   |   16 +-----
 drivers/mtd/nand/ndfc.c          |   15 +-----
 drivers/mtd/nand/socrates_nand.c |   22 +--------
 drivers/mtd/ofpart.c             |   98 ++++++++++++++++++++++++++++++++++++--
 include/linux/mtd/mtd.h          |    5 ++
 include/linux/mtd/partitions.h   |   16 ------
 12 files changed, 144 insertions(+), 198 deletions(-)



From dbaryshkov at gmail.com  Thu Jun  9 10:22:50 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:50 +0400
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions to
	partition parser
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>

Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
1) Register ofpart parser
2) Internally don't use passed device for error printing
3) Add device_node to mtd_info struct
4) Move of_mtd_parse_partitions from __devinit to common text section
5) add ofpart to the default list of partition parsers

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c          |   19 +++++++++++++++++++
 drivers/mtd/mtdpart.c          |    8 ++++++--
 drivers/mtd/ofpart.c           |   30 ++++++++++++++++++++++++++++--
 include/linux/mtd/mtd.h        |    5 +++++
 include/linux/mtd/partitions.h |    2 +-
 5 files changed, 59 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 1326747..2d5b865 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -36,6 +36,7 @@
 #include <linux/idr.h>
 #include <linux/backing-dev.h>
 #include <linux/gfp.h>
+#include <linux/of.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
 			const struct mtd_partition *parts,
 			int nr_parts)
 {
+#ifdef CONFIG_OF
+	if (master->node)
+		of_node_get(master->node);
+#endif
 	return parts ? add_mtd_partitions(master, parts, nr_parts) :
 		add_mtd_device(master);
 }
@@ -487,6 +492,11 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
 	int err;
 	struct mtd_partition *real_parts;
 
+#ifdef CONFIG_OF
+	if (mtd->node)
+		of_node_get(mtd->node);
+#endif
+
 	err = parse_mtd_partitions(mtd, types, &real_parts, origin);
 	if (err <= 0 && nr_parts) {
 		real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
@@ -505,6 +515,11 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
 			err = -ENODEV;
 	}
 
+#ifdef CONFIG_OF
+	if (err < 0 && mtd->node)
+		of_node_put(mtd->node);
+#endif
+
 	return err;
 }
 EXPORT_SYMBOL_GPL(mtd_device_parse_register);
@@ -519,6 +534,10 @@ int mtd_device_unregister(struct mtd_info *master)
 {
 	int err;
 
+#ifdef CONFIG_OF
+	if (master->node)
+		of_node_put(master->node);
+#endif
 	err = del_mtd_partitions(master);
 	if (err)
 		return err;
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 2b71ccb..584fa56 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -729,7 +729,11 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
  * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
  * are changing this array!
  */
-static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
+static const char * const default_mtd_part_types[] = {
+	"cmdlinepart",
+	"ofpart",
+	NULL
+};
 
 /**
  * parse_mtd_partitions - parse MTD partitions
@@ -741,7 +745,7 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  * This function tries to find partition on MTD device @master. It uses MTD
  * partition parsers, specified in @types. However, if @types is %NULL, then
  * the default list of parsers is used. The default list contains only the
- * "cmdlinepart" parser ATM.
+ * "cmdlinepart" and "ofpart" parsers ATM.
  *
  * This function may return:
  * o a negative error code in case of failure
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index a996718..4ac040e 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -20,7 +20,20 @@
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
-int __devinit of_mtd_parse_partitions(struct device *dev,
+static int parse_ofpart_partitions(struct mtd_info *master,
+				   struct mtd_partition **pparts,
+				   unsigned long origin)
+{
+	struct device_node *node;
+
+	node = master->node;
+	if (!node)
+		return 0;
+
+	return of_mtd_parse_partitions(NULL, node, pparts);
+}
+
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts)
 {
@@ -69,7 +82,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 
 	if (!i) {
 		of_node_put(pp);
-		dev_err(dev, "No valid partition found on %s\n", node->full_name);
+		pr_err("No valid partition found on %s\n", node->full_name);
 		kfree(*pparts);
 		*pparts = NULL;
 		return -EINVAL;
@@ -79,4 +92,17 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 }
 EXPORT_SYMBOL(of_mtd_parse_partitions);
 
+static struct mtd_part_parser ofpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofpart_partitions,
+	.name = "ofpart",
+};
+
+static int __init ofpart_parser_init(void)
+{
+	return register_mtd_parser(&ofpart_parser);
+}
+
+module_init(ofpart_parser_init);
+
 MODULE_LICENSE("GPL");
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index d28a241..55fbb60 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -171,6 +171,11 @@ struct mtd_info {
 	// Kernel-only stuff starts here.
 	const char *name;
 	int index;
+#ifdef CONFIG_OF
+	/* Set by driver, reference counting handled by MTD registration/
+	 * unregistration functions. */
+	struct device_node *node;
+#endif
 
 	/* ecc layout structure pointer - read only ! */
 	struct nand_ecclayout *ecclayout;
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 1431cf2..a8bd193 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -74,7 +74,7 @@ struct device;
 struct device_node;
 
 #ifdef CONFIG_MTD_OF_PARTS
-int __devinit of_mtd_parse_partitions(struct device *dev,
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts);
 #else
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:51 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:51 +0400
Subject: [PATCH 02/17] mtd: physmap_of: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-3-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   10 +++-------
 1 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index d251d1d..312eb17 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -165,7 +165,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
+static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+					"ofpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -331,6 +332,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	if (err)
 		goto err_out;
 
+	info->cmtd->node = dp;
 	part_probe_types = of_get_probes(dp);
 	err = parse_mtd_partitions(info->cmtd, part_probe_types,
 				   &info->parts, 0);
@@ -341,12 +343,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	of_free_probes(part_probe_types);
 
 	if (err == 0) {
-		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
-		if (err < 0)
-			goto err_out;
-	}
-
-	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
 		if (err < 0)
 			goto err_out;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:52 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:52 +0400
Subject: [PATCH 03/17] mtd: m25p80: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-4-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 70d5fca..a1cdb52 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -928,6 +928,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 
+	flash->mtd.node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
 
@@ -975,13 +976,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 		nr_parts = data->nr_parts;
 	}
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (nr_parts <= 0 && spi->dev.of_node) {
-		nr_parts = of_mtd_parse_partitions(&spi->dev,
-						   spi->dev.of_node, &parts);
-	}
-#endif
-
 	if (nr_parts > 0) {
 		for (i = 0; i < nr_parts; i++) {
 			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:54 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:54 +0400
Subject: [PATCH 05/17] mtd: fsl_upm: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-6-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 7c782eb..253b8ff 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -175,6 +175,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 
 	fun->mtd.priv = &fun->chip;
 	fun->mtd.owner = THIS_MODULE;
+	fun->mtd.node = flash_np;
 
 	flash_np = of_get_next_child(upm_np, NULL);
 	if (!flash_np)
@@ -193,13 +194,6 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 
 	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, 0);
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
-		if (ret < 0)
-			goto err;
-	}
-#endif
 	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
 err:
 	of_node_put(flash_np);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:53 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:53 +0400
Subject: [PATCH 04/17] mtd: fsl_elbc_nand: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-5-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    9 ++-------
 1 files changed, 2 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index f3384fa..5236840 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -842,7 +842,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct resource res;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
-		= { "cmdlinepart", "RedBoot", NULL };
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
 	struct mtd_partition *parts;
 	int ret;
 	int bank;
@@ -910,6 +910,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 		goto err;
 	}
 
+	priv->mtd.node = pdev->dev.of_node;
 	priv->mtd.name = kasprintf(GFP_KERNEL, "%x.flash", (unsigned)res.start);
 	if (!priv->mtd.name) {
 		ret = -ENOMEM;
@@ -938,12 +939,6 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(priv->dev, node, &parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	mtd_device_register(&priv->mtd, parts, ret);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:55 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:55 +0400
Subject: [PATCH 06/17] mtd: mpc5121_nfc: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-7-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |    5 +----
 1 files changed, 1 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 0b61367..c4e8cb9 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -725,6 +725,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	}
 
 	mtd->name = "MPC5121 NAND";
+	mtd->node = dn;
 	chip->dev_ready = mpc5121_nfc_dev_ready;
 	chip->cmdfunc = mpc5121_nfc_command;
 	chip->read_byte = mpc5121_nfc_read_byte;
@@ -837,10 +838,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 
 	/* Register device in MTD */
 	retval = parse_mtd_partitions(mtd, NULL, &parts, 0);
-#ifdef CONFIG_MTD_OF_PARTS
-	if (retval == 0)
-		retval = of_mtd_parse_partitions(dev, dn, &parts);
-#endif
 	if (retval < 0) {
 		dev_err(dev, "Error parsing MTD partitions!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:56 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:56 +0400
Subject: [PATCH 07/17] mtd: ndfc: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-8-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    8 +-------
 1 files changed, 1 insertions(+), 7 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 70c04ff..1ae94f0 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -188,6 +188,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (!flash_np)
 		return -ENODEV;
 
+	ndfc->mtd.node = flash_np;
 	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
 			dev_name(&ndfc->ofdev->dev), flash_np->name);
 	if (!ndfc->mtd.name) {
@@ -203,13 +204,6 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
-					      &ndfc->parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
 
 err:
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:57 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:57 +0400
Subject: [PATCH 08/17] mtd: socrates_nand: use ofpart through generic parsing
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-9-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 9023ac8..b256491 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -191,6 +191,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	mtd->name = "socrates_nand";
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &ofdev->dev;
+	mtd->node = ofdev->dev.of_node;
 
 	/*should never be accessed directly */
 	nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
@@ -229,16 +230,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto release;
 	}
 
-	if (num_partitions == 0) {
-		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-							 ofdev->dev.of_node,
-							 &partitions);
-		if (num_partitions < 0) {
-			res = num_partitions;
-			goto release;
-		}
-	}
-
 	res = mtd_device_register(mtd, partitions, num_partitions);
 	if (!res)
 		return res;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:59 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:59 +0400
Subject: [PATCH 10/17] physmap_of: move parse_obsolete_partitions to become
	separate parser
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-11-git-send-email-dbaryshkov@gmail.com>

Move parse_obsolete_partitions() to ofpart.c and register it as an
ofoldpart partitions parser.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   53 +-----------------------------
 drivers/mtd/ofpart.c          |   72 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 72 insertions(+), 53 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 312eb17..c953db3 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -40,51 +40,6 @@ struct of_flash {
 };
 
 #define OF_FLASH_PARTS(info)	((info)->parts)
-static int parse_obsolete_partitions(struct platform_device *dev,
-				     struct of_flash *info,
-				     struct device_node *dp)
-{
-	int i, plen, nr_parts;
-	const struct {
-		__be32 offset, len;
-	} *part;
-	const char *names;
-
-	part = of_get_property(dp, "partitions", &plen);
-	if (!part)
-		return 0; /* No partitions found */
-
-	dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
-
-	nr_parts = plen / sizeof(part[0]);
-
-	info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
-	if (!info->parts)
-		return -ENOMEM;
-
-	names = of_get_property(dp, "partition-names", &plen);
-
-	for (i = 0; i < nr_parts; i++) {
-		info->parts[i].offset = be32_to_cpu(part->offset);
-		info->parts[i].size   = be32_to_cpu(part->len) & ~1;
-		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
-			info->parts[i].mask_flags = MTD_WRITEABLE;
-
-		if (names && (plen > 0)) {
-			int len = strlen(names) + 1;
-
-			info->parts[i].name = (char *)names;
-			plen -= len;
-			names += len;
-		} else {
-			info->parts[i].name = "unnamed";
-		}
-
-		part++;
-	}
-
-	return nr_parts;
-}
 
 static int of_flash_remove(struct platform_device *dev)
 {
@@ -166,7 +121,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    default is use. These take precedence over other device tree
    information. */
 static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
-					"ofpart", NULL };
+					"ofpart", "ofoldpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -342,12 +297,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	}
 	of_free_probes(part_probe_types);
 
-	if (err == 0) {
-		err = parse_obsolete_partitions(dev, info, dp);
-		if (err < 0)
-			goto err_out;
-	}
-
 	mtd_device_register(info->cmtd, info->parts, err);
 
 	kfree(mtd_list);
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index bbcc269..311b248 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -90,9 +90,79 @@ static struct mtd_part_parser ofpart_parser = {
 	.name = "ofpart",
 };
 
+static int parse_ofoldpart_partitions(struct mtd_info *master,
+				      struct mtd_partition **pparts,
+				      unsigned long origin)
+{
+	struct device_node *dp;
+	int i, plen, nr_parts;
+	const struct {
+		__be32 offset, len;
+	} *part;
+	const char *names;
+
+	dp = master->node;
+	if (!dp)
+		return 0;
+
+	part = of_get_property(dp, "partitions", &plen);
+	if (!part)
+		return 0; /* No partitions found */
+
+	pr_warning("Device tree uses obsolete partition map binding: %s\n",
+			dp->full_name);
+
+	nr_parts = plen / sizeof(part[0]);
+
+	*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
+	if (!pparts)
+		return -ENOMEM;
+
+	names = of_get_property(dp, "partition-names", &plen);
+
+	for (i = 0; i < nr_parts; i++) {
+		(*pparts)[i].offset = be32_to_cpu(part->offset);
+		(*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
+		/* bit 0 set signifies read only partition */
+		if (be32_to_cpu(part->len) & 1)
+			(*pparts)[i].mask_flags = MTD_WRITEABLE;
+
+		if (names && (plen > 0)) {
+			int len = strlen(names) + 1;
+
+			(*pparts)[i].name = (char *)names;
+			plen -= len;
+			names += len;
+		} else {
+			(*pparts)[i].name = "unnamed";
+		}
+
+		part++;
+	}
+
+	return nr_parts;
+}
+
+static struct mtd_part_parser ofoldpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofoldpart_partitions,
+	.name = "ofoldpart",
+};
+
 static int __init ofpart_parser_init(void)
 {
-	return register_mtd_parser(&ofpart_parser);
+	int rc;
+	rc = register_mtd_parser(&ofpart_parser);
+	if (rc)
+		goto out;
+
+	rc = register_mtd_parser(&ofoldpart_parser);
+	if (!rc)
+		return 0;
+
+	deregister_mtd_parser(&ofoldpart_parser);
+out:
+	return rc;
 }
 
 module_init(ofpart_parser_init);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:00 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:00 +0400
Subject: [PATCH 11/17] mtd: m25p80.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-12-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   28 +++-------------------------
 1 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index a1cdb52..f76db1d 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -88,7 +88,6 @@ struct m25p {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-	unsigned		partitioned:1;
 	u16			page_size;
 	u16			addr_width;
 	u8			erase_opcode;
@@ -825,8 +824,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	struct m25p			*flash;
 	struct flash_info		*info;
 	unsigned			i;
-	struct mtd_partition		*parts = NULL;
-	int				nr_parts = 0;
 
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
@@ -969,28 +966,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-		flash->partitioned = 1;
-	}
-
-	return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
-		-ENODEV : 0;
+	return mtd_device_parse_register(&flash->mtd, NULL, 0,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
 }
 
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:01 +0400
Subject: [PATCH 11/17] mtd: physmap_of.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-13-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   18 +++---------------
 1 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index c953db3..779b184 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -34,13 +34,10 @@ struct of_flash_list {
 
 struct of_flash {
 	struct mtd_info		*cmtd;
-	struct mtd_partition	*parts;
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 };
 
-#define OF_FLASH_PARTS(info)	((info)->parts)
-
 static int of_flash_remove(struct platform_device *dev)
 {
 	struct of_flash *info;
@@ -56,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
 		mtd_concat_destroy(info->cmtd);
 	}
 
-	if (info->cmtd) {
-		if (OF_FLASH_PARTS(info))
-			kfree(OF_FLASH_PARTS(info));
+	if (info->cmtd)
 		mtd_device_unregister(info->cmtd);
-	}
 
 	for (i = 0; i < info->list_size; i++) {
 		if (info->list[i].mtd)
@@ -289,16 +283,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 
 	info->cmtd->node = dp;
 	part_probe_types = of_get_probes(dp);
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
-	if (err < 0) {
-		of_free_probes(part_probe_types);
-		goto err_out;
-	}
+	mtd_device_parse_register(info->cmtd, part_probe_types, 0,
+			NULL, 0);
 	of_free_probes(part_probe_types);
 
-	mtd_device_register(info->cmtd, info->parts, err);
-
 	kfree(mtd_list);
 
 	return 0;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:02 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:02 +0400
Subject: [PATCH 12/17] mtd: m25p80.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-14-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   28 +++-------------------------
 1 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index a1cdb52..f76db1d 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -88,7 +88,6 @@ struct m25p {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-	unsigned		partitioned:1;
 	u16			page_size;
 	u16			addr_width;
 	u8			erase_opcode;
@@ -825,8 +824,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	struct m25p			*flash;
 	struct flash_info		*info;
 	unsigned			i;
-	struct mtd_partition		*parts = NULL;
-	int				nr_parts = 0;
 
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
@@ -969,28 +966,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-		flash->partitioned = 1;
-	}
-
-	return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
-		-ENODEV : 0;
+	return mtd_device_parse_register(&flash->mtd, NULL, 0,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
 }
 
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:05 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:05 +0400
Subject: [PATCH 14/17] mtd: fsl_upm.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-17-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 253b8ff..04be80a 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -192,9 +192,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, 0);
-
-	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
+	ret = mtd_device_parse_register(&fun->mtd, NULL, 0, NULL, 0);
 err:
 	of_node_put(flash_np);
 	return ret;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:06 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:06 +0400
Subject: [PATCH 15/17] mtd: mpc5121_nfc.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-18-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index c4e8cb9..e06bde7 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -654,7 +654,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
 	struct mtd_info *mtd;
-	struct mtd_partition *parts;
 	struct nand_chip *chip;
 	unsigned long regs_paddr, regs_size;
 	const __be32 *chips_no;
@@ -837,15 +836,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, NULL, &parts, 0);
-	if (retval < 0) {
-		dev_err(dev, "Error parsing MTD partitions!\n");
-		devm_free_irq(dev, prv->irq, mtd);
-		retval = -EINVAL;
-		goto error;
-	}
-
-	retval = mtd_device_register(mtd, parts, retval);
+	retval = mtd_device_parse_register(mtd, NULL, 0, NULL, 0);
 	if (retval) {
 		dev_err(dev, "Error adding MTD device!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:07 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:07 +0400
Subject: [PATCH 16/17] mtd: ndfc.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-19-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 1ae94f0..24c449f 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -42,7 +42,6 @@ struct ndfc_controller {
 	struct nand_chip chip;
 	int chip_select;
 	struct nand_hw_control ndfc_control;
-	struct mtd_partition *parts;
 };
 
 static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
@@ -200,11 +199,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, 0);
-	if (ret < 0)
-		goto err;
-
-	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
+	ret = mtd_device_parse_register(&ndfc->mtd, NULL, 0, NULL, 0);
 
 err:
 	of_node_put(flash_np);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:03 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:03 +0400
Subject: [PATCH 12/17] mtd: physmap_of.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-15-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   18 +++---------------
 1 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index c953db3..779b184 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -34,13 +34,10 @@ struct of_flash_list {
 
 struct of_flash {
 	struct mtd_info		*cmtd;
-	struct mtd_partition	*parts;
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 };
 
-#define OF_FLASH_PARTS(info)	((info)->parts)
-
 static int of_flash_remove(struct platform_device *dev)
 {
 	struct of_flash *info;
@@ -56,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
 		mtd_concat_destroy(info->cmtd);
 	}
 
-	if (info->cmtd) {
-		if (OF_FLASH_PARTS(info))
-			kfree(OF_FLASH_PARTS(info));
+	if (info->cmtd)
 		mtd_device_unregister(info->cmtd);
-	}
 
 	for (i = 0; i < info->list_size; i++) {
 		if (info->list[i].mtd)
@@ -289,16 +283,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 
 	info->cmtd->node = dp;
 	part_probe_types = of_get_probes(dp);
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
-	if (err < 0) {
-		of_free_probes(part_probe_types);
-		goto err_out;
-	}
+	mtd_device_parse_register(info->cmtd, part_probe_types, 0,
+			NULL, 0);
 	of_free_probes(part_probe_types);
 
-	mtd_device_register(info->cmtd, info->parts, err);
-
 	kfree(mtd_list);
 
 	return 0;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:04 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:04 +0400
Subject: [PATCH 13/17] mtd: fsl_elbc_nand.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-16-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 5236840..73c8d87 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -843,7 +843,6 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
-	struct mtd_partition *parts;
 	int ret;
 	int bank;
 	struct device *dev;
@@ -935,11 +934,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
-	if (ret < 0)
-		goto err;
-
-	mtd_device_register(&priv->mtd, parts, ret);
+	mtd_device_parse_register(&priv->mtd, part_probe_types, 0, NULL, 0);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
 	       (unsigned long long)res.start, priv->bank);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:23:08 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:23:08 +0400
Subject: [PATCH 17/17] mtd: socrates_nand.c: use mtd_device_parse_register
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-20-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index b256491..e409d33 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -164,8 +164,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
 
 	/* Allocate memory for the device structure (and zero it) */
 	host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
@@ -224,17 +222,10 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, 0);
-	if (num_partitions < 0) {
-		res = num_partitions;
-		goto release;
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, 0, NULL, 0);
 	if (!res)
 		return res;
 
-release:
 	nand_release(mtd);
 
 out:
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun  9 10:22:58 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu,  9 Jun 2011 18:22:58 +0400
Subject: [PATCH 09/17] mtd: drop of_mtd_parse_partitions()
In-Reply-To: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629388-24769-10-git-send-email-dbaryshkov@gmail.com>

All users have been converted to call of_mtd_parse_partitions through
parse_mtd_partitions() multiplexer. Drop obsolete API.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/ofpart.c           |   16 ++++------------
 include/linux/mtd/partitions.h |   16 ----------------
 2 files changed, 4 insertions(+), 28 deletions(-)

diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 4ac040e..bbcc269 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -25,22 +25,15 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 				   unsigned long origin)
 {
 	struct device_node *node;
+	const char *partname;
+	struct device_node *pp;
+	int nr_parts, i;
+
 
 	node = master->node;
 	if (!node)
 		return 0;
 
-	return of_mtd_parse_partitions(NULL, node, pparts);
-}
-
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts)
-{
-	const char *partname;
-	struct device_node *pp;
-	int nr_parts, i;
-
 	/* First count the subnodes */
 	pp = NULL;
 	nr_parts = 0;
@@ -90,7 +83,6 @@ int of_mtd_parse_partitions(struct device *dev,
 
 	return nr_parts;
 }
-EXPORT_SYMBOL(of_mtd_parse_partitions);
 
 static struct mtd_part_parser ofpart_parser = {
 	.owner = THIS_MODULE,
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index a8bd193..cc9c577 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -70,22 +70,6 @@ extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-struct device;
-struct device_node;
-
-#ifdef CONFIG_MTD_OF_PARTS
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts);
-#else
-static inline int of_mtd_parse_partitions(struct device *dev,
-					  struct device_node *node,
-					  struct mtd_partition **pparts)
-{
-	return 0;
-}
-#endif
-
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
 		      long long offset, long long length);
-- 
1.7.5.3



From dedekind1 at gmail.com  Thu Jun  9 10:26:29 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 17:26:29 +0300
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307629589.7374.103.camel@localhost>

On Thu, 2011-06-09 at 18:22 +0400, Dmitry Eremin-Solenikov wrote:
> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
> 1) Register ofpart parser
> 2) Internally don't use passed device for error printing
> 3) Add device_node to mtd_info struct
> 4) Move of_mtd_parse_partitions from __devinit to common text section
> 5) add ofpart to the default list of partition parsers
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/mtdcore.c          |   19 +++++++++++++++++++
>  drivers/mtd/mtdpart.c          |    8 ++++++--
>  drivers/mtd/ofpart.c           |   30 ++++++++++++++++++++++++++++--
>  include/linux/mtd/mtd.h        |    5 +++++
>  include/linux/mtd/partitions.h |    2 +-
>  5 files changed, 59 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 1326747..2d5b865 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -36,6 +36,7 @@
>  #include <linux/idr.h>
>  #include <linux/backing-dev.h>
>  #include <linux/gfp.h>
> +#include <linux/of.h>
>  
>  #include <linux/mtd/mtd.h>
>  #include <linux/mtd/partitions.h>
> @@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
>  			const struct mtd_partition *parts,
>  			int nr_parts)
>  {
> +#ifdef CONFIG_OF
> +	if (master->node)
> +		of_node_get(master->node);
> +#endif

These ifdefs are not very nice, do you have ideas how to avoid them?
Ideally, mtdcore should not know or bother about OF things. All
OF-specific things should be done in ofpart.c...

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Thu Jun  9 10:37:14 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 09 Jun 2011 18:37:14 +0400
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307629589.7374.103.camel@localhost>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>	
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
	<1307629589.7374.103.camel@localhost>
Message-ID: <4DF0DA9A.2050301@gmail.com>

On 09.06.2011 18:26, Artem Bityutskiy wrote:
> On Thu, 2011-06-09 at 18:22 +0400, Dmitry Eremin-Solenikov wrote:
>> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
>> 1) Register ofpart parser
>> 2) Internally don't use passed device for error printing
>> 3) Add device_node to mtd_info struct
>> 4) Move of_mtd_parse_partitions from __devinit to common text section
>> 5) add ofpart to the default list of partition parsers
>>
>> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
>> ---
>>   drivers/mtd/mtdcore.c          |   19 +++++++++++++++++++
>>   drivers/mtd/mtdpart.c          |    8 ++++++--
>>   drivers/mtd/ofpart.c           |   30 ++++++++++++++++++++++++++++--
>>   include/linux/mtd/mtd.h        |    5 +++++
>>   include/linux/mtd/partitions.h |    2 +-
>>   5 files changed, 59 insertions(+), 5 deletions(-)
>>
>> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
>> index 1326747..2d5b865 100644
>> --- a/drivers/mtd/mtdcore.c
>> +++ b/drivers/mtd/mtdcore.c
>> @@ -36,6 +36,7 @@
>>   #include<linux/idr.h>
>>   #include<linux/backing-dev.h>
>>   #include<linux/gfp.h>
>> +#include<linux/of.h>
>>
>>   #include<linux/mtd/mtd.h>
>>   #include<linux/mtd/partitions.h>
>> @@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
>>   			const struct mtd_partition *parts,
>>   			int nr_parts)
>>   {
>> +#ifdef CONFIG_OF
>> +	if (master->node)
>> +		of_node_get(master->node);
>> +#endif
>
> These ifdefs are not very nice, do you have ideas how to avoid them?
> Ideally, mtdcore should not know or bother about OF things. All
> OF-specific things should be done in ofpart.c...

I know they aren't nice. OTOH ofpart.c also seems a bit non-logical: one 
can have of node in the MTD, but doesn't (strangely) want to compile in 
ofpart.c. Of course I can add separate small of-handling functions (to 
do OF handling) to mtdcore.c to be replaced by empty functions in the 
absence of CONFIG_OF, but this also look like overhead for me.

-- 
With best wishes
Dmitry



From dedekind1 at gmail.com  Thu Jun  9 11:02:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 18:02:47 +0300
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <4DF0DA9A.2050301@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
	<1307629589.7374.103.camel@localhost>  <4DF0DA9A.2050301@gmail.com>
Message-ID: <1307631767.7374.111.camel@localhost>

On Thu, 2011-06-09 at 18:37 +0400, Dmitry Eremin-Solenikov wrote:
> On 09.06.2011 18:26, Artem Bityutskiy wrote:
> > On Thu, 2011-06-09 at 18:22 +0400, Dmitry Eremin-Solenikov wrote:
> >> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
> >> 1) Register ofpart parser
> >> 2) Internally don't use passed device for error printing
> >> 3) Add device_node to mtd_info struct
> >> 4) Move of_mtd_parse_partitions from __devinit to common text section
> >> 5) add ofpart to the default list of partition parsers
> >>
> >> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
> >> ---
> >>   drivers/mtd/mtdcore.c          |   19 +++++++++++++++++++
> >>   drivers/mtd/mtdpart.c          |    8 ++++++--
> >>   drivers/mtd/ofpart.c           |   30 ++++++++++++++++++++++++++++--
> >>   include/linux/mtd/mtd.h        |    5 +++++
> >>   include/linux/mtd/partitions.h |    2 +-
> >>   5 files changed, 59 insertions(+), 5 deletions(-)
> >>
> >> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> >> index 1326747..2d5b865 100644
> >> --- a/drivers/mtd/mtdcore.c
> >> +++ b/drivers/mtd/mtdcore.c
> >> @@ -36,6 +36,7 @@
> >>   #include<linux/idr.h>
> >>   #include<linux/backing-dev.h>
> >>   #include<linux/gfp.h>
> >> +#include<linux/of.h>
> >>
> >>   #include<linux/mtd/mtd.h>
> >>   #include<linux/mtd/partitions.h>
> >> @@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
> >>   			const struct mtd_partition *parts,
> >>   			int nr_parts)
> >>   {
> >> +#ifdef CONFIG_OF
> >> +	if (master->node)
> >> +		of_node_get(master->node);
> >> +#endif
> >
> > These ifdefs are not very nice, do you have ideas how to avoid them?
> > Ideally, mtdcore should not know or bother about OF things. All
> > OF-specific things should be done in ofpart.c...
> 
> I know they aren't nice. OTOH ofpart.c also seems a bit non-logical: one 
> can have of node in the MTD, but doesn't (strangely) want to compile in 
> ofpart.c. Of course I can add separate small of-handling functions (to 
> do OF handling) to mtdcore.c to be replaced by empty functions in the 
> absence of CONFIG_OF, but this also look like overhead for me.

How about turning the "origin" argument into "void *private" and
declaring that this is "parser-specific info". It then can become
"origin" for the RedBoot parser and the OF node pointer for the ofpart
parser?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dbaryshkov at gmail.com  Thu Jun  9 11:08:24 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 09 Jun 2011 19:08:24 +0400
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307631767.7374.111.camel@localhost>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>	
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>	
	<1307629589.7374.103.camel@localhost> <4DF0DA9A.2050301@gmail.com>
	<1307631767.7374.111.camel@localhost>
Message-ID: <4DF0E1E8.9010307@gmail.com>

On 09.06.2011 19:02, Artem Bityutskiy wrote:
> On Thu, 2011-06-09 at 18:37 +0400, Dmitry Eremin-Solenikov wrote:
>> On 09.06.2011 18:26, Artem Bityutskiy wrote:
>>> On Thu, 2011-06-09 at 18:22 +0400, Dmitry Eremin-Solenikov wrote:
>>>> Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
>>>> 1) Register ofpart parser
>>>> 2) Internally don't use passed device for error printing
>>>> 3) Add device_node to mtd_info struct
>>>> 4) Move of_mtd_parse_partitions from __devinit to common text section
>>>> 5) add ofpart to the default list of partition parsers
>>>>
>>>> Signed-off-by: Dmitry Eremin-Solenikov<dbaryshkov at gmail.com>
>>>> ---
>>>>    drivers/mtd/mtdcore.c          |   19 +++++++++++++++++++
>>>>    drivers/mtd/mtdpart.c          |    8 ++++++--
>>>>    drivers/mtd/ofpart.c           |   30 ++++++++++++++++++++++++++++--
>>>>    include/linux/mtd/mtd.h        |    5 +++++
>>>>    include/linux/mtd/partitions.h |    2 +-
>>>>    5 files changed, 59 insertions(+), 5 deletions(-)
>>>>
>>>> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
>>>> index 1326747..2d5b865 100644
>>>> --- a/drivers/mtd/mtdcore.c
>>>> +++ b/drivers/mtd/mtdcore.c
>>>> @@ -36,6 +36,7 @@
>>>>    #include<linux/idr.h>
>>>>    #include<linux/backing-dev.h>
>>>>    #include<linux/gfp.h>
>>>> +#include<linux/of.h>
>>>>
>>>>    #include<linux/mtd/mtd.h>
>>>>    #include<linux/mtd/partitions.h>
>>>> @@ -446,6 +447,10 @@ int mtd_device_register(struct mtd_info *master,
>>>>    			const struct mtd_partition *parts,
>>>>    			int nr_parts)
>>>>    {
>>>> +#ifdef CONFIG_OF
>>>> +	if (master->node)
>>>> +		of_node_get(master->node);
>>>> +#endif
>>>
>>> These ifdefs are not very nice, do you have ideas how to avoid them?
>>> Ideally, mtdcore should not know or bother about OF things. All
>>> OF-specific things should be done in ofpart.c...
>>
>> I know they aren't nice. OTOH ofpart.c also seems a bit non-logical: one
>> can have of node in the MTD, but doesn't (strangely) want to compile in
>> ofpart.c. Of course I can add separate small of-handling functions (to
>> do OF handling) to mtdcore.c to be replaced by empty functions in the
>> absence of CONFIG_OF, but this also look like overhead for me.
>
> How about turning the "origin" argument into "void *private" and
> declaring that this is "parser-specific info". It then can become
> "origin" for the RedBoot parser and the OF node pointer for the ofpart
> parser?

And what will happen when ixp4xx (the only user of redboot "exception") 
will get OF support?

-- 
With best wishes
Dmitry



From gilles.ganault at free.fr  Thu Jun  9 11:18:35 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 09 Jun 2011 17:18:35 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<1307623105.7374.91.camel@localhost>
Message-ID: <mkn1v6d8n8i3pnsg89gppnv69ht102hj0c@4ax.com>

On Thu, 09 Jun 2011 15:38:25 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>On Thu, 2011-06-09 at 12:24 +0200, Gilles wrote:
>> vol_size=248MiB
>
>Put, say, 230MiB here. 248MiB is the total amount of space. UBI adds
>some overhead, so your volume size will be smaller, see here:

After updating ubi.cfg with "vol_size=230MiB" and re-running "ubinize
-o rootfs.ubi.img -m 2048 -p 128KiB -s 512 ./ubi.cfg", I reformateed
the appliance and tried to attach mtd2 to Ubi... and it worked! :-)

===============
appliance:> ubiformat /dev/mtd2 -s 512 -f rootfs.ubi.img

appliance:> ubiattach /dev/ubi_ctrl -m 2
UBI: attaching mtd2 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: volume 0 ("rootfs") re-sized from 1870 to 1961 LEBs
UBI: attached mtd2 to ubi0
UBI: MTD device name:            "filesystem_nand"
UBI: MTD device size:            248 MiB
UBI: number of good PEBs:        1984
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:     1
UBI: available PEBs:             0
UBI: total number of reserved PEBs: 1984
UBI: number of PEBs reserved for bad PEB handling: 19
UBI: max/mean erase counter: 14/9
UBI: image sequence number: 1879706523
mtd: Giving out device 3 to rootfs
UBI: background thread "ubi_bgt0d" started, PID 136
UBI device number 0, total 1984 LEBs (255983616 bytes, 244.1 MiB),
available 0 LEBs (0 bytes), LEB size 129024 bytes (126.0 KiB)
===============

So apparently, I lost about 4MiB in the process (248MiB -> 244.1).

I'll take advantage of this thread to ask a few questions that I have
after reading the docs + experimenting:

1. After running "ubiattach", I get a new mtd3 partition that is
linked to mtd2:

appliance> cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00800000 00001000 "ROMfs"
mtd1: 00800000 00020000 "kernel_nand"
mtd2: 0f800000 00020000 "filesystem_nand"
mtd3: 0f14b800 0001f800 "rootfs"

To reboot and use the NAND partition as root filesystem, am I correct
that I should forget about mtd2, and use this kernel command line:

"ubi.mtd=3 rootfstype=ubifs root=ubi0:rootfs rw"

?

2. ubiformat takes about 10-15mn to complete: Is there a way to speed
things up, or is it just due to the CPU+NAND that the appliance uses?

3. Finally, when do I have to use ubimkvol?

Thank you.



From gilles.ganault at free.fr  Thu Jun  9 11:19:30 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 09 Jun 2011 17:19:30 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<4DF0B36E.2020605@free-electrons.com>
	<7.0.1.0.2.20110609135430.06967d28@free.fr>
	<4DF0BFA0.4030402@free-electrons.com>
Message-ID: <e2p1v6tlj2gka1lq4q2bd0mk5al776ivms@4ax.com>

On Thu, 09 Jun 2011 14:42:08 +0200, David Wagner
<david.wagner at free-electrons.com> wrote:
>>> In most cases, the formula for the offset boils down to:
>>> LEB_size = PEB_size - (((Subpage_size + Page_size) * Page_size) /
>>> Page_size)
>> 
>> Thanks for the tip, but after recompiling a new root filesystem, I'm
>> still getting the same error:
>[...]
>> BTW, using the formula above, I find this: 131.072 - ((( 512 + 2.048) *
>> 2.048 ) / 2.048 ) = 128.512
>> 
>> I wonder if maybe I should leave some room in the NAND partition for the
>> Ubifs journal + error log? I used vol_size=248MiB in ubi.cfg, but maybe
>> this is toot big?
>
>(I forgot to reply to all in my first answer)
>
>Oops, sorry, the formula is
>((Subpage_size + Page_size)) / Page_size) * Page_size
>That is, subpage+page truncated to page.

Thanks, but I must have misunderstood the formula, as I find the same
number:

PEB_size - ((Subpage_size + Page_size)) / Page_size) * Page_size =
LEB_size

131.072 - ((512 + 2048 ) / 2048) * 2048) = 128.512



From dedekind1 at gmail.com  Thu Jun  9 11:17:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 18:17:34 +0300
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <4DF0E1E8.9010307@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
	<1307629589.7374.103.camel@localhost>  <4DF0DA9A.2050301@gmail.com>
	<1307631767.7374.111.camel@localhost>  <4DF0E1E8.9010307@gmail.com>
Message-ID: <1307632654.7374.121.camel@localhost>

On Thu, 2011-06-09 at 19:08 +0400, Dmitry Eremin-Solenikov wrote:
> >>>> +#ifdef CONFIG_OF
> >>>> +	if (master->node)
> >>>> +		of_node_get(master->node);
> >>>> +#endif
> >>>
> >>> These ifdefs are not very nice, do you have ideas how to avoid them?
> >>> Ideally, mtdcore should not know or bother about OF things. All
> >>> OF-specific things should be done in ofpart.c...
> >>
> >> I know they aren't nice. OTOH ofpart.c also seems a bit non-logical: one
> >> can have of node in the MTD, but doesn't (strangely) want to compile in
> >> ofpart.c. Of course I can add separate small of-handling functions (to
> >> do OF handling) to mtdcore.c to be replaced by empty functions in the
> >> absence of CONFIG_OF, but this also look like overhead for me.
> >
> > How about turning the "origin" argument into "void *private" and
> > declaring that this is "parser-specific info". It then can become
> > "origin" for the RedBoot parser and the OF node pointer for the ofpart
> > parser?
> 
> And what will happen when ixp4xx (the only user of redboot "exception") 
> will get OF support?

Hmm, may be introducing something like:

/**
 * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
 * @origin: blah blah, RedBoot-specific
 * @of_node: points to the OF node describing the partitions, ofpart-specific
 */
struct mtd_part_parser_data {
	unsigned long origin;
	struct device_node *of_node;
};

And change the current "origin" argument with a
"struct mtd_part_parser_data *data" pointer?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 11:20:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 18:20:40 +0300
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307632654.7374.121.camel@localhost>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
	<1307629589.7374.103.camel@localhost>  <4DF0DA9A.2050301@gmail.com>
	<1307631767.7374.111.camel@localhost>  <4DF0E1E8.9010307@gmail.com>
	<1307632654.7374.121.camel@localhost>
Message-ID: <1307632840.7374.123.camel@localhost>

On Thu, 2011-06-09 at 18:17 +0300, Artem Bityutskiy wrote:
> And change the current "origin" argument with a
> "struct mtd_part_parser_data *data" pointer?

Which of course can be NULL if there is nothing to say, as well as
of_node may be NULL, in which case the parsers which needs those things
can just return "no partitions" or something like that?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From dedekind1 at gmail.com  Thu Jun  9 11:25:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 18:25:04 +0300
Subject: [PATCH 01/17] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <4DF0DA9A.2050301@gmail.com>
References: <1307629388-24769-1-git-send-email-dbaryshkov@gmail.com>
	<1307629388-24769-2-git-send-email-dbaryshkov@gmail.com>
	<1307629589.7374.103.camel@localhost>  <4DF0DA9A.2050301@gmail.com>
Message-ID: <1307633104.7374.125.camel@localhost>

On Thu, 2011-06-09 at 18:37 +0400, Dmitry Eremin-Solenikov wrote:
> I know they aren't nice. OTOH ofpart.c also seems a bit non-logical: one 
> can have of node in the MTD, but doesn't (strangely) want to compile in 
> ofpart.c. Of course I can add separate small of-handling functions (to 
> do OF handling) to mtdcore.c to be replaced by empty functions in the 
> absence of CONFIG_OF, but this also look like overhead for me.

Anyway, if I understand correctly (correct me if I don't!) - this is
basically about passing parser-specific information to parsers. And if
this is right, your way of adding this parser-specific information to
'struct mtd_info *' is bad, and we need to invent something better.

Right?

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From david.wagner at free-electrons.com  Thu Jun  9 11:50:57 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Thu, 09 Jun 2011 17:50:57 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
In-Reply-To: <e2p1v6tlj2gka1lq4q2bd0mk5al776ivms@4ax.com>
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>	<4DF0B36E.2020605@free-electrons.com>	<7.0.1.0.2.20110609135430.06967d28@free.fr>	<4DF0BFA0.4030402@free-electrons.com>
	<e2p1v6tlj2gka1lq4q2bd0mk5al776ivms@4ax.com>
Message-ID: <4DF0EBE1.9000903@free-electrons.com>

>> Oops, sorry, the formula is
>> ((Subpage_size + Page_size)) / Page_size) * Page_size
>> That is, subpage+page truncated to page.
> 
> Thanks, but I must have misunderstood the formula, as I find the same
> number:
> 
> PEB_size - ((Subpage_size + Page_size)) / Page_size) * Page_size =
> LEB_size
> 
> 131.072 - ((512 + 2048 ) / 2048) * 2048) = 128.512

I should have mentionned that every sub-result has to be considered an
integer, here, sorry.
512+2048 = 2560
2560 / 2048 = 1 // That's where it is important that the result be
                // an integer.
1 * 2048 = 2048
131072 - 2048 = 129024

Regards,
-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From dedekind1 at gmail.com  Thu Jun  9 11:51:50 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 18:51:50 +0300
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
In-Reply-To: <4DF0EBE1.9000903@free-electrons.com>
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<4DF0B36E.2020605@free-electrons.com>
	<7.0.1.0.2.20110609135430.06967d28@free.fr>
	<4DF0BFA0.4030402@free-electrons.com>
	<e2p1v6tlj2gka1lq4q2bd0mk5al776ivms@4ax.com>
	<4DF0EBE1.9000903@free-electrons.com>
Message-ID: <1307634710.7374.126.camel@localhost>

On Thu, 2011-06-09 at 17:50 +0200, David Wagner wrote:
> >> Oops, sorry, the formula is
> >> ((Subpage_size + Page_size)) / Page_size) * Page_size
> >> That is, subpage+page truncated to page.
> > 
> > Thanks, but I must have misunderstood the formula, as I find the same
> > number:
> > 
> > PEB_size - ((Subpage_size + Page_size)) / Page_size) * Page_size =
> > LEB_size
> > 
> > 131.072 - ((512 + 2048 ) / 2048) * 2048) = 128.512
> 
> I should have mentionned that every sub-result has to be considered an
> integer, here, sorry.
> 512+2048 = 2560
> 2560 / 2048 = 1 // That's where it is important that the result be
>                 // an integer.
> 1 * 2048 = 2048
> 131072 - 2048 = 129024

An improvement patch to the mtd web-site is welcome - it is very simple
to change:

http://git.infradead.org/mtd-www.git

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From computersforpeace at gmail.com  Thu Jun  9 12:00:32 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 9 Jun 2011 09:00:32 -0700
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307605456.7374.35.camel@localhost>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307605456.7374.35.camel@localhost>
Message-ID: <BANLkTin5KLu8QknuM4ATHpLQP4Uq09tekA@mail.gmail.com>

On Thu, Jun 9, 2011 at 12:44 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> Wait, and why are we using pr_* while it is better to use dbg_* ? :-)

Just so we're on the same page...did you say "dbg_*" when you really
meant "dev_*"?

Anyway, the answer is: I'm mostly trying to do as little shakeup as
possible, so "printk" could translate pretty directly to the "pr_*"
with shorter code, etc. If it makes as much (or more) sense to have
the device name on all the prints, then I can just as well do it that
way.

Brian


From dedekind1 at gmail.com  Thu Jun  9 12:03:32 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 09 Jun 2011 19:03:32 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <BANLkTin5KLu8QknuM4ATHpLQP4Uq09tekA@mail.gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307605456.7374.35.camel@localhost>
	<BANLkTin5KLu8QknuM4ATHpLQP4Uq09tekA@mail.gmail.com>
Message-ID: <1307635412.7374.128.camel@localhost>

On Thu, 2011-06-09 at 09:00 -0700, Brian Norris wrote:
> On Thu, Jun 9, 2011 at 12:44 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > Wait, and why are we using pr_* while it is better to use dbg_* ? :-)
> 
> Just so we're on the same page...did you say "dbg_*" when you really
> meant "dev_*"?

Yes, I meant dev_*

> Anyway, the answer is: I'm mostly trying to do as little shakeup as
> possible, so "printk" could translate pretty directly to the "pr_*"
> with shorter code, etc. If it makes as much (or more) sense to have
> the device name on all the prints, then I can just as well do it that
> way.

Yes, I think it makes much more sense to specify for which device (out
of possibly many!) this message belongs.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From gilles.ganault at free.fr  Thu Jun  9 12:15:11 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 09 Jun 2011 18:15:11 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>	<4DF0B36E.2020605@free-electrons.com>	<7.0.1.0.2.20110609135430.06967d28@free.fr>	<4DF0BFA0.4030402@free-electrons.com>
	<e2p1v6tlj2gka1lq4q2bd0mk5al776ivms@4ax.com>
	<4DF0EBE1.9000903@free-electrons.com>
Message-ID: <8cs1v6pdevc4nv71mqcrnojipnctdco8hd@4ax.com>

On Thu, 09 Jun 2011 17:50:57 +0200, David Wagner
<david.wagner at free-electrons.com> wrote:
>I should have mentionned that every sub-result has to be considered an
>integer, here, sorry.
>512+2048 = 2560
>2560 / 2048 = 1 // That's where it is important that the result be
>                // an integer.
>1 * 2048 = 2048
>131072 - 2048 = 129024

Thanks a lot.



From gilles.ganault at free.fr  Thu Jun  9 12:17:24 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 09 Jun 2011 18:17:24 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
Message-ID: <ics1v6h6c3h777js8uh4j8bve2i1q7m5d0@4ax.com>

On Thu, 09 Jun 2011 12:24:22 +0200, Gilles <gilles.ganault at free.fr>
wrote:
(snip)

Now that I can successfully format + attach + mount the Ubifs NAND
partition, I tried rebooting with the following kernel command line:

==========
bootargs=ethaddr=00:09:45:56:72:9b console=ttyBF0,115200
rootfstype=ubifs ubi.mtd2 root=ubi0:rootfs
==========

However, uClinux isn't happy:
==========
...
UBIFS error (pid 1): ubifs_get_sb: cannot open "ubi0:rootfs", error
-19
VFS: Cannot open root device "ubi0:rootfs" or unknown-block(0,0)
Please append a correct "root=" boot option; here are the available
partitions:
1f00            8192 mtdblock0 (driver?)
1f01            8192 mtdblock1 (driver?)
1f02          253952 mtdblock2 (driver?)
Kernel panic - not syncing: VFS: Unable to mount root fs on
unknown-block(0,0)
Hardware Trace:
==========

I compiled Ubi(fs) statically in the kernel and included the MTD
utilities. Do I need something else for uClinux to be able to
attach/mount a Ubifs partition?

Thank you.



From computersforpeace at gmail.com  Thu Jun  9 12:22:32 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 9 Jun 2011 09:22:32 -0700
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307607194.7374.49.camel@localhost>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307607194.7374.49.camel@localhost>
Message-ID: <BANLkTik9T_R5xZO5_GrzyznxwNnpv4931g@mail.gmail.com>

On Thu, Jun 9, 2011 at 1:13 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> Brian, would you please send a new series? I suggest you the following
> order of things.
>
> 1. clean-up of non-DEBUG() messages.
> ? 1.1. go through all printks and check if KERN_* is ok, fix. E.g.,
> ? ? ? ?I can see that all KERN_DEBUG should become KERN_INFO
> ? 1.2. go through all printks and check if the function name prefix
> ? ? ? ?makes sense there - kill those which do not.
>
> ? Also, while doing this, keep in mind that messages will be later
> ? turned into dev_* (dev_info(), dev_err(), etc) so they will be
> ? automatically prefixed with the device name which is already some
> ? identification of the source of the message.
>
> ? 1.3. turn messages to dev_*
> ? 1.4. make another pass and do all the lines consolidations,
> ? ? ? ?alignments, punctuation, etc etc.
>
> 2. clean-up of DEBUG() cruft.
> ? 2.1 change DEBUG() with dev_dbg()
>
> ? Kill all function name prefixes as well. The rationale is: dev_dbg()
> ? already adds function name prefixe (and process id) if dynamic
> ? debugging is enabled. In case of debugging with DEBUG macro, you
> ? anyway have to change the code (adding #define DEBUG) so you might
> ? easily defind pr_fmt at the same time for youself.
>
> How does this sound to you?

Sounds good. Will send patches later today, I think.

> FWIW: I've moved the patches I pushed from the master branch to the
> "brian" branch of l2-mtd-2.6.git tree. But they will not be useful
> for you, I guess.

Thanks, although I will have to rework all of them :)

Brian


From gilles.ganault at free.fr  Thu Jun  9 19:05:56 2011
From: gilles.ganault at free.fr (Gilles)
Date: Fri, 10 Jun 2011 01:05:56 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<ics1v6h6c3h777js8uh4j8bve2i1q7m5d0@4ax.com>
Message-ID: <66k2v6hfdbhcd6onjr6binvhpujidimja0@4ax.com>

On Thu, 09 Jun 2011 18:17:24 +0200, Gilles <gilles.ganault at free.fr>
wrote:
>Now that I can successfully format + attach + mount the Ubifs NAND
>partition, I tried rebooting with the following kernel command line:
>
>==========
>bootargs=ethaddr=00:09:45:56:72:9b console=ttyBF0,115200
>rootfstype=ubifs ubi.mtd2 root=ubi0:rootfs
>==========

Even after correcting the mistake above ("ubi.mtd2" should be
"ubi=mtd2"), uClinux still can't access Ubifs on mtd2 and crashes.

I double-checked that the kernel has MTD + UBI + Ubifs compiled
statically.

Incidently, are those settings in "bootargs" enough to have the kernel
run the equivalent of ubiattach with the right commands for Ubi(fs)
before attempting to mount the NAND partition as root filesystem?



From gilles.ganault at free.fr  Thu Jun  9 20:45:55 2011
From: gilles.ganault at free.fr (Gilles)
Date: Fri, 10 Jun 2011 02:45:55 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<ics1v6h6c3h777js8uh4j8bve2i1q7m5d0@4ax.com>
	<66k2v6hfdbhcd6onjr6binvhpujidimja0@4ax.com>
Message-ID: <2tp2v6ld5qijnuc8gshkq63d4hr1d474nr@4ax.com>

On Fri, 10 Jun 2011 01:05:56 +0200, Gilles <gilles.ganault at free.fr>
wrote:
>Even after correcting the mistake above ("ubi.mtd2" should be
>"ubi=mtd2"), uClinux still can't access Ubifs on mtd2 and crashes.

Wrong again (blush)

Here's the correct bootargs:
===========
bootargs=... rootfstype=ubifs ubi.mtd=2 root=ubi0:rootfs rw
===========

Don't forget the trailing "rw", or it will be read-only and cause a
few errors.

I'm now successfully running with the root filesystem on the NAND with
Ubifs.

Thanks everyone for the great help.



From dedekind1 at gmail.com  Fri Jun 10 00:03:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 10 Jun 2011 07:03:40 +0300
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
In-Reply-To: <mkn1v6d8n8i3pnsg89gppnv69ht102hj0c@4ax.com>
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<1307623105.7374.91.camel@localhost>
	<mkn1v6d8n8i3pnsg89gppnv69ht102hj0c@4ax.com>
Message-ID: <1307678620.7374.131.camel@localhost>

On Thu, 2011-06-09 at 17:18 +0200, Gilles wrote:
> 2. ubiformat takes about 10-15mn to complete: Is there a way to speed
> things up, or is it just due to the CPU+NAND that the appliance uses?

http://www.linux-mtd.infradead.org/faq/ubi.html#L_attach_faster

> 3. Finally, when do I have to use ubimkvol?

When you want to dynamically (run-time) create a new UBI volume. You do
not necessarily have to do this.

-- 
Best Regards,
Artem Bityutskiy (????? ????????)



From matthieu.castet at parrot.com  Fri Jun 10 04:33:09 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Fri, 10 Jun 2011 10:33:09 +0200
Subject: omap2 : bug in omap_wait
Message-ID: <4DF1D6C5.8080503@parrot.com>

Hi,

omap nand driver implement the nand.waitfunc[1] but it is buggy and can lead to
 nand write/erase error :
- status = NAND_STATUS_FAIL
- timeo is computed
- thread is preempted
- timeo is expired and we never enter the loop
- we return NAND_STATUS_FAIL, even if the real status is okay.

The correct behavior is to read again the status after the loop like in nand_wait.


BTW why omap2 driver doesn't use nand_wait ?

Matthieu

[1]
static int omap_wait(struct mtd_info *mtd, struct nand_chip *chip)
{
    struct nand_chip *this = mtd->priv;
    struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
                            mtd);
    unsigned long timeo = jiffies;
    int status = NAND_STATUS_FAIL, state = this->state;

    if (state == FL_ERASING)
        timeo += (HZ * 400) / 1000;
    else
        timeo += (HZ * 20) / 1000;

    gpmc_nand_write(info->gpmc_cs,
            GPMC_NAND_COMMAND, (NAND_CMD_STATUS & 0xFF));
    while (time_before(jiffies, timeo)) {
        status = gpmc_nand_read(info->gpmc_cs, GPMC_NAND_DATA);
        if (status & NAND_STATUS_READY)
            break;
        cond_resched();
    }
    return status;
}


From gilles.ganault at free.fr  Fri Jun 10 05:25:30 2011
From: gilles.ganault at free.fr (Gilles)
Date: Fri, 10 Jun 2011 11:25:30 +0200
Subject: [Ubiattach] "vtbl_check: too large reserved_pebs"
References: <mv61v65qqumjmnr9dkejjacgg4id8srbe7@4ax.com>
	<1307623105.7374.91.camel@localhost>
	<mkn1v6d8n8i3pnsg89gppnv69ht102hj0c@4ax.com>
	<1307678620.7374.131.camel@localhost>
Message-ID: <ono3v6hd67aqe28icbs3s0qmpgojdgs4d8@4ax.com>

On Fri, 10 Jun 2011 07:03:40 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>When you want to dynamically (run-time) create a new UBI volume. You do
>not necessarily have to do this.

Thanks for the infos.



From brian at walsh.ws  Fri Jun 10 08:49:28 2011
From: brian at walsh.ws (Brian Walsh)
Date: Fri, 10 Jun 2011 08:49:28 -0400
Subject: Question reg. parsing of mtd partitions
In-Reply-To: <BANLkTi=rBr0YS9vApbhTGJLEWAsfWWu8Fg@mail.gmail.com>
References: <20110609083419.GA23553@doriath.ww600.siemens.net>
	<4DF08D79.9090707@gmail.com>
	<BANLkTi=rBr0YS9vApbhTGJLEWAsfWWu8Fg@mail.gmail.com>
Message-ID: <201106100849.29032.brian@walsh.ws>

On Thursday, June 09, 2011 05:23:31 am Dmitry Eremin-Solenikov wrote:
> On 6/9/11, Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> wrote:
> > On 09.06.2011 12:34, Dmitry Eremin-Solenikov wrote:
> >> Hello, colleagues,
> >>
> >> While doing MTD partitions cleanup I noticed one strange thing.
> >> parse_mtd_partitions function bears one extra argument (origin)
> >> which isn't clearly described, set to non-zero only by ixp4xx.c
> >> driver and then read by redboot partition table handling. I wander if we
> >> can add some other way to handle this situation and drop this extra 0
> >> argument from lots of drivers/handlers/etc.
> >>
> >> Could you please check it?
> >
> > At least the ixp4xx part was added by commit f40a6f1cc7fe522,
> > back in 2006:
> >
> > If the amount of flash is not divisible by 2 then the mask in
> > parse_mtd_partitions would fail to work as designed.  Passing in the
> > base address corrects this problem.
> 
> Found the original patch/report at
> http://thread.gmane.org/gmane.linux.ports.arm.kernel/24662
> 
> Awaiting for comments on this.
> 

The problem apparently only affects ixp4xx based boards running RedBoot as a 
boot loader. I thought that it should possibly go as a fix in 
drivers/mtd/redboot.c but I found the dev->resource->start parameter to 
parse_mtd_partitions to be the most graceful at the time.

RedBoot on ixp4xx based boards starts flash addresses at 0x50000000 which Linux
then starts at 0. So the partition table address entries are all offset by the 
RedBoot start point.

I may be the only one who actually ran into the problem. I was working with a 
modified design that only had 48MB of flash. So as far as I am concerned it can
be dropped. If every other board is using zero for that parameter it seems like
it would make more sense to handle this condition in drivers/mtd/redboot.c?

Brian


From ynezz at true.cz  Sat Jun 11 05:22:24 2011
From: ynezz at true.cz (Petr =?iso-8859-2?Q?=A9tetiar?=)
Date: Sat, 11 Jun 2011 11:22:24 +0200
Subject: [PATCH 2/3] ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
In-Reply-To: <1307369056-29319-3-git-send-email-dbaryshkov@gmail.com>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
	<1307369056-29319-3-git-send-email-dbaryshkov@gmail.com>
Message-ID: <20110611092224.GB16318@ibawizard.net>

Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> [2011-06-06 18:04:15]:

Hi,

> Instead of specifying a callback for dynamic partitioning, use
> MTDPART_OFS_RETAIN for reserving a place near the end of flash for
> RedBoot.

[...]

> -		.offset		= MTDPART_OFS_APPEND,
> -		.size		= 0,			/* filled in later */
> +		.offset		= MTDPART_OFS_RETAIN,
> +		.size		= TS72XX_REDBOOT_PART_SIZE,
> +				/* leave so much for last partition */

thank you for the mtd cleanup work. While testing this patch, I've noticed,
that the TS72XX_REDBOOT_PART_SIZE is by 16K bigger, then it should be:

Redboot:

	RedBoot> fis list
	Name              FLASH addr  Mem addr    Length      Entry point
	(reserved)        0x60000000  0x60000000  0x01D04000  0x00000000
	RedBoot           0x61D04000  0x61D04000  0x00040000  0x00000000
	vmlinux           0x61D44000  0x00218000  0x000C0000  0x00218000
	FIS directory     0x61FFC000  0x61FFC000  0x00003000  0x00000000
	RedBoot config    0x61FFF000  0x61FFF000  0x00001000  0x00000000

Linux:

	0x000000000000-0x000000004000 : "TS-BOOTROM"
	0x000000004000-0x000001d00000 : "Linux"
	0x000001d00000-0x000002000000 : "RedBoot"

So if I simply read now first 4 bytes from /dev/mtdblock2, there's no 'CRUS'
or 'SURC' boot HeaderID/signature and it means, that there's no valid Redboot
for ep93xx. The correct value is:

	#define TS72XX_REDBOOT_PART_SIZE	(SZ_2M + SZ_1M - SZ_16K)

And in the current state one could easily overwrite fis/fconfig while
upgrading the Redboot from the Linux userspace and brick the board, because
there's fis/fconfig stuff included in that Redboot partition.

I think, that it would be better to either make that Redboot partition
read-only by default, make it smaller so it wouldn't contain fconfig/fis parts
in it or add fis/fconfig partitions also. I don't know what's preffered way of
handling this, but since we're touching that part of the code, we should fix
it right.

Adding Mika to the Cc loop, since he has ts-7260.

-- ynezz


From srimugunthan.dhandapani at gmail.com  Fri Jun 10 08:42:09 2011
From: srimugunthan.dhandapani at gmail.com (srimugunthan dhandapani)
Date: Fri, 10 Jun 2011 18:12:09 +0530
Subject: logfs on nandsim, umount crash
Message-ID: <BANLkTino6S_ih8ULoqc6Pk1H51XtkAnuvg@mail.gmail.com>

Hi all,
I compiled 2.6.35 kernel with CONFIG_MTD=y and i am using the SMP i686
machine with Ubuntu 10.04 Lucid operating system.  The steps i
followed and the dmesg tail output are as follows:

1. sudo modprobe logfs
2. sudo modprobe mtd
3. sudo modprobe mtdblock
4. sudo modprobe nandsim first_id_byte=0x20 second_id_byte=0xaa
third_id_byte=0x00 fourth_id_byte=0x25
5. sudo flash_eraseall /dev/mtd0
6. sudo logfsprogs/mklogfs /dev/mtd0
I downloaded logfsprogs from "http://logfs-tools.sourcearchive.com/"
7. sudo mount -t logfs /dev/mtdblock0 /mnt/flash_drive/
8. df -h
9. sudo cp file.txt /mnt/flash_drive/
10. cat /mnt/flash_drive/file.txt
11. sudo umount /mnt/flash_drive/

Segmentation fault.

tail of the dmesg:

[  143.155682] NAND device: Manufacturer ID: 0x20, Chip ID: 0xaa (ST
Micro NAND 256MiB 1,8V 8-bit)
[  143.155691] flash size: 256 MiB
[  143.155696] page size: 2048 bytes
[  143.155700] OOB area size: 64 bytes
[  143.155703] sector size: 256 KiB
[  143.155707] pages number: 131072
[  143.155710] pages per sector: 128
[  143.155713] bus width: 8
[  143.155717] bits in sector size: 18
[  143.155720] bits in page size: 11
[  143.155724] bits in OOB size: 6
[  143.155728] flash size with OOB: 270336 KiB
[  143.155733] page address bytes: 5
[  143.155737] sector address bytes: 3
[  143.155740] options: 0x8
[  143.159059] Scanning device for bad blocks
[  143.160749] Creating 1 MTD partitions on "NAND 256MiB 1,8V 8-bit":
[  143.160755] 0x000000000000-0x000010000000 : "NAND simulator partition 0"
[  247.650884] LogFS: Start mount 0
[  247.657105] LogFS: Finished mounting
[  306.735432] LogFS: Start unmounting
[  306.748837] LogFS: Now in shutdown
[  306.748998] ------------[ cut here ]------------
[  306.749007] kernel BUG at fs/logfs/readwrite.c:1986!
[  306.749013] invalid opcode: 0000 [#1] SMP
[  306.749021] last sysfs file: /sys/devices/virtual/mtd/mtd0/size
[  306.749027] Modules linked in: mtdchar nandsim nand nand_ids
nand_ecc mtdblock mtd_blkdevs logfs zlib_deflate binfmt_misc
vboxnetadp vboxnetflt vboxdrv nfsd exportfs nfs lockd nfs_acl
auth_rpcgss sunrpc fbcon tileblit font snd_intel8x0 snd_ac97_codec
bitblit softcursor ac97_bus i915 snd_pcm_oss snd_mixer_oss snd_pcm
snd_seq_dummy drm_kms_helper snd_seq_oss ppdev parport_pc drm lp
snd_seq_midi snd_rawmidi parport snd_seq_midi_event snd_seq snd_timer
psmouse snd_seq_device snd i2c_algo_bit e1000 intel_agp joydev floppy
usbhid agpgart video output serio_raw hid shpchp soundcore
snd_page_alloc
[  306.749123]
[  306.749128] Pid: 1672, comm: umount Not tainted 2.6.35 #7 D865GBF
                     /
[  306.749133] EIP: 0060:[<f84867a2>] EFLAGS: 00010202 CPU: 1
[  306.749143] EIP is at logfs_clear_inode+0x62/0x70 [logfs]
[  306.749146] EAX: f4066840 EBX: f5e04e00 ECX: 00000000 EDX: 00000000
[  306.749150] ESI: f52a9ed4 EDI: 00000000 EBP: f52a9e98 ESP: f52a9e94
[  306.749154]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[  306.749158] Process umount (pid: 1672, ti=f52a8000 task=f5fb0cb0
task.ti=f52a8000)
[  306.749162] Stack:
[  306.749164]  f4066840 f52a9ea8 c021d27c ffffffff f4066840 f52a9ec0
c021d327 f5e04e70
[  306.749177] <0> f4066840 f4066850 f5e04e70 f52a9ee8 c021d774
f5e04e70 00000000 00000001
[  306.749190] <0> f52a9ed4 f52a9ed4 f5e04e00 f848c1a0 c07b7cfc
f52a9f00 c020ac22 f52a9f00
[  306.749205] Call Trace:
[  306.749216]  [<c021d27c>] ? clear_inode+0x7c/0x100
[  306.749221]  [<c021d327>] ? dispose_list+0x27/0x100
[  306.749226]  [<c021d774>] ? invalidate_inodes+0xf4/0x120
[  306.749232]  [<c020ac22>] ? generic_shutdown_super+0x42/0xd0
[  306.749239]  [<c0596aa2>] ? printk+0x1d/0x23
[  306.749247]  [<f848a0e6>] ? logfs_kill_sb+0x46/0xd0 [logfs]
[  306.749252]  [<c020b65d>] ? deactivate_locked_super+0x3d/0x60
[  306.749257]  [<c020be90>] ? deactivate_super+0x50/0x70
[  306.749263]  [<c02206ff>] ? mntput_no_expire+0x8f/0xd0
[  306.749269]  [<c0220a15>] ? sys_umount+0x65/0x340
[  306.749274]  [<c0220d0e>] ? sys_oldumount+0x1e/0x20
[  306.749280]  [<c0102fe3>] ? sysenter_do_call+0x12/0x28
[  306.749283] Code: ff ff 85 c0 74 29 8d 76 00 e8 2b e0 ff ff 5b 5d
c3 8b 4a 74 89 d8 8d 76 00 ff 51 04 5b 5d c3 0f 0b eb fe 83 78 28 00
66 90 74 bc <0f> 0b eb fe 0f 0b eb fe 8d b6 00 00 00 00 55 89 e5 57 56
53 83
[  306.749362] EIP: [<f84867a2>] logfs_clear_inode+0x62/0x70 [logfs]
SS:ESP 0068:f52a9e94
[  306.749404] ---[ end trace df7ecb1adf27c946 ]---
[  306.749410] ------------[ cut here ]------------
[  306.749418] WARNING: at kernel/exit.c:896 do_exit+0x64a/0x730()
[  306.749423] Hardware name:
[  306.749427] Modules linked in: mtdchar nandsim nand nand_ids
nand_ecc mtdblock mtd_blkdevs logfs zlib_deflate binfmt_misc
vboxnetadp vboxnetflt vboxdrv nfsd exportfs nfs lockd nfs_acl
auth_rpcgss sunrpc fbcon tileblit font snd_intel8x0 snd_ac97_codec
bitblit softcursor ac97_bus i915 snd_pcm_oss snd_mixer_oss snd_pcm
snd_seq_dummy drm_kms_helper snd_seq_oss ppdev parport_pc drm lp
snd_seq_midi snd_rawmidi parport snd_seq_midi_event snd_seq snd_timer
psmouse snd_seq_device snd i2c_algo_bit e1000 intel_agp joydev floppy
usbhid agpgart video output serio_raw hid shpchp soundcore
snd_page_alloc
[  306.749577] Pid: 1672, comm: umount Tainted: G      D     2.6.35 #7
[  306.749582] Call Trace:
[  306.749592]  [<c0149b62>] warn_slowpath_common+0x72/0xa0
[  306.749599]  [<c014deaa>] ? do_exit+0x64a/0x730
[  306.749606]  [<c014deaa>] ? do_exit+0x64a/0x730
[  306.749613]  [<c0149bb2>] warn_slowpath_null+0x22/0x30
[  306.749620]  [<c014deaa>] do_exit+0x64a/0x730
[  306.749628]  [<c014ab21>] ? kmsg_dump+0x121/0x130
[  306.749635]  [<c0596aa2>] ? printk+0x1d/0x23
[  306.749643]  [<c059ab35>] oops_end+0x95/0xd0
[  306.749652]  [<c0105ce4>] die+0x54/0x80
[  306.749659]  [<c059a246>] do_trap+0x96/0xc0
[  306.749666]  [<c0103d10>] ? do_invalid_op+0x0/0xa0
[  306.749673]  [<c0103d9b>] do_invalid_op+0x8b/0xa0
[  306.749685]  [<f84867a2>] ? logfs_clear_inode+0x62/0x70 [logfs]
[  306.749694]  [<c01cb6ce>] ? find_get_pages+0x2e/0xf0
[  306.749702]  [<c01d42e0>] ? pagevec_lookup+0x20/0x30
[  306.749710]  [<c01d5581>] ? truncate_inode_pages_range+0x141/0x2d0
[  306.749718]  [<c0599fc3>] error_code+0x73/0x80
[  306.749728]  [<f848007b>] ? logfs_rename_target+0x3b/0x3a0 [logfs]
[  306.749739]  [<f84867a2>] ? logfs_clear_inode+0x62/0x70 [logfs]
[  306.749747]  [<c021d27c>] clear_inode+0x7c/0x100
[  306.749755]  [<c021d327>] dispose_list+0x27/0x100
[  306.749762]  [<c021d774>] invalidate_inodes+0xf4/0x120
[  306.749769]  [<c020ac22>] generic_shutdown_super+0x42/0xd0
[  306.749777]  [<c0596aa2>] ? printk+0x1d/0x23
[  306.749787]  [<f848a0e6>] logfs_kill_sb+0x46/0xd0 [logfs]
[  306.749795]  [<c020b65d>] deactivate_locked_super+0x3d/0x60
[  306.749802]  [<c020be90>] deactivate_super+0x50/0x70
[  306.749811]  [<c02206ff>] mntput_no_expire+0x8f/0xd0
[  306.749818]  [<c0220a15>] sys_umount+0x65/0x340
[  306.749826]  [<c0220d0e>] sys_oldumount+0x1e/0x20
[  306.749833]  [<c0102fe3>] sysenter_do_call+0x12/0x28
[  306.749839] ---[ end trace df7ecb1adf27c947 ]---

Please let me know if i am missing anything.
Thanks,
Mugunthan


From ynezz at true.cz  Sat Jun 11 06:38:07 2011
From: ynezz at true.cz (Petr =?iso-8859-2?Q?=A9tetiar?=)
Date: Sat, 11 Jun 2011 12:38:07 +0200
Subject: [PATCH 2/3] ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
In-Reply-To: <20110611092224.GB16318@ibawizard.net>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
	<1307369056-29319-3-git-send-email-dbaryshkov@gmail.com>
	<20110611092224.GB16318@ibawizard.net>
Message-ID: <20110611103807.GC16318@ibawizard.net>

Petr ?tetiar <ynezz at true.cz> [2011-06-11 11:22:24]:

> I think, that it would be better to either make that Redboot partition
> read-only by default

Sorry for the noise, it's read-only already, I've just missed that mask.

-- ynezz


From dbaryshkov at gmail.com  Fri Jun 10 09:09:33 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Fri, 10 Jun 2011 17:09:33 +0400
Subject: Question reg. parsing of mtd partitions
In-Reply-To: <201106100849.29032.brian@walsh.ws>
References: <20110609083419.GA23553@doriath.ww600.siemens.net>
	<4DF08D79.9090707@gmail.com>
	<BANLkTi=rBr0YS9vApbhTGJLEWAsfWWu8Fg@mail.gmail.com>
	<201106100849.29032.brian@walsh.ws>
Message-ID: <BANLkTinQnExQvS5p7OJy7WfDLiXO6M6i9Q@mail.gmail.com>

On 6/10/11, Brian Walsh <brian at walsh.ws> wrote:
> On Thursday, June 09, 2011 05:23:31 am Dmitry Eremin-Solenikov wrote:
>> On 6/9/11, Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> wrote:
>> > On 09.06.2011 12:34, Dmitry Eremin-Solenikov wrote:
>> >> Hello, colleagues,
>> >>
>> >> While doing MTD partitions cleanup I noticed one strange thing.
>> >> parse_mtd_partitions function bears one extra argument (origin)
>> >> which isn't clearly described, set to non-zero only by ixp4xx.c
>> >> driver and then read by redboot partition table handling. I wander if
>> >> we
>> >> can add some other way to handle this situation and drop this extra 0
>> >> argument from lots of drivers/handlers/etc.
>> >>
>> >> Could you please check it?
>> >
>> > At least the ixp4xx part was added by commit f40a6f1cc7fe522,
>> > back in 2006:
>> >
>> > If the amount of flash is not divisible by 2 then the mask in
>> > parse_mtd_partitions would fail to work as designed.  Passing in the
>> > base address corrects this problem.
>>
>> Found the original patch/report at
>> http://thread.gmane.org/gmane.linux.ports.arm.kernel/24662
>>
>> Awaiting for comments on this.
>>
>
> The problem apparently only affects ixp4xx based boards running RedBoot as a
> boot loader. I thought that it should possibly go as a fix in
> drivers/mtd/redboot.c but I found the dev->resource->start parameter to
> parse_mtd_partitions to be the most graceful at the time.
>
> RedBoot on ixp4xx based boards starts flash addresses at 0x50000000 which
> Linux
> then starts at 0. So the partition table address entries are all offset by
> the
> RedBoot start point.
>
> I may be the only one who actually ran into the problem. I was working with
> a
> modified design that only had 48MB of flash. So as far as I am concerned it
> can
> be dropped. If every other board is using zero for that parameter it seems
> like
> it would make more sense to handle this condition in drivers/mtd/redboot.c?

I see your problem. It seems default code depends on size being a power of 2
_and_ start addr being aligned to the flash size. I think that usually that is
correct assumption, but we will need some override for the cases like yours.

Anyway I'm going to agree on the Artem's way to handle such cases.

-- 
With best wishes
Dmitry


From caiortp at gmail.com  Fri Jun 10 07:23:55 2011
From: caiortp at gmail.com (Caio)
Date: Fri, 10 Jun 2011 08:23:55 -0300
Subject: [JFFS2] No space for garbage collection
Message-ID: <BANLkTimFywX1=e+48Wb3qM9Rrvh1vaPJWA@mail.gmail.com>

Hello,

In my system I use Jffs2 in a NOR Flash (8MB), and there's a daemon
that write a configuration in a periodic time.
After few minutes the filesystem is corrupted and show a message


No space for garbage collection

MTD do_write_oneword(): WRITE 0x007fc0ac(0x00000085)
MTD do_write_oneword(): software timeout
MTD do_write_oneword(): software timeout
MTD do_write_oneword(): software timeout
MTD do_write_oneword(): software timeout
Write of 880 bytes at 0x005fc0ac failed. returned -5, retlen 0
Not marking the space at 0x005fc0ac as dirty because the flash driver returned o
MTD do_write_oneword(): WRITE 0x007fc0ac(0x00000085)
MTD do_write_oneword(): software timeout
MTD do_write_oneword(): software timeout
MTD do_write_oneword(): software timeout
MTD do_write_oneword(): software timeout
Write of 880 bytes at 0x005fc0ac failed. returned -5, retlen 0
Not marking the space at 0x005fc0ac as dirty because the flash driver returned o
Error garbage collecting node at 003112f8!
No space for garbage collection. Aborting GC thread

There's a way to call the garbage collector in my daemon?

I'm using kernel 2.6.30 but with a lot of patches


I applied all MTD/JFFS2 commits of the 2.6.30 to 2.6.31


MTD Patches

0001-mtd-nftl-write-support-is-broken.patch
0002-mtd-nftl-fix-offset-alignments.patch
1837-mtd_blkdevs-dequeue-in-flight-request.patch
2903--MTD-set-blkdev-parent-to-the-mtd-device-not-its-p.patch
2904--MTD-Restore-suspend-resume-support-for-mtd-devices.patch
2905--MTD-Remove-mtd-suspend-resume-calls-from-board.patch
2907--MTD-Remove-option-for-add_mtd_partitions-to-not.patch
3257-mtd-DIL-NetPC-broken-for-now.patch
3258-mtd-Add-armflash-support-for-multiple-blocks-of-fla.patch
3259-mtd-Fix-handling-of-mtdname-in-txx9ndfmc.c.patch
3261-mtd-add-MEMERASE64-ioctl-for-4GiB-devices.patch
3267-mtd-compat_ioctl-cleanup.patch
3268-mtd-add-OOB-ioctls-for-4GiB-devices.patch
3269-mtd-Handle-compat-ioctls-directly-remove-all-trace.patch
3270-mtd-Fix-pointer-handling-in-compat-ioctls-to-use-co.patch
3906-mtd-plat_nand-fix-section-error.patch
3909-mtd-nand-don-t-walk-past-end-of-oobfree.patch
3910-mtd-nand-minor-davinci_nand-cleanup.patch
3911-mtd-nand-davinci_nand-4-bit-ECC-for-smallpage.patch
3912-mtd-nand-fix-512-byte-software-ecc-support.patch
3913-mtd-mxc_nand-add-correct-dev_id-parameter-to-free_.patch
3914-mtd-m25p80-nand-add-m45pe10-ids.patch
3915-mtd-OneNAND-add-support-for-OneNAND-manufactured-b.patch
3916-mtd-davinci_nand-cmdlinepart-uses-MTD-IDs.patch
3917-mtd-add-SST39SF040-chip-to-jedec_probe.patch
3918-mtd-extend-plat_nand-for-read-write-_buf.patch
3919-mtd-CFI-quirk-for-PF38F4476.patch
3920-mtd-CFI-1.0-and-CFI-1.1.patch
3921-mtd-m25p80-add-support-for-Macronix-MX25L12805D.patch
3922-mtd-OneNAND-add-missing-__devexit_p.patch
3923-mtd-remove-pmcmsp-ramroot.c.patch
3924-mtd-plat_nand-add-platform-probe-remove-callbacks.patch
3925-mtd-plat_nand-allow-platform-to-set-partitions.patch
3926-mtd-MXC-NAND-support-for-2KiB-page-size-flashes.patch
3927-mtd-add-on-flash-BBT-support-for-Atmel-NAND-driver.patch
3928-mtd-blackfin-NFC-remove-pointless-return-value-in.patch
3929-mtd-blackfin-NFC-fix-hang-when-using-NAND-on-BF527.patch
3930-mtd-uclinux-allow-systems-to-override-map-addr-siz.patch
3931-mtd-uclinux-do-not-allow-to-be-built-as-a-module.patch
3932-mtd-uclinux-mark-local-stuff-static.patch
3933-mtd-maps-Blackfin-async-fix-memory-leaks-in-probe.patch
3935-mtd-nand-add-OMAP2-OMAP3-NAND-driver.patch
3936-mtd-Flex-OneNAND-support.patch
3937-mtd-onenand-add-bbt_wait-unlock_all-as-replaceab.patch
3940-mtd-nand-s3c2410_nand_setrate-use-correct-macro.patch
3941-mtd-nand-max_retries-off-by-one-in-mxc_nand.patch
3942-mtd-physmap_of-Add-multiple-regions-and-concatenat.patch
4072-mtd-nand-s3c6400-support-for-s3c2410-driver.patch
4073-mtd-orion_nand-use-burst-reads-with-double-word-ac.patch
4279-mtd-nand-Fix-memory-leak-on-txx9ndfmc-probe-failur.patch
5279-trivial-mtd-fix-Kconfig-comment-about-armflash.patch
6043-mtd-OneNAND-Allow-setting-of-boundary-information.patch
6044-sh-Add-support-mtd-mapping-for-highlander.patch
8425-mtd-maps-Remove-BUS_ID_SIZE-from-integrator_flash.patch
8471-mtd-cmdlineparts-Use-64-bit-format-when-printing-a.patch
8472-mtd-atmel_nand-Fix-typo-s-parititions-partitions.patch
8580-mtd-m25p80-timeout-too-short-for-worst-case-m25p16.patch
8603-mtd-Use-BLOCK_NIL-consistently-in-NFTL-INFTL.patch
8609-mtd-nand-fix-build-failure-and-incorrect-return-fr.patch
9940-mtd-let-include-linux-mtd-partitions.h-stand-on-its.patch
9941-mtd-fix-the-conversion-from-dev-to-mtd_info.patch
9942-mtd-blkdevs-do-not-forget-to-get-MTD-devices.patch
9943-mtd-OneNAND-fix-incorrect-bufferram-offset.patch
9944-mtd-OneNAND-OMAP2-3-free-GPMC-CS-on-module-remova.patch
9945-mtd-remove-SBC8240-Wind-River-Device-Driver-Code.patch
9946-mtd-mtdblock-introduce-mtdblks_lock.patch


JFFS2 Patches


3907-Kill-jffs2-user.h.patch
5046-jffs2-move-jffs2_write_super-to-super.c.patch
5079-jffs2-call-jffs2_write_super-from-jffs2_sync_fs.patch
5597-jffs2-leaking-jffs2_summary-in-function-jffs2_scan_.patch
8133-jffs2-fix-another-potential-leak-on-error-path-in-s.patch
8413-switch-jffs2-to-inode-i_acl.patch
9947-jffs2-Fix-return-value-from-jffs2_do_readpage_noloc.patch


My system:
Core: Nios2
NOR Flash: S29JL0674

Creating filesystem
mkfs.jffs2 -l -e64KiB -p -d romfs -D device_table.txt -o romfs.jffs2

Boot:
root=/dev/mtdblock0 rw rootfstype=jffs2


There's something I'm doing wrong? Maybe some ideia to fix this problem?

Thanks

Best Regards,

Caio Pereira


----------------------------------------------
Caio Pereira


From computersforpeace at gmail.com  Fri Jun 10 14:25:15 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 10 Jun 2011 11:25:15 -0700
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <BANLkTik9T_R5xZO5_GrzyznxwNnpv4931g@mail.gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307607194.7374.49.camel@localhost>
	<BANLkTik9T_R5xZO5_GrzyznxwNnpv4931g@mail.gmail.com>
Message-ID: <BANLkTin+pjQC6Y_BzME8RUFa-AtL_nJ14Q@mail.gmail.com>

On Thu, Jun 9, 2011 at 9:22 AM, Brian Norris
<computersforpeace at gmail.com> wrote:
> On Thu, Jun 9, 2011 at 1:13 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> Brian, would you please send a new series? I suggest you the following
>> order of things.
...
>> How does this sound to you?
>
> Sounds good. Will send patches later today, I think.

Hmm, actually, I'll get to this again on Monday! Have a good weekend.

Brian


From dbaryshkov at gmail.com  Sat Jun 11 17:02:21 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 01:02:21 +0400
Subject: [PATCH 2/3] ts72xx: use MTDPART_OFS_RETAIN for mtd partitioning
In-Reply-To: <20110611092224.GB16318@ibawizard.net>
References: <1307369056-29319-1-git-send-email-dbaryshkov@gmail.com>
	<1307369056-29319-3-git-send-email-dbaryshkov@gmail.com>
	<20110611092224.GB16318@ibawizard.net>
Message-ID: <BANLkTik4vJ6y6Y1igb_9HfaJ+ADeZ4xT0g@mail.gmail.com>

Hello, colleagues,

On 6/11/11, Petr ?tetiar <ynezz at true.cz> wrote:
> Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> [2011-06-06 18:04:15]:
>> Instead of specifying a callback for dynamic partitioning, use
>> MTDPART_OFS_RETAIN for reserving a place near the end of flash for
>> RedBoot.
>
> [...]
>
>> -		.offset		= MTDPART_OFS_APPEND,
>> -		.size		= 0,			/* filled in later */
>> +		.offset		= MTDPART_OFS_RETAIN,
>> +		.size		= TS72XX_REDBOOT_PART_SIZE,
>> +				/* leave so much for last partition */
>
> thank you for the mtd cleanup work. While testing this patch, I've noticed,
> that the TS72XX_REDBOOT_PART_SIZE is by 16K bigger, then it should be:
>
> Redboot:
>
> 	RedBoot> fis list
> 	Name              FLASH addr  Mem addr    Length      Entry point
> 	(reserved)        0x60000000  0x60000000  0x01D04000  0x00000000
> 	RedBoot           0x61D04000  0x61D04000  0x00040000  0x00000000
> 	vmlinux           0x61D44000  0x00218000  0x000C0000  0x00218000
> 	FIS directory     0x61FFC000  0x61FFC000  0x00003000  0x00000000
> 	RedBoot config    0x61FFF000  0x61FFF000  0x00001000  0x00000000
>
> Linux:
>
> 	0x000000000000-0x000000004000 : "TS-BOOTROM"
> 	0x000000004000-0x000001d00000 : "Linux"
> 	0x000001d00000-0x000002000000 : "RedBoot"
>
> So if I simply read now first 4 bytes from /dev/mtdblock2, there's no 'CRUS'
> or 'SURC' boot HeaderID/signature and it means, that there's no valid
> Redboot
> for ep93xx. The correct value is:
>
> 	#define TS72XX_REDBOOT_PART_SIZE	(SZ_2M + SZ_1M - SZ_16K)

Could you please verify/ack the attached patch?

-- 
With best wishes
Dmitry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-ts72xx-correct-partition-sizes.patch
Type: text/x-patch
Size: 1132 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110612/15ef0706/attachment.bin>

From dbaryshkov at gmail.com  Sat Jun 11 19:11:44 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:44 +0400
Subject: [PATCH V2 00/18] last part of big cleanup of partition handling
Message-ID: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>

Hello,

Changes in V2 of this serie:
* Introduce special struct mtd_parts_parser_data structure to hold data args
  passed to parsers
* small cleanups

The following changes since commit 3e1643b282542cf524d30cfab4cfe38f6b2afa99:

  mtd: edb7312: correctly pass MTD name to parsers (2011-06-09 15:30:44 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup

Dmitry Eremin-Solenikov (18):
      mtd: abstract last MTD partition parser argument
      mtd: prepare to convert of_mtd_parse_partitions to partition parser
      mtd: physmap_of: use ofpart through generic parsing
      mtd: m25p80: use ofpart through generic parsing
      mtd: fsl_elbc_nand: use ofpart through generic parsing
      mtd: fsl_upm: use ofpart through generic parsing
      mtd: mpc5121_nfc: use ofpart through generic parsing
      mtd: ndfc: use ofpart through generic parsing
      mtd: socrates_nand: use ofpart through generic parsing
      mtd: drop of_mtd_parse_partitions()
      mtd: physmap_of: move parse_obsolete_partitions to become separate parser
      mtd: physmap_of.c: use mtd_device_parse_register
      mtd: m25p80.c: use mtd_device_parse_register
      mtd: fsl_elbc_nand.c: use mtd_device_parse_register
      mtd: fsl_upm.c: use mtd_device_parse_register
      mtd: mpc5121_nfc.c: use mtd_device_parse_register
      mtd: ndfc.c: use mtd_device_parse_register
      mtd: socrates_nand.c: use mtd_device_parse_register

 drivers/mtd/cmdlinepart.c        |    2 +-
 drivers/mtd/devices/m25p80.c     |   37 ++------------
 drivers/mtd/maps/physmap_of.c    |   80 +++--------------------------
 drivers/mtd/mtdcore.c            |    6 +-
 drivers/mtd/mtdpart.c            |   15 ++++--
 drivers/mtd/nand/fsl_elbc_nand.c |   17 ++-----
 drivers/mtd/nand/fsl_upm.c       |   13 +----
 drivers/mtd/nand/mpc5121_nfc.c   |   17 +-----
 drivers/mtd/nand/ndfc.c          |   16 +-----
 drivers/mtd/nand/socrates_nand.c |   23 +-------
 drivers/mtd/ofpart.c             |  104 ++++++++++++++++++++++++++++++++++++--
 drivers/mtd/redboot.c            |    6 +-
 include/linux/mtd/mtd.h          |    3 +-
 include/linux/mtd/partitions.h   |   32 +++++-------
 14 files changed, 160 insertions(+), 211 deletions(-)



From dbaryshkov at gmail.com  Sat Jun 11 19:11:45 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:45 +0400
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>

Encapsulate last MTD partition parser argument into a separate
structure. Currently it holds only 'origin' field for RedBoot parser,
but will be extended in future to contain at least device_node for OF
devices.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/cmdlinepart.c      |    2 +-
 drivers/mtd/mtdcore.c          |    6 +++---
 drivers/mtd/mtdpart.c          |    7 ++++---
 drivers/mtd/redboot.c          |    6 +++---
 include/linux/mtd/mtd.h        |    3 ++-
 include/linux/mtd/partitions.h |   14 ++++++++++++--
 6 files changed, 25 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index be0c121..80851c6 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -314,7 +314,7 @@ static int mtdpart_setup_real(char *s)
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
                              struct mtd_partition **pparts,
-                             unsigned long origin)
+                             struct mtd_part_parser_data *data)
 {
 	unsigned long offset;
 	int i;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 1326747..a4067e7 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -457,7 +457,7 @@ EXPORT_SYMBOL_GPL(mtd_device_register);
  * @mtd: the MTD device to register
  * @types: the list of MTD partition probes to try, see
  *         'parse_mtd_partitions()' for more information
- * @origin: start address of MTD device, %0 unless you are sure you need this.
+ * @parser_data: data passed to mtd parsers
  * @parts: fallback partition information to register, if parsing fails;
  *         only valid if %nr_parts > %0
  * @nr_parts: the number of partitions in parts, if zero then the full
@@ -480,14 +480,14 @@ EXPORT_SYMBOL_GPL(mtd_device_register);
  * Returns zero in case of success and a negative error code in case of failure.
  */
 int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
-			      unsigned long origin,
+			      struct mtd_part_parser_data *parser_data,
 			      const struct mtd_partition *parts,
 			      int nr_parts)
 {
 	int err;
 	struct mtd_partition *real_parts;
 
-	err = parse_mtd_partitions(mtd, types, &real_parts, origin);
+	err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
 	if (err <= 0 && nr_parts) {
 		real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
 				     GFP_KERNEL);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 2b71ccb..09ebe69 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -736,7 +736,7 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  * @master: the master partition (describes whole MTD device)
  * @types: names of partition parsers to try or %NULL
  * @pparts: array of partitions found is returned here
- * @origin: MTD device start address (use %0 if unsure)
+ * @data: data passed to MTD partition parsers
  *
  * This function tries to find partition on MTD device @master. It uses MTD
  * partition parsers, specified in @types. However, if @types is %NULL, then
@@ -750,7 +750,8 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  *   point to an array containing this number of &struct mtd_info objects.
  */
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
-			 struct mtd_partition **pparts, unsigned long origin)
+			 struct mtd_partition **pparts,
+			 struct mtd_part_parser_data *data)
 {
 	struct mtd_part_parser *parser;
 	int ret = 0;
@@ -764,7 +765,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 				parser = get_partition_parser(*types);
 		if (!parser)
 			continue;
-		ret = (*parser->parse_fn)(master, pparts, origin);
+		ret = (*parser->parse_fn)(master, pparts, data);
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			       ret, parser->name, master->name);
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 7a87d07..2b65558 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -57,7 +57,7 @@ static inline int redboot_checksum(struct fis_image_desc *img)
 
 static int parse_redboot_partitions(struct mtd_info *master,
                              struct mtd_partition **pparts,
-                             unsigned long fis_origin)
+                             struct mtd_part_parser_data *data)
 {
 	int nrparts = 0;
 	struct fis_image_desc *buf;
@@ -197,8 +197,8 @@ static int parse_redboot_partitions(struct mtd_info *master,
 			goto out;
 		}
 		new_fl->img = &buf[i];
-                if (fis_origin) {
-                        buf[i].flash_base -= fis_origin;
+                if (data && data->origin) {
+                        buf[i].flash_base -= data->origin;
                 } else {
                         buf[i].flash_base &= master->size-1;
                 }
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index d28a241..b2b454b 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -323,13 +323,14 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
 	/* Kernel-side ioctl definitions */
 
 struct mtd_partition;
+struct mtd_part_parser_data;
 
 extern int mtd_device_register(struct mtd_info *master,
 			       const struct mtd_partition *parts,
 			       int nr_parts);
 extern int mtd_device_parse_register(struct mtd_info *mtd,
 			      const char **part_probe_types,
-			      unsigned long origin,
+			      struct mtd_part_parser_data *parser_data,
 			      const struct mtd_partition *defparts,
 			      int defnr_parts);
 extern int mtd_device_unregister(struct mtd_info *master);
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 1431cf2..4e91abf 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -52,6 +52,15 @@ struct mtd_partition {
 
 struct mtd_info;
 
+/**
+ * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
+ * @origin: for RedBoot, start address of MTD device, %0 unless you are sure you need this.
+ */
+struct mtd_part_parser_data {
+	unsigned long origin;
+};
+
+
 /*
  * Functions dealing with the various ways of partitioning the space
  */
@@ -60,13 +69,14 @@ struct mtd_part_parser {
 	struct list_head list;
 	struct module *owner;
 	const char *name;
-	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
+	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, struct mtd_part_parser_data *);
 };
 
 extern int register_mtd_parser(struct mtd_part_parser *parser);
 extern int deregister_mtd_parser(struct mtd_part_parser *parser);
 extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
-				struct mtd_partition **pparts, unsigned long origin);
+				struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data);
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:47 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:47 +0400
Subject: [PATCH 03/18] mtd: physmap_of: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-4-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   13 +++++--------
 1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index d251d1d..6a75743 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -165,7 +165,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
+static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+					"ofpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -218,6 +219,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	int reg_tuple_size;
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
+	struct mtd_part_parser_data ppdata;
 
 	match = of_match_device(of_flash_match, &dev->dev);
 	if (!match)
@@ -331,9 +333,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	if (err)
 		goto err_out;
 
+	ppdata.of_node = dp;
 	part_probe_types = of_get_probes(dp);
 	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
+				   &info->parts, &ppdata);
 	if (err < 0) {
 		of_free_probes(part_probe_types);
 		goto err_out;
@@ -341,12 +344,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	of_free_probes(part_probe_types);
 
 	if (err == 0) {
-		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
-		if (err < 0)
-			goto err_out;
-	}
-
-	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
 		if (err < 0)
 			goto err_out;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:46 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:46 +0400
Subject: [PATCH 02/18] mtd: prepare to convert of_mtd_parse_partitions to
	partition parser
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-3-git-send-email-dbaryshkov@gmail.com>

Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
1) Register ofpart parser
2) Internally don't use passed device for error printing
3) Add device_node to mtd_part_parser_data struct
4) Move of_mtd_parse_partitions from __devinit to common text section
5) add ofpart to the default list of partition parsers

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdpart.c          |    8 ++++++--
 drivers/mtd/ofpart.c           |   27 +++++++++++++++++++++++++--
 include/linux/mtd/partitions.h |    4 +++-
 3 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 09ebe69..54160c0 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -729,7 +729,11 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
  * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
  * are changing this array!
  */
-static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
+static const char *default_mtd_part_types[] = {
+	"cmdlinepart",
+	"ofpart",
+	NULL
+};
 
 /**
  * parse_mtd_partitions - parse MTD partitions
@@ -741,7 +745,7 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  * This function tries to find partition on MTD device @master. It uses MTD
  * partition parsers, specified in @types. However, if @types is %NULL, then
  * the default list of parsers is used. The default list contains only the
- * "cmdlinepart" parser ATM.
+ * "cmdlinepart" and "ofpart" parsers ATM.
  *
  * This function may return:
  * o a negative error code in case of failure
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index a996718..7c2c926 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -20,7 +20,17 @@
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
-int __devinit of_mtd_parse_partitions(struct device *dev,
+static int parse_ofpart_partitions(struct mtd_info *master,
+				   struct mtd_partition **pparts,
+				   struct mtd_part_parser_data *data)
+{
+	if (!data || !data->of_node)
+		return 0;
+
+	return of_mtd_parse_partitions(NULL, data->of_node, pparts);
+}
+
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts)
 {
@@ -69,7 +79,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 
 	if (!i) {
 		of_node_put(pp);
-		dev_err(dev, "No valid partition found on %s\n", node->full_name);
+		pr_err("No valid partition found on %s\n", node->full_name);
 		kfree(*pparts);
 		*pparts = NULL;
 		return -EINVAL;
@@ -79,4 +89,17 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 }
 EXPORT_SYMBOL(of_mtd_parse_partitions);
 
+static struct mtd_part_parser ofpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofpart_partitions,
+	.name = "ofpart",
+};
+
+static int __init ofpart_parser_init(void)
+{
+	return register_mtd_parser(&ofpart_parser);
+}
+
+module_init(ofpart_parser_init);
+
 MODULE_LICENSE("GPL");
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 4e91abf..dad4edf 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -51,6 +51,7 @@ struct mtd_partition {
 
 
 struct mtd_info;
+struct device_node;
 
 /**
  * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
@@ -58,6 +59,7 @@ struct mtd_info;
  */
 struct mtd_part_parser_data {
 	unsigned long origin;
+	struct device_node *of_node;
 };
 
 
@@ -84,7 +86,7 @@ struct device;
 struct device_node;
 
 #ifdef CONFIG_MTD_OF_PARTS
-int __devinit of_mtd_parse_partitions(struct device *dev,
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts);
 #else
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:49 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:49 +0400
Subject: [PATCH 05/18] mtd: fsl_elbc_nand: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-6-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index f3384fa..6b66a14 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -842,13 +842,15 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct resource res;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
-		= { "cmdlinepart", "RedBoot", NULL };
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
 	struct mtd_partition *parts;
 	int ret;
 	int bank;
 	struct device *dev;
 	struct device_node *node = pdev->dev.of_node;
+	struct mtd_part_parser_data ppdata;
 
+	ppdata.of_node = pdev->dev.of_node;
 	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
 		return -ENODEV;
 	lbc = fsl_lbc_ctrl_dev->regs;
@@ -934,16 +936,10 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
+	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, &ppdata);
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(priv->dev, node, &parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	mtd_device_register(&priv->mtd, parts, ret);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:48 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:48 +0400
Subject: [PATCH 04/18] mtd: m25p80: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-5-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 70d5fca..399c234 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -827,6 +827,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	unsigned			i;
 	struct mtd_partition		*parts = NULL;
 	int				nr_parts = 0;
+	struct mtd_part_parser_data	ppdata;
 
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
@@ -928,6 +929,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 
+	ppdata.of_node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
 
@@ -968,20 +970,13 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
+	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, &ppdata);
 
 	if (nr_parts <= 0 && data && data->parts) {
 		parts = data->parts;
 		nr_parts = data->nr_parts;
 	}
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (nr_parts <= 0 && spi->dev.of_node) {
-		nr_parts = of_mtd_parse_partitions(&spi->dev,
-						   spi->dev.of_node, &parts);
-	}
-#endif
-
 	if (nr_parts > 0) {
 		for (i = 0; i < nr_parts; i++) {
 			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:50 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:50 +0400
Subject: [PATCH 06/18] mtd: fsl_upm: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-7-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 7c782eb..714d831 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -158,6 +158,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 {
 	int ret;
 	struct device_node *flash_np;
+	struct mtd_part_parser_data ppdata;
 
 	fun->chip.IO_ADDR_R = fun->io_base;
 	fun->chip.IO_ADDR_W = fun->io_base;
@@ -191,15 +192,9 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, 0);
+	ppdata.of_node = flash_np;
+	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, &ppdata);
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
-		if (ret < 0)
-			goto err;
-	}
-#endif
 	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
 err:
 	of_node_put(flash_np);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:51 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:51 +0400
Subject: [PATCH 07/18] mtd: mpc5121_nfc: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-8-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 0b61367..996ee29 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -661,6 +661,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	int resettime = 0;
 	int retval = 0;
 	int rev, len;
+	struct mtd_part_parser_data ppdata;
 
 	/*
 	 * Check SoC revision. This driver supports only NFC
@@ -725,6 +726,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	}
 
 	mtd->name = "MPC5121 NAND";
+	ppdata.of_node = dn;
 	chip->dev_ready = mpc5121_nfc_dev_ready;
 	chip->cmdfunc = mpc5121_nfc_command;
 	chip->read_byte = mpc5121_nfc_read_byte;
@@ -836,11 +838,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, NULL, &parts, 0);
-#ifdef CONFIG_MTD_OF_PARTS
-	if (retval == 0)
-		retval = of_mtd_parse_partitions(dev, dn, &parts);
-#endif
+	retval = parse_mtd_partitions(mtd, NULL, &parts, &ppdata);
 	if (retval < 0) {
 		dev_err(dev, "Error parsing MTD partitions!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:52 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:52 +0400
Subject: [PATCH 08/18] mtd: ndfc: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-9-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 70c04ff..1528734 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -161,6 +161,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 {
 	struct device_node *flash_np;
 	struct nand_chip *chip = &ndfc->chip;
+	struct mtd_part_parser_data ppdata;
 	int ret;
 
 	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
@@ -188,6 +189,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (!flash_np)
 		return -ENODEV;
 
+	ppdata->of_node = flash_np;
 	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
 			dev_name(&ndfc->ofdev->dev), flash_np->name);
 	if (!ndfc->mtd.name) {
@@ -199,17 +201,10 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, 0);
+	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, &ppdata);
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
-					      &ndfc->parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
 
 err:
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:53 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:53 +0400
Subject: [PATCH 09/18] mtd: socrates_nand: use ofpart through generic parsing
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-10-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   14 +++-----------
 1 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 9023ac8..f4f79ec 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -166,6 +166,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	int res;
 	struct mtd_partition *partitions = NULL;
 	int num_partitions = 0;
+	struct mtd_part_parser_data ppdata;
 
 	/* Allocate memory for the device structure (and zero it) */
 	host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
@@ -191,6 +192,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	mtd->name = "socrates_nand";
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &ofdev->dev;
+	ppdata.of_node = ofdev->dev.of_node;
 
 	/*should never be accessed directly */
 	nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
@@ -223,22 +225,12 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, 0);
+	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, &ppdata);
 	if (num_partitions < 0) {
 		res = num_partitions;
 		goto release;
 	}
 
-	if (num_partitions == 0) {
-		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-							 ofdev->dev.of_node,
-							 &partitions);
-		if (num_partitions < 0) {
-			res = num_partitions;
-			goto release;
-		}
-	}
-
 	res = mtd_device_register(mtd, partitions, num_partitions);
 	if (!res)
 		return res;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:54 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:54 +0400
Subject: [PATCH 10/18] mtd: drop of_mtd_parse_partitions()
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-11-git-send-email-dbaryshkov@gmail.com>

All users have been converted to call of_mtd_parse_partitions through
parse_mtd_partitions() multiplexer. Drop obsolete API.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/ofpart.c           |   20 +++++++++-----------
 include/linux/mtd/partitions.h |   16 ----------------
 2 files changed, 9 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 7c2c926..24007f3 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -24,20 +24,19 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 				   struct mtd_partition **pparts,
 				   struct mtd_part_parser_data *data)
 {
-	if (!data || !data->of_node)
-		return 0;
-
-	return of_mtd_parse_partitions(NULL, data->of_node, pparts);
-}
-
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts)
-{
+	struct device_node *node;
 	const char *partname;
 	struct device_node *pp;
 	int nr_parts, i;
 
+
+	if (!data)
+		return 0;
+
+	node = data->of_node;
+	if (!node)
+		return 0;
+
 	/* First count the subnodes */
 	pp = NULL;
 	nr_parts = 0;
@@ -87,7 +86,6 @@ int of_mtd_parse_partitions(struct device *dev,
 
 	return nr_parts;
 }
-EXPORT_SYMBOL(of_mtd_parse_partitions);
 
 static struct mtd_part_parser ofpart_parser = {
 	.owner = THIS_MODULE,
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index dad4edf..3d330e0 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -82,22 +82,6 @@ extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-struct device;
-struct device_node;
-
-#ifdef CONFIG_MTD_OF_PARTS
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts);
-#else
-static inline int of_mtd_parse_partitions(struct device *dev,
-					  struct device_node *node,
-					  struct mtd_partition **pparts)
-{
-	return 0;
-}
-#endif
-
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
 		      long long offset, long long length);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:55 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:55 +0400
Subject: [PATCH 11/18] mtd: physmap_of: move parse_obsolete_partitions to
	become separate parser
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-12-git-send-email-dbaryshkov@gmail.com>

Move parse_obsolete_partitions() to ofpart.c and register it as an
ofoldpart partitions parser.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   53 +----------------------------
 drivers/mtd/ofpart.c          |   75 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 6a75743..55c4e2e 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -40,51 +40,6 @@ struct of_flash {
 };
 
 #define OF_FLASH_PARTS(info)	((info)->parts)
-static int parse_obsolete_partitions(struct platform_device *dev,
-				     struct of_flash *info,
-				     struct device_node *dp)
-{
-	int i, plen, nr_parts;
-	const struct {
-		__be32 offset, len;
-	} *part;
-	const char *names;
-
-	part = of_get_property(dp, "partitions", &plen);
-	if (!part)
-		return 0; /* No partitions found */
-
-	dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
-
-	nr_parts = plen / sizeof(part[0]);
-
-	info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
-	if (!info->parts)
-		return -ENOMEM;
-
-	names = of_get_property(dp, "partition-names", &plen);
-
-	for (i = 0; i < nr_parts; i++) {
-		info->parts[i].offset = be32_to_cpu(part->offset);
-		info->parts[i].size   = be32_to_cpu(part->len) & ~1;
-		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
-			info->parts[i].mask_flags = MTD_WRITEABLE;
-
-		if (names && (plen > 0)) {
-			int len = strlen(names) + 1;
-
-			info->parts[i].name = (char *)names;
-			plen -= len;
-			names += len;
-		} else {
-			info->parts[i].name = "unnamed";
-		}
-
-		part++;
-	}
-
-	return nr_parts;
-}
 
 static int of_flash_remove(struct platform_device *dev)
 {
@@ -166,7 +121,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    default is use. These take precedence over other device tree
    information. */
 static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
-					"ofpart", NULL };
+					"ofpart", "ofoldpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -343,12 +298,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	}
 	of_free_probes(part_probe_types);
 
-	if (err == 0) {
-		err = parse_obsolete_partitions(dev, info, dp);
-		if (err < 0)
-			goto err_out;
-	}
-
 	mtd_device_register(info->cmtd, info->parts, err);
 
 	kfree(mtd_list);
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 24007f3..41c4518 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -93,9 +93,82 @@ static struct mtd_part_parser ofpart_parser = {
 	.name = "ofpart",
 };
 
+static int parse_ofoldpart_partitions(struct mtd_info *master,
+				      struct mtd_partition **pparts,
+				      struct mtd_part_parser_data *data)
+{
+	struct device_node *dp;
+	int i, plen, nr_parts;
+	const struct {
+		__be32 offset, len;
+	} *part;
+	const char *names;
+
+	if (!data)
+		return 0;
+
+	dp = data->of_node;
+	if (!dp)
+		return 0;
+
+	part = of_get_property(dp, "partitions", &plen);
+	if (!part)
+		return 0; /* No partitions found */
+
+	pr_warning("Device tree uses obsolete partition map binding: %s\n",
+			dp->full_name);
+
+	nr_parts = plen / sizeof(part[0]);
+
+	*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
+	if (!pparts)
+		return -ENOMEM;
+
+	names = of_get_property(dp, "partition-names", &plen);
+
+	for (i = 0; i < nr_parts; i++) {
+		(*pparts)[i].offset = be32_to_cpu(part->offset);
+		(*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
+		/* bit 0 set signifies read only partition */
+		if (be32_to_cpu(part->len) & 1)
+			(*pparts)[i].mask_flags = MTD_WRITEABLE;
+
+		if (names && (plen > 0)) {
+			int len = strlen(names) + 1;
+
+			(*pparts)[i].name = (char *)names;
+			plen -= len;
+			names += len;
+		} else {
+			(*pparts)[i].name = "unnamed";
+		}
+
+		part++;
+	}
+
+	return nr_parts;
+}
+
+static struct mtd_part_parser ofoldpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofoldpart_partitions,
+	.name = "ofoldpart",
+};
+
 static int __init ofpart_parser_init(void)
 {
-	return register_mtd_parser(&ofpart_parser);
+	int rc;
+	rc = register_mtd_parser(&ofpart_parser);
+	if (rc)
+		goto out;
+
+	rc = register_mtd_parser(&ofoldpart_parser);
+	if (!rc)
+		return 0;
+
+	deregister_mtd_parser(&ofoldpart_parser);
+out:
+	return rc;
 }
 
 module_init(ofpart_parser_init);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:56 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:56 +0400
Subject: [PATCH 12/18] mtd: physmap_of.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-13-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   18 +++---------------
 1 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 55c4e2e..7d65f9d 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -34,13 +34,10 @@ struct of_flash_list {
 
 struct of_flash {
 	struct mtd_info		*cmtd;
-	struct mtd_partition	*parts;
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 };
 
-#define OF_FLASH_PARTS(info)	((info)->parts)
-
 static int of_flash_remove(struct platform_device *dev)
 {
 	struct of_flash *info;
@@ -56,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
 		mtd_concat_destroy(info->cmtd);
 	}
 
-	if (info->cmtd) {
-		if (OF_FLASH_PARTS(info))
-			kfree(OF_FLASH_PARTS(info));
+	if (info->cmtd)
 		mtd_device_unregister(info->cmtd);
-	}
 
 	for (i = 0; i < info->list_size; i++) {
 		if (info->list[i].mtd)
@@ -290,16 +284,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 
 	ppdata.of_node = dp;
 	part_probe_types = of_get_probes(dp);
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, &ppdata);
-	if (err < 0) {
-		of_free_probes(part_probe_types);
-		goto err_out;
-	}
+	mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
+			NULL, 0);
 	of_free_probes(part_probe_types);
 
-	mtd_device_register(info->cmtd, info->parts, err);
-
 	kfree(mtd_list);
 
 	return 0;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:57 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:57 +0400
Subject: [PATCH 13/18] mtd: m25p80.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-14-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   28 +++-------------------------
 1 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 399c234..66a3555 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -88,7 +88,6 @@ struct m25p {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-	unsigned		partitioned:1;
 	u16			page_size;
 	u16			addr_width;
 	u8			erase_opcode;
@@ -825,8 +824,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	struct m25p			*flash;
 	struct flash_info		*info;
 	unsigned			i;
-	struct mtd_partition		*parts = NULL;
-	int				nr_parts = 0;
 	struct mtd_part_parser_data	ppdata;
 
 	/* Platform data helps sort out which chip type we have, as
@@ -970,28 +967,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, &ppdata);
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-		flash->partitioned = 1;
-	}
-
-	return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
-		-ENODEV : 0;
+	return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
 }
 
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:58 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:58 +0400
Subject: [PATCH 14/18] mtd: fsl_elbc_nand.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-15-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 6b66a14..004dbc2 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -843,7 +843,6 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
-	struct mtd_partition *parts;
 	int ret;
 	int bank;
 	struct device *dev;
@@ -936,11 +935,7 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, &ppdata);
-	if (ret < 0)
-		goto err;
-
-	mtd_device_register(&priv->mtd, parts, ret);
+	mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata, NULL, 0);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
 	       (unsigned long long)res.start, priv->bank);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:11:59 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:11:59 +0400
Subject: [PATCH 15/18] mtd: fsl_upm.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-16-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 714d831..da92fed 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -193,9 +193,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 		goto err;
 
 	ppdata.of_node = flash_np;
-	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, &ppdata);
-
-	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
+	ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
 err:
 	of_node_put(flash_np);
 	return ret;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:12:00 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:12:00 +0400
Subject: [PATCH 16/18] mtd: mpc5121_nfc.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-17-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 996ee29..871095f 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -654,7 +654,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
 	struct mtd_info *mtd;
-	struct mtd_partition *parts;
 	struct nand_chip *chip;
 	unsigned long regs_paddr, regs_size;
 	const __be32 *chips_no;
@@ -838,15 +837,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, NULL, &parts, &ppdata);
-	if (retval < 0) {
-		dev_err(dev, "Error parsing MTD partitions!\n");
-		devm_free_irq(dev, prv->irq, mtd);
-		retval = -EINVAL;
-		goto error;
-	}
-
-	retval = mtd_device_register(mtd, parts, retval);
+	retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (retval) {
 		dev_err(dev, "Error adding MTD device!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:12:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:12:01 +0400
Subject: [PATCH 17/18] mtd: ndfc.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-18-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 1528734..ee17139 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -42,7 +42,6 @@ struct ndfc_controller {
 	struct nand_chip chip;
 	int chip_select;
 	struct nand_hw_control ndfc_control;
-	struct mtd_partition *parts;
 };
 
 static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
@@ -201,11 +200,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, &ppdata);
-	if (ret < 0)
-		goto err;
-
-	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
+	ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0);
 
 err:
 	of_node_put(flash_np);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Sat Jun 11 19:12:02 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Sun, 12 Jun 2011 03:12:02 +0400
Subject: [PATCH 18/18] mtd: socrates_nand.c: use mtd_device_parse_register
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1307833922-21602-19-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index f4f79ec..0fb24f9 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -164,8 +164,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
 	struct mtd_part_parser_data ppdata;
 
 	/* Allocate memory for the device structure (and zero it) */
@@ -225,17 +223,10 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, &ppdata);
-	if (num_partitions < 0) {
-		res = num_partitions;
-		goto release;
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (!res)
 		return res;
 
-release:
 	nand_release(mtd);
 
 out:
-- 
1.7.5.3



From Shaohui.Xie at freescale.com  Sun Jun 12 22:23:12 2011
From: Shaohui.Xie at freescale.com (Shaohui Xie)
Date: Mon, 13 Jun 2011 10:23:12 +0800
Subject: [PATCH] powerpc/85xx: fix NAND_CMD_READID read bytes number
Message-ID: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>

when nand_get_flash_type() is called, it will read 8 bytes of ID instead of 5,
but the driver only read 5 bytes, so kernel will dump error messages like:

fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
fsl-lbc ffe124000.localbus: read_byte beyond end of buffer

Signed-off-by: Shaohui Xie <Shaohui.Xie at freescale.com>
Acked-by: Scott Wood <scottwood at freescale.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 0bb254c..33d8aad 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -339,9 +339,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		                    (FIR_OP_UA  << FIR_OP1_SHIFT) |
 		                    (FIR_OP_RBW << FIR_OP2_SHIFT));
 		out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
-		/* 5 bytes for manuf, device and exts */
-		out_be32(&lbc->fbcr, 5);
-		elbc_fcm_ctrl->read_bytes = 5;
+		/* nand_get_flash_type() reads 8 bytes of entire ID string */
+		out_be32(&lbc->fbcr, 8);
+		elbc_fcm_ctrl->read_bytes = 8;
 		elbc_fcm_ctrl->use_mdr = 1;
 		elbc_fcm_ctrl->mdr = 0;
 
-- 
1.6.4




From computersforpeace at gmail.com  Mon Jun 13 14:24:23 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 11:24:23 -0700
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <1307635412.7374.128.camel@localhost>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307605456.7374.35.camel@localhost>
	<BANLkTin5KLu8QknuM4ATHpLQP4Uq09tekA@mail.gmail.com>
	<1307635412.7374.128.camel@localhost>
Message-ID: <BANLkTimh12AhqfE+Yx3Yi_m=NyUb34JoXA@mail.gmail.com>

On Thu, Jun 9, 2011 at 9:03 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2011-06-09 at 09:00 -0700, Brian Norris wrote:
>> On Thu, Jun 9, 2011 at 12:44 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> > Wait, and why are we using pr_* while it is better to use dbg_* ? :-)
>>
>> Just so we're on the same page...did you say "dbg_*" when you really
>> meant "dev_*"?
>
> Yes, I meant dev_*
>
>> Anyway, the answer is: I'm mostly trying to do as little shakeup as
>> possible, so "printk" could translate pretty directly to the "pr_*"
>> with shorter code, etc. If it makes as much (or more) sense to have
>> the device name on all the prints, then I can just as well do it that
>> way.
>
> Yes, I think it makes much more sense to specify for which device (out
> of possibly many!) this message belongs.

I've been testing some of the "dev_*" printing, and it seems as if our
mtd_info structs never have fully initialized "device" fields (i.e.,
mtd->dev.driver, mtd->dev.bus, mtd->dev.class, mtd->dev.init_name,
etc. are never filled in with anything meaningful). That means that
our dev_* messages do not have anything to work from and simply print
" (null): " references before our strings instead of device
driver/name information, for example:

 (null): ONFI flash detected

I'm a little new to the Linux device model, so I'm not sure if it's
safe and sensible to add lines to a driver's nand_probe function,
like, for plat_nand.c:
data->mtd.dev.driver = pdev->dev.driver;
data->mtd.dev.init_name = dev_name(&pdev->dev);

Is there some better way to initialize these device values? Or should
we scrap the whole dev_* thing since MTD doesn't match the device
model well enough?

Brian


From computersforpeace at gmail.com  Mon Jun 13 15:17:18 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 12:17:18 -0700
Subject: nanddump badblock options
In-Reply-To: <1307608004.7374.56.camel@localhost>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
	<1307608004.7374.56.camel@localhost>
Message-ID: <BANLkTimU-fzEj6ByC9X6DX=tUQ0ay_eYrQ@mail.gmail.com>

One last idea, while I'm trying to bring nanddump and nandwrite a
little closer together:

It makes sense for nanddump and nandwrite to have the same defaults
regarding OOB. Right now, nandwrite doesn't write OOB by default, and
nanddump dumps OOB by default. Is it OK to unify this and make
nanddump default to *not* dumping OOB? Then the nanddump '-o' and
'--oob' options would stand for 'Dump OOB data'. Unfortunately, this
makes the '-o' option completely reverse its meaning...

I would include this with my other change-ups if that's alright
(they're ready to send).

Mike:
any comments on my '--omitbad' question?

Thanks,
Brian


From jj at chaosbits.net  Mon Jun 13 16:16:44 2011
From: jj at chaosbits.net (Jesper Juhl)
Date: Mon, 13 Jun 2011 22:16:44 +0200 (CEST)
Subject: [PATCH/Trivial] jffs2: Avoid unneeded 'if' before kfree
Message-ID: <alpine.LNX.2.00.1106132213500.30934@swampdragon.chaosbits.net>

kfree() deals gracefully with NULL pointers, so it's pointless to test for 
one prior to calling it.
This removes such a test from jffs2_scan_medium().

Signed-off-by: Jesper Juhl <jj at chaosbits.net>
---
 scan.c |    4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c
index 8d8cd34..28107ca 100644
--- a/fs/jffs2/scan.c
+++ b/fs/jffs2/scan.c
@@ -275,9 +275,7 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
 	else
 		c->mtd->unpoint(c->mtd, 0, c->mtd->size);
 #endif
-	if (s)
-		kfree(s);
-
+	kfree(s);
 	return ret;
 }
 

-- 
Jesper Juhl <jj at chaosbits.net>       http://www.chaosbits.net/
Don't top-post http://www.catb.org/jargon/html/T/top-post.html
Plain text mails only, please.



From computersforpeace at gmail.com  Mon Jun 13 19:31:59 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 16:31:59 -0700
Subject: [PATCH 2/6] nanddump: remove --skipbad, leaving --bb=skipbad
In-Reply-To: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
References: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308007923-6820-2-git-send-email-computersforpeace@gmail.com>

We are moving to unify bad block handling methods under the --bb=METHOD
option. Since --skipbad has not been included in a mtd-utils release yet,
we can safely replace it without a deprecation and phase-out period.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   13 +------------
 1 files changed, 1 insertions(+), 12 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index c3771c5..a945081 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -57,7 +57,6 @@ static void display_help(void)
 "-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
-"-k         --skipbad            Skip over bad blocks (see below)\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
 "-N         --noskipbad          Read without bad block skipping\n"
@@ -117,7 +116,7 @@ static void process_options(int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "bs:f:l:opqnNcak";
+		static const char *short_options = "bs:f:l:opqnNca";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
@@ -132,7 +131,6 @@ static void process_options(int argc, char * const argv[])
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
 			{"noskipbad", no_argument, 0, 'N'},
-			{"skipbad", no_argument, 0, 'k'},
 			{"quiet", no_argument, 0, 'q'},
 			{0, 0, 0, 0},
 		};
@@ -215,15 +213,6 @@ static void process_options(int argc, char * const argv[])
 					error++;
 				}
 				break;
-			case 'k':
-				/* Check if bb_method was already set explicitly */
-				if (bb_default) {
-					bb_default = false;
-					bb_method = skipbad;
-				} else {
-					error++;
-				}
-				break;
 			case '?':
 				error++;
 				break;
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 13 19:32:01 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 16:32:01 -0700
Subject: [PATCH 4/6] nanddump: warn about changing default badblock
 method
In-Reply-To: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
References: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308007923-6820-4-git-send-email-computersforpeace@gmail.com>

In an upcoming release, we will no longer default to --bb=padbad. Instead,
the default will be --bb=skipbad. This makes nanddump a better inverse
operation to nandwrite.

This patch prints warnings for users so that they get a chance to update
their scripts before the default changes officially.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 4f28e33..211f8ae 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -249,6 +249,11 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (bb_default)
+		fprintf(stderr, "Warning: you did not specify a default bad-block handling\n"
+				"  method. In future versions, the default will change to\n"
+				"  --bb=skipbad. Use \"nanddump --help\" for more information.\n");
+
 	if ((argc - optind) != 1 || error)
 		display_help();
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 13 19:32:02 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 16:32:02 -0700
Subject: [PATCH 5/6] feature-removal-schedule: describe nanddump changes
In-Reply-To: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
References: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308007923-6820-5-git-send-email-computersforpeace@gmail.com>

Include a few notes about the edited options and new default options in
nanddump.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index a5980f7..0f1f5c5 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -40,3 +40,28 @@ This is duplicating behavior with the mtdinfo utility.  Now the util
 warns when people use it, but it'll be removed in release 1.4.6.
 
 ---------------------------
+
+4. Rename --omitbad and --noskipbad options for nanddump, change default
+
+These and a few other bad block handling methods are getting disorganized. They
+will be replaced by a series of --bb=METHOD options (see 'nanddump --help').
+
+In addition, the previous default bad block behavior was to dump 0xFF in place
+of bad blocks. This was not a good "inverse operation" of nandwrite. Thus, the
+current default behavior has become the (new) option --bb=padbad, and in 1.4.6,
+the default will be --bb=skipbad.
+
+All of these changes will occur in 1.4.6. For now, there are appropriate
+deprecation warning messages and an alert telling about the soon-to-be-default
+options.
+
+Transition summary table:
+-----------------------------------------------------------------------------------------------------------
+ Old option     New option                 Comment
+-----------------------------------------------------------------------------------------------------------
+ <default>      --bb=padbad                dump flash data, substituting 0xFF for any bad blocks
+ --noskipbad    --bb=dumpbad               dump flash data, including any bad blocks
+ --skipbad      --bb=skipbad, <default>    dump good data, completely skipping any bad blocks (new default)
+ --omitbad      --bb=omitbad               dump flash data, substituting nothing for any bad blocks
+
+---------------------------
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 13 19:32:00 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 16:32:00 -0700
Subject: [PATCH 3/6] nanddump: deprecation messages for old BB options
In-Reply-To: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
References: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308007923-6820-3-git-send-email-computersforpeace@gmail.com>

--omitbad and --noskipbad will soon be replaced by --bb=omitbad and
--bb=dumpbad. Please plan to migrate to the new usage shortly.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index a945081..4f28e33 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -54,17 +54,21 @@ static void display_help(void)
 "                                    skipbad\n"
 "                                    omitbad\n"
 "-a         --forcebinary        Force printing of binary data to tty\n"
-"-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"-N         --noskipbad          Read without bad block skipping\n"
 "-o         --omitoob            Omit oob data\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
 "\n"
+"Deprecated options:\n"
+"The following options are being replaced by --bb=METHOD flags.\n"
+"Do not continue to use these options.\n"
+"-b         --omitbad            Omit bad blocks from the dump\n"
+"-N         --noskipbad          Read without bad block skipping\n"
+"\n"
 "Notes on --bb=omitbad and --bb=skipbad:\n"
 "  With either option, we stop dumping data when we encounter a bad block\n"
 "  and resume dumping at the next good block. However, with `omitbad', we\n"
@@ -171,6 +175,9 @@ static void process_options(int argc, char * const argv[])
 				if (bb_default) {
 					bb_default = false;
 					bb_method = omitbad;
+					fprintf(stderr, "Warning: --omitbad is being deprecated in favor of --bb=omitbad.\n"
+							"         --omitbad will not be available in future releases.\n"
+							"         Please update your usage accordingly.\n");
 				} else {
 					error++;
 				}
@@ -209,6 +216,9 @@ static void process_options(int argc, char * const argv[])
 				if (bb_default) {
 					bb_default = false;
 					bb_method = dumpbad;
+					fprintf(stderr, "Warning: --noskipbad is being deprecated in favor of --bb=dumpbad.\n"
+							"         --noskipbad will not be available in future releases.\n"
+							"         Please update your usage accordingly.\n");
 				} else {
 					error++;
 				}
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 13 19:31:58 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 16:31:58 -0700
Subject: [PATCH 1/6] nanddump: add --bb=METHOD option
Message-ID: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>

We have too many separate bad block handling methods:
 --omitbad
 --noskipbad
 --skipbad
On top of these, we have the default option: that bad blocks are
replaced with 0xFF.

These options will be unified under --bb=METHOD. The end goal will be
something like:

----------------------------------------------------------------------------------------------
Old option     New option     Comment
----------------------------------------------------------------------------------------------
<default>      --bb=padbad    dump flash data, substituting 0xFF for any bad blocks
--noskipbad    --bb=dumpbad   dump flash data, including any bad blocks
--skipbad      --bb=skipbad   dump good data, completely skipping any bad blocks (new default)
--omitbad      --bb=omitbad   dump flash data, substituting nothing for any bad blocks

The BB options are all mutually exclusive, so we check that we do not
have more than one BB option explicitly enabled on the command line.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   81 +++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 56 insertions(+), 25 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index c9d7e8b..c3771c5 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -47,6 +47,12 @@ static void display_help(void)
 "\n"
 "           --help               Display this help and exit\n"
 "           --version            Output version information and exit\n"
+"           --bb=METHOD          Choose a bad block handling method.\n"
+"                                METHOD can be:\n"
+"                                    padbad (default)\n"
+"                                    dumpbad\n"
+"                                    skipbad\n"
+"                                    omitbad\n"
 "-a         --forcebinary        Force printing of binary data to tty\n"
 "-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
@@ -60,11 +66,11 @@ static void display_help(void)
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
 "\n"
-"Notes on --omitbad and --skipbad:\n"
+"Notes on --bb=omitbad and --bb=skipbad:\n"
 "  With either option, we stop dumping data when we encounter a bad block\n"
-"  and resume dumping at the next good block. However, with --omitbad, we\n"
+"  and resume dumping at the next good block. However, with `omitbad', we\n"
 "  count the bad block as part of the total dump length, whereas with\n"
-"  --skipbad, the bad block is 'skipped,' that is, not counted toward the\n"
+"  `skipbad', the bad block is skipped, that is, not counted toward the\n"
 "  total dump length.\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
@@ -88,21 +94,26 @@ static void display_version(void)
 
 static bool			pretty_print = false;	// print nice
 static bool			noecc = false;		// don't error correct
-static bool			noskipbad = false;	// don't skip bad blocks
 static bool			omitoob = false;	// omit oob data
 static long long		start_addr;		// start address
 static long long		length;			// dump length
 static const char		*mtddev;		// mtd device name
 static const char		*dumpfile;		// dump file name
-static bool			omitbad = false;
 static bool			quiet = false;		// suppress diagnostic output
 static bool			canonical = false;	// print nice + ascii
 static bool			forcebinary = false;	// force printing binary to tty
-static bool			skipbad = false;	// skip over bad blocks
+
+static enum {
+	padbad,   // dump flash data, substituting 0xFF for any bad blocks
+	dumpbad,  // dump flash data, including any bad blocks
+	skipbad,  // dump good data, completely skipping any bad blocks
+	omitbad   // dump flash data, substituting nothing for any bad blocks
+} bb_method = padbad;
 
 static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
+	bool bb_default = true;
 
 	for (;;) {
 		int option_index = 0;
@@ -110,6 +121,7 @@ static void process_options(int argc, char * const argv[])
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
+			{"bb", required_argument, 0, 0},
 			{"forcebinary", no_argument, 0, 'a'},
 			{"canonicalprint", no_argument, 0, 'c'},
 			{"file", required_argument, 0, 'f'},
@@ -140,10 +152,30 @@ static void process_options(int argc, char * const argv[])
 					case 1:
 						display_version();
 						break;
+					case 2:
+						/* Handle --bb=METHOD */
+						if (!strcmp(optarg, "padbad"))
+							bb_method = padbad;
+						else if (!strcmp(optarg, "dumpbad"))
+							bb_method = dumpbad;
+						else if (!strcmp(optarg, "skipbad"))
+							bb_method = skipbad;
+						else if (!strcmp(optarg, "omitbad"))
+							bb_method = omitbad;
+						else
+							error++;
+						bb_default = false;
+						break;
 				}
 				break;
 			case 'b':
-				omitbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = omitbad;
+				} else {
+					error++;
+				}
 				break;
 			case 's':
 				start_addr = simple_strtoll(optarg, &error);
@@ -175,10 +207,22 @@ static void process_options(int argc, char * const argv[])
 				noecc = true;
 				break;
 			case 'N':
-				noskipbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = dumpbad;
+				} else {
+					error++;
+				}
 				break;
 			case 'k':
-				skipbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = skipbad;
+				} else {
+					error++;
+				}
 				break;
 			case '?':
 				error++;
@@ -206,19 +250,6 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (noskipbad && skipbad) {
-		fprintf(stderr, "The noskipbad and skipbad options are "
-				"mutually-exclusive.\n"
-				"Choose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (omitbad && skipbad) {
-		fprintf(stderr, "The omitbad and skipbad options are mutually-"
-				"exclusive.\nChoose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
 	if ((argc - optind) != 1 || error)
 		display_help();
 
@@ -416,7 +447,7 @@ int main(int argc, char * const argv[])
 	/* Dump the flash contents */
 	for (ofs = start_addr; ofs < end_addr; ofs += bs) {
 		/* Check for bad block */
-		if (noskipbad) {
+		if (bb_method == dumpbad) {
 			badblock = 0;
 		} else if (blockstart != (ofs & (~mtd.eb_size + 1)) ||
 				firstblock) {
@@ -430,14 +461,14 @@ int main(int argc, char * const argv[])
 
 		if (badblock) {
 			/* skip bad block, increase end_addr */
-			if (skipbad) {
+			if (bb_method == skipbad) {
 				end_addr += mtd.eb_size;
 				ofs += mtd.eb_size - bs;
 				if (end_addr > mtd.size)
 					end_addr = mtd.size;
 				continue;
 			}
-			if (omitbad)
+			if (bb_method == omitbad)
 				continue;
 			memset(readbuf, 0xff, bs);
 		} else {
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 13 19:32:03 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 13 Jun 2011 16:32:03 -0700
Subject: [PATCH 6/6] nanddump: warn about future default --nooob
In-Reply-To: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
References: <1308007923-6820-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308007923-6820-6-git-send-email-computersforpeace@gmail.com>

To work as a proper inverse to nandwrite, nanddump must not dump OOB data by
default. This patch prints a warning regarding the future change.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |    8 ++++++++
 nanddump.c                   |    3 +++
 2 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index 0f1f5c5..0bb5cb2 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -65,3 +65,11 @@ Transition summary table:
  --omitbad      --bb=omitbad               dump flash data, substituting nothing for any bad blocks
 
 ---------------------------
+
+5. nanddump will not dump OOB by default
+
+In 1.4.6, nanddump will not dump OOB by default. To dump OOB, you will have to
+explicitly use the option '-o' or '--oob'. For now, there is simply a warning
+every time you use nanddump.
+
+---------------------------
diff --git a/nanddump.c b/nanddump.c
index 211f8ae..9c2e326 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -355,6 +355,9 @@ int main(int argc, char * const argv[])
 
 	process_options(argc, argv);
 
+	fprintf(stderr, "Warning: in next release, nanddump will not dump OOB"
+			" by default.\n");
+
 	/* Initialize libmtd */
 	mtd_desc = libmtd_open();
 	if (!mtd_desc)
-- 
1.7.0.4




From adam.thomson at alcatel-lucent.com  Tue Jun 14 10:52:38 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Tue, 14 Jun 2011 16:52:38 +0200
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi before
	writing OOB data
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

In nand_do_write_ops() code it is possible for a caller to provide
ops.oobbuf populated and ops.mode == MTD_OOB_AUTO, which currently
means that the chip->oob_poi buffer isn't initialised to all 0xFF.
The nand_fill_oob() method then carries out the task of copying
the provided OOB data to oob_poi, but with MTD_OOB_AUTO it skips
areas marked as unavailable by the layout struct, including the
bad block marker bytes.

An example of this causing issues is when the last OOB data read
was from the start of a bad block where the markers are not 0xFF,
and the caller wishes to write new OOB data at the beginning of
another block. In this scenario the caller would provide OOB data,
but nand_fill_oob() would skip the bad block marker bytes in
oob_poi before copying the OOB data provided by the caller.
This means that when the OOB data is written back to NAND,
the block is inadvertently marked as bad without the caller knowing.
This has been witnessed when using YAFFS2 where tags are stored
in the OOB.

To avoid this oob_poi is always initialised to 0xFF to make sure
no left over data is inadvertently written back to the OOB area.

Signed-off-by: Adam Thomson <adam.thomson at alcatel-lucent.com>
---

Applies to: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Tested on: ARM based board with Hynix 256MB NAND chip

 drivers/mtd/nand/nand_base.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a46e9bb..0815a3d 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2098,13 +2098,20 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 /**
  * nand_fill_oob - [Internal] Transfer client buffer to oob
  * @chip:	nand chip structure
+ * @mtd:	MTD device 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,
-						struct mtd_oob_ops *ops)
+static uint8_t *nand_fill_oob(struct nand_chip *chip, struct mtd_info *mtd,
+			      uint8_t *oob, size_t len,	struct mtd_oob_ops *ops)
 {
+	/*
+	 * Initialise to all 0xFF, to avoid the possibility of
+	 * left over OOB data from a previous OOB read.
+	 */
+	memset(chip->oob_poi, 0xff, mtd->oobsize);
+
 	switch (ops->mode) {
 
 	case MTD_OOB_PLACE:
@@ -2201,10 +2208,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
 		chip->pagebuf = -1;
 
-	/* If we're not given explicit OOB data, let it be 0xFF */
-	if (likely(!oob))
-		memset(chip->oob_poi, 0xff, mtd->oobsize);
-
 	/* Don't allow multipage oob writes with offset */
 	if (oob && ops->ooboffs && (ops->ooboffs + ops->ooblen > oobmaxlen))
 		return -EINVAL;
@@ -2226,7 +2229,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 
 		if (unlikely(oob)) {
 			size_t len = min(oobwritelen, oobmaxlen);
-			oob = nand_fill_oob(chip, oob, len, ops);
+			oob = nand_fill_oob(chip, mtd, oob, len, ops);
 			oobwritelen -= len;
 		}
 
@@ -2401,10 +2404,8 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 	if (page == chip->pagebuf)
 		chip->pagebuf = -1;
 
-	memset(chip->oob_poi, 0xff, mtd->oobsize);
-	nand_fill_oob(chip, ops->oobbuf, ops->ooblen, ops);
+	nand_fill_oob(chip, mtd, ops->oobbuf, ops->ooblen, ops);
 	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
-	memset(chip->oob_poi, 0xff, mtd->oobsize);
 
 	if (status)
 		return status;
-- 
1.7.5.4



From adam.thomson at alcatel-lucent.com  Tue Jun 14 10:51:31 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Tue, 14 Jun 2011 16:51:31 +0200
Subject: [PATCH v3] nand: nand_base: Always initialise oob_poi before
	writing OOB data
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12B@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

In nand_do_write_ops() code it is possible for a caller to provide
ops.oobbuf populated and ops.mode == MTD_OOB_AUTO, which currently
means that the chip->oob_poi buffer isn't initialised to all 0xFF.
The nand_fill_oob() method then carries out the task of copying
the provided OOB data to oob_poi, but with MTD_OOB_AUTO it skips
areas marked as unavailable by the layout struct, including the
bad block marker bytes.

An example of this causing issues is when the last OOB data read
was from the start of a bad block where the markers are not 0xFF,
and the caller wishes to write new OOB data at the beginning of
another block. In this scenario the caller would provide OOB data,
but nand_fill_oob() would skip the bad block marker bytes in
oob_poi before copying the OOB data provided by the caller.
This means that when the OOB data is written back to NAND,
the block is inadvertently marked as bad without the caller knowing.
This has been witnessed when using YAFFS2 where tags are stored
in the OOB.

To avoid this oob_poi is always initialised to 0xFF to make sure
no left over data is inadvertently written back to the OOB area.

Signed-off-by: Adam Thomson <adam.thomson at alcatel-lucent.com>
Cc: stable at kernel.org [2.6.20+]
---

Applies to: 2.6.20+ stable releases
Tested on: ARM based board with Hynix 256MB NAND chip

 drivers/mtd/nand/nand_base.c |   20 +++++++++++---------
 1 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index dfe56e0..137dcb9 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1545,14 +1545,21 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 /**
  * nand_fill_oob - [Internal] Transfer client buffer to oob
  * @chip:	nand chip structure
+ * @mtd:	MTD device structure
  * @oob:	oob data buffer
  * @ops:	oob ops structure
  */
-static uint8_t *nand_fill_oob(struct nand_chip *chip, uint8_t *oob,
-				  struct mtd_oob_ops *ops)
+static uint8_t *nand_fill_oob(struct nand_chip *chip, struct mtd_info *mtd,
+			      uint8_t *oob, struct mtd_oob_ops *ops)
 {
 	size_t len = ops->ooblen;
 
+	/*
+	 * Initialise to all 0xFF, to avoid the possibility of
+	 * left over OOB data from a previous OOB read.
+	 */
+	memset(chip->oob_poi, 0xff, mtd->oobsize);
+
 	switch(ops->mode) {
 
 	case MTD_OOB_PLACE:
@@ -1644,10 +1651,6 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 	    (chip->pagebuf << chip->page_shift) < (to + ops->len))
 		chip->pagebuf = -1;
 
-	/* If we're not given explicit OOB data, let it be 0xFF */
-	if (likely(!oob))
-		memset(chip->oob_poi, 0xff, mtd->oobsize);
-
 	while(1) {
 		int bytes = mtd->writesize;
 		int cached = writelen > bytes && page != blockmask;
@@ -1664,7 +1667,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
 		}
 
 		if (unlikely(oob))
-			oob = nand_fill_oob(chip, oob, ops);
+			oob = nand_fill_oob(chip, mtd, oob, ops);
 
 		ret = chip->write_page(mtd, chip, wbuf, page, cached,
 				       (ops->mode == MTD_OOB_RAW));
@@ -1777,8 +1780,7 @@ static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 	if (page == chip->pagebuf)
 		chip->pagebuf = -1;
 
-	memset(chip->oob_poi, 0xff, mtd->oobsize);
-	nand_fill_oob(chip, ops->oobbuf, ops);
+	nand_fill_oob(chip, mtd, ops->oobbuf, ops);
 	status = chip->ecc.write_oob(mtd, chip, page & chip->pagemask);
 	memset(chip->oob_poi, 0xff, mtd->oobsize);
 
-- 
1.7.5.4

From peter.barada at gmail.com  Tue Jun 14 12:19:08 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Tue, 14 Jun 2011 12:19:08 -0400
Subject: Preventing JFFS2 partial page writes?
Message-ID: <4DF789FC.1030305@gmail.com>

I'm using a Micron 512MB NAND which has an internal 4-bit ECC engine, 
and am finding lots of ECC errors while using JFFS2.  The same NAND 
works find using YAFFS so I know the underlying MTD driver works properly.

The big question I have is whether JFFS2 does partial page writes and if 
so how to disable them.

Thanks in advance!

-- 
Peter Barada
peter.barada at gmail.com



From timcussins at eml.cc  Tue Jun 14 12:32:34 2011
From: timcussins at eml.cc (Tim Cussins)
Date: Tue, 14 Jun 2011 17:32:34 +0100
Subject: Runtime repartitioning
Message-ID: <4DF78D22.6030101@eml.cc>

Hi all,

In July 2010 a couple of competing patchsets were submitted that aimed 
to provide runtime repartitioning of mtd devices.

http://thread.gmane.org/gmane.linux.drivers.mtd/30458
http://thread.gmane.org/gmane.linux.drivers.mtd/30950
http://thread.gmane.org/gmane.linux.drivers.mtd/30949

Neither submission was accepted, comments were given on and off list, 
and that was the end of it :)

The ability to create new mtd partitions after boot would be awesome - 
how can I get involved in getting such functionality into the tree?

Cheers,
Tim


From computersforpeace at gmail.com  Wed Jun 15 11:44:41 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 15 Jun 2011 08:44:41 -0700
Subject: Runtime repartitioning
In-Reply-To: <4DF78D22.6030101@eml.cc>
References: <4DF78D22.6030101@eml.cc>
Message-ID: <BANLkTimSoZqt-NR=AG69PQnMC2wpMB63Eg@mail.gmail.com>

Hi Tim,

On Tue, Jun 14, 2011 at 9:32 AM, Tim Cussins <timcussins at eml.cc> wrote:
> Hi all,
>
> In July 2010 a couple of competing patchsets were submitted that aimed to
> provide runtime repartitioning of mtd devices.
>
> http://thread.gmane.org/gmane.linux.drivers.mtd/30458
> http://thread.gmane.org/gmane.linux.drivers.mtd/30950
> http://thread.gmane.org/gmane.linux.drivers.mtd/30949
>
> Neither submission was accepted, comments were given on and off list, and
> that was the end of it :)
>
> The ability to create new mtd partitions after boot would be awesome - how
> can I get involved in getting such functionality into the tree?

It's probably a good idea to at least CC those who worked on this
before...I added Roman Tereshonkov, the one who started the
discussion.

Anyway, it looks like Roman ended up submitting a revised version of
the patch from the first discussion. His work made it into the kernel
as the following two commits. You can feel free to test it yourself!

5daa7b21496aebf057c12be03038e7220e33353b
mtd: prepare partition add and del functions for ioctl requests

d0f7959e2b708d775c3b6b53cc6a8abb8ff0a00b
mtd: add BLKPG API based repartition support

Brian


From mlcreech at gmail.com  Wed Jun 15 15:48:32 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Wed, 15 Jun 2011 15:48:32 -0400
Subject: NAND BBT corruption on MPC83xx
Message-ID: <BANLkTi=L8CqtTt=+sJ-CHVyXyTsxTR_o8Q@mail.gmail.com>

Hi, I'm not sure whether this list or the U-Boot list is more
appropriate, but figured I'd start here and see if anyone can help.

We've gotten some devices back from the field which all suffer from
this same problem on bootup when attaching UBI (these messages are
from U-Boot):


...
Bad block table found at page 524224, version 0x01
Bad block table found at page 524160, version 0x01
nand_bbt: ECC error while reading bad block table
...(long stream of bogus bad blocks)...
UBI: attaching mtd1 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: vtbl_check: volume table check failed: record 0, error 9
UBI error: ubi_init: cannot attach mtd1
UBI error: ubi_init: UBI error: cannot initialize UBI, error -22
UBI init error -22

A full console dump is here:

http://mcreech.com/work/bbt-ecc-error.txt

Question #1: Is the UBI error here attributable to the blocks which
are wrongly marked as bad?  I would assume that it's a red herring,
and I should focus on figuring out how the BBT got corrupted, but
figured I'd check first.

Question #2: Are there any known issues that could cause the BBT to
become corrupt like this?

I noticed that the reported bad blocks were all aligned at multiples
of 0x80000 (with one exception).  Dumping the last 2 blocks shows:
  - one BBT with lots of bytes that have their lower 1 or 2 bits
un-set (e.g. 0xfe instead of 0xff): this explains all the
each-4th-block alignment.
  - the other BBT shows only one factory-marked bad block at
0x062e0000, which is presumably correct.  This is preserved in the
bogus BBT, and is the only non-0x80000-aligned bad block in the table.
  - Only the first 1024 bytes of the BBT contain bogus info - the
latter half of the BBT is all correct

It seems like the original BBT somehow had 0-2 bits corrupted at the
low end of each of its bytes, either while in memory or when the BBT
was written to NAND.  Any ideas on what I can do to isolate the
problem?  Thanks in advance!

More info on this board:
- MPC 8313 SoC
- 1GB Samsung NAND flash (K9K8G08U0B)
- Linux 2.6.31
- U-Boot 2009.06

-- 
Matthew L. Creech


From mhench at elutions.com  Wed Jun 15 16:17:19 2011
From: mhench at elutions.com (Mike Hench)
Date: Wed, 15 Jun 2011 16:17:19 -0400
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <BANLkTi=L8CqtTt=+sJ-CHVyXyTsxTR_o8Q@mail.gmail.com>
Message-ID: <F87D23B7E1F84E4AB52E4FA4A55F85DC0259E00F@tpamail.elutions.com>

This is the read page -1 problem we discussed earlier Round about line
485 of linux-2.6.39.1/drivers/mtd/nand/fsl_elbc_nand.c

        /* Read back the page in order to fill in the ECC for the
         * caller.  Is this really needed?
         */
        if (full_page && elbc_fcm_ctrl->oob_poi) {
            out_be32(&lbc->fbcr, 3);
            set_addr(mtd, 6, page_addr, 1);

page_addr at this point is always -1.
now WHY a read corrupts that last block I do not know.
-1 is not a valid page address, the address 'protocol' allows more bits
Than the flash uses. So it does not mean 'last block', or last page in
last block.
Maybe it is upsetting the state machine in the flash.
Maybe it is upsetting the ELBC.
You will find that the secondary bad block table (first page, second to
last block) is fine.

the kernel works fine without that block of code. So oob_poi must not be
used anywhere. In any case it is always garbage with the above code.
I raised this issue on this list earlier, no response.
I think Freescale might be more likely to notice on the PPC list.
I don't think they hang out here.

I am happy without that block of useless code.


-----Original Message-----
From: linux-mtd-bounces at lists.infradead.org
[mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Matthew L.
Creech
Sent: Wednesday, June 15, 2011 2:49 PM
To: MTD list
Subject: NAND BBT corruption on MPC83xx

Hi, I'm not sure whether this list or the U-Boot list is more
appropriate, but figured I'd start here and see if anyone can help.

We've gotten some devices back from the field which all suffer from
this same problem on bootup when attaching UBI (these messages are
from U-Boot):


...
Bad block table found at page 524224, version 0x01
Bad block table found at page 524160, version 0x01
nand_bbt: ECC error while reading bad block table
...(long stream of bogus bad blocks)...
UBI: attaching mtd1 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: vtbl_check: volume table check failed: record 0, error 9
UBI error: ubi_init: cannot attach mtd1
UBI error: ubi_init: UBI error: cannot initialize UBI, error -22
UBI init error -22

A full console dump is here:

http://mcreech.com/work/bbt-ecc-error.txt

Question #1: Is the UBI error here attributable to the blocks which
are wrongly marked as bad?  I would assume that it's a red herring,
and I should focus on figuring out how the BBT got corrupted, but
figured I'd check first.

Question #2: Are there any known issues that could cause the BBT to
become corrupt like this?

I noticed that the reported bad blocks were all aligned at multiples
of 0x80000 (with one exception).  Dumping the last 2 blocks shows:
  - one BBT with lots of bytes that have their lower 1 or 2 bits
un-set (e.g. 0xfe instead of 0xff): this explains all the
each-4th-block alignment.
  - the other BBT shows only one factory-marked bad block at
0x062e0000, which is presumably correct.  This is preserved in the
bogus BBT, and is the only non-0x80000-aligned bad block in the table.
  - Only the first 1024 bytes of the BBT contain bogus info - the
latter half of the BBT is all correct

It seems like the original BBT somehow had 0-2 bits corrupted at the
low end of each of its bytes, either while in memory or when the BBT
was written to NAND.  Any ideas on what I can do to isolate the
problem?  Thanks in advance!

More info on this board:
- MPC 8313 SoC
- 1GB Samsung NAND flash (K9K8G08U0B)
- Linux 2.6.31
- U-Boot 2009.06

-- 
Matthew L. Creech

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/


From fggs at terra.com.br  Wed Jun 15 20:55:57 2011
From: fggs at terra.com.br (=?iso-8859-1?Q?Fl=E1vio_Silveira?=)
Date: Wed, 15 Jun 2011 21:55:57 -0300
Subject: [Help] SST39VF6401B Support
In-Reply-To: <201010221950.57594.fabio.giovagnini@aurion-tech.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com><AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com><AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com>
	<201010221950.57594.fabio.giovagnini@aurion-tech.com>
Message-ID: <DEF16A5C46894A5DB447E0F7C81A9D5F@THOR>

Hi guys,

  I've tested this patch on kernel 2.6.23 (actually it's called 2.6.24.111) 
and didn't work.

  Below are my diffs and I can post original files as well, please help me 
make it work!

Thanks in advance!

cfi_util.c

29a30,107
> int __xipram cfi_qry_present(struct map_info *map, __u32 base,
>         struct cfi_private *cfi)
> {
>  int osf = cfi->interleave * cfi->device_type; /* scale factor */
>  map_word val[3];
>  map_word qry[3];
>
>  qry[0] = cfi_build_cmd('Q', map, cfi);
>  qry[1] = cfi_build_cmd('R', map, cfi);
>  qry[2] = cfi_build_cmd('Y', map, cfi);
>
>  val[0] = map_read(map, base + osf*0x10);
>  val[1] = map_read(map, base + osf*0x11);
>  val[2] = map_read(map, base + osf*0x12);
>
>  if (!map_word_equal(map, qry[0], val[0]))
>   return 0;
>
>  if (!map_word_equal(map, qry[1], val[1]))
>   return 0;
>
>  if (!map_word_equal(map, qry[2], val[2]))
>   return 0;
>
>  return 1;  /* "QRY" found */
> }
> EXPORT_SYMBOL_GPL(cfi_qry_present);
>
> int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
>         struct cfi_private *cfi)
> {
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* QRY not found probably we deal with some odd CFI chips */
>  /* Some revisions of some old Intel chips? */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* ST M29DW chips */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* some old SST chips, e.g. 39VF160x/39VF320x */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* SST 39VF640xB */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* QRY not found */
>  return 0;
> }
> EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
>
> void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
>           struct cfi_private *cfi)
> {
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>  /* M29W128G flashes require an additional reset command
>     when exit qry mode */
>  if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
>   cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
> }
> EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
>

cfi_cmdset_0002.c

219a220,253
> static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
> {
>    struct map_info *map = mtd->priv;
>    struct cfi_private *cfi = map->fldrv_priv;
>
>    /*
>     * These flashes report two seperate eraseblock regions based on the
>     * sector_erase-size and block_erase-size, although they both operate 
> on the
>     * same memory. This is not allowed according to CFI, so we just pick 
> the
>     * sector_erase-size.
>     */
>    cfi->cfiq->NumEraseRegions = 1;
> }
>
> static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
> {
>    struct map_info *map = mtd->priv;
>    struct cfi_private *cfi = map->fldrv_priv;
>
>    fixup_old_sst_eraseregion(mtd);
>
>    cfi->addr_unlock1 = 0x555;
>    cfi->addr_unlock2 = 0x2AA;
> }
>
> /* Used to fix CFI-Tables of chips without Extended Query Tables */
> static struct cfi_fixup cfi_nopri_fixup_table[] = {
>    { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B
>    { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B
>    { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B
>    { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
>    { 0, 0, NULL, NULL }
> };
>


----- Original Message ----- 
From: "Fabio Giovagnini" <fabio.giovagnini at aurion-tech.com>
To: <linux-mtd at lists.infradead.org>
Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>; 
"Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>; 
"Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
Sent: Friday, October 22, 2010 2:50 PM
Subject: Re: [Help] SST39VF6401B Support


Hi Guys,
As Gullelm remeber for sure, I used the jedec probe for such a flash in a 
very
old 2.6 kernel.

Now I'm migrating to the newets one kernel.
Do you tell me how the kernel will be updated with the last mtd stuff
developed; or in place of it how to patch a standard kernel?

Thanks a  lot and sorry for my question if it is improper


In data venerd? 22 ottobre 2010 17:42:39, yidong zhang ha scritto:
: > On Fri, Oct 22, 2010 at 11:36 PM, Guillaume LECERF <glecerf at gmail.com>
wrote:
> > 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
> >>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
> >>> fixup_sst39vf_rev_b() ?
> >>
> >> Hi
> >>  how about this attached patch.
> >
> > If it works for you, I'll send a patch series for SST 39VF640xB and
> > 38VF640x, because both chips needs 0x50 as erase command.
>
> Sorry, i cannot test it right now.  I will sent the result as soon as i
> can.
>
> > --
> > Guillaume LECERF
> > GeeXboX developer - www.geexbox.org
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Ing. Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Cell. +39.335.83.50.919
www.aurion-tech.com

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/



From timcussins at eml.cc  Thu Jun 16 04:52:12 2011
From: timcussins at eml.cc (Tim Cussins)
Date: Thu, 16 Jun 2011 09:52:12 +0100
Subject: Runtime repartitioning
In-Reply-To: <BANLkTimSoZqt-NR=AG69PQnMC2wpMB63Eg@mail.gmail.com>
References: <4DF78D22.6030101@eml.cc>
	<BANLkTimSoZqt-NR=AG69PQnMC2wpMB63Eg@mail.gmail.com>
Message-ID: <4DF9C43C.2060405@eml.cc>

On 15/06/11 16:44, Brian Norris wrote:
> Hi Tim,
>
> On Tue, Jun 14, 2011 at 9:32 AM, Tim Cussins<timcussins at eml.cc>  wrote:
>> Hi all,
>>
>> In July 2010 a couple of competing patchsets were submitted that aimed to
>> provide runtime repartitioning of mtd devices.
>>
>> http://thread.gmane.org/gmane.linux.drivers.mtd/30458
>> http://thread.gmane.org/gmane.linux.drivers.mtd/30950
>> http://thread.gmane.org/gmane.linux.drivers.mtd/30949
>>
>> Neither submission was accepted, comments were given on and off list, and
>> that was the end of it :)
>>
>> The ability to create new mtd partitions after boot would be awesome - how
>> can I get involved in getting such functionality into the tree?
>
> It's probably a good idea to at least CC those who worked on this
> before...I added Roman Tereshonkov, the one who started the
> discussion.
>
> Anyway, it looks like Roman ended up submitting a revised version of
> the patch from the first discussion. His work made it into the kernel
> as the following two commits. You can feel free to test it yourself!
>
> 5daa7b21496aebf057c12be03038e7220e33353b
> mtd: prepare partition add and del functions for ioctl requests
>
> d0f7959e2b708d775c3b6b53cc6a8abb8ff0a00b
> mtd: add BLKPG API based repartition support
>
> Brian

Hi Brian,

Whoa, they've been in for a while... I was looking in mtd-api.h for ioctls

Thanks heaps,
Tim


From dbaryshkov at gmail.com  Thu Jun 16 04:56:50 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 16 Jun 2011 12:56:50 +0400
Subject: [PATCH V2 00/18] last part of big cleanup of partition handling
In-Reply-To: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <BANLkTi=DAYYsB0SqhsXtdY_KN4ACVh0qKg@mail.gmail.com>

Hello,

On 6/12/11, Dmitry Eremin-Solenikov <dbaryshkov at gmail.com> wrote:
> Hello,
>
> Changes in V2 of this serie:
> * Introduce special struct mtd_parts_parser_data structure to hold data args
>   passed to parsers
> * small cleanups
>
> The following changes since commit 3e1643b282542cf524d30cfab4cfe38f6b2afa99:
>
>   mtd: edb7312: correctly pass MTD name to parsers (2011-06-09 15:30:44
> +0300)
>
> are available in the git repository at:
>   git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup
>
> Dmitry Eremin-Solenikov (18):
>       mtd: abstract last MTD partition parser argument
>       mtd: prepare to convert of_mtd_parse_partitions to partition parser
>       mtd: physmap_of: use ofpart through generic parsing
>       mtd: m25p80: use ofpart through generic parsing
>       mtd: fsl_elbc_nand: use ofpart through generic parsing
>       mtd: fsl_upm: use ofpart through generic parsing
>       mtd: mpc5121_nfc: use ofpart through generic parsing
>       mtd: ndfc: use ofpart through generic parsing
>       mtd: socrates_nand: use ofpart through generic parsing
>       mtd: drop of_mtd_parse_partitions()
>       mtd: physmap_of: move parse_obsolete_partitions to become separate
> parser
>       mtd: physmap_of.c: use mtd_device_parse_register
>       mtd: m25p80.c: use mtd_device_parse_register
>       mtd: fsl_elbc_nand.c: use mtd_device_parse_register
>       mtd: fsl_upm.c: use mtd_device_parse_register
>       mtd: mpc5121_nfc.c: use mtd_device_parse_register
>       mtd: ndfc.c: use mtd_device_parse_register
>       mtd: socrates_nand.c: use mtd_device_parse_register
>
>  drivers/mtd/cmdlinepart.c        |    2 +-
>  drivers/mtd/devices/m25p80.c     |   37 ++------------
>  drivers/mtd/maps/physmap_of.c    |   80 +++--------------------------
>  drivers/mtd/mtdcore.c            |    6 +-
>  drivers/mtd/mtdpart.c            |   15 ++++--
>  drivers/mtd/nand/fsl_elbc_nand.c |   17 ++-----
>  drivers/mtd/nand/fsl_upm.c       |   13 +----
>  drivers/mtd/nand/mpc5121_nfc.c   |   17 +-----
>  drivers/mtd/nand/ndfc.c          |   16 +-----
>  drivers/mtd/nand/socrates_nand.c |   23 +-------
>  drivers/mtd/ofpart.c             |  104
> ++++++++++++++++++++++++++++++++++++--
>  drivers/mtd/redboot.c            |    6 +-
>  include/linux/mtd/mtd.h          |    3 +-
>  include/linux/mtd/partitions.h   |   32 +++++-------
>  14 files changed, 160 insertions(+), 211 deletions(-)

What about this patchset?

-- 
With best wishes
Dmitry


From gilles.ganault at free.fr  Thu Jun 16 07:23:52 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 16 Jun 2011 13:23:52 +0200
Subject: [NAND] Are partitions persistent?
Message-ID: <khpjv6l6bhe815s0rj9frue0l5qqpb8hfq@4ax.com>

Hello

	I was wondering: Are partitions on NAND persistent, or is it up to
the developer to make sure the images used to populate the different
partitions are small enough to fit the partitions set in the NAND
driver?

For instance, this found through Google:
=============
static struct mtd_partition bfin_spi_flash_partitions[ ] = {
    {
        .name = "bootloader(spi)",
        .size = 0x00040000,
        .offset = 0,
        .mask_flags = MTD_CAP_ROM
    }, {
        .name = "linux kernel(spi)",
        .size = 0x180000,
        .offset = MTDPART_OFS_APPEND,
};
=============

Does it mean that, for instance, when using Uboot's nandwrite to
update the bootloader above, it's up to me to make sure that the image
is smaller than 0x40000 and Uboot will happily keep going and erase
part of the linux kernel, or is the MTDPART_OFS_APPEND option
precisely made to avoid this and trigger an error?

Thank you.



From plagnioj at jcrosoft.com  Thu Jun 16 09:48:46 2011
From: plagnioj at jcrosoft.com (Jean-Christophe PLAGNIOL-VILLARD)
Date: Thu, 16 Jun 2011 15:48:46 +0200
Subject: [PATCH] ATMEL, AVR32: inline nand partition table access
In-Reply-To: <4DEC8A56.1030707@atmel.com>
References: <1306676962-22308-1-git-send-email-dbaryshkov@gmail.com>
	<1306935129.1097.3.camel@hcegtvedt.norway.atmel.com>
	<BANLkTi=s4kGg5NKrzNs1nu8S00Ue_Zv8vQ@mail.gmail.com>
	<4DEC8A56.1030707@atmel.com>
Message-ID: <20110616134846.GF4581@game.jcrosoft.org>

On 10:05 Mon 06 Jun     , Nicolas Ferre wrote:
> Le 01/06/2011 16:54, Dmitry Eremin-Solenikov :
> > On 6/1/11, Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com> wrote:
> >> On Sun, 2011-05-29 at 17:49 +0400, Dmitry Eremin-Solenikov wrote:
> >>> Currently atmel_nand driver used by AT91 and AVR32 calls a special
> >>> callback
> >>> which return nand partition table and number of partitions. However in all
> >>> boards this callback returns just static data. So drop this callback and
> >>> make atmel_nand use partition table provided statically via platform_data.
> >>>
> >>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> >>
> >> Thanks for this update, always nice seeing code being optimized. I
> >> really can't recall why it was made like this in the first place...
> >>
> >> For the AVR32 related parts:
> >>
> >> Acked-by: Hans-Christian Egtvedt <hans-christian.egtvedt at atmel.com>
> >>
> >> <snipp diff>
> >>
> >> Will this go through the linux-mtd tree (since it spans two archs) or
> >> should it go through an arch tree?
> > 
> > On one hand, I'd prefer for this to go through the linux-mtd, if noone objects,
> > as I'd also like to submit several (a pile) patches cleaning up mtd
> > partitioning, which would depend on this.
> > 
> > OTOH, I think there will be a cleanup of AT91 platform, which would bring
> > lot's of conflicts with this patch, if it goes through linux-mtd.
> 
> 
> I am in favor for a mainline inclusion through linux-mtd tree.
> 
> On the AT91 side, we will have to take this inclusion into account to
> avoid merge conflicts... But as long as this cleanup is not ready yet, I
> prefer to go forward this way.
> 
> For that purpose, that would be good to see this patch in linux-next.
agreed

Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>

Best Regards,
J.


From gilles.ganault at free.fr  Thu Jun 16 10:12:00 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 16 Jun 2011 16:12:00 +0200
Subject: [NAND] Are partitions persistent?
References: <khpjv6l6bhe815s0rj9frue0l5qqpb8hfq@4ax.com>
Message-ID: <se3kv6dpdvslsqbrmfime09062h4rj3767@4ax.com>

On Thu, 16 Jun 2011 13:23:52 +0200, Gilles <gilles.ganault at free.fr>
wrote:
>	I was wondering: Are partitions on NAND persistent, or is it up to
>the developer to make sure the images used to populate the different
>partitions are small enough to fit the partitions set in the NAND
>driver?

To investigate, I went ahead, built a kernel + initramfs + ext2, used
nand to erase/write this new kernel in the first partition in the
NAND, and booted... but Linux isn't happy :-/

"No filesystem could mount root, tried:  ubifs
Kernel panic - not syncing: VFS: Unable to mount root fs on
unknown-block(0,0)"

Here's what I did
========================
appliance>tftp 0x1000000 uImage
Filename 'uImage'.
Load address: 0x1000000
Loading:
#################################################################
 #################################################################
done
Bytes transferred = 3656651 (37cbcb hex)
========================
appliance>nand erase clean 0x0 0x800000

NAND erase: device 0 offset 0x0, size 0x800000
Erasing at 0x7e0000 -- 100% complete. Cleanmarker written at 0x7e0000.
OK
========================
appliance>nand erase 0x0 0x8000000

NAND erase: device 0 offset 0x0, size 0x8000000
Erasing at 0x7fe0000 -- 100% complete.
OK
========================
appliance>nand write 0x1000000 0x0 0x37cbcb

NAND write: device 0 offset 0, size 3656651 ... nand_write_ecc:
Attempt to write not page aligned data
 0 bytes written: ERROR
========================
appliance>nand write 0x1000000 0x0 0x400000

NAND write: device 0 offset 0, size 4194304 ...  4194304 bytes
written: OK
========================
appliance>reset
========================
appliance>set bootargs  rootfstype=ubifs ubi.mtd=2 root=ubi0:rootfs rw
appliance>set autostart yes
========================
appliance>run nandboot

Loading from device 0: NAND 256MiB 3,3V 8-bit (offset 0x0)
   Image Name:   Linux Kernel and ext2
   Image Type:   Blackfin Linux Kernel Image (gzip compressed)
   Data Size:    3656587 Bytes =  3.5 MB
   Load Address: 00001000
   Entry Point:  001f43ec
Automatic boot of image at addr 0x02000000 ...
## Booting image at 02000000 ...
   Image Name:   Linux Kernel and ext2
   Image Type:   Blackfin Linux Kernel Image (gzip compressed)
   Data Size:    3656587 Bytes =  3.5 MB
   Load Address: 00001000
   Entry Point:  001f43ec
   Verifying Checksum ... OK
   Uncompressing Kernel Image ... OK
Starting Kernel at = 1f43ec
console [ttyBF0] enabled, bootconsole disabled
Calibrating delay loop... 796.67 BogoMIPS (lpj=1593344)
Security Framework initialized
Mount-cache hash table entries: 512
Blackfin Scratchpad data SRAM: 4 KB
Blackfin L1 Instruction SRAM: 32 KB (20 KB free)
NET: Registered protocol family 16
Blackfin DMA Controller
ip0x_init(): registering device resources
gpio_request OK
CLE is 2 and ALE is 1
bio: create slab <bio-0> at 0
Switching to clocksource bfin_cs_cycles
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 2048 (order: 2, 16384 bytes)
TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
TCP: Hash tables configured (established 2048 bind 2048)
TCP reno registered
UDP hash table entries: 256 (order: 0, 4096 bytes)
UDP-Lite hash table entries: 256 (order: 0, 4096 bytes)
NET: Registered protocol family 1
msgmni has been set to 104
Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253)
io scheduler noop registered
io scheduler cfq registered (default)
bfin_sport: registered sport0
bfin_sport: registered sport1
bfin-uart: Blackfin serial driver
bfin-uart.0: ttyBF0 at MMIO 0xffc00400 (irq = 21) is a BFIN-UART
brd: module loaded
uclinux[mtd]: RAM probe address=0x3700000 size=0x800000
Creating 1 MTD partitions on "RAM":
0x000000000000-0x000000800000 : "ROMfs"
mtd: Giving out device 0 to ROMfs
Generic platform RAM MTD, (c) 2004 Simtec Electronics
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB
3,3V 8-bit)
Scanning device for bad blocks
INFO: RCU detected CPU 0 stall (t=2500 jiffies)
cmdlinepart partition parsing not available
RedBoot partition parsing not available
Creating 2 MTD partitions on "My_great_flash_memory":
0x000000000000-0x000000800000 : "kernel_nand"
mtd: Giving out device 1 to kernel_nand
0x000000800000-0x000010000000 : "filesystem_nand"
mtd: Giving out device 2 to filesystem_nand
UBI: attaching mtd2 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: attached mtd2 to ubi0
UBI: MTD device name:            "filesystem_nand"
UBI: MTD device size:            248 MiB
UBI: number of good PEBs:        1984
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:     1
UBI: available PEBs:             0
UBI: total number of reserved PEBs: 1984
UBI: number of PEBs reserved for bad PEB handling: 19
UBI: max/mean erase counter: 18/14
UBI: image sequence number: 0
mtd: Giving out device 3 to rootfs
dm9000 Ethernet Driver, V1.31
UBI: background thread "ubi_bgt0d" started, PID 23
eth0: dm9000a at 20100000,20100002 IRQ 48 MAC: 00:09:45:56:72:9b
(chip)
ip_tables: (C) 2000-2006 Netfilter Core Team
TCP cubic registered
NET: Registered protocol family 17
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
dma_alloc_init: dma_page @ 0x02133000 - 256 pages at 0x03f00000
UBIFS error (pid 1): ubifs_recover_master_node: failed to recover
master node
List of all partitions:
1f00            8192 mtdblock0 (driver?)
1f01            8192 mtdblock1 (driver?)
1f02          253952 mtdblock2 (driver?)
1f03          247086 mtdblock3 (driver?)
No filesystem could mount root, tried:  ubifs
Kernel panic - not syncing: VFS: Unable to mount root fs on
unknown-block(0,0)
Hardware Trace:
========================

So it looks like Linux successfully attached to the Ubifs partition,
but for some reason, can't mount as root filesystem?

Thanks for any hint.



From vapier.adi at gmail.com  Fri Jun 17 02:26:15 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 17 Jun 2011 02:26:15 -0400
Subject: [NAND] Are partitions persistent?
In-Reply-To: <khpjv6l6bhe815s0rj9frue0l5qqpb8hfq@4ax.com>
References: <khpjv6l6bhe815s0rj9frue0l5qqpb8hfq@4ax.com>
Message-ID: <BANLkTi=fnNB2CXkbSGhrs91TLUB05KWwrQ@mail.gmail.com>

On Thu, Jun 16, 2011 at 07:23, Gilles wrote:
> ? ? ? ?I was wondering: Are partitions on NAND persistent, or is it up to
> the developer to make sure the images used to populate the different
> partitions are small enough to fit the partitions set in the NAND
> driver?
>
> For instance, this found through Google:
> =============
> static struct mtd_partition bfin_spi_flash_partitions[ ] = {
> ? ?{
> ? ? ? ?.name = "bootloader(spi)",
> ? ? ? ?.size = 0x00040000,
> ? ? ? ?.offset = 0,
> ? ? ? ?.mask_flags = MTD_CAP_ROM
> ? ?}, {
> ? ? ? ?.name = "linux kernel(spi)",
> ? ? ? ?.size = 0x180000,
> ? ? ? ?.offset = MTDPART_OFS_APPEND,
> };
> =============
>
> Does it mean that, for instance, when using Uboot's nandwrite to
> update the bootloader above, it's up to me to make sure that the image
> is smaller than 0x40000 and Uboot will happily keep going and erase
> part of the linux kernel, or is the MTDPART_OFS_APPEND option
> precisely made to avoid this and trigger an error?

the kernel's concept of partitions really has nothing to do with
u-boot.  further, the layout you define in the kernel via platform
resources is static and always used exactly as declared regardless of
the content on there.

u-boot by default does not know any of partitions, only offsets and
lengths.  it is up to you to make sure the two concepts are kept in
line.
-mike


From axel.lin at gmail.com  Fri Jun 17 04:09:36 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 17 Jun 2011 16:09:36 +0800
Subject: [PATCH 1/2] mtd: onenand/omap2.c: fix build error
Message-ID: <1308298176.13535.1.camel@phoenix>

Fix below build error:
  CC      drivers/mtd/onenand/omap2.o
drivers/mtd/onenand/omap2.c: In function 'omap2_onenand_probe':
drivers/mtd/onenand/omap2.c:754: error: 'info' undeclared (first use in this function)
drivers/mtd/onenand/omap2.c:754: error: (Each undeclared identifier is reported only once
drivers/mtd/onenand/omap2.c:754: error: for each function it appears in.)
make[3]: *** [drivers/mtd/onenand/omap2.o] Error 1
make[2]: *** [drivers/mtd/onenand] Error 2
make[1]: *** [drivers/mtd] Error 2
make: *** [drivers] Error 2

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/onenand/omap2.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/onenand/omap2.c b/drivers/mtd/onenand/omap2.c
index eb9cbd9..06efa14 100644
--- a/drivers/mtd/onenand/omap2.c
+++ b/drivers/mtd/onenand/omap2.c
@@ -751,7 +751,7 @@ static int __devinit omap2_onenand_probe(struct platform_device *pdev)
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	r = mtd_device_parse_register(&info->mtd, NULL, 0,
+	r = mtd_device_parse_register(&c->mtd, NULL, 0,
 			pdata ? pdata->parts : NULL,
 			pdata ? pdata->nr_parts : 0);
 	if (r)
-- 
1.7.4.1





From axel.lin at gmail.com  Fri Jun 17 04:11:34 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 17 Jun 2011 16:11:34 +0800
Subject: [PATCH 2/2] mtd: onenand/samsung.c: fix build error
In-Reply-To: <1308298176.13535.1.camel@phoenix>
References: <1308298176.13535.1.camel@phoenix>
Message-ID: <1308298294.13535.3.camel@phoenix>

Fix below build error:
  CC      drivers/mtd/onenand/samsung.o
drivers/mtd/onenand/samsung.c: In function 's3c_onenand_probe':
drivers/mtd/onenand/samsung.c:1017: error: 'info' undeclared (first use in this function)
drivers/mtd/onenand/samsung.c:1017: error: (Each undeclared identifier is reported only once
drivers/mtd/onenand/samsung.c:1017: error: for each function it appears in.)
make[3]: *** [drivers/mtd/onenand/samsung.o] Error 1
make[2]: *** [drivers/mtd/onenand] Error 2
make[1]: *** [drivers/mtd] Error 2
make: *** [drivers] Error 2

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/onenand/samsung.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 597dffc..d324074 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -1014,7 +1014,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+	err = mtd_device_parse_register(onenand->mtd, NULL, 0,
 			pdata ? pdata->parts : NULL,
 			pdata ? pdata->nr_parts : 0);
 
-- 
1.7.4.1





From gilles.ganault at free.fr  Fri Jun 17 05:03:57 2011
From: gilles.ganault at free.fr (Gilles)
Date: Fri, 17 Jun 2011 11:03:57 +0200
Subject: [NAND] Are partitions persistent?
References: <khpjv6l6bhe815s0rj9frue0l5qqpb8hfq@4ax.com>
	<BANLkTi=fnNB2CXkbSGhrs91TLUB05KWwrQ@mail.gmail.com>
Message-ID: <u26mv6p5o25fugrjepefl74q8rgct8uq0s@4ax.com>

On Fri, 17 Jun 2011 02:26:15 -0400, Mike Frysinger
<vapier.adi at gmail.com> wrote:
>u-boot by default does not know any of partitions, only offsets and
>lengths.  it is up to you to make sure the two concepts are kept in
>line.

Thanks Mike, that's what I thought.



From axel.lin at gmail.com  Fri Jun 17 07:06:33 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Fri, 17 Jun 2011 19:06:33 +0800
Subject: [PATCH] mtd: onenand: remove redundant mtd_device_unregister
	before onenand_release
Message-ID: <1308308793.2628.0.camel@phoenix>

onenand_release() will call mtd_device_unregister(), thus remove the redundant
mtd_device_unregister() call before onenand_release().

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/onenand/generic.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c
index 8152a31..7813095 100644
--- a/drivers/mtd/onenand/generic.c
+++ b/drivers/mtd/onenand/generic.c
@@ -97,7 +97,6 @@ static int __devexit generic_onenand_remove(struct platform_device *pdev)
 	platform_set_drvdata(pdev, NULL);
 
 	if (info) {
-		mtd_device_unregister(&info->mtd);
 		onenand_release(&info->mtd);
 		release_mem_region(res->start, size);
 		iounmap(info->onenand.base);
-- 
1.7.4.1





From computersforpeace at gmail.com  Fri Jun 17 13:10:42 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 17 Jun 2011 10:10:42 -0700
Subject: [PATCH 2/2] mtd: onenand/samsung.c: fix build error
In-Reply-To: <1308298294.13535.3.camel@phoenix>
References: <1308298176.13535.1.camel@phoenix>
	<1308298294.13535.3.camel@phoenix>
Message-ID: <BANLkTi=MiT1PrcJMdAfegTg74BQYNHC2fw@mail.gmail.com>

Hi,

On Fri, Jun 17, 2011 at 1:11 AM, Axel Lin <axel.lin at gmail.com> wrote:
> - ? ? ? err = mtd_device_parse_register(&info->mtd, NULL, 0,
> + ? ? ? err = mtd_device_parse_register(onenand->mtd, NULL, 0,
> ? ? ? ? ? ? ? ? ? ? ? ?pdata ? pdata->parts : NULL,
> ? ? ? ? ? ? ? ? ? ? ? ?pdata ? pdata->nr_parts : 0);

Wouldn't it be just the same (and shorter) to use "mtd" instead of
onenand->mtd? Like:

       err = mtd_device_parse_register(mtd, NULL, 0,
                     pdata ? pdata->parts : NULL,
                     pdata ? pdata->nr_parts : 0);

Brian


From peter.barada at gmail.com  Fri Jun 17 13:52:24 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Fri, 17 Jun 2011 13:52:24 -0400
Subject: Problem with clean markers/partial writes on Micron 4-bit ECC NAND
Message-ID: <4DFB9458.1030304@gmail.com>

I'm using a 2K page Micron NAND that has an internal 4-bit ECC engine.

The Micron NAND chip uses 8-bytes per 512 bytes of main data area + 4 
bytes of the OOB.  This allows the 32 bytes of ECC to correct 2048 bytes 
of the main data area and 16 bytes of the OOB area.

The problem I'm running into with JFFS2 is that empty flash is first 
marked with a clean marker into the OOB, and then a 2nd write to the 
main data area is done (w/o an intervening erase) to that page with data 
which corrupts the ECCs that were first modified by writing the cleanmarker.

The OOB layout I'm using (which allows ECC'ng 16 bytes of the OOB) is:

ecclayout = {
         eccbytes = 32,
         eccpos = { 8, 9, 10, 11, 12, 13, 14, 15,
                 24, 25, 26, 27, 28, 19, 30, 31,
                 40, 41, 42, 43, 44, 45, 46, 47,
                 56, 57, 58, 59, 60, 61, 62, 63},
         .oobfree = {
                 { .offset = 4,
                   .length = 4},
                 { .offset = 20,
                   .length = 4},
                 { .offset = 36,
                   .length = 4},
                 { .offset = 52,
                   .length = 4},
         },
};

After the cleanmarker is written into bytes 4-7 and 16-23 of the OOB, 
nanddump shows:

   OOB Data: ff ff ff ff 85 19 03 20 5a e3 da 69 01 40 f1 36
   OOB Data: ff ff ff ff 08 00 00 00 91 99 3c 05 01 d0 5d b3
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Note the ECCs in bytes 8-15 and 25-31 are no longer 0xFF since the ECC 
at bytes 8-15 covers data area bytes 0-511 as well as OOB bytes 4-7 and 
the ECC at bytes 16-23 covers data area bytes 512-1023 as well as OOB 
bytes 16-23.

I believe I've figured out a workaround:

1) Modify the ecclayout to add the other 8 bytes of the OOB that are NOT 
ECCd *after* the 16 bytes that are ECCd (so the ecc layout looks like):

  ecclayout = {
         eccbytes = 32,
         eccpos = { 8, 9, 10, 11, 12, 13, 14, 15,
                 24, 25, 26, 27, 28, 19, 30, 31,
                 40, 41, 42, 43, 44, 45, 46, 47,
                 56, 57, 58, 59, 60, 61, 62, 63},
         .oobfree = {
                 { .offset = 4,
                   .length = 4},
                 { .offset = 20,
                   .length = 4},
                 { .offset = 36,
                   .length = 4},
                 { .offset = 52,
                   .length = 4},
                 { .offset = 2,
                   .length = 2},
                 { .offset = 18,
                   .length = 2},
                 { .offset = 24,
                   .length = 2},
                 { .offset = 42,
                   .length = 2},
         },
};

2) Then set ops.ooboffs to 16 in jffs2_write_nand_cleanmarker and 
jffs2_check_nand_cleanmarker.

This "offsets" the read/writes by 16 bytes to move the cleanmarker into 
OOB bytes that do not perturb the ECCs, and so far it looks to work.

However I feel this is a hack as our product will use two different NAND 
chips, the other being a more traditional SLC that can use 1-bit hamming 
for ECC (which does not ECC any bytes in the OOB).

How can I best code this into the MTD layer such that JFFS2 (and other 
NAND FSs that does partial writes including OOB bytes) can understand 
that some OOB bytes perturb the data area ECC?

I think adding a "non_ecc_oob_offset" variable to the ecclayout could 
capture this nuance of the OOB/ECC interaction for this chip and JFFS2 
could set ops.ooboffs to non_ecc_oob_offset in 
jffs2_write_nand_cleanmarker and jffs2_check_nand_cleanmarker.

Any comments are appreciated!

-- 
Peter Barada
peter.barada at gmail.com



From bryanhundven at gmail.com  Fri Jun 17 13:58:53 2011
From: bryanhundven at gmail.com (Bryan Hundven)
Date: Fri, 17 Jun 2011 10:58:53 -0700
Subject: [PATCH] powerpc/85xx: fix NAND_CMD_READID read bytes number
In-Reply-To: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>
References: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>
Message-ID: <BANLkTikoRk9OUrQGOFJZjMWOLLT5GXAEDQ@mail.gmail.com>

On Sun, Jun 12, 2011 at 7:23 PM, Shaohui Xie <Shaohui.Xie at freescale.com> wrote:
> when nand_get_flash_type() is called, it will read 8 bytes of ID instead of 5,
> but the driver only read 5 bytes, so kernel will dump error messages like:
>
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
>
> Signed-off-by: Shaohui Xie <Shaohui.Xie at freescale.com>
> Acked-by: Scott Wood <scottwood at freescale.com>
> ---
> ?drivers/mtd/nand/fsl_elbc_nand.c | ? ?6 +++---
> ?1 files changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> index 0bb254c..33d8aad 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -339,9 +339,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(FIR_OP_UA ?<< FIR_OP1_SHIFT) |
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(FIR_OP_RBW << FIR_OP2_SHIFT));
> ? ? ? ? ? ? ? ?out_be32(&lbc->fcr, NAND_CMD_READID << FCR_CMD0_SHIFT);
> - ? ? ? ? ? ? ? /* 5 bytes for manuf, device and exts */
> - ? ? ? ? ? ? ? out_be32(&lbc->fbcr, 5);
> - ? ? ? ? ? ? ? elbc_fcm_ctrl->read_bytes = 5;
> + ? ? ? ? ? ? ? /* nand_get_flash_type() reads 8 bytes of entire ID string */
> + ? ? ? ? ? ? ? out_be32(&lbc->fbcr, 8);
> + ? ? ? ? ? ? ? elbc_fcm_ctrl->read_bytes = 8;
> ? ? ? ? ? ? ? ?elbc_fcm_ctrl->use_mdr = 1;
> ? ? ? ? ? ? ? ?elbc_fcm_ctrl->mdr = 0;
>
> --
> 1.6.4
>
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>

Shaohui,

I have tested this on p1011rdb, p1020rdb, and p2020rdb on 2.6.35.13
and 2.6.39.1.
Thank you for fixing this :-)

-Bryan


From ivan.djelic at parrot.com  Fri Jun 17 17:00:14 2011
From: ivan.djelic at parrot.com (Ivan Djelic)
Date: Fri, 17 Jun 2011 23:00:14 +0200
Subject: Problem with clean markers/partial writes on Micron 4-bit ECC NAND
In-Reply-To: <4DFB9458.1030304@gmail.com>
References: <4DFB9458.1030304@gmail.com>
Message-ID: <20110617210014.GA28332@parrot.com>

On Fri, Jun 17, 2011 at 06:52:24PM +0100, Peter Barada wrote:
(...)
> The problem I'm running into with JFFS2 is that empty flash is first 
> marked with a clean marker into the OOB, and then a 2nd write to the 
> main data area is done (w/o an intervening erase) to that page with data 
> which corrupts the ECCs that were first modified by writing the cleanmarker.
> 
(...)
> 
> I believe I've figured out a workaround:
> 
> 1) Modify the ecclayout to add the other 8 bytes of the OOB that are NOT 
> ECCd *after* the 16 bytes that are ECCd (so the ecc layout looks like):
> 
(...)
> 2) Then set ops.ooboffs to 16 in jffs2_write_nand_cleanmarker and 
> jffs2_check_nand_cleanmarker.
> 
> This "offsets" the read/writes by 16 bytes to move the cleanmarker into 
> OOB bytes that do not perturb the ECCs, and so far it looks to work.
> 

OK, so now the cleanmarker is in an unprotected area; did you also patch
jffs2_check_nand_cleanmarker() so that it does its pattern comparison in a
bitflip-robust way (instead of just doing a memcmp) ?
I think you may also need to modify jffs2_check_oob_empty() to take into
account the new offset of your cleanmarker.

> However I feel this is a hack as our product will use two different NAND 
> chips, the other being a more traditional SLC that can use 1-bit hamming 
> for ECC (which does not ECC any bytes in the OOB).
> 
> How can I best code this into the MTD layer such that JFFS2 (and other 
> NAND FSs that does partial writes including OOB bytes) can understand 
> that some OOB bytes perturb the data area ECC?
> 
> I think adding a "non_ecc_oob_offset" variable to the ecclayout could 
> capture this nuance of the OOB/ECC interaction for this chip and JFFS2 
> could set ops.ooboffs to non_ecc_oob_offset in 
> jffs2_write_nand_cleanmarker and jffs2_check_nand_cleanmarker.

I believe JFFS2 only uses oob for its cleanmarker; then, maybe you could just
omit the ecc-protected bytes from the .oobfree list, like this:

  ecclayout = {
         eccbytes = 32,
         eccpos = { 8, 9, 10, 11, 12, 13, 14, 15,
                 24, 25, 26, 27, 28, 19, 30, 31,
                 40, 41, 42, 43, 44, 45, 46, 47,
                 56, 57, 58, 59, 60, 61, 62, 63},
         .oobfree = {
                 { .offset = 2,
                   .length = 2},
                 { .offset = 18,
                   .length = 2},
                 { .offset = 24,
                   .length = 2},
                 { .offset = 42,
                   .length = 2},
         },
};

and only modify jffs2_check_nand_cleanmarker() and jffs2_check_oob_empty()
so that they are robust to bitflips in unprotected oob bytes ?
Or are you also using on the same mtd device another filesystem requiring
protected oob bytes, like YAFFS2 ?
Regards,

Ivan


From scottwood at freescale.com  Fri Jun 17 17:34:42 2011
From: scottwood at freescale.com (Scott Wood)
Date: Fri, 17 Jun 2011 16:34:42 -0500
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <BANLkTikyKObukzVw+c10HyDz+Q=PH4jozA@mail.gmail.com>
References: <BANLkTikyKObukzVw+c10HyDz+Q=PH4jozA@mail.gmail.com>
Message-ID: <20110617163442.204348a0@schlenkerla.am.freescale.net>

On Fri, 17 Jun 2011 16:54:27 -0400
"Matthew L. Creech" <mlcreech at gmail.com> wrote:

> Hi, I posted this on the Linux-MTD list but haven't gotten any hits.
> Since it looks like it could be MPC83xx-specific, I'm reposting here.
> Rick Johnson noted a problem in fsl_elbc_nand.c back in May which
> might be related:
> 
> http://lists.infradead.org/pipermail/linux-mtd/2011-May/035372.html

It seems that the generic code always passes -1 with PAGEPROG, and only
provides the actual page address on SEQIN.

I don't think the ECC readback is needed, and the fact that it looks like
it has always been broken would seem to confirm that.  It's broken in
other ways, too -- it assumes a particular ECC layout.  Let's get rid of it.

As for the corruption, could it be degradation from repeated reads of that
one page?

> More info on this board:
> - MPC 8313 SoC
> - 1GB Samsung NAND flash (K9K8G08U0B)
> - Linux 2.6.31
> - U-Boot 2009.06

Hmm, 2.6.31... it's probably not related to this problem, but you
should cherry pick b3a70f0bc32d1b70584bcaa6019fa4260b0da92e and
476459a6cf46d20ec73d9b211f3894ced5f9871e.

-Scott



From ANDY.KENNEDY at adtran.com  Fri Jun 17 18:09:26 2011
From: ANDY.KENNEDY at adtran.com (ANDY KENNEDY)
Date: Fri, 17 Jun 2011 22:09:26 +0000
Subject: NAND OOB data.
Message-ID: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>

I have overwritten my OOB data, to the point where all blocks are seen
as bad.  What do I do to recover from this?

Thanks,
Andy


From axel.lin at gmail.com  Fri Jun 17 21:40:00 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Sat, 18 Jun 2011 09:40:00 +0800
Subject: [PATCH 2/2 v2] mtd: onenand/samsung.c: fix build error
Message-ID: <1308361200.2400.1.camel@phoenix>

Fix below build error:
  CC      drivers/mtd/onenand/samsung.o
drivers/mtd/onenand/samsung.c: In function 's3c_onenand_probe':
drivers/mtd/onenand/samsung.c:1017: error: 'info' undeclared (first use in this function)
drivers/mtd/onenand/samsung.c:1017: error: (Each undeclared identifier is reported only once
drivers/mtd/onenand/samsung.c:1017: error: for each function it appears in.)
make[3]: *** [drivers/mtd/onenand/samsung.o] Error 1
make[2]: *** [drivers/mtd/onenand] Error 2
make[1]: *** [drivers/mtd] Error 2
make: *** [drivers] Error 2

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/onenand/samsung.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
index 597dffc..a0ef087 100644
--- a/drivers/mtd/onenand/samsung.c
+++ b/drivers/mtd/onenand/samsung.c
@@ -1014,7 +1014,7 @@ static int s3c_onenand_probe(struct platform_device *pdev)
 	if (s3c_read_reg(MEM_CFG_OFFSET) & ONENAND_SYS_CFG1_SYNC_READ)
 		dev_info(&onenand->pdev->dev, "OneNAND Sync. Burst Read enabled\n");
 
-	err = mtd_device_parse_register(&info->mtd, NULL, 0,
+	err = mtd_device_parse_register(mtd, NULL, 0,
 			pdata ? pdata->parts : NULL,
 			pdata ? pdata->nr_parts : 0);
 
-- 
1.7.4.1





From peter.barada at gmail.com  Sat Jun 18 12:37:30 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Sat, 18 Jun 2011 12:37:30 -0400
Subject: Problem with clean markers/partial writes on Micron 4-bit ECC NAND
In-Reply-To: <20110617210014.GA28332@parrot.com>
References: <4DFB9458.1030304@gmail.com> <20110617210014.GA28332@parrot.com>
Message-ID: <4DFCD44A.4090909@gmail.com>

On 06/17/2011 05:00 PM, Ivan Djelic wrote:
> On Fri, Jun 17, 2011 at 06:52:24PM +0100, Peter Barada wrote:
> (...)
>> The problem I'm running into with JFFS2 is that empty flash is first
>> marked with a clean marker into the OOB, and then a 2nd write to the
>> main data area is done (w/o an intervening erase) to that page with data
>> which corrupts the ECCs that were first modified by writing the cleanmarker.
>>
> (...)
>> I believe I've figured out a workaround:
>>
>> 1) Modify the ecclayout to add the other 8 bytes of the OOB that are NOT
>> ECCd *after* the 16 bytes that are ECCd (so the ecc layout looks like):
>>
> (...)
>> 2) Then set ops.ooboffs to 16 in jffs2_write_nand_cleanmarker and
>> jffs2_check_nand_cleanmarker.
>>
>> This "offsets" the read/writes by 16 bytes to move the cleanmarker into
>> OOB bytes that do not perturb the ECCs, and so far it looks to work.
>>
> OK, so now the cleanmarker is in an unprotected area; did you also patch
> jffs2_check_nand_cleanmarker() so that it does its pattern comparison in a
> bitflip-robust way (instead of just doing a memcmp) ?
> I think you may also need to modify jffs2_check_oob_empty() to take into
> account the new offset of your cleanmarker.
No, I haven't yet created a bitflip-robust jffs2_check_nand_cleanmarker 
- will code up a version that calculates the number of flips between the 
expected and read markers and if less than some threshold accept it.  
I'm surprised such code isn't already in JFFS2, unless JFFS2 assumes 
that area of the OOB is already protected (and that protection is OOB-only).

>> However I feel this is a hack as our product will use two different NAND
>> chips, the other being a more traditional SLC that can use 1-bit hamming
>> for ECC (which does not ECC any bytes in the OOB).
>>
>> How can I best code this into the MTD layer such that JFFS2 (and other
>> NAND FSs that does partial writes including OOB bytes) can understand
>> that some OOB bytes perturb the data area ECC?
>>
>> I think adding a "non_ecc_oob_offset" variable to the ecclayout could
>> capture this nuance of the OOB/ECC interaction for this chip and JFFS2
>> could set ops.ooboffs to non_ecc_oob_offset in
>> jffs2_write_nand_cleanmarker and jffs2_check_nand_cleanmarker.
> I believe JFFS2 only uses oob for its cleanmarker; then, maybe you could just
> omit the ecc-protected bytes from the .oobfree list, like this:
>
>    ecclayout = {
>           eccbytes = 32,
>           eccpos = { 8, 9, 10, 11, 12, 13, 14, 15,
>                   24, 25, 26, 27, 28, 19, 30, 31,
>                   40, 41, 42, 43, 44, 45, 46, 47,
>                   56, 57, 58, 59, 60, 61, 62, 63},
>           .oobfree = {
>                   { .offset = 2,
>                     .length = 2},
>                   { .offset = 18,
>                     .length = 2},
>                   { .offset = 24,
>                     .length = 2},
>                   { .offset = 42,
>                     .length = 2},
>           },
> };
>
> and only modify jffs2_check_nand_cleanmarker() and jffs2_check_oob_empty()
> so that they are robust to bitflips in unprotected oob bytes ?
> Or are you also using on the same mtd device another filesystem requiring
> protected oob bytes, like YAFFS2 ?
Yes we are using YAFFS2 in our system so I need not only protected OOB 
bytes, but at least 16 of them for YAFFS to hold its meta data - hence 
our OOB layout.  What's nice is that the 16 currently available are ECCd 
so there's not need to ECC the YAFFS meta data (which saves time).

The issue I have is how can I best tell MTD (and FS layers on top of it) 
that some of the OOB bytes can not be used in partial writes due to 
those bytes perturbing the ECC, or how to change JFFS2 to erase the 
block after writing the cleanmarker when it wants to write data into the 
block.

Why does JFFS2 write a clean marker into the empty block?  Is it to 
cover some state transition where power could be interrupted?

> Regards,
>
> Ivan
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/


-- 
Peter Barada
peter.barada at gmail.com



From cernekee at gmail.com  Sat Jun 18 13:49:52 2011
From: cernekee at gmail.com (Kevin Cernekee)
Date: Sat, 18 Jun 2011 10:49:52 -0700
Subject: Problem with clean markers/partial writes on Micron 4-bit ECC NAND
In-Reply-To: <4DFCD44A.4090909@gmail.com>
References: <4DFB9458.1030304@gmail.com> <20110617210014.GA28332@parrot.com>
	<4DFCD44A.4090909@gmail.com>
Message-ID: <BANLkTinXQ7aPOf7L1tqj362SR+b3TRe-XQ@mail.gmail.com>

On Sat, Jun 18, 2011 at 9:37 AM, Peter Barada <peter.barada at gmail.com> wrote:
> The issue I have is how can I best tell MTD (and FS layers on top of it)
> that some of the OOB bytes can not be used in partial writes due to those
> bytes perturbing the ECC, or how to change JFFS2 to erase the block after
> writing the cleanmarker when it wants to write data into the block.

FWIW, the product I work on used to utilize JFFS2 and YAFFS2.  We
needed to hack around many of the same OOB/NOP limitations you are
seeing.  (As well as several cases where corrupted filesystem metadata
caused a kernel oops on mount.)

Once UBIFS became a viable alternative, we found that supporting
JFFS2/YAFFS2 on NAND flash was far more trouble than it was worth.

> Why does JFFS2 write a clean marker into the empty block? ?Is it to cover
> some state transition where power could be interrupted?

Here is a good explanation:

http://linux-mtd.infradead.org/faq/jffs2.html#L_clmarker


From mhench at elutions.com  Sat Jun 18 13:55:01 2011
From: mhench at elutions.com (Mike Hench)
Date: Sat, 18 Jun 2011 13:55:01 -0400
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <20110617163442.204348a0@schlenkerla.am.freescale.net>
Message-ID: <F87D23B7E1F84E4AB52E4FA4A55F85DC0259E343@tpamail.elutions.com>

Scott Wood wrote:
> As for the corruption, could it be degradation from repeated reads of
that
> one page?

Read Disturb. I Did not know SLC did that.
It just takes 10x as long as MLC, on the order of a million reads.
Supposedly erasing the block fixes it.
It is not a permanent damage thing.
I was seeing ~9 hours before failure with heavy writes.
~4GByte/hour = 2M pages, total ~18 million reads before errors in that
last block showed up.

Cool. Now we know.
Thanks.

Mike Hench




From robert.jarzmik at free.fr  Sun Jun 19 04:57:27 2011
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sun, 19 Jun 2011 10:57:27 +0200
Subject: [PATCH v2 0/1] mtd/docg3: M-Systems DOC G3 support
Message-ID: <1308473848-27065-1-git-send-email-robert.jarzmik@free.fr>

Hi Artem and David,

I posted this 3 weeks ago, and unfortunately nobody commented the
submission.

This is the new version of the same driver, with only my own review
and Artem's comment on new mtd partitions API.
Please either comment or schedule for one of your linux-next tree, but
don't let it sleeping for weeks.

Cheers.

--
Robert

Robert Jarzmik (1):
  mtd: Add DiskOnChip G3 support

 drivers/mtd/devices/Kconfig  |   10 +
 drivers/mtd/devices/Makefile |    1 +
 drivers/mtd/devices/docg3.c  | 1138 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/devices/docg3.h  |  224 +++++++++
 4 files changed, 1373 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/devices/docg3.c
 create mode 100644 drivers/mtd/devices/docg3.h

-- 
1.7.4.4



From robert.jarzmik at free.fr  Sun Jun 19 04:57:28 2011
From: robert.jarzmik at free.fr (Robert Jarzmik)
Date: Sun, 19 Jun 2011 10:57:28 +0200
Subject: [PATCH v2 1/1] mtd: Add DiskOnChip G3 support
In-Reply-To: <1308473848-27065-1-git-send-email-robert.jarzmik@free.fr>
References: <1308473848-27065-1-git-send-email-robert.jarzmik@free.fr>
Message-ID: <1308473848-27065-2-git-send-email-robert.jarzmik@free.fr>

From: Robert Jarzmik <robert.jarzmik at free.com>

Add support for DiskOnChip G3 chips. The support is quite
limited yet :
 - no flash writes/erases are implemented
 - ECC fixes are not implemented
 - powerdown is not implemented
 - IPL handling is not yet done

On the brighter side, the chip reading does work.

Signed-off-by: Robert Jarzmik <robert.jarzmik at free.com>

---

Since V1:
 - more static functions, less global functions
 - prevent BCH calculation over OTP/BBT area
 - add bad blocks table support
 - fix the number of available blocks on G3 M512 (2048
 blocks)
 - cleaner double plane handling (2 pages being necessary to
   read 2 "virtual pages" of 512 bytes.
 - select device 0 after each operation
   Upon power failure or reboot, floor 0 needs to be
   selected as IPL is only on floor 0.
 - debug: add protection states reports
 - convert to new mtd partition API
   Effect of commit "mtd: introduce
   mtd_device_(un)register()"
---
 drivers/mtd/devices/Kconfig  |   10 +
 drivers/mtd/devices/Makefile |    1 +
 drivers/mtd/devices/docg3.c  | 1138 ++++++++++++++++++++++++++++++++++++++++++
 drivers/mtd/devices/docg3.h  |  224 +++++++++
 4 files changed, 1373 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/devices/docg3.c
 create mode 100644 drivers/mtd/devices/docg3.h

diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig
index 35081ce..6d91a1f 100644
--- a/drivers/mtd/devices/Kconfig
+++ b/drivers/mtd/devices/Kconfig
@@ -249,6 +249,16 @@ config MTD_DOC2001PLUS
 	  under "NAND Flash Device Drivers" (currently that driver does not
 	  support all Millennium Plus devices).
 
+config MTD_DOCG3
+	tristate "M-Systems Disk-On-Chip G3"
+	---help---
+	  This provides an MTD device driver for the M-Systems DiskOnChip
+	  G3 devices.
+
+	  The driver provides access to G3 DiskOnChip, distributed by
+	  M-Systems and now Sandisk. The support is very experimental,
+	  and doesn't give access to any write operations.
+
 config MTD_DOCPROBE
 	tristate
 	select MTD_DOCECC
diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile
index f3226b1..e71991f 100644
--- a/drivers/mtd/devices/Makefile
+++ b/drivers/mtd/devices/Makefile
@@ -5,6 +5,7 @@
 obj-$(CONFIG_MTD_DOC2000)	+= doc2000.o
 obj-$(CONFIG_MTD_DOC2001)	+= doc2001.o
 obj-$(CONFIG_MTD_DOC2001PLUS)	+= doc2001plus.o
+obj-$(CONFIG_MTD_DOCG3)		+= docg3.o
 obj-$(CONFIG_MTD_DOCPROBE)	+= docprobe.o
 obj-$(CONFIG_MTD_DOCECC)	+= docecc.o
 obj-$(CONFIG_MTD_SLRAM)		+= slram.o
diff --git a/drivers/mtd/devices/docg3.c b/drivers/mtd/devices/docg3.c
new file mode 100644
index 0000000..ef2c054
--- /dev/null
+++ b/drivers/mtd/devices/docg3.c
@@ -0,0 +1,1138 @@
+/*
+ * Handles the M-Systems DiskOnChip G3 chip
+ *
+ * Copyright (C) 2011 Robert Jarzmik
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+
+#include "docg3.h"
+
+/*
+ * This driver handles the DiskOnChip G3 flash memory.
+ *
+ * As no specification is available from M-Systems/Sandisk, this drivers lacks
+ * several functions available on the chip, as :
+ *  - block erase
+ *  - page write
+ *  - IPL write
+ *  - ECC fixing (lack of BCH algorith understanding)
+ *  - powerdown / powerup
+ *
+ * The bus data width (8bits versus 16bits) is not handled (if_cfg flag), and
+ * the driver assumes a 16bits data bus.
+ *
+ * DocG3 relies on 2 ECC algorithms, which are handled in hardware :
+ *  - a 1 byte Hamming code stored in the OOB for each page
+ *  - a 7 bytes BCH code stored in the OOB for each page
+ * The BCH part is only used for check purpose, no correction is available as
+ * some information is missing. What is known is that :
+ *  - BCH is in GF(2^14)
+ *  - BCH is over data of 520 bytes (512 page + 7 page_info bytes
+ *                                   + 1 hamming byte)
+ *  - BCH can correct up to 4 bits (t = 4)
+ *  - BCH syndroms are calculated in hardware, and checked in hardware as well
+ *
+ */
+
+#define doc_readb(reg)	\
+	__raw_readb(docg3->base + (reg));
+#define doc_writeb(value, reg)						\
+do {									\
+	doc_vdbg("Write %02x to register %04x\n", (value), (reg));	\
+	__raw_writeb((value), docg3->base + (reg));			\
+} while (0)
+#define doc_readw(reg)	\
+	__raw_readw(docg3->base + (reg));
+#define doc_writew(value, reg)						\
+do {									\
+	doc_vdbg("Write %04x to register %04x\n", (value), (reg));	\
+	__raw_writew((value), docg3->base + (reg));			\
+} while (0)
+
+#define doc_flashCommand(cmd)						\
+do {									\
+	doc_dbg("doc_flashCommand:  %02x " #cmd "\n", DoC_Cmd_##cmd);	\
+	doc_writeb(DoC_Cmd_##cmd, DoC_FlashCommand);			\
+} while (0)
+
+#define doc_flashSequence(seq)						\
+do {									\
+	doc_dbg("doc_flashSequence: %02x " #seq "\n", DoC_Seq_##seq);	\
+	doc_writeb(DoC_Seq_##seq, DoC_FlashSequence);			\
+} while (0)
+
+#define doc_flashAddress(addr)						\
+do {									\
+	doc_dbg("doc_flashAddress:  %02x\n", (addr));			\
+	doc_writeb((addr), DoC_FlashAddress);				\
+} while (0)
+
+static const char const *part_probes[] = { "cmdlinepart", "saftlpart", NULL };
+
+static int doc_register_readb(struct docg3 *docg3, int reg)
+{
+	u8 val;
+
+	doc_writew(reg, DoC_ReadAddress);
+	val = doc_readb(reg);
+	doc_vdbg("Read register %04x : %02x\n", reg, val);
+	return val;
+}
+
+static int doc_register_readw(struct docg3 *docg3, int reg)
+{
+	u16 val;
+
+	doc_writew(reg, DoC_ReadAddress);
+	val = doc_readw(reg);
+	doc_vdbg("Read register %04x : %04x\n", reg, val);
+	return val;
+}
+
+static void doc_delay(struct docg3 *docg3, int nbNOPs)
+{
+	int i;
+
+	doc_dbg("NOP x %d\n", nbNOPs);
+	for (i = 0; i < nbNOPs; i++)
+		doc_writeb(0, DoC_NOP);
+}
+
+static int is_prot_seq_error(struct docg3 *docg3)
+{
+	int ctrl;
+
+	ctrl = doc_register_readb(docg3, DoC_FlashControl);
+	return ctrl & (Doc_Ctrl_PROTECTION_ERROR | Doc_Ctrl_SEQUENCE_ERROR);
+}
+
+static int doc_is_ready(struct docg3 *docg3)
+{
+	int ctrl;
+
+	ctrl = doc_register_readb(docg3, DoC_FlashControl);
+	return ctrl & Doc_Ctrl_FLASHREADY;
+}
+
+static int doc_wait_ready(struct docg3 *docg3)
+{
+	int maxWaitCycles = 100;
+
+	do {
+		doc_delay(docg3, 4);
+	} while (!doc_is_ready(docg3) && maxWaitCycles--);
+	doc_delay(docg3, 2);
+	if (maxWaitCycles > 0)
+		return 0;
+	else
+		return -EIO;
+}
+
+static int doc_reset_seq(struct docg3 *docg3)
+{
+	int ret;
+
+	doc_writeb(0x10, DoC_FlashControl);
+	doc_flashSequence(RESET);
+	doc_flashCommand(RESET);
+	doc_delay(docg3, 2);
+	ret = doc_wait_ready(docg3);
+
+	doc_dbg("doc_reset_seq() -> isReady=%s\n", ret ? "false" : "true");
+	return ret;
+}
+
+/**
+ * doc_read_data_area - Read data from data area
+ * @docg3: the device
+ * @buf: the buffer to fill in
+ * @len: the lenght to read
+ * @first: first time read, DoC_ReadAddress should be set
+ *
+ * Reads bytes from flash data. Handles the single byte / even bytes reads.
+ */
+static void doc_read_data_area(struct docg3 *docg3, void *buf, int len,
+			       int first)
+{
+	int i, cdr, len4;
+	u16 data16, *dst16;
+	u8 data8, *dst8;
+
+	doc_dbg("doc_read_data_area(buf=%p, len=%d)\n", buf, len);
+	cdr = len & 0x3;
+	len4 = len - cdr;
+
+	if (first)
+		doc_writew(DOC_IOSPACE_DATA, DoC_ReadAddress);
+	dst16 = buf;
+	for (i = 0; i < len4; i += 2) {
+		data16 = doc_readw(DOC_IOSPACE_DATA);
+		*dst16 = data16;
+		dst16++;
+	}
+
+	if (cdr) {
+		doc_writew(DOC_IOSPACE_DATA | Doc_ReadAddr_ONE_BYTE,
+			   DoC_ReadAddress);
+		doc_delay(docg3, 1);
+		dst8 = (u8 *)dst16;
+		for (i = 0; i < cdr; i++) {
+			data8 = doc_readb(DOC_IOSPACE_DATA);
+			*dst8 = data8;
+			dst8++;
+		}
+	}
+}
+
+/**
+ * doc_set_data_mode - Sets the flash to reliable data mode
+ * @docg3: the device
+ *
+ * The reliable data mode is a bit slower than the fast mode, but less errors
+ * occur.  Entering the reliable mode cannot be done without entering the fast
+ * mode first.
+ */
+static void doc_set_reliable_mode(struct docg3 *docg3)
+{
+	doc_dbg("doc_set_reliable_mode()\n");
+	doc_flashSequence(SET_MODE);
+	doc_flashCommand(FAST_MODE);
+	doc_flashCommand(RELIABLE_MODE);
+	doc_delay(docg3, 2);
+}
+
+/**
+ * doc_set_asic_mode - Set the ASIC mode
+ * @docg3: the device
+ * @mode: the mode
+ *
+ * The ASIC can work in 3 modes :
+ *  - RESET: all registers are zeroed
+ *  - NORMAL: receives and handles commands
+ *  - POWERDOWN: minimal poweruse, flash parts shut off
+ */
+static void doc_set_asic_mode(struct docg3 *docg3, u8 mode)
+{
+	int i;
+
+	for (i = 0; i < 12; i++)
+		doc_readb(DOC_IOSPACE_IPL);
+
+	mode |= Doc_AsicMode_MDWREN;
+	doc_dbg("doc_set_asic_mode(%02x)\n", mode);
+	doc_writeb(mode, DoC_AsicMode);
+	doc_writeb(~mode, DoC_AsicModeConfirm);
+	doc_delay(docg3, 1);
+}
+
+/**
+ * doc_set_device_id - Sets the devices id for cascaded G3 chips
+ * @docg3: the device
+ * @id: the chip to select (amongst 0, 1, 2, 3)
+ *
+ * There can be 4 cascaded G3 chips. This function selects the one which will
+ * should be the active one.
+ */
+static void doc_set_device_id(struct docg3 *docg3, int id)
+{
+	u8 ctrl;
+
+	doc_dbg("doc_set_device_id(%d)\n", id);
+	doc_writeb(id, DoC_DeviceSelect);
+	ctrl = doc_register_readb(docg3, DoC_FlashControl);
+
+	ctrl &= ~Doc_Ctrl_Violation;
+	ctrl |= Doc_Ctrl_CE;
+	doc_writeb(ctrl, DoC_FlashControl);
+}
+
+/**
+ * doc_set_extra_page_mode - Change flash page layout
+ * @docg3: the device
+ *
+ * Normally, the flash page is split into the data (512 bytes) and the out of
+ * band data (16 bytes). For each, 4 more bytes can be accessed, where the wear
+ * leveling counters are stored.  To access this last area of 4 bytes, a special
+ * mode must be input to the flash ASIC.
+ *
+ * Returns 0 if no error occured, -EIO else.
+ */
+static int doc_set_extra_page_mode(struct docg3 *docg3)
+{
+	int fctrl;
+
+	doc_dbg("doc_set_extra_page_mode()\n");
+	doc_flashSequence(PAGE_SIZE_532);
+	doc_flashCommand(PAGE_SIZE_532);
+	doc_delay(docg3, 2);
+
+	fctrl = doc_register_readb(docg3, DoC_FlashControl);
+	if (fctrl & (Doc_Ctrl_PROTECTION_ERROR | Doc_Ctrl_SEQUENCE_ERROR))
+		return -EIO;
+	else
+		return 0;
+}
+
+/**
+ * doc_seek - Set both flash planes to the specified block, page for reading
+ * @docg3: the device
+ * @block0: the first plane block index
+ * @block1: the second plane block index
+ * @page: the page index within the block
+ * @wear: if true, read will occur on the 4 extra bytes of the wear area
+ * @ofs: offset in page to read
+ *
+ * Programs the flash even and odd planes to the specific block and page.
+ * Alternatively, programs the flash to the wear area of the specified page.
+ */
+static int doc_read_seek(struct docg3 *docg3, int block0, int block1, int page,
+			 int wear, int ofs)
+{
+	int sector, ret = 0;
+
+	doc_dbg("doc_seek(blocks=(%d,%d), page=%d, ofs=%d, wear=%d)\n",
+		block0, block1, page, ofs, wear);
+
+	if (!wear && (ofs < 2 * DOC_LAYOUT_PAGE_SIZE)) {
+		doc_flashSequence(SET_PLANE1);
+		doc_flashCommand(READ_PLANE1);
+		doc_delay(docg3, 2);
+	} else {
+		doc_flashSequence(SET_PLANE2);
+		doc_flashCommand(READ_PLANE2);
+		doc_delay(docg3, 2);
+	}
+
+	doc_set_reliable_mode(docg3);
+	if (wear)
+		ret = doc_set_extra_page_mode(docg3);
+	if (ret)
+		goto out;
+
+	sector = (block0 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+	doc_flashSequence(READ);
+	doc_flashCommand(PROG_BLOCK_ADDR);
+	doc_delay(docg3, 1);
+	doc_flashAddress(sector & 0xff);
+	doc_flashAddress((sector >> 8) & 0xff);
+	doc_flashAddress((sector >> 16) & 0xff);
+	doc_delay(docg3, 1);
+
+	sector = (block1 << DOC_ADDR_BLOCK_SHIFT) + (page & DOC_ADDR_PAGE_MASK);
+	doc_flashCommand(PROG_BLOCK_ADDR);
+	doc_delay(docg3, 1);
+	doc_flashAddress(sector & 0xff);
+	doc_flashAddress((sector >> 8) & 0xff);
+	doc_flashAddress((sector >> 16) & 0xff);
+	doc_delay(docg3, 2);
+
+out:
+	return ret;
+}
+
+/**
+ * doc_read_page_ecc_init - Initialize hardware ECC engine
+ * @docg3: the device
+ * @len: the number of bytes covered by the ECC (BCH covered)
+ *
+ * The function does initialize the hardware ECC engine to compute the Hamming
+ * ECC (on 1 byte) and the BCH Syndroms (on 7 bytes).
+ *
+ * Return 0 if succeeded, -EIO on error
+ */
+static int doc_read_page_ecc_init(struct docg3 *docg3, int len)
+{
+	doc_writew(Doc_ECCConf0_READ_MODE
+		   | Doc_ECCConf0_BCH_ENABLE | Doc_ECCConf0_HAMMING_ENABLE
+		   | (len & Doc_ECCConf0_DATA_BYTES_MASK),
+		   DoC_EccConf0);
+	doc_delay(docg3, 4);
+	doc_register_readb(docg3, DoC_FlashControl);
+	return doc_wait_ready(docg3);
+}
+
+/**
+ * doc_read_page_prepare - Prepares reading data from a flash page
+ * @docg3: the device
+ * @block0: the first plane block index on flash memory
+ * @block1: the second plane block index on flash memory
+ * @page: the page index in the block
+ * @offset: the offset in the page (must be a multiple of 4)
+ *
+ * Prepares the page to be read in the flash memory :
+ *   - tell ASIC to map the flash pages
+ *   - tell ASIC to be in read mode
+ *
+ * After a call to this method, a call to doc_read_page_finish is mandatory,
+ * to end the read cycle of the flash.
+ *
+ * Read data from a flash page. The length to be read must be between 0 and
+ * (page_size + oob_size + wear_size), ie. 532, and a multiple of 4 (because
+ * the extra bytes reading is not implemented).
+ *
+ * As pages are grouped by 2 (in 2 planes), reading from a page must be done
+ * in two steps:
+ *  - one read of 512 bytes at offset 0
+ *  - one read of 512 bytes at offset 512 + 16
+ *
+ * Returns 0 if successful, -EIO if a read error occured.
+ */
+static int doc_read_page_prepare(struct docg3 *docg3, int block0, int block1,
+				 int page, int offset)
+{
+	int wear_area = 0, ret = 0;
+
+	doc_dbg("doc_read_page_prepare(blocks=(%d,%d), page=%d, ofsInPage=%d)\n",
+		block0, block1, page, offset);
+	if (offset >= DOC_LAYOUT_WEAR_OFFSET)
+		wear_area = 1;
+	if (!wear_area && offset > (DOC_LAYOUT_PAGE_OOB_SIZE * 2))
+		return -EINVAL;
+
+	doc_set_device_id(docg3, docg3->device_id);
+	ret = doc_reset_seq(docg3);
+	if (ret)
+		goto err;
+
+	/* Program the flash address block and page */
+	ret = doc_read_seek(docg3, block0, block1, page, wear_area, offset);
+	if (ret)
+		goto err;
+
+	doc_flashCommand(READ_ALL_PLANES);
+	doc_delay(docg3, 2);
+	doc_wait_ready(docg3);
+
+	doc_flashCommand(SET_ADDR_READ);
+	doc_delay(docg3, 1);
+	if (offset >= DOC_LAYOUT_PAGE_SIZE * 2)
+		offset -= 2 * DOC_LAYOUT_PAGE_SIZE;
+	doc_flashAddress(offset >> 2);
+	doc_delay(docg3, 1);
+	doc_wait_ready(docg3);
+
+	doc_flashCommand(READ_FLASH);
+
+	return 0;
+err:
+	doc_writeb(0, DoC_DataEnd);
+	doc_delay(docg3, 2);
+	return -EIO;
+}
+
+/**
+ * doc_read_page_getbytes - Reads bytes from a prepared page
+ * @docg3: the device
+ * @len: the number of bytes to be read (must be a multiple of 4)
+ * @buf: the buffer to be filled in
+ * @first: 1 if first time read, DoC_ReadAddress should be set
+ *
+ */
+static int doc_read_page_getbytes(struct docg3 *docg3, int len, u_char *buf,
+				  int first)
+{
+	doc_read_data_area(docg3, buf, len, first);
+	doc_delay(docg3, 2);
+	return len;
+}
+
+/**
+ * doc_get_hw_bch_syndroms - Get hardware calculated BCH syndroms
+ * @docg3: the device
+ * @syns:  the array of 7 integers where the syndroms will be stored
+ */
+static void doc_get_hw_bch_syndroms(struct docg3 *docg3, int *syns)
+{
+	int i;
+
+	for (i = 0; i < DOC_ECC_BCH_SIZE; i++)
+		syns[i] = doc_register_readb(docg3, DoC_BCH_Syndrom(i));
+}
+
+/**
+ * doc_read_page_finish - Ends reading of a flash page
+ * @docg3: the device
+ *
+ * As a side effect, resets the chip selector to 0. This ensures that after each
+ * read operation, the floor 0 is selected. Therefore, if the systems halts, the
+ * reboot will boot on floor 0, where the IPL is.
+ */
+static void doc_read_page_finish(struct docg3 *docg3)
+{
+	doc_writeb(0, DoC_DataEnd);
+	doc_delay(docg3, 2);
+	doc_set_device_id(docg3, 0);
+}
+
+/**
+ * calc_block_sector - Calculate blocks, pages and ofs.
+
+ * @from: offset in flash
+ * @block0: first plane block index calculated
+ * @block1: second plane block index calculated
+ * @page: page calculated
+ * @ofs: offset in page
+ */
+static void calc_block_sector(loff_t from, int *block0, int *block1, int *page,
+			      int *ofs)
+{
+	uint sector;
+
+	sector = from / DOC_LAYOUT_PAGE_SIZE;
+	*block0 = sector / (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES)
+		* DOC_LAYOUT_NBPLANES;
+	*block1 = *block0 + 1;
+	*page = sector % (DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_NBPLANES);
+	*page /= DOC_LAYOUT_NBPLANES;
+	if (sector % 2)
+		*ofs = DOC_LAYOUT_PAGE_OOB_SIZE;
+	else
+		*ofs = 0;
+}
+
+/**
+ * doc_read - Read bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @len: the number of bytes to read (must be a multiple of 4)
+ * @retlen: the number of bytes actually read
+ * @buf: the filled in buffer
+ *
+ * Reads flash memory pages. This function does not read the OOB chunk, but only
+ * the page data.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
+	     size_t *retlen, u_char *buf)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, readlen, ret, ofs = 0;
+	int syn[DOC_ECC_BCH_SIZE], eccconf1;
+	u8 oob[DOC_LAYOUT_OOB_SIZE];
+
+	ret = -EINVAL;
+	doc_dbg("doc_read(from=%lld, len=%u, buf=%p)\n", from, len, buf);
+	if (from % DOC_LAYOUT_PAGE_SIZE)
+		goto err;
+	if (len % 4)
+		goto err;
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		goto err;
+
+	*retlen = 0;
+	ret = 0;
+	readlen = min(len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+	while (!ret && len > 0) {
+		readlen = min(len, (size_t)DOC_LAYOUT_PAGE_SIZE);
+		ret = doc_read_page_prepare(docg3, block0, block1, page, ofs);
+		if (ret < 0)
+			goto err;
+		ret = doc_read_page_ecc_init(docg3, DOC_ECC_BCH_COVERED_BYTES);
+		if (ret < 0)
+			goto err_in_read;
+		ret = doc_read_page_getbytes(docg3, readlen, buf, 1);
+		if (ret < readlen)
+			goto err_in_read;
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+					     oob, 0);
+		if (ret < DOC_LAYOUT_OOB_SIZE)
+			goto err_in_read;
+
+		*retlen += readlen;
+		buf += readlen;
+		len -= readlen;
+
+		ofs ^= DOC_LAYOUT_PAGE_OOB_SIZE;
+		if (ofs == 0)
+			page += 2;
+		if (page > DOC_ADDR_PAGE_MASK) {
+			page = 0;
+			block0 += 2;
+			block1 += 2;
+		}
+
+		/*
+		 * There should be a BCH bitstream fixing algorithm here ...
+		 * By now, a page read failure is triggered by BCH error
+		 */
+		doc_get_hw_bch_syndroms(docg3, syn);
+		eccconf1 = doc_register_readb(docg3, DoC_EccConf1);
+
+		doc_dbg("OOB - INFO: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 oob[0], oob[1], oob[2], oob[3], oob[4],
+			 oob[5], oob[6]);
+		doc_dbg("OOB - HAMMING: %02x\n", oob[7]);
+		doc_dbg("OOB - BCH_ECC: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			 oob[8], oob[9], oob[10], oob[11], oob[12],
+			 oob[13], oob[14]);
+		doc_dbg("OOB - UNUSED: %02x\n", oob[15]);
+		doc_dbg("ECC checks: ECCConf1=%x\n", eccconf1);
+		doc_dbg("ECC BCH syndrom: %02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
+			syn[0], syn[1], syn[2], syn[3], syn[4], syn[5], syn[6]);
+
+		ret = -EBADMSG;
+		if (block0 >= DOC_LAYOUT_BLOCK_FIRST_DATA) {
+			if (eccconf1 & Doc_ECCConf1_BCH_SYNDROM_ERR)
+				goto err_in_read;
+			if (is_prot_seq_error(docg3))
+				goto err_in_read;
+		}
+		doc_read_page_finish(docg3);
+	}
+
+	return 0;
+err_in_read:
+	doc_read_page_finish(docg3);
+err:
+	return ret;
+}
+
+/**
+ * doc_read_oob - Read out of band bytes from flash
+ * @mtd: the device
+ * @from: the offset from first block and first page, in bytes, aligned on page
+ *        size
+ * @ops: the mtd oob structure
+ *
+ * Reads flash memory OOB area of pages.
+ *
+ * Returns 0 if read successfull, of -EIO, -EINVAL if an error occured
+ */
+static int doc_read_oob(struct mtd_info *mtd, loff_t from,
+			struct mtd_oob_ops *ops)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, ofs, ret;
+	u8 *buf = ops->oobbuf;
+	size_t len = ops->ooblen;
+
+	doc_dbg("doc_read_oob(from=%lld, buf=%p, len=%d)\n", from, buf, len);
+	if (len != DOC_LAYOUT_OOB_SIZE)
+		return -EINVAL;
+
+	switch (ops->mode) {
+	case MTD_OOB_PLACE:
+		buf += ops->ooboffs;
+		break;
+	default:
+		break;
+	}
+
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	ret = doc_read_page_prepare(docg3, block0, block1, page,
+				    ofs + DOC_LAYOUT_PAGE_SIZE);
+	if (!ret)
+		ret = doc_read_page_ecc_init(docg3, DOC_LAYOUT_OOB_SIZE);
+	if (!ret)
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_OOB_SIZE,
+					     buf, 1);
+	doc_read_page_finish(docg3);
+
+	if (ret > 0)
+		ops->oobretlen = ret;
+	else
+		ops->oobretlen = 0;
+	return (ret > 0) ? 0 : ret;
+}
+
+static int doc_reload_bbt(struct docg3 *docg3)
+{
+	int block = DOC_LAYOUT_BLOCK_BBT;
+	int ret = 0, nbpages, page;
+	u_char *buf = docg3->bbt;
+
+	nbpages = DIV_ROUND_UP(docg3->max_block + 1, 8 * DOC_LAYOUT_PAGE_SIZE);
+	for (page = 0; !ret && (page < nbpages); page++) {
+		ret = doc_read_page_prepare(docg3, block, block + 1,
+					    page + DOC_LAYOUT_PAGE_BBT, 0);
+		if (!ret)
+			ret = doc_read_page_ecc_init(docg3,
+						     DOC_LAYOUT_PAGE_SIZE);
+		if (!ret)
+			doc_read_page_getbytes(docg3, DOC_LAYOUT_PAGE_SIZE,
+					       buf, 1);
+		buf += DOC_LAYOUT_PAGE_SIZE;
+	}
+	doc_read_page_finish(docg3);
+	return ret;
+}
+
+/**
+ * doc_block_isbad - Checks whether a block is good or not
+ * @mtd: the device
+ * @from: the offset to find the correct block
+ *
+ * Returns 1 if block is bad, 0 if block is good
+ */
+static int doc_block_isbad(struct mtd_info *mtd, loff_t from)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int block0, block1, page, ofs, is_good;
+
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	doc_dbg("doc_block_isbad(from=%lld) => block=(%d,%d), page=%d, ofs=%d\n",
+		from, block0, block1, page, ofs);
+
+	if (block0 < DOC_LAYOUT_BLOCK_FIRST_DATA)
+		return 0;
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	is_good = docg3->bbt[block0 >> 3] & (1 << (block0 & 0x7));
+	return !is_good;
+}
+
+/**
+ * doc_get_erase_count - Get block erase count
+ * @docg3: the device
+ * @from: the offset in which the block is.
+ *
+ * Get the number of times a block was erased. The number is the maximum of
+ * erase times between first and second plane (which should be equal normally).
+ *
+ * Returns The number of erases, or -EINVAL or -EIO on error.
+ */
+int doc_get_erase_count(struct docg3 *docg3, loff_t from)
+{
+	u8 buf[DOC_LAYOUT_WEAR_SIZE];
+	int ret, plane1_erase_count, plane2_erase_count;
+	int block0, block1, page, ofs;
+
+	doc_dbg("doc_get_erase_count(from=%lld, buf=%p)\n", from, buf);
+	if (from % DOC_LAYOUT_PAGE_SIZE)
+		return -EINVAL;
+	calc_block_sector(from, &block0, &block1, &page, &ofs);
+	if (block1 > docg3->max_block)
+		return -EINVAL;
+
+	ret = doc_reset_seq(docg3);
+	if (!ret)
+		ret = doc_read_page_prepare(docg3, block0, block1, page,
+					    ofs + DOC_LAYOUT_WEAR_OFFSET);
+	if (!ret)
+		ret = doc_read_page_getbytes(docg3, DOC_LAYOUT_WEAR_SIZE,
+					     buf, 1);
+	doc_read_page_finish(docg3);
+
+	if (ret || (buf[0] != DOC_ERASE_MARK) || (buf[2] != DOC_ERASE_MARK))
+		return -EIO;
+	plane1_erase_count = (u8)(~buf[1]) | ((u8)(~buf[4]) << 8)
+		| ((u8)(~buf[5]) << 16);
+	plane2_erase_count = (u8)(~buf[3]) | ((u8)(~buf[6]) << 8)
+		| ((u8)(~buf[7]) << 16);
+
+	return max(plane1_erase_count, plane2_erase_count);
+}
+
+/*
+ * Debug sysfs entries
+ */
+#ifdef DEBUG
+static ssize_t dbg_flashctrl_read(struct device *dev,
+				      struct device_attribute *attr,
+				      char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+
+	int pos = 0;
+	u8 fctrl = doc_register_readb(docg3, DoC_FlashControl);
+
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos,
+		 "FlashControl : 0x%02x (%s,CE# %s,%s,%s,flash %s)\n",
+		 fctrl,
+		 fctrl & Doc_Ctrl_Violation ? "protocol violation" : "-",
+		 fctrl & Doc_Ctrl_CE ? "active" : "inactive",
+		 fctrl & Doc_Ctrl_PROTECTION_ERROR ? "protection error" : "-",
+		 fctrl & Doc_Ctrl_SEQUENCE_ERROR ? "sequence error" : "-",
+		 fctrl & Doc_Ctrl_FLASHREADY ? "ready" : "not ready");
+	return pos;
+}
+static ssize_t dbg_flashctrl_write(struct device *dev,
+				   struct device_attribute *attr,
+				   const char *buf, size_t count)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+	int i, val;
+
+	i = sscanf(buf, "0x%x", &val);
+	if (i == 0)
+		i = sscanf(buf, "%x", &val);
+	if (i == 0)
+		return -EINVAL;
+	doc_writeb(val, DoC_FlashControl);
+	return count;
+}
+DEVICE_ATTR(flashcontrol, S_IRWXU, dbg_flashctrl_read, dbg_flashctrl_write);
+
+static ssize_t dbg_reset(struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+
+	doc_reset_seq(docg3);
+	return count;
+}
+DEVICE_ATTR(reset, S_IWUSR, NULL, dbg_reset);
+
+static ssize_t dbg_asicmode_read(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+
+	int pos = 0;
+	int pctrl = doc_register_readb(docg3, DoC_AsicMode);
+	int mode = pctrl & 0x03;
+
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos,
+			 "%04x : RAM_WE=%d,RSTIN_RESET=%d,BDETCT_RESET=%d,WRITE_ENABLE=%d,POWERDOWN=%d,MODE=%d%d (",
+			 pctrl,
+			 pctrl & Doc_AsicMode_RAM_WE ? 1 : 0,
+			 pctrl & Doc_AsicMode_RSTIN_RESET ? 1 : 0,
+			 pctrl & Doc_AsicMode_BDETCT_RESET ? 1 : 0,
+			 pctrl & Doc_AsicMode_MDWREN ? 1 : 0,
+			 pctrl & Doc_AsicMode_POWERDOWN ? 1 : 0,
+			 mode >> 1, mode & 0x1);
+
+	switch (mode) {
+	case Doc_AsicMode_RESET:
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "reset");
+		break;
+	case Doc_AsicMode_NORMAL:
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "normal");
+		break;
+	case Doc_AsicMode_POWERDOWN:
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "powerdown");
+		break;
+	}
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos, ")\n");
+	return pos;
+}
+static ssize_t dbg_asicmode_write(struct device *dev,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+	int i, val;
+
+	i = sscanf(buf, "0x%x", &val);
+	if (i == 1)
+		doc_set_asic_mode(docg3, val);
+	i = sscanf(buf, "%x", &val);
+	if (i == 1)
+		doc_set_asic_mode(docg3, val);
+
+	return count;
+}
+DEVICE_ATTR(asic_mode, S_IRWXU, dbg_asicmode_read, dbg_asicmode_write);
+
+static ssize_t dbg_deviceid_read(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+	int pos = 0;
+	int id = doc_register_readb(docg3, DoC_DeviceSelect);
+
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos, "DeviceId = %d\n", id);
+	return pos;
+}
+DEVICE_ATTR(device_id, S_IRUGO, dbg_deviceid_read, NULL);
+
+static ssize_t dbg_protection_read(struct device *dev,
+				 struct device_attribute *attr,
+				 char *buf)
+{
+	struct mtd_info *mtd = dev_get_drvdata(dev);
+	struct docg3 *docg3 = mtd->priv;
+	int pos = 0;
+	int protect = doc_register_readb(docg3, DoC_Protection);
+	int dps0 = doc_register_readb(docg3, DoC_DPS0_Status);
+	int dps0_low = doc_register_readb(docg3, DoC_DPS0_AddrLow);
+	int dps0_high = doc_register_readb(docg3, DoC_DPS0_AddrHigh);
+	int dps1 = doc_register_readb(docg3, DoC_DPS1_Status);
+	int dps1_low = doc_register_readb(docg3, DoC_DPS1_AddrLow);
+	int dps1_high = doc_register_readb(docg3, DoC_DPS1_AddrHigh);
+
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos, "Protection = 0x%02x (",
+			 protect);
+	if (protect & Doc_Protect_FOUNDRY_OTP_LOCK)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "FOUNDRY_OTP_LOCK,");
+	if (protect & Doc_Protect_CUSTOMER_OTP_LOCK)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "CUSTOMER_OTP_LOCK,");
+	if (protect & Doc_Protect_LOCK_INPUT)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "LOCK_INPUT,");
+	if (protect & Doc_Protect_STICKY_LOCK)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "STICKY_LOCK,");
+	if (protect & Doc_Protect_PROTECTION_ENABLED)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "PROTECTION ON,");
+	if (protect & Doc_Protect_IPL_DOWNLOAD_LOCK)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "IPL_DOWNLOAD_LOCK,");
+	if (protect & Doc_Protect_PROTECTION_ERROR)
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "PROTECT_ERR,");
+	else
+		pos += scnprintf(buf + pos, PAGE_SIZE - pos, "NO_PROTECT_ERR");
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos, ")\n");
+
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos, "DPS0 = 0x%02x : "
+			 "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+			 "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+			 dps0, dps0_low, dps0_high,
+			 !!(dps0 & Doc_DPS_OTP_PROTECTED),
+			 !!(dps0 & Doc_DPS_READ_PROTECTED),
+			 !!(dps0 & Doc_DPS_WRITE_PROTECTED),
+			 !!(dps0 & Doc_DPS_HW_LOCK_ENABLED),
+			 !!(dps0 & Doc_DPS_KEY_OK));
+	pos += scnprintf(buf + pos, PAGE_SIZE - pos, "DPS1 = 0x%02x : "
+			 "Protected area [0x%x - 0x%x] : OTP=%d, READ=%d, "
+			 "WRITE=%d, HW_LOCK=%d, KEY_OK=%d\n",
+			 dps1, dps1_low, dps1_high,
+			 !!(dps1 & Doc_DPS_OTP_PROTECTED),
+			 !!(dps1 & Doc_DPS_READ_PROTECTED),
+			 !!(dps1 & Doc_DPS_WRITE_PROTECTED),
+			 !!(dps1 & Doc_DPS_HW_LOCK_ENABLED),
+			 !!(dps1 & Doc_DPS_KEY_OK));
+	return pos;
+}
+DEVICE_ATTR(protection, S_IRUGO, dbg_protection_read, NULL);
+
+static int __init doc_dbg_register(struct device *dev)
+{
+	int ret = 0;
+
+	ret = device_create_file(dev, &dev_attr_flashcontrol);
+	if (!ret)
+		ret = device_create_file(dev, &dev_attr_reset);
+	if (!ret)
+		ret = device_create_file(dev, &dev_attr_asic_mode);
+	if (!ret)
+		ret = device_create_file(dev, &dev_attr_device_id);
+	if (!ret)
+		ret = device_create_file(dev, &dev_attr_protection);
+	return ret;
+}
+
+static void __exit doc_dbg_unregister(struct device *dev)
+{
+	device_remove_file(dev, &dev_attr_protection);
+	device_remove_file(dev, &dev_attr_device_id);
+	device_remove_file(dev, &dev_attr_asic_mode);
+	device_remove_file(dev, &dev_attr_reset);
+	device_remove_file(dev, &dev_attr_flashcontrol);
+}
+#else
+static int __init doc_dbg_register(struct device *dev) {}
+static void __exit doc_dbg_unregister(struct device *dev) {}
+#endif
+
+/**
+ * doc_set_driver_info - Fill the mtd_info structure and docg3 structure
+ * @chip_id: The chip ID of the supported chip
+ * @mtd: The structure to fill
+ */
+static void __init doc_set_driver_info(int chip_id, struct mtd_info *mtd)
+{
+	struct docg3 *docg3 = mtd->priv;
+	int cfg;
+
+	cfg = doc_register_readb(docg3, DoC_Configuration);
+	docg3->if_cfg = (cfg & Doc_Conf_IF_CFG ? 1 : 0);
+
+	switch (chip_id) {
+	case DOC_CHIPID_G3:
+		mtd->name = "DiskOnChip G3";
+		docg3->max_block = 2047;
+		break;
+	}
+	mtd->type = MTD_NANDFLASH;
+	/*
+	 * Once write methods are added, the correct flags will be set.
+	 * mtd->flags = MTD_CAP_NANDFLASH;
+	 */
+	mtd->flags = MTD_CAP_ROM;
+	mtd->size = (docg3->max_block + 1) * DOC_LAYOUT_BLOCK_SIZE;
+	mtd->erasesize = DOC_LAYOUT_BLOCK_SIZE * DOC_LAYOUT_NBPLANES;
+	mtd->writesize = DOC_LAYOUT_PAGE_SIZE;
+	mtd->oobsize = DOC_LAYOUT_OOB_SIZE;
+	mtd->owner = THIS_MODULE;
+	mtd->erase = NULL;
+	mtd->point = NULL;
+	mtd->unpoint = NULL;
+	mtd->read = doc_read;
+	mtd->write = NULL;
+	mtd->read_oob = doc_read_oob;
+	mtd->write_oob = NULL;
+	mtd->sync = NULL;
+	mtd->block_isbad = doc_block_isbad;
+}
+
+/**
+ * doc_probe - Probe the IO space for a DiskOnChip G3 chip
+ * @pdev: platform device
+ *
+ * Probes for a G3 chip at the specified IO space in the platform data
+ * ressources.
+ *
+ * Returns 0 on success, -ENOMEM, -ENXIO on error
+ */
+static int __init docg3_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct docg3 *docg3;
+	struct mtd_info *mtd;
+	struct resource *ress;
+	struct mtd_partition *parts = NULL;
+	int ret, bbt_nbpages;
+	u16 chip_id, chip_id_inv;
+
+	ret = -ENOMEM;
+	docg3 = kzalloc(sizeof(struct docg3), GFP_KERNEL);
+	if (!docg3)
+		goto nomem1;
+	mtd = kzalloc(sizeof(struct mtd_info), GFP_KERNEL);
+	if (!mtd)
+		goto nomem2;
+	mtd->priv = docg3;
+
+	ret = -ENXIO;
+	ress = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ress) {
+		dev_err(dev, "No I/O memory resource defined\n");
+		goto noress;
+	}
+	docg3->base = ioremap(ress->start, DOC_IOSPACE_SIZE);
+
+	docg3->dev = &pdev->dev;
+	docg3->device_id = 0;
+	doc_set_device_id(docg3, docg3->device_id);
+	doc_set_asic_mode(docg3, Doc_AsicMode_RESET);
+	doc_set_asic_mode(docg3, Doc_AsicMode_NORMAL);
+
+	chip_id = doc_register_readw(docg3, DoC_ChipID);
+	chip_id_inv = doc_register_readw(docg3, DoC_ChipID_Inv);
+
+	ret = -ENODEV;
+	if (chip_id != (u16)(~chip_id_inv)) {
+		doc_info("No device found at IO addr %x\n", ress->start);
+		goto nochipfound;
+	}
+
+	switch (chip_id) {
+	case DOC_CHIPID_G3:
+		doc_info("Found a G3 DiskOnChip at addr %x\n", ress->start);
+		break;
+	default:
+		doc_err("Chip id %04x is not a DiskOnChip G3 chip\n", chip_id);
+		goto nochipfound;
+	}
+
+	doc_set_driver_info(chip_id, mtd);
+	platform_set_drvdata(pdev, mtd);
+
+	bbt_nbpages = (docg3->max_block + 1) / 8;
+	docg3->bbt = kzalloc(bbt_nbpages * DOC_LAYOUT_PAGE_SIZE, GFP_KERNEL);
+	if (!docg3->bbt)
+		goto nochipfound;
+	doc_reload_bbt(docg3);
+
+	ret = mtd_device_register(mtd, NULL, 0);
+	if (!ret)
+		ret = parse_mtd_partitions(mtd, part_probes, &parts, 0);
+	if (ret > 0)
+		ret = mtd_device_register(mtd, parts, ret);
+
+	doc_dbg_register(docg3->dev);
+	return 0;
+
+nochipfound:
+	iounmap(docg3->base);
+noress:
+	kfree(mtd);
+nomem2:
+	kfree(docg3);
+nomem1:
+	return ret;
+}
+
+/**
+ * docg3_release - Release the driver
+ * @pdev: the platform device
+ *
+ * Returns 0
+ */
+static int __exit docg3_release(struct platform_device *pdev)
+{
+	struct mtd_info *mtd = platform_get_drvdata(pdev);
+	struct docg3 *docg3 = mtd->priv;
+
+	doc_dbg_unregister(docg3->dev);
+	mtd_device_unregister(mtd);
+	iounmap(docg3->base);
+	kfree(docg3->bbt);
+	kfree(docg3);
+	kfree(mtd);
+	return 0;
+}
+
+static struct platform_driver g3_driver = {
+	.driver		= {
+		.name	= "docg3",
+		.owner	= THIS_MODULE,
+	},
+	.remove		= __exit_p(docg3_release),
+};
+
+static int __init docg3_init(void)
+{
+	return platform_driver_probe(&g3_driver, docg3_probe);
+}
+module_init(docg3_init);
+
+
+static void __exit docg3_exit(void)
+{
+	platform_driver_unregister(&g3_driver);
+}
+module_exit(docg3_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Robert Jarzmik <robert.jarzmik at free.fr>");
+MODULE_DESCRIPTION("MTD driver for DiskOnChip G3");
diff --git a/drivers/mtd/devices/docg3.h b/drivers/mtd/devices/docg3.h
new file mode 100644
index 0000000..355ac57
--- /dev/null
+++ b/drivers/mtd/devices/docg3.h
@@ -0,0 +1,224 @@
+#include <linux/mtd/nand_bch.h>
+
+/*
+ * Flash memory areas :
+ *   - 0x0000 .. 0x07ff : IPL
+ *   - 0x0800 .. 0x0fff : Data area
+ *   - 0x1000 .. 0x17ff : Registers
+ *   - 0x1800 .. 0x1fff : Unknown
+ */
+#define DOC_IOSPACE_IPL			0x0000
+#define DOC_IOSPACE_DATA		0x0800
+#define DOC_IOSPACE_SIZE		0x2000
+
+/*
+ * DOC G3 layout and adressing scheme
+ *   A page address for the block "b", plane "P" and page "p":
+ *   address = [bbbb bPpp pppp]
+ */
+
+#define DOC_ADDR_PAGE_MASK		0x3f
+#define DOC_ADDR_BLOCK_SHIFT		6
+#define DOC_LAYOUT_NBPLANES		2
+#define DOC_LAYOUT_PAGES_PER_BLOCK	64
+#define DOC_LAYOUT_PAGE_SIZE		512
+#define DOC_LAYOUT_OOB_SIZE		16
+#define DOC_LAYOUT_WEAR_SIZE		8
+#define DOC_LAYOUT_PAGE_OOB_SIZE				\
+	(DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_SIZE)
+#define DOC_LAYOUT_WEAR_OFFSET		(DOC_LAYOUT_PAGE_OOB_SIZE * 2)
+#define DOC_LAYOUT_BLOCK_SIZE					\
+	(DOC_LAYOUT_PAGES_PER_BLOCK * DOC_LAYOUT_PAGE_SIZE)
+#define DOC_ECC_BCH_SIZE		7
+#define DOC_ECC_BCH_COVERED_BYTES				\
+	(DOC_LAYOUT_PAGE_SIZE + DOC_LAYOUT_OOB_PAGEINFO_SZ +	\
+	 DOC_LAYOUT_OOB_HAMMING_SZ + DOC_LAYOUT_OOB_BCH_SZ)
+
+/*
+ * Blocks distribution
+ */
+#define DOC_LAYOUT_BLOCK_BBT		0
+#define DOC_LAYOUT_BLOCK_OTP		0
+#define DOC_LAYOUT_BLOCK_FIRST_DATA	6
+
+#define DOC_LAYOUT_PAGE_BBT		4
+
+/*
+ * Extra page OOB (16 bytes wide) layout
+ */
+#define DOC_LAYOUT_OOB_PAGEINFO_OFS	0
+#define DOC_LAYOUT_OOB_HAMMING_OFS	7
+#define DOC_LAYOUT_OOB_BCH_OFS		8
+#define DOC_LAYOUT_OOB_UNUSED_OFS	15
+#define DOC_LAYOUT_OOB_PAGEINFO_SZ	7
+#define DOC_LAYOUT_OOB_HAMMING_SZ	1
+#define DOC_LAYOUT_OOB_BCH_SZ		7
+#define DOC_LAYOUT_OOB_UNUSED_SZ	1
+
+
+#define DOC_CHIPID_G3			0x200
+#define DOC_ERASE_MARK			0xaa
+/*
+ * Flash registers
+ */
+#define DoC_ChipID			0x1000
+#define DoC_Test			0x1004
+#define DoC_BusLock			0x1006
+#define DoC_EndianControl		0x1008
+#define DoC_DeviceSelect		0x100a
+#define DoC_AsicMode			0x100c
+#define DoC_Configuration		0x100e
+#define DoC_InterruptControl		0x1010
+#define DoC_ReadAddress			0x101a
+#define DoC_DataEnd			0x101e
+#define DoC_InterruptStatus		0x1020
+
+#define DoC_FlashSequence		0x1032
+#define DoC_FlashCommand		0x1034
+#define DoC_FlashAddress		0x1036
+#define DoC_FlashControl		0x1038
+#define DoC_NOP				0x103e
+
+#define DoC_EccConf0			0x1040
+#define DoC_EccConf1			0x1042
+#define DoC_EccPreset			0x1044
+#define DoC_HammingParity		0x1046
+#define DoC_BCH_Syndrom(idx)		(0x1048 + (idx << 1))
+
+#define DoC_Protection			0x1056
+#define DoC_DPS0_AddrLow		0x1060
+#define DoC_DPS0_AddrHigh		0x1062
+#define DoC_DPS1_AddrLow		0x1064
+#define DoC_DPS1_AddrHigh		0x1066
+#define DoC_DPS0_Status			0x106c
+#define DoC_DPS1_Status			0x106e
+
+#define DoC_AsicModeConfirm		0x1072
+#define DoC_ChipID_Inv			0x1074
+
+/*
+ * Flash sequences
+ * A sequence is preset before one or more commands are input to the chip.
+ */
+#define DoC_Seq_RESET			0x00
+#define DoC_Seq_PAGE_SIZE_532		0x03
+#define DoC_Seq_SET_MODE		0x09
+#define DoC_Seq_READ			0x12
+#define DoC_Seq_SET_PLANE1		0x0e
+#define DoC_Seq_SET_PLANE2		0x10
+#define DoC_Seq_PAGE_SETUP		0x1d
+
+/*
+ * Flash commands
+ */
+#define DoC_Cmd_READ_PLANE1		0x00
+#define DoC_Cmd_SET_ADDR_READ		0x05
+#define DoC_Cmd_READ_ALL_PLANES		0x30
+#define DoC_Cmd_READ_PLANE2		0x50
+#define DoC_Cmd_READ_FLASH		0xe0
+#define DoC_Cmd_PAGE_SIZE_532		0x3c
+
+#define DoC_Cmd_PROG_BLOCK_ADDR		0x60
+#define DoC_Cmd_PROG_CYCLE1		0x80
+#define DoC_Cmd_PROG_CYCLE2		0x10
+#define DoC_Cmd_ERASECYCLE2		0xd0
+
+#define DoC_Cmd_RELIABLE_MODE		0x22
+#define DoC_Cmd_FAST_MODE		0xa2
+
+#define DoC_Cmd_RESET			0xff
+
+/*
+ * Flash register : DoC_FlashControl
+ */
+#define Doc_Ctrl_Violation		0x20
+#define Doc_Ctrl_CE			0x10
+#define Doc_Ctrl_UNKNOWN_BITS		0x08
+#define Doc_Ctrl_PROTECTION_ERROR	0x04
+#define Doc_Ctrl_SEQUENCE_ERROR		0x02
+#define Doc_Ctrl_FLASHREADY		0x01
+
+/*
+ * Flash register : DoC_AsicMode
+ */
+#define Doc_AsicMode_RESET		0x00
+#define Doc_AsicMode_NORMAL		0x01
+#define Doc_AsicMode_POWERDOWN		0x02
+#define Doc_AsicMode_MDWREN		0x04
+#define Doc_AsicMode_BDETCT_RESET	0x08
+#define Doc_AsicMode_RSTIN_RESET	0x10
+#define Doc_AsicMode_RAM_WE		0x20
+
+/*
+ * Flash register : DoC_EccConf0
+ */
+#define Doc_ECCConf0_READ_MODE		0x8000
+#define Doc_ECCConf0_AUTO_ECC_ENABLE	0x4000
+#define Doc_ECCConf0_HAMMING_ENABLE	0x1000
+#define Doc_ECCConf0_BCH_ENABLE		0x0800
+#define Doc_ECCConf0_DATA_BYTES_MASK	0x07ff
+
+/*
+ * Flash register : DoC_EccConf1
+ */
+#define Doc_ECCConf1_BCH_SYNDROM_ERR	0x80
+#define Doc_ECCConf1_UNKOWN1		0x40
+#define Doc_ECCConf1_UNKOWN2		0x20
+#define Doc_ECCConf1_UNKOWN3		0x10
+#define Doc_ECCConf1_HAMMING_BITS_MASK	0x0f
+
+/*
+ * Flash register : DoC_Protection
+ */
+#define Doc_Protect_FOUNDRY_OTP_LOCK	0x01
+#define Doc_Protect_CUSTOMER_OTP_LOCK	0x02
+#define Doc_Protect_LOCK_INPUT		0x04
+#define Doc_Protect_STICKY_LOCK		0x08
+#define Doc_Protect_PROTECTION_ENABLED	0x10
+#define Doc_Protect_IPL_DOWNLOAD_LOCK	0x20
+#define Doc_Protect_PROTECTION_ERROR	0x80
+
+/*
+ * Flash register : DoC_DPS0_Status and DoC_DPS1_Status
+ */
+#define Doc_DPS_OTP_PROTECTED		0x01
+#define Doc_DPS_READ_PROTECTED		0x02
+#define Doc_DPS_WRITE_PROTECTED		0x04
+#define Doc_DPS_HW_LOCK_ENABLED		0x08
+#define Doc_DPS_KEY_OK			0x80
+
+/*
+ * Flash register : DoC_Configuration
+ */
+#define Doc_Conf_IF_CFG			0x80
+#define Doc_Conf_MAX_ID_MASK		0x30
+#define Doc_Conf_VCCQ_3V		0x01
+
+/*
+ * Flash register : DoC_ReadAddress
+ */
+#define Doc_ReadAddr_INC		0x8000
+#define Doc_ReadAddr_ONE_BYTE		0x4000
+#define Doc_ReadAddr_ADDR_MASK		0x1fff
+
+/**
+ * struct docg3 - DiskOnChip driver private data
+ * @dev: the device currently under control
+ * @base: mapped IO space
+ * @device_id: number of the cascaded DoCG3 device (0, 1, 2 or 3)
+ * @if_cfg: if true, reads are on 16bits, else reads are on 8bits
+ * @bbt: bad block table cache
+ */
+struct docg3 {
+	struct device *dev;
+	void __iomem *base;
+	int device_id:4;
+	int if_cfg:1;
+	int max_block;
+	u8 *bbt;
+};
+
+#define doc_err(fmt, arg...) dev_err(docg3->dev, (fmt), ## arg)
+#define doc_info(fmt, arg...) dev_info(docg3->dev, (fmt), ## arg)
+#define doc_dbg(fmt, arg...) dev_dbg(docg3->dev, (fmt), ## arg)
+#define doc_vdbg(fmt, arg...) dev_vdbg(docg3->dev, (fmt), ## arg)
-- 
1.7.4.4



From gilles.ganault at free.fr  Sun Jun 19 06:37:13 2011
From: gilles.ganault at free.fr (Gilles)
Date: Sun, 19 Jun 2011 12:37:13 +0200
Subject: "warning!: only 995 of 1984 eraseblocks have valid erase counter"
Message-ID: <o4krv69m77vomji84cs3flljf6obpgfgcs@4ax.com>

Hello

	After "make" built rootfs.ubifs, I ran ubinize before uploading the
file to a web server.

I then downloaded that file on a uClinux appliance, and ran the
following command to format /dev/mtd2 with the image:
=========
ubiformat /dev/mtd2 -s 512 -f rootfs.ubi.img
=========

This command triggers the following warning:
=========
...
libscan: scanning eraseblock 1982 -- 99 % complete  MTD_ioctl
MTD_read
libscan: scanning eraseblock 1983 -- 100 % complete  MTD_ioctl
MTD_read

ubiformat: 995 eraseblocks have valid erase counter, mean value is 14
ubiformat: 989 eraseblocks are supposedly empty
ubiformat: warning!: only 995 of 1984 eraseblocks have valid erase
counter
ubiformat: mean erase counter 14 will be used for the rest of
eraseblock
ubiformat: continue? (yes/no)
=========

Running just "ubiformat /dev/mtd2 -s 512" triggers the same warning.

I don't know what the warning really means, and what the consequences
are when answering "yes". Could someone tell me?

Thank you.



From gilles.ganault at free.fr  Sun Jun 19 11:39:27 2011
From: gilles.ganault at free.fr (Gilles)
Date: Sun, 19 Jun 2011 17:39:27 +0200
Subject: Claiming back space from NAND?
Message-ID: <lv5sv610ivu2a8de8nmdl652jsvv5p1s0r@4ax.com>

Hello,

	After booting up a new kernel with the root filesystem on the second
partition in the NAND, I notice that the 248MiB partition is down to
only 225MiB.

I understand that Ubifs uses some space for journaling, but does it
really need that much space? Is it possible to reclaim some space?

Here's some information:
============= dmesg
Found mtd parition at 0x0020a000, (len=0x800000), moving to 0x03700000
...
uclinux[mtd]: RAM probe address=0x3700000 size=0x800000
Creating 1 MTD partitions on "RAM":
0x000000000000-0x000000800000 : "ROMfs"
mtd: Giving out device 0 to ROMfs
Generic platform RAM MTD, (c) 2004 Simtec Electronics
NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB
3,3V 8-bit)
Scanning device for bad blocks
INFO: RCU detected CPU 0 stall (t=2500 jiffies)
cmdlinepart partition parsing not available
RedBoot partition parsing not available
Creating 2 MTD partitions on "My_great_flash_memory":
0x000000000000-0x000000800000 : "kernel_nand"
mtd: Giving out device 1 to kernel_nand
0x000000800000-0x000010000000 : "filesystem_nand"
mtd: Giving out device 2 to filesystem_nand
UBI: attaching mtd2 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: attached mtd2 to ubi0
UBI: MTD device name:            "filesystem_nand"
UBI: MTD device size:            248 MiB
UBI: number of good PEBs:        1984
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:     1
UBI: available PEBs:             0
UBI: total number of reserved PEBs: 1984
UBI: number of PEBs reserved for bad PEB handling: 19
UBI: max/mean erase counter: 19/14
UBI: image sequence number: 393609284
mtd: Giving out device 3 to rootfs
============= /proc/mtd
dev:    size   erasesize  name
mtd0: 00800000 00001000 "ROMfs"
mtd1: 00800000 00020000 "kernel_nand"
mtd2: 0f800000 00020000 "filesystem_nand"
mtd3: 0f14b800 0001f800 "rootfs"
============= df -h
Filesystem                Size      Used Available Use% Mounted on
ubi0:rootfs             225.0M      3.2M    221.8M   1% /
=============

Thank you.



From fggs at terra.com.br  Sun Jun 19 23:12:14 2011
From: fggs at terra.com.br (=?iso-8859-1?Q?Fl=E1vio_Silveira?=)
Date: Mon, 20 Jun 2011 00:12:14 -0300
Subject: [Help] SST39VF6401B Support
In-Reply-To: <DEF16A5C46894A5DB447E0F7C81A9D5F@THOR>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com><AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com><AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com><201010221950.57594.fabio.giovagnini@aurion-tech.com>
	<DEF16A5C46894A5DB447E0F7C81A9D5F@THOR>
Message-ID: <F8730DE65A2E4EB3BC47D4C2DC317502@THOR>

Hi,

  I'm attaching some other files to see if it helps finding what's wrong.

  Thanks in advance!

----- Original Message ----- 
From: "Fl?vio Silveira" <fggs at terra.com.br>
To: "Fabio Giovagnini" <fabio.giovagnini at aurion-tech.com>; 
<linux-mtd at lists.infradead.org>
Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>; 
"Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>; 
"Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
Sent: Wednesday, June 15, 2011 9:55 PM
Subject: Re: [Help] SST39VF6401B Support


Hi guys,

  I've tested this patch on kernel 2.6.23 (actually it's called 2.6.24.111)
and didn't work.

  Below are my diffs and I can post original files as well, please help me
make it work!

Thanks in advance!

cfi_util.c

29a30,107
> int __xipram cfi_qry_present(struct map_info *map, __u32 base,
>         struct cfi_private *cfi)
> {
>  int osf = cfi->interleave * cfi->device_type; /* scale factor */
>  map_word val[3];
>  map_word qry[3];
>
>  qry[0] = cfi_build_cmd('Q', map, cfi);
>  qry[1] = cfi_build_cmd('R', map, cfi);
>  qry[2] = cfi_build_cmd('Y', map, cfi);
>
>  val[0] = map_read(map, base + osf*0x10);
>  val[1] = map_read(map, base + osf*0x11);
>  val[2] = map_read(map, base + osf*0x12);
>
>  if (!map_word_equal(map, qry[0], val[0]))
>   return 0;
>
>  if (!map_word_equal(map, qry[1], val[1]))
>   return 0;
>
>  if (!map_word_equal(map, qry[2], val[2]))
>   return 0;
>
>  return 1;  /* "QRY" found */
> }
> EXPORT_SYMBOL_GPL(cfi_qry_present);
>
> int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
>         struct cfi_private *cfi)
> {
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* QRY not found probably we deal with some odd CFI chips */
>  /* Some revisions of some old Intel chips? */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* ST M29DW chips */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* some old SST chips, e.g. 39VF160x/39VF320x */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* SST 39VF640xB */
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>  if (cfi_qry_present(map, base, cfi))
>   return 1;
>  /* QRY not found */
>  return 0;
> }
> EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
>
> void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
>           struct cfi_private *cfi)
> {
>  cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>  cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>  /* M29W128G flashes require an additional reset command
>     when exit qry mode */
>  if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
>   cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
> }
> EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
>

cfi_cmdset_0002.c

219a220,253
> static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
> {
>    struct map_info *map = mtd->priv;
>    struct cfi_private *cfi = map->fldrv_priv;
>
>    /*
>     * These flashes report two seperate eraseblock regions based on the
>     * sector_erase-size and block_erase-size, although they both operate 
> on the
>     * same memory. This is not allowed according to CFI, so we just pick 
> the
>     * sector_erase-size.
>     */
>    cfi->cfiq->NumEraseRegions = 1;
> }
>
> static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
> {
>    struct map_info *map = mtd->priv;
>    struct cfi_private *cfi = map->fldrv_priv;
>
>    fixup_old_sst_eraseregion(mtd);
>
>    cfi->addr_unlock1 = 0x555;
>    cfi->addr_unlock2 = 0x2AA;
> }
>
> /* Used to fix CFI-Tables of chips without Extended Query Tables */
> static struct cfi_fixup cfi_nopri_fixup_table[] = {
>    { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B
>    { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B
>    { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B
>    { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
>    { 0, 0, NULL, NULL }
> };
>


----- Original Message ----- 
From: "Fabio Giovagnini" <fabio.giovagnini at aurion-tech.com>
To: <linux-mtd at lists.infradead.org>
Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>;
"Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>;
"Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
Sent: Friday, October 22, 2010 2:50 PM
Subject: Re: [Help] SST39VF6401B Support


Hi Guys,
As Gullelm remeber for sure, I used the jedec probe for such a flash in a
very
old 2.6 kernel.

Now I'm migrating to the newets one kernel.
Do you tell me how the kernel will be updated with the last mtd stuff
developed; or in place of it how to patch a standard kernel?

Thanks a  lot and sorry for my question if it is improper


In data venerd? 22 ottobre 2010 17:42:39, yidong zhang ha scritto:
: > On Fri, Oct 22, 2010 at 11:36 PM, Guillaume LECERF <glecerf at gmail.com>
wrote:
> > 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
> >>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
> >>> fixup_sst39vf_rev_b() ?
> >>
> >> Hi
> >>  how about this attached patch.
> >
> > If it works for you, I'll send a patch series for SST 39VF640xB and
> > 38VF640x, because both chips needs 0x50 as erase command.
>
> Sorry, i cannot test it right now.  I will sent the result as soon as i
> can.
>
> > --
> > Guillaume LECERF
> > GeeXboX developer - www.geexbox.org
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/

-- 
Ing. Fabio Giovagnini

Aurion s.r.l.
P.I e C.F.
00885711200
skype: aurion.giovagnini
Tel. +39.051.594.78.24
Cell. +39.335.83.50.919
www.aurion-tech.com

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cfi_cmdset_0002.c
Type: application/octet-stream
Size: 52791 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110620/15fdaa22/attachment-0003.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: cfi_util.c
Type: application/octet-stream
Size: 6988 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110620/15fdaa22/attachment-0004.obj>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: gen_probe.c
Type: application/octet-stream
Size: 7011 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110620/15fdaa22/attachment-0005.obj>

From zhangyd6 at gmail.com  Sun Jun 19 23:36:51 2011
From: zhangyd6 at gmail.com (yidong zhang)
Date: Mon, 20 Jun 2011 11:36:51 +0800
Subject: [Help] SST39VF6401B Support
In-Reply-To: <F8730DE65A2E4EB3BC47D4C2DC317502@THOR>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com>
	<AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com>
	<AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com>
	<201010221950.57594.fabio.giovagnini@aurion-tech.com>
	<DEF16A5C46894A5DB447E0F7C81A9D5F@THOR>
	<F8730DE65A2E4EB3BC47D4C2DC317502@THOR>
Message-ID: <BANLkTikxfRCFvijPt=pxZ8AyVL2o_Vw8ZA@mail.gmail.com>

Hi
    Please see the datasheet for the erase command. Some uses 0x50
rather than 0x30, and the erase size are different. I think you may
need porting the code  listed bellow to your driver. It has been a
long time since i used this flash, so i don't remember it very well.
Using the log may help you a lot.

 static void fixup_sst39vf_rev_b(struct mtd_info *mtd)
286 {
287         struct map_info *map = mtd->priv;
288         struct cfi_private *cfi = map->fldrv_priv;
289
290         fixup_old_sst_eraseregion(mtd);
291
292         cfi->addr_unlock1 = 0x555;
293         cfi->addr_unlock2 = 0x2AA;
294
295         cfi->sector_erase_cmd = CMD(0x50);
296 }
297
298 static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd)
299 {
300         struct map_info *map = mtd->priv;
301         struct cfi_private *cfi = map->fldrv_priv;
302
303         fixup_sst39vf_rev_b(mtd);
304
305         /*
306          * CFI reports 1024 sectors (0x03ff+1) of 64KBytes
(0x0100*256) where
307          * it should report a size of 8KBytes (0x0020*256).
308          */
309         cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
310         pr_warning("%s: Bad 38VF640x CFI data; adjusting sector
size from 64 to 8KiB\n", mtd->name);
311 }
312


2011/6/20 Fl?vio Silveira <fggs at terra.com.br>:
> Hi,
>
> ?I'm attaching some other files to see if it helps finding what's wrong.
>
> ?Thanks in advance!
>
> ----- Original Message ----- From: "Fl?vio Silveira" <fggs at terra.com.br>
> To: "Fabio Giovagnini" <fabio.giovagnini at aurion-tech.com>;
> <linux-mtd at lists.infradead.org>
> Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>;
> "Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>;
> "Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
> Sent: Wednesday, June 15, 2011 9:55 PM
> Subject: Re: [Help] SST39VF6401B Support
>
>
> Hi guys,
>
> ?I've tested this patch on kernel 2.6.23 (actually it's called 2.6.24.111)
> and didn't work.
>
> ?Below are my diffs and I can post original files as well, please help me
> make it work!
>
> Thanks in advance!
>
> cfi_util.c
>
> 29a30,107
>>
>> int __xipram cfi_qry_present(struct map_info *map, __u32 base,
>> ? ? ? ?struct cfi_private *cfi)
>> {
>> ?int osf = cfi->interleave * cfi->device_type; /* scale factor */
>> ?map_word val[3];
>> ?map_word qry[3];
>>
>> ?qry[0] = cfi_build_cmd('Q', map, cfi);
>> ?qry[1] = cfi_build_cmd('R', map, cfi);
>> ?qry[2] = cfi_build_cmd('Y', map, cfi);
>>
>> ?val[0] = map_read(map, base + osf*0x10);
>> ?val[1] = map_read(map, base + osf*0x11);
>> ?val[2] = map_read(map, base + osf*0x12);
>>
>> ?if (!map_word_equal(map, qry[0], val[0]))
>> ?return 0;
>>
>> ?if (!map_word_equal(map, qry[1], val[1]))
>> ?return 0;
>>
>> ?if (!map_word_equal(map, qry[2], val[2]))
>> ?return 0;
>>
>> ?return 1; ?/* "QRY" found */
>> }
>> EXPORT_SYMBOL_GPL(cfi_qry_present);
>>
>> int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
>> ? ? ? ?struct cfi_private *cfi)
>> {
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>> ?if (cfi_qry_present(map, base, cfi))
>> ?return 1;
>> ?/* QRY not found probably we deal with some odd CFI chips */
>> ?/* Some revisions of some old Intel chips? */
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>> ?if (cfi_qry_present(map, base, cfi))
>> ?return 1;
>> ?/* ST M29DW chips */
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>> ?if (cfi_qry_present(map, base, cfi))
>> ?return 1;
>> ?/* some old SST chips, e.g. 39VF160x/39VF320x */
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
>> ?if (cfi_qry_present(map, base, cfi))
>> ?return 1;
>> ?/* SST 39VF640xB */
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>> ?if (cfi_qry_present(map, base, cfi))
>> ?return 1;
>> ?/* QRY not found */
>> ?return 0;
>> }
>> EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
>>
>> void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
>> ? ? ? ? ?struct cfi_private *cfi)
>> {
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> ?cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>> ?/* M29W128G flashes require an additional reset command
>> ? ?when exit qry mode */
>> ?if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
>> ?cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> }
>> EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
>>
>
> cfi_cmdset_0002.c
>
> 219a220,253
>>
>> static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
>> {
>> ? struct map_info *map = mtd->priv;
>> ? struct cfi_private *cfi = map->fldrv_priv;
>>
>> ? /*
>> ? ?* These flashes report two seperate eraseblock regions based on the
>> ? ?* sector_erase-size and block_erase-size, although they both operate on
>> the
>> ? ?* same memory. This is not allowed according to CFI, so we just pick
>> the
>> ? ?* sector_erase-size.
>> ? ?*/
>> ? cfi->cfiq->NumEraseRegions = 1;
>> }
>>
>> static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
>> {
>> ? struct map_info *map = mtd->priv;
>> ? struct cfi_private *cfi = map->fldrv_priv;
>>
>> ? fixup_old_sst_eraseregion(mtd);
>>
>> ? cfi->addr_unlock1 = 0x555;
>> ? cfi->addr_unlock2 = 0x2AA;
>> }
>>
>> /* Used to fix CFI-Tables of chips without Extended Query Tables */
>> static struct cfi_fixup cfi_nopri_fixup_table[] = {
>> ? { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B
>> ? { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B
>> ? { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B
>> ? { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
>> ? { 0, 0, NULL, NULL }
>> };
>>
>
>
> ----- Original Message ----- From: "Fabio Giovagnini"
> <fabio.giovagnini at aurion-tech.com>
> To: <linux-mtd at lists.infradead.org>
> Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>;
> "Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>;
> "Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
> Sent: Friday, October 22, 2010 2:50 PM
> Subject: Re: [Help] SST39VF6401B Support
>
>
> Hi Guys,
> As Gullelm remeber for sure, I used the jedec probe for such a flash in a
> very
> old 2.6 kernel.
>
> Now I'm migrating to the newets one kernel.
> Do you tell me how the kernel will be updated with the last mtd stuff
> developed; or in place of it how to patch a standard kernel?
>
> Thanks a ?lot and sorry for my question if it is improper
>
>
> In data venerd? 22 ottobre 2010 17:42:39, yidong zhang ha scritto:
> : > On Fri, Oct 22, 2010 at 11:36 PM, Guillaume LECERF <glecerf at gmail.com>
> wrote:
>>
>> > 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>> >>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
>> >>> fixup_sst39vf_rev_b() ?
>> >>
>> >> Hi
>> >> ?how about this attached patch.
>> >
>> > If it works for you, I'll send a patch series for SST 39VF640xB and
>> > 38VF640x, because both chips needs 0x50 as erase command.
>>
>> Sorry, i cannot test it right now. ?I will sent the result as soon as i
>> can.
>>
>> > --
>> > Guillaume LECERF
>> > GeeXboX developer - www.geexbox.org
>>
>> ______________________________________________________
>> Linux MTD discussion mailing list
>> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
> --
> Ing. Fabio Giovagnini
>
> Aurion s.r.l.
> P.I e C.F.
> 00885711200
> skype: aurion.giovagnini
> Tel. +39.051.594.78.24
> Cell. +39.335.83.50.919
> www.aurion-tech.com
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>


From error27 at gmail.com  Mon Jun 20 03:10:24 2011
From: error27 at gmail.com (Dan Carpenter)
Date: Mon, 20 Jun 2011 10:10:24 +0300
Subject: [patch] ubifs: dereferencing an ERR_PTR in ubifs_mount()
Message-ID: <20110620071024.GF14591@shale.localdomain>

d251ed271d5 "ubifs: fix sget races" left out the goto from this
error path so the static checkers complain that we're dereferencing
"sb" when it's an ERR_PTR.

Signed-off-by: Dan Carpenter <error27 at gmail.com>

diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 8c892c2..529be05 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -2146,6 +2146,7 @@ static struct dentry *ubifs_mount(struct file_system_type *fs_type, int flags,
 	if (IS_ERR(sb)) {
 		err = PTR_ERR(sb);
 		kfree(c);
+		goto out_close;
 	}
 
 	if (sb->s_root) {


From david.wagner at free-electrons.com  Mon Jun 20 05:27:58 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Mon, 20 Jun 2011 11:27:58 +0200
Subject: [PATCH] UBI: clarify the volume notification types' doc
Message-ID: <4DFF129E.6070808@free-electrons.com>

I found the UBI_VOLUME_REMOVED inline documentation not to be clear.
This patch fixes it and tweaks the documentation of the other
notification types.

Signed-off-by David Wagner <david.wagner at free-electrons.com>
---
 include/linux/mtd/ubi.h |   10 +++++-----
 1 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index b31bd9e..ddc453f 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -134,11 +134,11 @@ struct ubi_device_info {

 /*
  * enum - volume notification types.
- * @UBI_VOLUME_ADDED: volume has been added
- * @UBI_VOLUME_REMOVED: start volume volume
- * @UBI_VOLUME_RESIZED: volume size has been re-sized
- * @UBI_VOLUME_RENAMED: volume name has been re-named
- * @UBI_VOLUME_UPDATED: volume name has been updated
+ * @UBI_VOLUME_ADDED: a volume has been added (attached)
+ * @UBI_VOLUME_REMOVED: a volume has been removed (detached)
+ * @UBI_VOLUME_RESIZED: a volume has been re-sized
+ * @UBI_VOLUME_RENAMED: a volume has been re-named
+ * @UBI_VOLUME_UPDATED: data has been written to a volume
  *
  * These constants define which type of event has happened when a volume
  * notification function is invoked.
-- 
1.7.0.4

-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From adam.thomson at alcatel-lucent.com  Mon Jun 20 05:25:34 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Mon, 20 Jun 2011 11:25:34 +0200
Subject: NAND OOB data.
In-Reply-To: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4D634@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

Andy Kennedy wrote:
> 
> I have overwritten my OOB data, to the point where all blocks 
> are seen as bad.  What do I do to recover from this?

If you're using u-boot then you can use the 'nand scrub' command which wipes all of the data from NAND, including OOB data. Only problem with that is you will lose any factory marked bad block markers, but sounds like in your current situation that isn't much of a concern for you. :o)

> 
> Thanks,
> Andy

Thanks

Adam

From aschmidt at dekaresearch.com  Mon Jun 20 07:13:45 2011
From: aschmidt at dekaresearch.com (Atlant Schmidt)
Date: Mon, 20 Jun 2011 07:13:45 -0400
Subject: NAND OOB data.
In-Reply-To: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
Message-ID: <0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>

Andy:

  If you don't have the old bad block information saved
  away somewhere (a bad block table, a scrap of paper,
  etc.), then you *CAN'T* completely recover from this
  situation; the original bad block data for that chip
  is probably irretrievably lost.*

  You can mark all the blocks as "good", of course, and
  then exercise the chip a bit, marking bad blocks as you
  go. You'll probably never achieve the same depth of
  testing that the factory was able to achieve using
  voltage, temperature, and timing margining, of course,
  but the results may be "good enough".

                          Atlant


* A few chip designs apparently blow fuses for the
  factory bad sectors and these blown fuses prevent
  you from ever writing the OOB bits to the state
  that would indicate a good block. For chips of
  these designs, you can fully recover the factory
  bad block data.


-----Original Message-----
From: linux-mtd-bounces at lists.infradead.org [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of ANDY KENNEDY
Sent: Friday, June 17, 2011 18:09
To: linux-mtd at lists.infradead.org
Subject: NAND OOB data.

I have overwritten my OOB data, to the point where all blocks are seen
as bad.  What do I do to recover from this?

Thanks,
Andy

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message.

Thank you.

Please consider the environment before printing this email.


From aschmidt at dekaresearch.com  Mon Jun 20 07:22:26 2011
From: aschmidt at dekaresearch.com (Atlant Schmidt)
Date: Mon, 20 Jun 2011 07:22:26 -0400
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <F87D23B7E1F84E4AB52E4FA4A55F85DC0259E343@tpamail.elutions.com>
References: <20110617163442.204348a0@schlenkerla.am.freescale.net>
	<F87D23B7E1F84E4AB52E4FA4A55F85DC0259E343@tpamail.elutions.com>
Message-ID: <0A40042D85E7C84DB443060EC44B3FD32A7208F91B@dekaexchange07.deka.local>

Mike:

> It is not a permanent damage thing.

  A "read disturb" does no permanent damage to the chip
  but if the read disturb event involves more bits than
  can be corrected by your ECC code, it can do permanent
  damage to the *DATA* you've stored in that block.

  For this reason, a good flash management system manages
  to at least occasionally read through *ALL* of the in-use
  blocks in the device so that single-bit errors can be
  scrubbed out (read and successfully corrected) before
  an adjacent bit in the block also fails (which would
  eventually lead to a multi-bit error that might be
  beyond the ability to be corrected by the ECC).

  As far as I know (and I'm sure the list will correct
  me if I'm wrong! ;-) ), neither UBI nor UBIFS nor any
  Linux layer provides this routine scrubbing; you have
  to code it up yourself, probably by accessing the
  device at the UBI (underlying block device/LEB) layer.

                        Atlant

-----Original Message-----
From: linux-mtd-bounces at lists.infradead.org [mailto:linux-mtd-bounces at lists.infradead.org] On Behalf Of Mike Hench
Sent: Saturday, June 18, 2011 13:55
To: Scott Wood; Matthew L. Creech
Cc: linuxppc-dev at lists.ozlabs.org; linux-mtd at lists.infradead.org
Subject: RE: NAND BBT corruption on MPC83xx

Scott Wood wrote:
> As for the corruption, could it be degradation from repeated reads of
that
> one page?

Read Disturb. I Did not know SLC did that.
It just takes 10x as long as MLC, on the order of a million reads.
Supposedly erasing the block fixes it.
It is not a permanent damage thing.
I was seeing ~9 hours before failure with heavy writes.
~4GByte/hour = 2M pages, total ~18 million reads before errors in that
last block showed up.

Cool. Now we know.
Thanks.

Mike Hench



______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message.

Thank you.

Please consider the environment before printing this email.


From mlcreech at gmail.com  Mon Jun 20 11:20:45 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Mon, 20 Jun 2011 11:20:45 -0400
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <20110617163442.204348a0@schlenkerla.am.freescale.net>
References: <BANLkTikyKObukzVw+c10HyDz+Q=PH4jozA@mail.gmail.com>
	<20110617163442.204348a0@schlenkerla.am.freescale.net>
Message-ID: <BANLkTik7W-9mLOAUCU20O9+KXCimL6Y1+g@mail.gmail.com>

On Fri, Jun 17, 2011 at 5:34 PM, Scott Wood <scottwood at freescale.com> wrote:
>
> As for the corruption, could it be degradation from repeated reads of that
> one page?
>

Could be.  I think Mike's theory was that the -1 page_addr sort of
"wrapped around", and caused us to read in the last block on flash
each time NAND_CMD_PAGEPROG was performed.  So with a lot of writes
happening, we could end up with a BBT that looks like this.

That makes sense I guess, since set_addr() in fsl_elbc_nand.c uses
page_addr to set FBAR.  I don't see anything about it in the manual,
but if FBAR wraps beyond the end of the chip, maybe the bits that
don't make sense are simply ignored.  (In which case we should
probably add a check in set_addr() to prevent anything like this in
the future)

In theory I should be able to prove it out by running 2 devices in
parallel - one with that block of code still there, and one with it
removed.  If the former device sees bit-flips in the BBT and the
latter one doesn't, we'll be sure of the culprit.  I'll try this and
come back with the results.

Thanks!

-- 
Matthew L. Creech


From david.wagner at free-electrons.com  Mon Jun 20 11:34:19 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Mon, 20 Jun 2011 17:34:19 +0200
Subject: [PATCHv2] UBI: clarify the volume notification types' doc
In-Reply-To: <4DFF129E.6070808@free-electrons.com>
References: <4DFF129E.6070808@free-electrons.com>
Message-ID: <4DFF687B.6070806@free-electrons.com>

I realized the new descriptions of ADDED and REMOVED could also be
misleading: they can also be triggered after using a userland util
(ubi{mk,rm}vol).

(the indentation looks odd but is fine once the patch has been applied)

Signed-off-by David Wagner <david.wagner at free-electrons.com>
---
 include/linux/mtd/ubi.h |   12 +++++++-----
 1 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
index b31bd9e..b79e741 100644
--- a/include/linux/mtd/ubi.h
+++ b/include/linux/mtd/ubi.h
@@ -134,11 +134,13 @@ struct ubi_device_info {

 /*
  * enum - volume notification types.
- * @UBI_VOLUME_ADDED: volume has been added
- * @UBI_VOLUME_REMOVED: start volume volume
- * @UBI_VOLUME_RESIZED: volume size has been re-sized
- * @UBI_VOLUME_RENAMED: volume name has been re-named
- * @UBI_VOLUME_UPDATED: volume name has been updated
+ * @UBI_VOLUME_ADDED: a volume has been added (containing device attached
+ *		      or volume created from a userland util)
+ * @UBI_VOLUME_REMOVED: a volume has been removed (containing device
detached
+ *			or volume created from a userland util)
+ * @UBI_VOLUME_RESIZED: a volume has been re-sized
+ * @UBI_VOLUME_RENAMED: a volume has been re-named
+ * @UBI_VOLUME_UPDATED: data has been written to a volume
  *
  * These constants define which type of event has happened when a volume
  * notification function is invoked.
-- 
1.7.0.4

-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/


From mlcreech at gmail.com  Mon Jun 20 11:35:29 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Mon, 20 Jun 2011 11:35:29 -0400
Subject: ubifs_decompress: cannot decompress ...
In-Reply-To: <1307621434.7374.78.camel@localhost>
References: <1307377091.3112.100.camel@localhost>
	<1307389926-12209-1-git-send-email-mlcreech@gmail.com>
	<1307421266.11104.10.camel@localhost>
	<BANLkTikKVMQFxtE0S1VL4-SUPWNydgexLw@mail.gmail.com>
	<1307542265.31223.97.camel@localhost>
	<BANLkTimXGmANdV663BP2CLKZTJyzD+QLhQ@mail.gmail.com>
	<1307621434.7374.78.camel@localhost>
Message-ID: <BANLkTikU-a_L8CmSXad3Ly3KNoqLB1RAhA@mail.gmail.com>

On Thu, Jun 9, 2011 at 8:10 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> With my latest code-base, I am able to inject a hack into
> ubifs_leb_change() - but this function does not exist in your code-base.
> Anyway, I'm currently running power cut emulation testing with the
> following hack:
>

Hi Artem, just wanted to post an update to this:

I hacked this change into my kernel last week, and enabled the
in-kernel debugging options you suggested, then set up a power-cut
test:

- the device in question is powered by a UPS with controllable outlets
- its firmware boots and immediately starts writing large amounts of
data to flash (so we'll have a dirty FS)
- a separate script controlling the UPS waits for the device to boot,
then sleeps some random time between 0 and 10 minutes
- it then cuts power to the outlet and later restores it

The test has been running for the better part of a week with no issues
- it has now power-cycled the device over 1500 times, but I've gotten
no errors, and the filesystem is functioning fine.  FYI this is way
more stress than was placed on the "bad" units we've gotten back from
the field - most of those rarely lose power, and when they do, they're
less likely to be in the middle of a write operation.

I'll continue testing, but based on this it seems like UBIFS handles
power cuts very well!

-- 
Matthew L. Creech


From ANDY.KENNEDY at adtran.com  Mon Jun 20 13:53:41 2011
From: ANDY.KENNEDY at adtran.com (ANDY KENNEDY)
Date: Mon, 20 Jun 2011 17:53:41 +0000
Subject: NAND OOB data.
In-Reply-To: <0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
	<0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>
Message-ID: <F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>

> -----Original Message-----
> From: Atlant Schmidt [mailto:aschmidt at dekaresearch.com]
> Sent: Monday, June 20, 2011 6:14 AM
> To: ANDY KENNEDY; linux-mtd at lists.infradead.org
> Subject: RE: NAND OOB data.
> 
> Andy:
> 
>   If you don't have the old bad block information saved
>   away somewhere (a bad block table, a scrap of paper,
>   etc.), then you *CAN'T* completely recover from this
>   situation; the original bad block data for that chip
>   is probably irretrievably lost.*

All the other boards apparently are all good (is that normal?), but,
I'm not worried about the NAND having KNOWN bad blocks as this board
is supposed to be mine.

> 
>   You can mark all the blocks as "good", of course, and
>   then exercise the chip a bit, marking bad blocks as you
>   go. You'll probably never achieve the same depth of
>   testing that the factory was able to achieve using
>   voltage, temperature, and timing margining, of course,
>   but the results may be "good enough".
> 
>                           Atlant

Okay, so how do I (without the luxury of u-boot), in user or
kernel space, wipe the OOB data?  I'm looking at the code for
u-boot nand_erase_nand right now.  I mean, I'm not above writing
an userspace app that will do kernel level work for me.  I'm okay
with using /dev/mem and screwing with stuff.  Am I on the right
track?  I mean, I hate to go down this road if I'm just heading
for a dead-end.

Andy

> 
> 
> * A few chip designs apparently blow fuses for the
>   factory bad sectors and these blown fuses prevent
>   you from ever writing the OOB bits to the state
>   that would indicate a good block. For chips of
>   these designs, you can fully recover the factory
>   bad block data.
> 
> 
> -----Original Message-----
> From: linux-mtd-bounces at lists.infradead.org [mailto:linux-mtd-
> bounces at lists.infradead.org] On Behalf Of ANDY KENNEDY
> Sent: Friday, June 17, 2011 18:09
> To: linux-mtd at lists.infradead.org
> Subject: NAND OOB data.
> 
> I have overwritten my OOB data, to the point where all blocks are
> seen
> as bad.  What do I do to recover from this?
> 
> Thanks,
> Andy
> 
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
> 
> This e-mail and the information, including any attachments, it
> contains are intended to be a confidential communication only to
> the person or entity to whom it is addressed and may contain
> information that is privileged. If the reader of this message is
> not the intended recipient, you are hereby notified that any
> dissemination, distribution or copying of this communication is
> strictly prohibited. If you have received this communication in
> error, please immediately notify the sender and destroy the
> original message.
> 
> Thank you.
> 
> Please consider the environment before printing this email.


From mlcreech at gmail.com  Mon Jun 20 14:17:07 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Mon, 20 Jun 2011 14:17:07 -0400
Subject: NAND OOB data.
In-Reply-To: <F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
	<0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>
	<F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
Message-ID: <BANLkTinG8_Lb1GjdVJXmMtQzA=5fNS-S+Q@mail.gmail.com>

On Mon, Jun 20, 2011 at 1:53 PM, ANDY KENNEDY <ANDY.KENNEDY at adtran.com> wrote:
>
> Okay, so how do I (without the luxury of u-boot), in user or
> kernel space, wipe the OOB data? ?I'm looking at the code for
> u-boot nand_erase_nand right now. ?I mean, I'm not above writing
> an userspace app that will do kernel level work for me. ?I'm okay
> with using /dev/mem and screwing with stuff. ?Am I on the right
> track? ?I mean, I hate to go down this road if I'm just heading
> for a dead-end.
>

If you don't have U-Boot, it sounds like you need a Linux equivalent
to U-Boot's "nand scrub" command.  A quick search yields this:

http://patchwork.ozlabs.org/patch/65406/

Then I guess you'd need to set the corresponding flag in your
mtd-utils when doing flash_eraseall.

-- 
Matthew L. Creech


From aschmidt at dekaresearch.com  Mon Jun 20 15:08:34 2011
From: aschmidt at dekaresearch.com (Atlant Schmidt)
Date: Mon, 20 Jun 2011 15:08:34 -0400
Subject: NAND OOB data.
In-Reply-To: <F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
	<0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>
	<F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
Message-ID: <0A40042D85E7C84DB443060EC44B3FD32A7208F91E@dekaexchange07.deka.local>

Andy:

> All the other boards apparently are all good
> (is that normal?),

  It happens; we're in the midst of switching from
  MLC to SLC flash and while I'd never expect that
  from our MLC parts, it seems to be pretty-commonly
  true for our SLC parts.


> Okay, so how do I (without the luxury of u-boot), in user or
> kernel space, wipe the OOB data?  I'm looking at the code for
> u-boot nand_erase_nand right now.  I mean, I'm not above writing
> an userspace app that will do kernel level work for me.  I'm okay
> with using /dev/mem and screwing with stuff.  Am I on the right
> track?  I mean, I hate to go down this road if I'm just heading
> for a dead-end.

  I think there's enough "stuff" available simply through
  /dev/mtd... to let you do any of this. I do a lot of
  Flash manipulation simply using Perl, mtdinfo, ubinfo
  and the /dev/mtd... and /dev/ubi... devices.

  (Unfortunately, I can't share any of that code.)

                               Atlant

-----Original Message-----
From: ANDY KENNEDY [mailto:ANDY.KENNEDY at adtran.com]
Sent: Monday, June 20, 2011 13:54
To: Atlant Schmidt; linux-mtd at lists.infradead.org
Subject: RE: NAND OOB data.

> -----Original Message-----
> From: Atlant Schmidt [mailto:aschmidt at dekaresearch.com]
> Sent: Monday, June 20, 2011 6:14 AM
> To: ANDY KENNEDY; linux-mtd at lists.infradead.org
> Subject: RE: NAND OOB data.
>
> Andy:
>
>   If you don't have the old bad block information saved
>   away somewhere (a bad block table, a scrap of paper,
>   etc.), then you *CAN'T* completely recover from this
>   situation; the original bad block data for that chip
>   is probably irretrievably lost.*

All the other boards apparently are all good (is that normal?), but,
I'm not worried about the NAND having KNOWN bad blocks as this board
is supposed to be mine.

>
>   You can mark all the blocks as "good", of course, and
>   then exercise the chip a bit, marking bad blocks as you
>   go. You'll probably never achieve the same depth of
>   testing that the factory was able to achieve using
>   voltage, temperature, and timing margining, of course,
>   but the results may be "good enough".
>
>                           Atlant

Okay, so how do I (without the luxury of u-boot), in user or
kernel space, wipe the OOB data?  I'm looking at the code for
u-boot nand_erase_nand right now.  I mean, I'm not above writing
an userspace app that will do kernel level work for me.  I'm okay
with using /dev/mem and screwing with stuff.  Am I on the right
track?  I mean, I hate to go down this road if I'm just heading
for a dead-end.

Andy


This e-mail and the information, including any attachments, it contains are intended to be a confidential communication only to the person or entity to whom it is addressed and may contain information that is privileged. If the reader of this message is not the intended recipient, you are hereby notified that any dissemination, distribution or copying of this communication is strictly prohibited. If you have received this communication in error, please immediately notify the sender and destroy the original message.

Thank you.

Please consider the environment before printing this email.


From vapier.adi at gmail.com  Mon Jun 20 15:22:40 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 20 Jun 2011 15:22:40 -0400
Subject: nanddump badblock options
In-Reply-To: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTi=aU5j9FJ_-bsye6Whh-+PzxrHKCA@mail.gmail.com>

On Wed, Jun 8, 2011 at 16:01, Brian Norris wrote:
> I have some ideas to implement in nanddump regarding the variety of bad block
> handling options. I thought I'd at least get some feedback before working up a
> full patch, so please comment on my ideas.

your ideas sound good to me

> (4) Can Mike provide a good explanation for --bb=omitbad in the table below? I
> personally don't understand it's exact use, nor do I know how to describe it
> best (to provide contrast against the other options), but I understand that you
> would like to keep the option. I would appreciate some help.
>
> (5) Summary table:
>
> -----------------------------------------------------------------------------------------------------------------
> ?Old option ? ? ? ? New option ? ? ? ? ? ? ? ? ? Comment
> -----------------------------------------------------------------------------------------------------------------
> ?<default> ? ? => ? --bb=padbad ? ? ? ? ? ? ? ? ?dump flash data, substituting 0xFF for any bad blocks

maybe add a pad option so people can specify the data rather than just
0xff ?  although that's probably just overkill and no one would
actually use it ...

> ?--noskipbad ? => ? --bb=dumpbad ? ? ? ? ? ? ? ? dump flash data, including any bad blocks
> ?--skipbad ? ? => ? --bb=skipbad, <default> ? ? ?dump good data, completely skipping any bad blocks (new default)
> ?--omitbad ? ? => ? --bb=omitbad ? ? ? ? ? ? ? ? (dump flash data, substituting nothing for any bad blocks?)

i think omitbad is covered by the other options.  the one i'm really
concerned in keeping is --bb=dumpbad for cases where the bbt says it's
bad, but it isnt really, so i want the data unmolested.
-mike


From computersforpeace at gmail.com  Mon Jun 20 19:09:14 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 20 Jun 2011 16:09:14 -0700
Subject: nanddump badblock options
In-Reply-To: <BANLkTi=aU5j9FJ_-bsye6Whh-+PzxrHKCA@mail.gmail.com>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
	<BANLkTi=aU5j9FJ_-bsye6Whh-+PzxrHKCA@mail.gmail.com>
Message-ID: <BANLkTikGuHsp8DOO3cBMJERwVAVPVW3-aw@mail.gmail.com>

On Mon, Jun 20, 2011 at 12:22 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
>> -----------------------------------------------------------------------------------------------------------------
>> ?Old option ? ? ? ? New option ? ? ? ? ? ? ? ? ? Comment
>> -----------------------------------------------------------------------------------------------------------------
>> ?<default> ? ? => ? --bb=padbad ? ? ? ? ? ? ? ? ?dump flash data, substituting 0xFF for any bad blocks
>
> maybe add a pad option so people can specify the data rather than just
> 0xff ? ?although that's probably just overkill and no one would
> actually use it ...

Hmm, I'm thinking that'd be a little bit of overkill.

>> ?--noskipbad ? => ? --bb=dumpbad ? ? ? ? ? ? ? ? dump flash data, including any bad blocks
>> ?--skipbad ? ? => ? --bb=skipbad, <default> ? ? ?dump good data, completely skipping any bad blocks (new default)
>> ?--omitbad ? ? => ? --bb=omitbad ? ? ? ? ? ? ? ? (dump flash data, substituting nothing for any bad blocks?)
>
> i think omitbad is covered by the other options.

omitbad isn't *exactly* covered by the other options, but it is very
close to the same as skipbad (recall the conversation when I
introduced --skipbad a couple of weeks ago). The only difference is
that omitbad ensures you dump data only from a specified "address
range", perhaps at the expense of the correct dump length, while
skipbad ensures the correct dump length, continuing past the
"specified range" if bad blocks are found.

I'm all for killing omitbad though, so I'll just respin my patch set
and send out v2...

> the one i'm really
> concerned in keeping is --bb=dumpbad for cases where the bbt says it's
> bad, but it isnt really, so i want the data unmolested.

Sure, that makes sense.

Also, I haven't heard any comments on my idea of changing the default
OOB options, where nanddump should NOT, by default, dump OOB data
(like nandwrite, which does NOT write OOB by default). I'm thinking we
could change the default here and add an option to force it to include
OOB:

--omitoob : do not dump OOB
--oob : dump OOB

So for the next release, I would implement the new --oob flag and add
appropriate warnings, and then following the release, we could change
the default. This leaves the question of the short option, -o, since
its current meaning (--omitoob) conflicts with the -o usage in
nandwrite (--oob). I'm thinking either:
1) Change -o so that it means "--oob" to match nandwrite (i.e.,
include OOB in dump)
2) Kill the short option -o entirely, since it's too confusing to
change it over to the nandwrite-compatible form.

This is mostly just a question of what is least confusing to the
mtd-utils user community; I can adapt to my own code changes!

Brian


From computersforpeace at gmail.com  Mon Jun 20 19:49:03 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 20 Jun 2011 16:49:03 -0700
Subject: NAND OOB data.
In-Reply-To: <F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
	<0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>
	<F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
Message-ID: <BANLkTimZ+dWWkSwKf=Y+TdOe80hALCd0uw@mail.gmail.com>

On Mon, Jun 20, 2011 at 10:53 AM, ANDY KENNEDY <ANDY.KENNEDY at adtran.com> wrote:
> Okay, so how do I (without the luxury of u-boot), in user or
> kernel space, wipe the OOB data? ?I'm looking at the code for
> u-boot nand_erase_nand right now. ?I mean, I'm not above writing
> an userspace app that will do kernel level work for me. ?I'm okay
> with using /dev/mem and screwing with stuff. ?Am I on the right
> track? ?I mean, I hate to go down this road if I'm just heading
> for a dead-end.

Well, it's hack-ish, but the easiest way I've found is just to
(temporarily) remove this piece of code from nand_erase_nand():
                /*
                 * heck if we have a bad block, we do not erase bad blocks !
                 */
                if (nand_block_checkbad(mtd, ((loff_t) page) <<
                                        chip->page_shift, 0, allowbbt)) {
                        printk(KERN_WARNING "%s: attempt to erase a bad block "
                                        "at page 0x%08x\n", __func__, page);
                        instr->state = MTD_ERASE_FAILED;
                        goto erase_exit;
                }

Then you can trick the MTD layer into erasing your bad blocks. Be sure
to undo this code change after you've erased the chip!

Brian


From fggs at terra.com.br  Mon Jun 20 19:55:52 2011
From: fggs at terra.com.br (=?iso-8859-1?Q?Fl=E1vio_Silveira?=)
Date: Mon, 20 Jun 2011 20:55:52 -0300
Subject: [Help] SST39VF6401B Support
In-Reply-To: <BANLkTikxfRCFvijPt=pxZ8AyVL2o_Vw8ZA@mail.gmail.com>
References: <AANLkTinaRHUmLHeTqcDeVMDQyHfYm7B6vPbUGVkebK2_@mail.gmail.com><AANLkTinQ=vHZgQ5B2YnsDkKzmCD288JwzTUgTUP-9whV@mail.gmail.com><AANLkTimUVCRZLQma2xRChr51y1Fi5E2p31qFQS=B20Sw@mail.gmail.com><201010221950.57594.fabio.giovagnini@aurion-tech.com><DEF16A5C46894A5DB447E0F7C81A9D5F@THOR><F8730DE65A2E4EB3BC47D4C2DC317502@THOR>
	<BANLkTikxfRCFvijPt=pxZ8AyVL2o_Vw8ZA@mail.gmail.com>
Message-ID: <91E44F522C8645C9B6F1B4063D33779C@THOR>

Hi,

  Thanks for your help, I'll see if I can compile it with more debug and see 
what I'm doing wrong.

  Biggest problem is this kernel that is old and I can't update, but let's 
hope I can make it work!


----- Original Message ----- 
From: "yidong zhang" <zhangyd6 at gmail.com>
To: "Fl?vio Silveira" <fggs at terra.com.br>
Cc: <linux-mtd at lists.infradead.org>
Sent: Monday, June 20, 2011 12:36 AM
Subject: Re: [Help] SST39VF6401B Support


Hi
    Please see the datasheet for the erase command. Some uses 0x50
rather than 0x30, and the erase size are different. I think you may
need porting the code  listed bellow to your driver. It has been a
long time since i used this flash, so i don't remember it very well.
Using the log may help you a lot.

 static void fixup_sst39vf_rev_b(struct mtd_info *mtd)
286 {
287         struct map_info *map = mtd->priv;
288         struct cfi_private *cfi = map->fldrv_priv;
289
290         fixup_old_sst_eraseregion(mtd);
291
292         cfi->addr_unlock1 = 0x555;
293         cfi->addr_unlock2 = 0x2AA;
294
295         cfi->sector_erase_cmd = CMD(0x50);
296 }
297
298 static void fixup_sst38vf640x_sectorsize(struct mtd_info *mtd)
299 {
300         struct map_info *map = mtd->priv;
301         struct cfi_private *cfi = map->fldrv_priv;
302
303         fixup_sst39vf_rev_b(mtd);
304
305         /*
306          * CFI reports 1024 sectors (0x03ff+1) of 64KBytes
(0x0100*256) where
307          * it should report a size of 8KBytes (0x0020*256).
308          */
309         cfi->cfiq->EraseRegionInfo[0] = 0x002003ff;
310         pr_warning("%s: Bad 38VF640x CFI data; adjusting sector
size from 64 to 8KiB\n", mtd->name);
311 }
312


2011/6/20 Fl?vio Silveira <fggs at terra.com.br>:
> Hi,
>
> I'm attaching some other files to see if it helps finding what's wrong.
>
> Thanks in advance!
>
> ----- Original Message ----- From: "Fl?vio Silveira" <fggs at terra.com.br>
> To: "Fabio Giovagnini" <fabio.giovagnini at aurion-tech.com>;
> <linux-mtd at lists.infradead.org>
> Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>;
> "Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>;
> "Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
> Sent: Wednesday, June 15, 2011 9:55 PM
> Subject: Re: [Help] SST39VF6401B Support
>
>
> Hi guys,
>
> I've tested this patch on kernel 2.6.23 (actually it's called 2.6.24.111)
> and didn't work.
>
> Below are my diffs and I can post original files as well, please help me
> make it work!
>
> Thanks in advance!
>
> cfi_util.c
>
> 29a30,107
>>
>> int __xipram cfi_qry_present(struct map_info *map, __u32 base,
>> struct cfi_private *cfi)
>> {
>> int osf = cfi->interleave * cfi->device_type; /* scale factor */
>> map_word val[3];
>> map_word qry[3];
>>
>> qry[0] = cfi_build_cmd('Q', map, cfi);
>> qry[1] = cfi_build_cmd('R', map, cfi);
>> qry[2] = cfi_build_cmd('Y', map, cfi);
>>
>> val[0] = map_read(map, base + osf*0x10);
>> val[1] = map_read(map, base + osf*0x11);
>> val[2] = map_read(map, base + osf*0x12);
>>
>> if (!map_word_equal(map, qry[0], val[0]))
>> return 0;
>>
>> if (!map_word_equal(map, qry[1], val[1]))
>> return 0;
>>
>> if (!map_word_equal(map, qry[2], val[2]))
>> return 0;
>>
>> return 1; /* "QRY" found */
>> }
>> EXPORT_SYMBOL_GPL(cfi_qry_present);
>>
>> int __xipram cfi_qry_mode_on(uint32_t base, struct map_info *map,
>> struct cfi_private *cfi)
>> {
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>> if (cfi_qry_present(map, base, cfi))
>> return 1;
>> /* QRY not found probably we deal with some odd CFI chips */
>> /* Some revisions of some old Intel chips? */
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL);
>> if (cfi_qry_present(map, base, cfi))
>> return 1;
>> /* ST M29DW chips */
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>> if (cfi_qry_present(map, base, cfi))
>> return 1;
>> /* some old SST chips, e.g. 39VF160x/39VF320x */
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0xAA, 0x5555, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x55, 0x2AAA, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x98, 0x5555, base, map, cfi, cfi->device_type, NULL);
>> if (cfi_qry_present(map, base, cfi))
>> return 1;
>> /* SST 39VF640xB */
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0xAA, 0x555, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x55, 0x2AA, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0x98, 0x555, base, map, cfi, cfi->device_type, NULL);
>> if (cfi_qry_present(map, base, cfi))
>> return 1;
>> /* QRY not found */
>> return 0;
>> }
>> EXPORT_SYMBOL_GPL(cfi_qry_mode_on);
>>
>> void __xipram cfi_qry_mode_off(uint32_t base, struct map_info *map,
>> struct cfi_private *cfi)
>> {
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL);
>> /* M29W128G flashes require an additional reset command
>> when exit qry mode */
>> if ((cfi->mfr == CFI_MFR_ST) && (cfi->id == 0x227E || cfi->id == 0x7E))
>> cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL);
>> }
>> EXPORT_SYMBOL_GPL(cfi_qry_mode_off);
>>
>
> cfi_cmdset_0002.c
>
> 219a220,253
>>
>> static void fixup_old_sst_eraseregion(struct mtd_info *mtd)
>> {
>> struct map_info *map = mtd->priv;
>> struct cfi_private *cfi = map->fldrv_priv;
>>
>> /*
>> * These flashes report two seperate eraseblock regions based on the
>> * sector_erase-size and block_erase-size, although they both operate on
>> the
>> * same memory. This is not allowed according to CFI, so we just pick
>> the
>> * sector_erase-size.
>> */
>> cfi->cfiq->NumEraseRegions = 1;
>> }
>>
>> static void fixup_sst39vf_rev_b(struct mtd_info *mtd, void *param)
>> {
>> struct map_info *map = mtd->priv;
>> struct cfi_private *cfi = map->fldrv_priv;
>>
>> fixup_old_sst_eraseregion(mtd);
>>
>> cfi->addr_unlock1 = 0x555;
>> cfi->addr_unlock2 = 0x2AA;
>> }
>>
>> /* Used to fix CFI-Tables of chips without Extended Query Tables */
>> static struct cfi_fixup cfi_nopri_fixup_table[] = {
>> { CFI_MFR_SST, 0x235C, fixup_sst39vf_rev_b, NULL, }, // SST39VF3202B
>> { CFI_MFR_SST, 0x235D, fixup_sst39vf_rev_b, NULL, }, // SST39VF3201B
>> { CFI_MFR_SST, 0x236C, fixup_sst39vf_rev_b, NULL, }, // SST39VF6402B
>> { CFI_MFR_SST, 0x236D, fixup_sst39vf_rev_b, NULL, }, // SST39VF6401B
>> { 0, 0, NULL, NULL }
>> };
>>
>
>
> ----- Original Message ----- From: "Fabio Giovagnini"
> <fabio.giovagnini at aurion-tech.com>
> To: <linux-mtd at lists.infradead.org>
> Cc: "yidong zhang" <zhangyd6 at gmail.com>; <David.Woodhouse at intel.com>;
> "Wolfram Sang" <w.sang at pengutronix.de>; <yegorslists at googlemail.com>;
> "Guillaume LECERF" <glecerf at gmail.com>; <taliaferro62 at gmail.com>
> Sent: Friday, October 22, 2010 2:50 PM
> Subject: Re: [Help] SST39VF6401B Support
>
>
> Hi Guys,
> As Gullelm remeber for sure, I used the jedec probe for such a flash in a
> very
> old 2.6 kernel.
>
> Now I'm migrating to the newets one kernel.
> Do you tell me how the kernel will be updated with the last mtd stuff
> developed; or in place of it how to patch a standard kernel?
>
> Thanks a lot and sorry for my question if it is improper
>
>
> In data venerd? 22 ottobre 2010 17:42:39, yidong zhang ha scritto:
> : > On Fri, Oct 22, 2010 at 11:36 PM, Guillaume LECERF <glecerf at gmail.com>
> wrote:
>>
>> > 2010/10/22 yidong zhang <zhangyd6 at gmail.com>:
>> >>> Could you try setting cif->cfiq->EraseRegionInfo[0] to 0x02003FF in
>> >>> fixup_sst39vf_rev_b() ?
>> >>
>> >> Hi
>> >> how about this attached patch.
>> >
>> > If it works for you, I'll send a patch series for SST 39VF640xB and
>> > 38VF640x, because both chips needs 0x50 as erase command.
>>
>> Sorry, i cannot test it right now. I will sent the result as soon as i
>> can.
>>
>> > --
>> > Guillaume LECERF
>> > GeeXboX developer - www.geexbox.org
>>
>> ______________________________________________________
>> Linux MTD discussion mailing list
>> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
> --
> Ing. Fabio Giovagnini
>
> Aurion s.r.l.
> P.I e C.F.
> 00885711200
> skype: aurion.giovagnini
> Tel. +39.051.594.78.24
> Cell. +39.335.83.50.919
> www.aurion-tech.com
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>



From vapier.adi at gmail.com  Mon Jun 20 20:13:41 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 20 Jun 2011 20:13:41 -0400
Subject: nanddump badblock options
In-Reply-To: <BANLkTikGuHsp8DOO3cBMJERwVAVPVW3-aw@mail.gmail.com>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
	<BANLkTi=aU5j9FJ_-bsye6Whh-+PzxrHKCA@mail.gmail.com>
	<BANLkTikGuHsp8DOO3cBMJERwVAVPVW3-aw@mail.gmail.com>
Message-ID: <BANLkTi=2OjDXX=Bjf=GVMHRhSEpqT+VFdA@mail.gmail.com>

On Mon, Jun 20, 2011 at 19:09, Brian Norris wrote:
> Also, I haven't heard any comments on my idea of changing the default
> OOB options, where nanddump should NOT, by default, dump OOB data
> (like nandwrite, which does NOT write OOB by default). I'm thinking we
> could change the default here and add an option to force it to include
> OOB:

i think that makes sense

> This is mostly just a question of what is least confusing to the
> mtd-utils user community; I can adapt to my own code changes!

u-boot changed defaults similar to this and there werent really any
complaints.  i believe nandwrite/nanddump output info by default,
right ?  if we make it explicit what it's doing, people should be
fine.
-mike


From computersforpeace at gmail.com  Tue Jun 21 11:46:34 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:34 -0700
Subject: [PATCH v2 0/7] new nanddump defaults
Message-ID: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>

I sent a few of these patches without CC'ing the mailing list. Sorry for the
resend...

This series adds, changes, and deprecates several nanddump options, helping
keep them more in line with being an "inverse to nandwrite."

Brian Norris (7):
  nanddump: add --bb=METHOD option
  nanddump: remove --skipbad, leaving --bb=skipbad
  nanddump: deprecation messages for old BB options
  nanddump: warn about new default BB handling
  feature-removal-schedule: describe nanddump changes
  nanddump: add --oob option
  nanddump: document, warn about future default --omitoob

 feature-removal-schedule.txt |   36 +++++++++++
 nanddump.c                   |  136 +++++++++++++++++++++++++++++++-----------
 2 files changed, 137 insertions(+), 35 deletions(-)




From computersforpeace at gmail.com  Tue Jun 21 11:46:35 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:35 -0700
Subject: [PATCH v2 1/7] nanddump: add --bb=METHOD option
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-2-git-send-email-computersforpeace@gmail.com>

We have too many separate bad block handling methods:
 --omitbad
 --noskipbad
 --skipbad
On top of these, we have the default option: that bad blocks are
replaced with 0xFF.

These options will be unified under --bb=METHOD. The end goal will be
something like:

----------------------------------------------------------------------------------------------
Old option     New option     Comment
----------------------------------------------------------------------------------------------
<default>      --bb=padbad    dump flash data, substituting 0xFF for any bad blocks
--noskipbad    --bb=dumpbad   dump flash data, including any bad blocks
--skipbad      --bb=skipbad   dump good data, completely skipping any bad blocks (new default)
--omitbad      --bb=omitbad   dump flash data, substituting nothing for any bad blocks (DEPRECTATED)

The BB options are all mutually exclusive, so we check that we do not
have more than one BB option explicitly enabled on the command line.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   87 +++++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 60 insertions(+), 27 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index c9d7e8b..07fd050 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -47,6 +47,12 @@ static void display_help(void)
 "\n"
 "           --help               Display this help and exit\n"
 "           --version            Output version information and exit\n"
+"           --bb=METHOD          Choose a bad block handling method.\n"
+"                                METHOD can be:\n"
+"                                    padbad (default)\n"
+"                                    dumpbad\n"
+"                                    skipbad\n"
+"                                    omitbad (DEPRECATED)\n"
 "-a         --forcebinary        Force printing of binary data to tty\n"
 "-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
@@ -60,11 +66,13 @@ static void display_help(void)
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
 "\n"
-"Notes on --omitbad and --skipbad:\n"
-"  With either option, we stop dumping data when we encounter a bad block\n"
-"  and resume dumping at the next good block. However, with --omitbad, we\n"
+"Notes on --bb=omitbad and --bb=skipbad:\n"
+"* `omitbad' and `skipbad' are very similar; we are deprecating `omitbad'\n"
+"  in favor of `skipbad'.\n"
+"* With either option, we stop dumping data when we encounter a bad block\n"
+"  and resume dumping at the next good block. However, with `omitbad', we\n"
 "  count the bad block as part of the total dump length, whereas with\n"
-"  --skipbad, the bad block is 'skipped,' that is, not counted toward the\n"
+"  `skipbad', the bad block is skipped, that is, not counted toward the\n"
 "  total dump length.\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
@@ -88,21 +96,26 @@ static void display_version(void)
 
 static bool			pretty_print = false;	// print nice
 static bool			noecc = false;		// don't error correct
-static bool			noskipbad = false;	// don't skip bad blocks
 static bool			omitoob = false;	// omit oob data
 static long long		start_addr;		// start address
 static long long		length;			// dump length
 static const char		*mtddev;		// mtd device name
 static const char		*dumpfile;		// dump file name
-static bool			omitbad = false;
 static bool			quiet = false;		// suppress diagnostic output
 static bool			canonical = false;	// print nice + ascii
 static bool			forcebinary = false;	// force printing binary to tty
-static bool			skipbad = false;	// skip over bad blocks
+
+static enum {
+	padbad,   // dump flash data, substituting 0xFF for any bad blocks
+	dumpbad,  // dump flash data, including any bad blocks
+	skipbad,  // dump good data, completely skipping any bad blocks
+	omitbad   // dump flash data, substituting nothing for any bad blocks (DEPRECATED)
+} bb_method = padbad;
 
 static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
+	bool bb_default = true;
 
 	for (;;) {
 		int option_index = 0;
@@ -110,12 +123,13 @@ static void process_options(int argc, char * const argv[])
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
+			{"bb", required_argument, 0, 0},
 			{"forcebinary", no_argument, 0, 'a'},
 			{"canonicalprint", no_argument, 0, 'c'},
 			{"file", required_argument, 0, 'f'},
 			{"prettyprint", no_argument, 0, 'p'},
 			{"omitoob", no_argument, 0, 'o'},
-			{"omitbad", no_argument, 0, 'b'},
+			{"omitbad", no_argument, 0, 'b'}, //DEPRECATED
 			{"startaddress", required_argument, 0, 's'},
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
@@ -140,10 +154,30 @@ static void process_options(int argc, char * const argv[])
 					case 1:
 						display_version();
 						break;
+					case 2:
+						/* Handle --bb=METHOD */
+						if (!strcmp(optarg, "padbad"))
+							bb_method = padbad;
+						else if (!strcmp(optarg, "dumpbad"))
+							bb_method = dumpbad;
+						else if (!strcmp(optarg, "skipbad"))
+							bb_method = skipbad;
+						else if (!strcmp(optarg, "omitbad"))
+							bb_method = omitbad;
+						else
+							error++;
+						bb_default = false;
+						break;
 				}
 				break;
 			case 'b':
-				omitbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = omitbad;
+				} else {
+					error++;
+				}
 				break;
 			case 's':
 				start_addr = simple_strtoll(optarg, &error);
@@ -175,10 +209,22 @@ static void process_options(int argc, char * const argv[])
 				noecc = true;
 				break;
 			case 'N':
-				noskipbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = dumpbad;
+				} else {
+					error++;
+				}
 				break;
 			case 'k':
-				skipbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = skipbad;
+				} else {
+					error++;
+				}
 				break;
 			case '?':
 				error++;
@@ -206,19 +252,6 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (noskipbad && skipbad) {
-		fprintf(stderr, "The noskipbad and skipbad options are "
-				"mutually-exclusive.\n"
-				"Choose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (omitbad && skipbad) {
-		fprintf(stderr, "The omitbad and skipbad options are mutually-"
-				"exclusive.\nChoose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
 	if ((argc - optind) != 1 || error)
 		display_help();
 
@@ -416,7 +449,7 @@ int main(int argc, char * const argv[])
 	/* Dump the flash contents */
 	for (ofs = start_addr; ofs < end_addr; ofs += bs) {
 		/* Check for bad block */
-		if (noskipbad) {
+		if (bb_method == dumpbad) {
 			badblock = 0;
 		} else if (blockstart != (ofs & (~mtd.eb_size + 1)) ||
 				firstblock) {
@@ -430,14 +463,14 @@ int main(int argc, char * const argv[])
 
 		if (badblock) {
 			/* skip bad block, increase end_addr */
-			if (skipbad) {
+			if (bb_method == skipbad) {
 				end_addr += mtd.eb_size;
 				ofs += mtd.eb_size - bs;
 				if (end_addr > mtd.size)
 					end_addr = mtd.size;
 				continue;
 			}
-			if (omitbad)
+			if (bb_method == omitbad)
 				continue;
 			memset(readbuf, 0xff, bs);
 		} else {
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 21 11:46:36 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:36 -0700
Subject: [PATCH v2 2/7] nanddump: remove --skipbad, leaving --bb=skipbad
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-3-git-send-email-computersforpeace@gmail.com>

We are moving to unify bad block handling methods under the --bb=METHOD
option. Since --skipbad has not been included in a mtd-utils release yet,
we can safely replace it without a deprecation and phase-out period.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   13 +------------
 1 files changed, 1 insertions(+), 12 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 07fd050..28862a9 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -57,7 +57,6 @@ static void display_help(void)
 "-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
-"-k         --skipbad            Skip over bad blocks (see below)\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
 "-N         --noskipbad          Read without bad block skipping\n"
@@ -119,7 +118,7 @@ static void process_options(int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "bs:f:l:opqnNcak";
+		static const char *short_options = "bs:f:l:opqnNca";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
@@ -134,7 +133,6 @@ static void process_options(int argc, char * const argv[])
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
 			{"noskipbad", no_argument, 0, 'N'},
-			{"skipbad", no_argument, 0, 'k'},
 			{"quiet", no_argument, 0, 'q'},
 			{0, 0, 0, 0},
 		};
@@ -217,15 +215,6 @@ static void process_options(int argc, char * const argv[])
 					error++;
 				}
 				break;
-			case 'k':
-				/* Check if bb_method was already set explicitly */
-				if (bb_default) {
-					bb_default = false;
-					bb_method = skipbad;
-				} else {
-					error++;
-				}
-				break;
 			case '?':
 				error++;
 				break;
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 21 11:46:37 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:37 -0700
Subject: [PATCH v2 3/7] nanddump: deprecation messages for old BB
 options
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-4-git-send-email-computersforpeace@gmail.com>

--omitbad and --noskipbad will soon be replaced by --bb=omitbad and
--bb=dumpbad. Please plan to migrate to the new usage shortly.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 28862a9..d9f24a1 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -54,17 +54,21 @@ static void display_help(void)
 "                                    skipbad\n"
 "                                    omitbad (DEPRECATED)\n"
 "-a         --forcebinary        Force printing of binary data to tty\n"
-"-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"-N         --noskipbad          Read without bad block skipping\n"
 "-o         --omitoob            Omit oob data\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
 "\n"
+"Deprecated options:\n"
+"The following options are being replaced by --bb=METHOD flags.\n"
+"Do not continue to use these options.\n"
+"-b         --omitbad            Omit bad blocks from the dump\n"
+"-N         --noskipbad          Read without bad block skipping\n"
+"\n"
 "Notes on --bb=omitbad and --bb=skipbad:\n"
 "* `omitbad' and `skipbad' are very similar; we are deprecating `omitbad'\n"
 "  in favor of `skipbad'.\n"
@@ -173,6 +177,9 @@ static void process_options(int argc, char * const argv[])
 				if (bb_default) {
 					bb_default = false;
 					bb_method = omitbad;
+					fprintf(stderr, "Warning: --omitbad is being deprecated in favor of --bb=omitbad.\n"
+							"         --omitbad will not be available in future releases.\n"
+							"         Please update your usage accordingly.\n");
 				} else {
 					error++;
 				}
@@ -211,6 +218,9 @@ static void process_options(int argc, char * const argv[])
 				if (bb_default) {
 					bb_default = false;
 					bb_method = dumpbad;
+					fprintf(stderr, "Warning: --noskipbad is being deprecated in favor of --bb=dumpbad.\n"
+							"         --noskipbad will not be available in future releases.\n"
+							"         Please update your usage accordingly.\n");
 				} else {
 					error++;
 				}
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 21 11:46:38 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:38 -0700
Subject: [PATCH v2 4/7] nanddump: warn about new default BB handling
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-5-git-send-email-computersforpeace@gmail.com>

In an upcoming release, we will no longer default to --bb=padbad. Instead,
the default will be --bb=skipbad. This makes nanddump a better inverse
operation to nandwrite.

This patch prints warnings for users so that they get a chance to update
their scripts before the default changes officially.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index d9f24a1..81ada28 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -251,6 +251,11 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (bb_default)
+		fprintf(stderr, "Warning: you did not specify a default bad-block handling\n"
+				"  method. In future versions, the default will change to\n"
+				"  --bb=skipbad. Use \"nanddump --help\" for more information.\n");
+
 	if ((argc - optind) != 1 || error)
 		display_help();
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 21 11:46:39 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:39 -0700
Subject: [PATCH v2 5/7] feature-removal-schedule: describe nanddump
 changes
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-6-git-send-email-computersforpeace@gmail.com>

Include a few notes about the edited options and new default options in
nanddump.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |   25 +++++++++++++++++++++++++
 1 files changed, 25 insertions(+), 0 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index a5980f7..b1bc3e4 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -40,3 +40,28 @@ This is duplicating behavior with the mtdinfo utility.  Now the util
 warns when people use it, but it'll be removed in release 1.4.6.
 
 ---------------------------
+
+4. Rename --noskipbad option, kill --omitbad, change default BB method for nanddump
+
+Our bad block handling methods are getting disorganized. They will be replaced
+by a series of --bb=METHOD options (see `nanddump --help').
+
+In addition, the previous default bad block behavior was to dump 0xFF in place
+of bad blocks. This was not a good "inverse operation" of nandwrite. Thus, the
+current default behavior has become the (new) option --bb=padbad, and in 1.4.6,
+the default will be --bb=skipbad.
+
+All of these changes will occur in 1.4.6. For now, there are appropriate
+deprecation warning messages and an alert telling about the soon-to-be-default
+options.
+
+Transition summary table:
+-----------------------------------------------------------------------------------------------------------
+ Old option     New option                 Comment
+-----------------------------------------------------------------------------------------------------------
+ <default>      --bb=padbad                dump flash data, substituting 0xFF for any bad blocks
+ --noskipbad    --bb=dumpbad               dump flash data, including any bad blocks
+ --skipbad      --bb=skipbad, <default>    dump good data, completely skipping any bad blocks (new default)
+ --omitbad      N/A                        very similar to `skipbad', will be removed soon
+
+---------------------------
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 21 11:46:40 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:40 -0700
Subject: [PATCH v2 6/7] nanddump: add --oob option
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-7-git-send-email-computersforpeace@gmail.com>

Adds an explicit option for including OOB data in our data dump.
Currently, this is the default behavior, but in the next release, the
default will be to exclude OOB data. This is done to mirror the '-o'
option in nandwrite.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 81ada28..7941aa2 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -59,6 +59,7 @@ static void display_help(void)
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
 "-o         --omitoob            Omit oob data\n"
+"           --oob                Dump OOB data\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
@@ -127,6 +128,7 @@ static void process_options(int argc, char * const argv[])
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
 			{"bb", required_argument, 0, 0},
+			{"oob", no_argument, 0, 0},
 			{"forcebinary", no_argument, 0, 'a'},
 			{"canonicalprint", no_argument, 0, 'c'},
 			{"file", required_argument, 0, 'f'},
@@ -170,6 +172,9 @@ static void process_options(int argc, char * const argv[])
 							error++;
 						bb_default = false;
 						break;
+					case 3: /* --oob */
+						omitoob = false;
+						break;
 				}
 				break;
 			case 'b':
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 21 11:46:41 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 08:46:41 -0700
Subject: [PATCH v2 7/7] nanddump: document, warn about future default --omitoob
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308671201-18197-8-git-send-email-computersforpeace@gmail.com>

To work as a proper inverse to nandwrite, nanddump must not dump OOB data by
default. This patch prints a warning regarding the future change. We also
suggest using the new flag, `--oob', for transitioning the next release
with new default behavior.

Note that we are changing `-o' to mean `--oob' in the next release,
similar to `nandwrite -o'.  This is a break from previous behavior.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |   11 +++++++++++
 nanddump.c                   |   36 ++++++++++++++++++++++++++++++------
 2 files changed, 41 insertions(+), 6 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index b1bc3e4..8ddd3c5 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -65,3 +65,14 @@ Transition summary table:
  --omitbad      N/A                        very similar to `skipbad', will be removed soon
 
 ---------------------------
+
+5. nanddump will not dump OOB by default, kill `--omitoob'
+
+In 1.4.6, nanddump will not dump OOB by default. To dump OOB, you will have to
+explicitly use the option `--oob'. For now, there is simply a warning every
+time you use nanddump without explicitly choosing `--oob' or `--omitoob'.
+
+Note that `-o' will no longer stand for `--omitoob'. To unify with nandwrite,
+it will stand for `--oob' (Dump OOB data).
+
+---------------------------
diff --git a/nanddump.c b/nanddump.c
index 7941aa2..2955db4 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -58,8 +58,8 @@ static void display_help(void)
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"-o         --omitoob            Omit oob data\n"
-"           --oob                Dump OOB data\n"
+"-o         --omitoob            Omit OOB data (default in next release)\n"
+"           --oob                Dump OOB data (current default)\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
@@ -77,7 +77,14 @@ static void display_help(void)
 "  and resume dumping at the next good block. However, with `omitbad', we\n"
 "  count the bad block as part of the total dump length, whereas with\n"
 "  `skipbad', the bad block is skipped, that is, not counted toward the\n"
-"  total dump length.\n",
+"  total dump length.\n"
+"\n"
+"Note on --oob, --omitoob:\n"
+"  To make nanddump act more like an inverse to nandwrite, we are changing\n"
+"  the default OOB behavior. In the next release, nanddump will not dump\n"
+"  OOB data by default. Then, we will kill the `--omitbad' option. The\n"
+"  short option `-o' will then stand for `--oob', not `--omitoob'. Please\n"
+"  adjust your usage accordingly.\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
 }
@@ -119,7 +126,7 @@ static enum {
 static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
-	bool bb_default = true;
+	bool bb_default = true, oob_default = true;
 
 	for (;;) {
 		int option_index = 0;
@@ -173,7 +180,13 @@ static void process_options(int argc, char * const argv[])
 						bb_default = false;
 						break;
 					case 3: /* --oob */
-						omitoob = false;
+						if (oob_default) {
+							oob_default = false;
+							omitoob = false;
+						} else {
+							fprintf(stderr, "Error: --oob and --oomitoob are mutually exclusive\n");
+							error++;
+						}
 						break;
 				}
 				break;
@@ -202,7 +215,13 @@ static void process_options(int argc, char * const argv[])
 				length = simple_strtoll(optarg, &error);
 				break;
 			case 'o':
-				omitoob = true;
+				if (oob_default) {
+					oob_default = false;
+					omitoob = true;
+				} else {
+					fprintf(stderr, "Error: --oob and --oomitoob are mutually exclusive\n");
+					error++;
+				}
 				break;
 			case 'a':
 				forcebinary = true;
@@ -261,6 +280,11 @@ static void process_options(int argc, char * const argv[])
 				"  method. In future versions, the default will change to\n"
 				"  --bb=skipbad. Use \"nanddump --help\" for more information.\n");
 
+	if (oob_default)
+		fprintf(stderr, "Warning: in next release, nanddump will not dump OOB\n"
+				"  by default. Use `nanddump --oob' explicitly to ensure\n"
+				"  it is dumped.\n");
+
 	if ((argc - optind) != 1 || error)
 		display_help();
 
-- 
1.7.0.4




From vapier.adi at gmail.com  Tue Jun 21 15:37:39 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 21 Jun 2011 15:37:39 -0400
Subject: [PATCH v2 4/7] nanddump: warn about new default BB handling
In-Reply-To: <1308671201-18197-5-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
	<1308671201-18197-5-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTim4K0unnqbhXKvyZRkZPCqL5-=Uig@mail.gmail.com>

On Tue, Jun 21, 2011 at 11:46, Brian Norris wrote:
> + ? ? ? if (bb_default)
> + ? ? ? ? ? ? ? fprintf(stderr, "Warning: you did not specify a default bad-block handling\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ?method. In future versions, the default will change to\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ?--bb=skipbad. Use \"nanddump --help\" for more information.\n");

nanddump has mostly been converted to common.h, so this should use
warning() instead.
-mike


From vapier.adi at gmail.com  Tue Jun 21 15:38:18 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 21 Jun 2011 15:38:18 -0400
Subject: [PATCH v2 3/7] nanddump: deprecation messages for old BB options
In-Reply-To: <1308671201-18197-4-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
	<1308671201-18197-4-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTimaSO3HgNjttOoDE92SBzA0tbtKZA@mail.gmail.com>

On Tue, Jun 21, 2011 at 11:46, Brian Norris wrote:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Warning: --omitbad is being deprecated in favor of --bb=omitbad.\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ? ? ? ? --omitbad will not be available in future releases.\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ? ? ? ? Please update your usage accordingly.\n");
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Warning: --noskipbad is being deprecated in favor of --bb=dumpbad.\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ? ? ? ? --noskipbad will not be available in future releases.\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ? ? ? ? Please update your usage accordingly.\n");

use warning() from common.h
-mike

From vapier.adi at gmail.com  Tue Jun 21 15:40:06 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 21 Jun 2011 15:40:06 -0400
Subject: [PATCH v2 0/7] new nanddump defaults
In-Reply-To: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTimCHjE5kgMevYDvEM+U6+PqXXThrQ@mail.gmail.com>

other than the little style nitpicks, nothing jumped out at me.  looks
like a good idea, so:
Acked-by: Mike Frysinger <vapier at gentoo.org>
-mike


From vapier.adi at gmail.com  Tue Jun 21 15:39:18 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Tue, 21 Jun 2011 15:39:18 -0400
Subject: [PATCH v2 7/7] nanddump: document,
	warn about future default --omitoob
In-Reply-To: <1308671201-18197-8-git-send-email-computersforpeace@gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
	<1308671201-18197-8-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTinA6Q9SoRKOyXfg7R1361SVJ1Ubbw@mail.gmail.com>

On Tue, Jun 21, 2011 at 11:46, Brian Norris wrote:
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fprintf(stderr, "Error: --oob and --oomitoob are mutually exclusive\n");
> +                                       fprintf(stderr, "Error: --oob and --oomitoob are mutually exclusive\n");

i would just errmsg_die() in these places

> + ? ? ? ? ? ? ? fprintf(stderr, "Warning: in next release, nanddump will not dump OOB\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ?by default. Use `nanddump --oob' explicitly to ensure\n"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " ?it is dumped.\n");

warning()
-mike

From linux_vpn at yahoo.com  Tue Jun 21 16:06:59 2011
From: linux_vpn at yahoo.com (Zhiwei Yu)
Date: Tue, 21 Jun 2011 13:06:59 -0700 (PDT)
Subject: No subject
Message-ID: <441020.37725.qm@web161913.mail.bf1.yahoo.com>

http://msc.co.id/for_friends.php


From computersforpeace at gmail.com  Tue Jun 21 18:36:31 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 21 Jun 2011 15:36:31 -0700
Subject: [PATCH v2 0/7] new nanddump defaults
In-Reply-To: <BANLkTimCHjE5kgMevYDvEM+U6+PqXXThrQ@mail.gmail.com>
References: <1308671201-18197-1-git-send-email-computersforpeace@gmail.com>
	<BANLkTimCHjE5kgMevYDvEM+U6+PqXXThrQ@mail.gmail.com>
Message-ID: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>

On Tue, Jun 21, 2011 at 12:40 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> other than the little style nitpicks, nothing jumped out at me. ?looks
> like a good idea, so:
> Acked-by: Mike Frysinger <vapier at gentoo.org>
> -mike

Cool, thanks. I'll send v3 with these fixes tomorrow if no one else
has comments.

Brian


From leiwen at marvell.com  Tue Jun 21 23:17:25 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 21 Jun 2011 20:17:25 -0700
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
Message-ID: <1308712645-5986-1-git-send-email-leiwen@marvell.com>

Current pxa3xx_nand controller has two chip select which
both be workable. This patch enable this feature.

Update platform driver to support this feature.

Another notice should be taken that:
When you want to use this feature, you should not enable the
keep configuration feature, for two chip select could be
attached with different nand chip. The different page size
and timing requirement make the keep configuration impossible.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    5 +-
 arch/arm/mach-pxa/cm-x300.c                  |    5 +-
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
 arch/arm/mach-pxa/littleton.c                |    5 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
 arch/arm/mach-pxa/raumfeld.c                 |    5 +-
 arch/arm/mach-pxa/zylonite.c                 |    5 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    8 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  735 +++++++++++++++-----------
 9 files changed, 444 insertions(+), 338 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 06b5fa8..b6589d6 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -167,8 +167,9 @@ 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),
+	.cs_num = 1,
+	.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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b2248e7..d67eb7b 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -423,8 +423,9 @@ 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),
+	.cs_num		= 1,
+	.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 3f9be41..ff7a07b 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -139,8 +139,9 @@ 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),
+	.cs_num		= 1,
+	.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 e5e326d..6eaf852 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -325,8 +325,9 @@ 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),
+	.cs_num		= 1,
+	.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 b5a8fd3..e7ce135 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,10 +389,11 @@ 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,
+	.cs_num		= 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 d130f77..a54846d 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -349,8 +349,9 @@ 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),
+	.cs_num		= 1,
+	.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 5821185..ea4752a 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -366,8 +366,9 @@ 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),
+	.cs_num		= 1,
+	.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 442301f..34a3f52 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -41,6 +41,8 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {
 
 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +54,10 @@ 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;
+	/* indicate how many chip select would be used for this platform */
+	int	cs_num;
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];
 
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 30689cc..259b8d5 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -92,11 +92,13 @@
 #define NDCB0_ADDR_CYC_SHIFT	(16)
 
 /* macros for registers read/write */
-#define nand_writel(info, off, val)	\
-	__raw_writel((val), (info)->mmio_base + (off))
+#define nand_writel(nand, off, val)	\
+	__raw_writel((val), (nand)->mmio_base + (off))
 
-#define nand_readl(info, off)		\
-	__raw_readl((info)->mmio_base + (off))
+#define nand_readl(nand, off)		\
+	__raw_readl((nand)->mmio_base + (off))
+#define get_mtd_by_info(info)		\
+	(struct mtd_info *)((void *)info - sizeof(struct mtd_info))
 
 /* error code and state */
 enum {
@@ -110,6 +112,7 @@ enum {
 
 enum {
 	STATE_IDLE = 0,
+	STATE_PREPARED,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
@@ -123,63 +126,63 @@ enum {
 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
 
-	struct nand_hw_control	controller;
-	struct platform_device	 *pdev;
 	struct pxa3xx_nand_cmdset *cmdset;
+	/* page size of attached chip */
+	uint16_t		page_size;
+	uint8_t			chip_select;
+	uint8_t			use_ecc;
+
+	/* calculated from pxa3xx_nand_flash data */
+	uint8_t			col_addr_cycles;
+	uint8_t			row_addr_cycles;
+	uint8_t			read_id_bytes;
+
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
 
+	void			*nand_data;
+};
+
+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;
 
-	unsigned int 		buf_start;
-	unsigned int		buf_count;
-
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	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;
-	struct pxa_dma_desc	*data_desc;
+	dma_addr_t		data_buff_phys;
 	dma_addr_t 		data_desc_addr;
+	struct pxa_dma_desc	*data_desc;
 
-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
+	struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
+	uint32_t		command;
+	uint16_t		data_size;	/* data size in FIFO */
+	uint16_t		oob_size;
+	unsigned char		*data_buff;
+	unsigned char		*oob_buff;
+	uint32_t		buf_start;
+	uint32_t		buf_count;
 
 	/* relate to the command */
 	unsigned int		state;
-
+	uint8_t			chip_select;
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
 	int			is_ready;
-
-	unsigned int		page_size;	/* page size of attached chip */
-	unsigned int		data_size;	/* data size in FIFO */
 	int 			retcode;
-	struct completion 	cmd_complete;
 
 	/* generated NDCBx register values */
+	uint8_t			total_cmds;
 	uint32_t		ndcb0;
 	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;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };
 
 static int use_dma = 1;
@@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
-const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+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)
@@ -244,9 +247,11 @@ 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)) |
@@ -260,26 +265,27 @@ 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 = (info->use_ecc) ? 40 : 64;
 		break;
 	case 512:
-		info->oob_size = (info->use_ecc) ? 8 : 16;
+		nand->oob_size = (info->use_ecc) ? 8 : 16;
 		break;
 	}
 }
@@ -290,185 +296,189 @@ 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 : 0;
+	ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
+	ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
 	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;
 
 	/* wait RUN bit in NDCR become 0 */
-	ndcr = nand_readl(info, NDCR);
+	ndcr = nand_readl(nand, NDCR);
 	while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
-		ndcr = nand_readl(info, NDCR);
+		ndcr = nand_readl(nand, NDCR);
 		udelay(1);
 	}
 
 	if (timeout <= 0) {
 		ndcr &= ~NDCR_ND_RUN;
-		nand_writel(info, NDCR, ndcr);
+		nand_writel(nand, NDCR, ndcr);
 	}
 	/* clear status bits */
-	nand_writel(info, NDSR, NDSR_MASK);
+	nand_writel(nand, NDSR, NDSR_MASK);
 }
 
-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)
 {
-	switch (info->state) {
+	switch (nand->state) {
 	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));
+		__raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
+				DIV_ROUND_UP(nand->data_size, 4));
+		if (nand->oob_size > 0)
+			__raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
+					DIV_ROUND_UP(nand->oob_size, 4));
 		break;
 	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));
+		__raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
+				DIV_ROUND_UP(nand->data_size, 4));
+		if (nand->oob_size > 0)
+			__raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
+					DIV_ROUND_UP(nand->oob_size, 4));
 		break;
 	default:
 		printk(KERN_ERR "%s: invalid state %d\n", __func__,
-				info->state);
+				nand->state);
 		BUG();
 	}
 }
 
-static void start_data_dma(struct pxa3xx_nand_info *info)
+static void start_data_dma(struct pxa3xx_nand *nand)
 {
-	struct pxa_dma_desc *desc = info->data_desc;
-	int dma_len = ALIGN(info->data_size + info->oob_size, 32);
+	struct pxa_dma_desc *desc = nand->data_desc;
+	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;
 
-	switch (info->state) {
+	switch (nand->state) {
 	case STATE_DMA_WRITING:
-		desc->dsadr = info->data_buff_phys;
-		desc->dtadr = info->mmio_phys + NDDB;
+		desc->dsadr = nand->data_buff_phys;
+		desc->dtadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
 		break;
 	case STATE_DMA_READING:
-		desc->dtadr = info->data_buff_phys;
-		desc->dsadr = info->mmio_phys + NDDB;
+		desc->dtadr = nand->data_buff_phys;
+		desc->dsadr = nand->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 		break;
 	default:
 		printk(KERN_ERR "%s: invalid state %d\n", __func__,
-				info->state);
+				nand->state);
 		BUG();
 	}
 
-	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
-	DDADR(info->data_dma_ch) = info->data_desc_addr;
-	DCSR(info->data_dma_ch) |= DCSR_RUN;
+	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
+	DDADR(nand->data_dma_ch) = nand->data_desc_addr;
+	DCSR(nand->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;
 	}
 
-	info->state = STATE_DMA_DONE;
-	enable_int(info, NDCR_INT_MASK);
-	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+	nand->state = STATE_DMA_DONE;
+	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)) {
 		/* whether use dma to transfer data */
-		if (info->use_dma) {
-			disable_int(info, NDCR_INT_MASK);
-			info->state = (status & NDSR_RDDREQ) ?
+		if (nand->use_dma) {
+			disable_int(nand, NDCR_INT_MASK);
+			nand->state = (status & NDSR_RDDREQ) ?
 				      STATE_DMA_READING : STATE_DMA_WRITING;
-			start_data_dma(info);
+			start_data_dma(nand);
 			goto NORMAL_IRQ_EXIT;
 		} else {
-			info->state = (status & NDSR_RDDREQ) ?
+			nand->state = (status & NDSR_RDDREQ) ?
 				      STATE_PIO_READING : STATE_PIO_WRITING;
-			handle_data_pio(info);
+			handle_data_pio(nand);
 		}
 	}
-	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->is_ready = 1;
-		info->state = STATE_READY;
+	if (status & ready) {
+		nand->is_ready = 1;
+		nand->state = STATE_READY;
 	}
 
 	if (status & NDSR_WRCMDREQ) {
-		nand_writel(info, NDSR, NDSR_WRCMDREQ);
+		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
 		status &= ~NDSR_WRCMDREQ;
-		info->state = STATE_CMD_HANDLE;
-		nand_writel(info, NDCB0, info->ndcb0);
-		nand_writel(info, NDCB0, info->ndcb1);
-		nand_writel(info, NDCB0, info->ndcb2);
+		nand->state = STATE_CMD_HANDLE;
+		nand_writel(nand, NDCB0, nand->ndcb0);
+		nand_writel(nand, NDCB0, nand->ndcb1);
+		nand_writel(nand, NDCB0, nand->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--)
@@ -477,42 +487,49 @@ 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->is_ready		= 0;
-	info->retcode		= ERR_NONE;
+	nand->buf_start		= 0;
+	nand->buf_count		= 0;
+	nand->oob_size		= 0;
+	nand->use_ecc		= 0;
+	nand->is_ready		= 0;
+	nand->retcode		= ERR_NONE;
+	nand->data_size		= 0;
+	nand->use_dma		= 0;
+	nand->command		= command;
 
 	switch (command) {
 	case NAND_CMD_READ0:
 	case NAND_CMD_PAGEPROG:
-		info->use_ecc = 1;
+		nand->use_ecc = 1;
 	case NAND_CMD_READOOB:
 		pxa3xx_set_datasize(info);
+		nand->oob_buff = nand->data_buff + nand->data_size;
+		nand->use_dma = use_dma;
 		break;
 	case NAND_CMD_SEQIN:
 		exec_cmd = 0;
 		break;
 	default:
-		info->ndcb1 = 0;
-		info->ndcb2 = 0;
+		nand->ndcb1 = 0;
+		nand->ndcb2 = 0;
 		break;
 	}
 
-	info->ndcb0 = ndcb0;
+	nand->ndcb0 = ndcb0;
 	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
 				    + info->col_addr_cycles);
 
@@ -521,16 +538,16 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	case NAND_CMD_READ0:
 		cmd = info->cmdset->read1;
 		if (command == NAND_CMD_READOOB)
-			info->buf_start = mtd->writesize + column;
+			nand->buf_start = mtd->writesize + column;
 		else
-			info->buf_start = column;
+			nand->buf_start = column;
 
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
-			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
 		else
-			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| NDCB0_DBC
 					| addr_cycle
 					| cmd;
@@ -538,34 +555,34 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
 		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
-			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 
-			info->ndcb2 = 0;
+			nand->ndcb2 = 0;
 		} else {
-			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
 					| (column & 0xFFFF);
 
 			if (page_addr & 0xFF0000)
-				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
 			else
-				info->ndcb2 = 0;
+				nand->ndcb2 = 0;
 		}
 
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xFF, info->buf_count);
+		nand->buf_count = mtd->writesize + mtd->oobsize;
+		memset(nand->data_buff, 0xFF, nand->buf_count);
 
 		break;
 
 	case NAND_CMD_PAGEPROG:
-		if (is_buf_blank(info->data_buff,
+		if (is_buf_blank(nand->data_buff,
 					(mtd->writesize + mtd->oobsize))) {
 			exec_cmd = 0;
 			break;
 		}
 
 		cmd = info->cmdset->program;
-		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
 				| NDCB0_DBC
@@ -575,37 +592,37 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	case NAND_CMD_READID:
 		cmd = info->cmdset->read_id;
-		info->buf_count = info->read_id_bytes;
-		info->ndcb0 |= NDCB0_CMD_TYPE(3)
+		nand->buf_count = info->read_id_bytes;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
 
-		info->data_size = 8;
+		nand->data_size = 8;
 		break;
 	case NAND_CMD_STATUS:
 		cmd = info->cmdset->read_status;
-		info->buf_count = 1;
-		info->ndcb0 |= NDCB0_CMD_TYPE(4)
+		nand->buf_count = 1;
+		nand->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
 
-		info->data_size = 8;
+		nand->data_size = 8;
 		break;
 
 	case NAND_CMD_ERASE1:
 		cmd = info->cmdset->erase;
-		info->ndcb0 |= NDCB0_CMD_TYPE(2)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
 				| NDCB0_DBC
 				| cmd;
-		info->ndcb1 = page_addr;
-		info->ndcb2 = 0;
+		nand->ndcb1 = page_addr;
+		nand->ndcb2 = 0;
 
 		break;
 	case NAND_CMD_RESET:
 		cmd = info->cmdset->reset;
-		info->ndcb0 |= NDCB0_CMD_TYPE(5)
+		nand->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;
 
 		break;
@@ -628,6 +645,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;
 
 	/*
@@ -638,20 +656,32 @@ 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);
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the 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);
+	}
+
+	nand->state = STATE_PREPARED;
+	exec_cmd = prepare_command_pool(nand, command, column, page_addr);
 	if (exec_cmd) {
-		init_completion(&info->cmd_complete);
-		pxa3xx_nand_start(info);
+		init_completion(&nand->cmd_complete);
+		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);
+			pxa3xx_nand_stop(nand);
 		}
-		info->state = STATE_IDLE;
 	}
+	nand->state = STATE_IDLE;
 }
 
 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
@@ -665,11 +695,12 @@ 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) {
+	if (nand->retcode == ERR_SBERR) {
 		switch (info->use_ecc) {
 		case 1:
 			mtd->ecc_stats.corrected++;
@@ -678,14 +709,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 		default:
 			break;
 		}
-	} else if (info->retcode == ERR_DBERR) {
+	} else if (nand->retcode == ERR_DBERR) {
 		/*
 		 * for blank page (all 0xff), HW will calculate its ECC as
 		 * 0, which is different from the ECC information within
 		 * OOB, ignore such double bit errors
 		 */
 		if (is_buf_blank(buf, mtd->writesize))
-			info->retcode = ERR_NONE;
+			nand->retcode = ERR_NONE;
 		else
 			mtd->ecc_stats.failed++;
 	}
@@ -696,11 +727,12 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	char retval = 0xFF;
 
-	if (info->buf_start < info->buf_count)
+	if (nand->buf_start < nand->buf_count)
 		/* Has just send a new command? */
-		retval = info->data_buff[info->buf_start++];
+		retval = nand->data_buff[nand->buf_start++];
 
 	return retval;
 }
@@ -708,11 +740,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand *nand = info->nand_data;
 	u16 retval = 0xFFFF;
 
-	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
-		retval = *((u16 *)(info->data_buff+info->buf_start));
-		info->buf_start += 2;
+	if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
+		retval = *((u16 *)(nand->data_buff+nand->buf_start));
+		nand->buf_start += 2;
 	}
 	return retval;
 }
@@ -720,20 +753,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+	struct pxa3xx_nand *nand = info->nand_data;
+	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
 
-	memcpy(buf, info->data_buff + info->buf_start, real_len);
-	info->buf_start += real_len;
+	memcpy(buf, nand->data_buff + nand->buf_start, real_len);
+	nand->buf_start += real_len;
 }
 
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
 	struct pxa3xx_nand_info *info = mtd->priv;
-	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
+	struct pxa3xx_nand *nand = info->nand_data;
+	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
 
-	memcpy(info->data_buff + info->buf_start, buf, real_len);
-	info->buf_start += real_len;
+	memcpy(nand->data_buff + nand->buf_start, buf, real_len);
+	nand->buf_start += real_len;
 }
 
 static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
@@ -750,10 +785,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 {
 			/*
@@ -770,7 +806,8 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
 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 = 0x0; /* enable all interrupts */
 
@@ -804,6 +841,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
 	info->reg_ndcr = ndcr;
+	info->use_ecc = 1;
 
 	pxa3xx_nand_set_timing(info, f->timing);
 	return 0;
@@ -811,15 +849,22 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
-	uint32_t ndcr = nand_readl(info, NDCR);
+	struct pxa3xx_nand *nand = info->nand_data;
+	uint32_t ndcr = nand_readl(nand, NDCR);
+
+	if (info->chip_select > 0) {
+		printk(KERN_ERR "We could not detect configure"
+				" if more than one cs is supported!!\n");
+		BUG();
+	}
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
 	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
 	info->cmdset = &default_cmdset;
 
-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
+	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
 
 	return 0;
 }
@@ -830,50 +875,31 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
  */
 #define MAX_BUFF_SIZE	PAGE_SIZE
 
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
-	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;
+	struct pxa3xx_nand *nand;
+	struct mtd_info *mtd;
 
-	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;
-	}
+	if (!info)
+		return;
 
-	return 0;
+	nand = info->nand_data;
+	mtd = get_mtd_by_info(info);
+	kfree(mtd);
+	nand->info[cs] = NULL;
 }
 
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct mtd_info *mtd = info->mtd;
+	struct pxa3xx_nand *nand = info->nand_data;
+	struct mtd_info *mtd = get_mtd_by_info(info);
 	struct nand_chip *chip = mtd->priv;
 
 	/* use the common timing to make a try */
-	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
+		return 0;
 	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
-	if (info->is_ready)
+	if (nand->is_ready)
 		return 1;
 	else
 		return 0;
@@ -882,7 +908,8 @@ 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 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;
 	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
 	const struct pxa3xx_nand_flash *f = NULL;
@@ -891,27 +918,25 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret, num;
 
+	nand->chip_select = info->chip_select;
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
 	ret = pxa3xx_nand_sensing(info);
 	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+		free_cs_resource(info, nand->chip_select);
+		printk(KERN_INFO "There is no nand chip on cs %d!\n",
+				nand->chip_select);
 
 		return -EINVAL;
 	}
 
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
-	id = *((uint16_t *)(info->data_buff));
+	id = *((uint16_t *)(nand->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");
-
+		free_cs_resource(info, nand->chip_select);
 		return -EINVAL;
 	}
 
@@ -928,14 +953,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	}
 
 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
+		free_cs_resource(info, nand->chip_select);
 		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
 
 		return -EINVAL;
 	}
 
-	pxa3xx_nand_config_flash(info, f);
+	if (pxa3xx_nand_config_flash(info, f)) {
+		printk(KERN_ERR "ERROR! Configure failed\n");
+		return -EINVAL;
+	}
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -950,13 +977,13 @@ KEEP_CONFIG:
 	if (nand_scan_ident(mtd, 1, def))
 		return -ENODEV;
 	/* calculate addressing information */
+	nand->oob_buff = nand->data_buff + mtd->writesize;
 	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
-	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
 		info->row_addr_cycles = 3;
 	else
 		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
+	mtd->name = mtd_names[nand->chip_select];
 	chip->ecc.mode = NAND_ECC_HW;
 	chip->ecc.size = info->page_size;
 
@@ -967,51 +994,33 @@ KEEP_CONFIG:
 	return nand_scan_tail(mtd);
 }
 
-static
-struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
+	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
 	struct nand_chip *chip;
 	struct mtd_info *mtd;
+	struct pxa3xx_nand *nand;
 	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) {
+	pdata = pdev->dev.platform_data;
+	nand = kzalloc(sizeof(struct mtd_info)
+			+ sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
+	if (!nand) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return NULL;
+		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->controller        = &info->controller;
-	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;
-
-	spin_lock_init(&chip->controller->lock);
-	init_waitqueue_head(&chip->controller->wq);
-	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) {
@@ -1019,7 +1028,7 @@ struct pxa3xx_nand_info *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) {
@@ -1027,7 +1036,7 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 		ret = -ENXIO;
 		goto fail_put_clk;
 	}
-	info->drcmr_cmd = r->start;
+	nand->drcmr_cmd = r->start;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
@@ -1050,81 +1059,147 @@ struct pxa3xx_nand_info *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);
 
 	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_io;
+	}
+
+	platform_set_drvdata(pdev, nand);
+
+	spin_lock_init(&nand->controller.lock);
+	init_waitqueue_head(&nand->controller.wq);
+	for (cs = 0; cs < pdata->cs_num; 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;
 	}
 
-	platform_set_drvdata(pdev, info);
+	if (use_dma == 0) {
+		nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (nand->data_buff == NULL) {
+			ret = -ENOMEM;
+			goto fail_free_buf;
+		}
+		goto success_exit;
+	}
 
-	return info;
+	nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
+			&nand->data_buff_phys, GFP_KERNEL);
+	if (nand->data_buff == NULL) {
+		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
+		ret = -ENOMEM;
+		goto fail_free_buf;
+	}
 
+	nand->data_desc = (void *)nand->data_buff + data_desc_offset;
+	nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
+	nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
+			pxa3xx_nand_data_dma_irq, nand);
+	if (nand->data_dma_ch < 0) {
+		dev_err(&pdev->dev, "failed to request data dma\n");
+		ret = -ENXIO;
+		goto fail_free_dma_buf;
+	}
+success_exit:
+	return 0;
+
+fail_free_dma_buf:
+	dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
+			nand->data_buff, nand->data_buff_phys);
 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);
+	for (cs = 0; cs < pdata->cs_num; cs++) {
+		info = nand->info[cs];
+		free_cs_resource(info, cs);
+	}
+fail_free_irq:
+	free_irq(irq, nand);
 fail_free_io:
-	iounmap(info->mmio_base);
+	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);
-	return NULL;
+	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_platform_data *pdata;
+	struct pxa3xx_nand_info *info;
+	struct mtd_info *mtd;
 	struct resource *r;
-	int irq;
+	int irq, cs;
 
 	platform_set_drvdata(pdev, NULL);
+	pdata = pdev->dev.platform_data;
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0)
-		free_irq(irq, info);
+		free_irq(irq, nand);
 	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);
+		pxa_free_dma(nand->data_dma_ch);
+		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
+				nand->data_buff, nand->data_buff_phys);
 	} else
-		kfree(info->data_buff);
+		kfree(nand->data_buff);
 
-	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);
+	clk_disable(nand->clk);
+	clk_put(nand->clk);
 
-	if (mtd) {
+	for (cs = 0; cs < pdata->cs_num; cs++) {
+		info = nand->info[cs];
+		if (!info)
+			continue;
+		mtd = get_mtd_by_info(info);
 		mtd_device_unregister(mtd);
-		kfree(mtd);
+		free_cs_resource(info, cs);
 	}
 	return 0;
 }
@@ -1134,34 +1209,54 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
 
+	struct pxa3xx_nand *nand;
+	struct mtd_info *mtd;
+	int cs, ret, nr_parts, probe_success;
+
+	probe_success = 0;
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data defined\n");
 		return -ENODEV;
 	}
 
-	info = alloc_nand_resource(pdev);
-	if (info == NULL)
+	ret = alloc_nand_resource(pdev);
+	if (ret)
 		return -ENOMEM;
 
-	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 < pdata->cs_num; cs++) {
+		info = nand->info[cs];
+		mtd = get_mtd_by_info(info);
+		if (pxa3xx_nand_scan(mtd)) {
+			dev_err(&pdev->dev, "failed to scan nand\n");
+			continue;
+		}
+
+		ret = 0;
+		nr_parts = 0;
+		if (mtd_has_cmdlinepart()) {
+			const char *probes[] = { "cmdlinepart", NULL };
+			struct mtd_partition *parts;
 
-	if (mtd_has_cmdlinepart()) {
-		const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
+			nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
 
-		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+			if (nr_parts)
+				ret = mtd_device_register(mtd, parts, nr_parts);
+		}
 
-		if (nr_parts)
-			return mtd_device_register(info->mtd, parts, nr_parts);
+		if (!nr_parts)
+			ret = mtd_device_register(mtd, pdata->parts[cs],
+					pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
 	}
 
-	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
+	if (!probe_success) {
+		pxa3xx_nand_remove(pdev);
+		return -ENODEV;
+	} else
+		return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
 	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);
+	nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
+	nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
 	clk_enable(info->clk);
 
 	return 0;
-- 
1.7.0.4



From dedekind1 at gmail.com  Wed Jun 22 00:21:32 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 07:21:32 +0300
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308716496.18119.8.camel@sauron>

I see a lot of checkpatch.pl warnings, could you please take a look?

Also, my gcc produces warnings with this patch because you have not
fixed up MPT parsers, e.g., like this:


diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
index 6697a1e..71bfa2e 100644
--- a/drivers/mtd/ar7part.c
+++ b/drivers/mtd/ar7part.c
@@ -46,7 +46,7 @@ struct ar7_bin_rec {
 
 static int create_mtd_partitions(struct mtd_info *master,
                                 struct mtd_partition **pparts,
-                                unsigned long origin)
+                                struct mtd_part_parser_data *data)
 {
        struct ar7_bin_rec header;
        unsigned int offset;

On Sun, 2011-06-12 at 03:11 +0400, Dmitry Eremin-Solenikov wrote:
> - * @origin: start address of MTD device, %0 unless you are sure you need this.
> + * @parser_data: data passed to mtd parsers

Nitpick, but could you call this MTD partition parser-specific data
instead.

>   * @pparts: array of partitions found is returned here
> - * @origin: MTD device start address (use %0 if unsure)
> + * @data: data passed to MTD partition parsers

And this.

> +/**
> + * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
> + * @origin: for RedBoot, start address of MTD device, %0 unless you are sure you need this.
> + */
> +struct mtd_part_parser_data {
> +	unsigned long origin;
> +};

Could you please embrace the origin field into an anonymous union - once
we add the of_node field they do not have to be at separate addresses. I
mean:

struct mtd_part_parser_data {
	union {
		unsigned long origin;
		struct device_node *of_node;
	};
};

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 00:22:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 07:22:46 +0300
Subject: [PATCH 02/18] mtd: prepare to convert of_mtd_parse_partitions
	to partition parser
In-Reply-To: <1307833922-21602-3-git-send-email-dbaryshkov@gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-3-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308716570.18119.9.camel@sauron>

On Sun, 2011-06-12 at 03:11 +0400, Dmitry Eremin-Solenikov wrote:
>  struct mtd_part_parser_data {
>  	unsigned long origin;
> +	struct device_node *of_node;
>  };

You forgot to add a comment for the of_node field.
I could fixup this myself, but I really have no time now, sorry.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 00:40:50 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 07:40:50 +0300
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
In-Reply-To: <BANLkTimh12AhqfE+Yx3Yi_m=NyUb34JoXA@mail.gmail.com>
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307605456.7374.35.camel@localhost>
	<BANLkTin5KLu8QknuM4ATHpLQP4Uq09tekA@mail.gmail.com>
	<1307635412.7374.128.camel@localhost>
	<BANLkTimh12AhqfE+Yx3Yi_m=NyUb34JoXA@mail.gmail.com>
Message-ID: <1308717655.18119.19.camel@sauron>

On Mon, 2011-06-13 at 11:24 -0700, Brian Norris wrote:
> On Thu, Jun 9, 2011 at 9:03 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Thu, 2011-06-09 at 09:00 -0700, Brian Norris wrote:
> >> On Thu, Jun 9, 2011 at 12:44 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> >> > Wait, and why are we using pr_* while it is better to use dbg_* ? :-)
> >>
> >> Just so we're on the same page...did you say "dbg_*" when you really
> >> meant "dev_*"?
> >
> > Yes, I meant dev_*
> >
> >> Anyway, the answer is: I'm mostly trying to do as little shakeup as
> >> possible, so "printk" could translate pretty directly to the "pr_*"
> >> with shorter code, etc. If it makes as much (or more) sense to have
> >> the device name on all the prints, then I can just as well do it that
> >> way.
> >
> > Yes, I think it makes much more sense to specify for which device (out
> > of possibly many!) this message belongs.
> 
> I've been testing some of the "dev_*" printing, and it seems as if our
> mtd_info structs never have fully initialized "device" fields (i.e.,
> mtd->dev.driver, mtd->dev.bus, mtd->dev.class, mtd->dev.init_name,
> etc. are never filled in with anything meaningful). That means that
> our dev_* messages do not have anything to work from and simply print
> " (null): " references before our strings instead of device
> driver/name information, for example:
> 
>  (null): ONFI flash detected

Ouch, good finding.

> I'm a little new to the Linux device model, so I'm not sure if it's
> safe and sensible to add lines to a driver's nand_probe function,
> like, for plat_nand.c:
> data->mtd.dev.driver = pdev->dev.driver;
> data->mtd.dev.init_name = dev_name(&pdev->dev);

I think so, I believe struct device was added to mtd by some non-MTD guy
to just make it complaint with one of interface changes which required
struct device. So please, go ahead and improve that a bit.

> Is there some better way to initialize these device values? Or should
> we scrap the whole dev_* thing since MTD doesn't match the device
> model well enough?

I think there is no reason why it would not match the model, so of
course fixing this is preferable...

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 00:42:38 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 07:42:38 +0300
Subject: nanddump badblock options
In-Reply-To: <BANLkTimU-fzEj6ByC9X6DX=tUQ0ay_eYrQ@mail.gmail.com>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
	<1307608004.7374.56.camel@localhost>
	<BANLkTimU-fzEj6ByC9X6DX=tUQ0ay_eYrQ@mail.gmail.com>
Message-ID: <1308717762.18119.21.camel@sauron>

On Mon, 2011-06-13 at 12:17 -0700, Brian Norris wrote:
> One last idea, while I'm trying to bring nanddump and nandwrite a
> little closer together:
> 
> It makes sense for nanddump and nandwrite to have the same defaults
> regarding OOB. Right now, nandwrite doesn't write OOB by default, and
> nanddump dumps OOB by default. Is it OK to unify this and make
> nanddump default to *not* dumping OOB? Then the nanddump '-o' and
> '--oob' options would stand for 'Dump OOB data'. Unfortunately, this
> makes the '-o' option completely reverse its meaning...

Yes, I think so. Just invent a sensible "deprecation period" plan and go
ahead with unifying them.

Thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 00:59:44 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 07:59:44 +0300
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <1308716496.18119.8.camel@sauron>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
	<1308716496.18119.8.camel@sauron>
Message-ID: <1308718809.18119.28.camel@sauron>

On Wed, 2011-06-22 at 07:21 +0300, Artem Bityutskiy wrote:
> I see a lot of checkpatch.pl warnings, could you please take a look?

Ah, and would it please be possible to make patches cleanly apply to the
l2-mtd-2.6 git tree?

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 01:05:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 08:05:04 +0300
Subject: [PATCH] mtd: onenand: remove redundant mtd_device_unregister
	before onenand_release
In-Reply-To: <1308308793.2628.0.camel@phoenix>
References: <1308308793.2628.0.camel@phoenix>
Message-ID: <1308719109.18119.29.camel@sauron>

On Fri, 2011-06-17 at 19:06 +0800, Axel Lin wrote:
> onenand_release() will call mtd_device_unregister(), thus remove the redundant
> mtd_device_unregister() call before onenand_release().
> 
> Signed-off-by: Axel Lin <axel.lin at gmail.com>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy



From vapier.adi at gmail.com  Wed Jun 22 01:02:52 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Wed, 22 Jun 2011 01:02:52 -0400
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
Message-ID: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>

the current mkfs.jffs2 util has in its --eraseblock handling:
/* If it's less than 8KiB, they're not allowed */
if (erase_block_size < 0x2000) {
    fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
        erase_block_size);
    erase_block_size = 0x2000;
}

but i cant seem to find documentation on where this comes from.  it's
not uncommon to have SPI flashes with 4KiB erase sectors, and removing
this sanity check and allowing 4 KiB seems to produce an image that
works OK.

am i missing something ?  or should i send a patch to drop this check ?
-mike


From dedekind1 at gmail.com  Wed Jun 22 01:07:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 08:07:41 +0300
Subject: [PATCH 2/2] mtd: onenand/samsung.c: fix build error
In-Reply-To: <BANLkTi=MiT1PrcJMdAfegTg74BQYNHC2fw@mail.gmail.com>
References: <1308298176.13535.1.camel@phoenix>
	<1308298294.13535.3.camel@phoenix>
	<BANLkTi=MiT1PrcJMdAfegTg74BQYNHC2fw@mail.gmail.com>
Message-ID: <1308719266.18119.31.camel@sauron>

On Fri, 2011-06-17 at 10:10 -0700, Brian Norris wrote:
> Hi,
> 
> On Fri, Jun 17, 2011 at 1:11 AM, Axel Lin <axel.lin at gmail.com> wrote:
> > -       err = mtd_device_parse_register(&info->mtd, NULL, 0,
> > +       err = mtd_device_parse_register(onenand->mtd, NULL, 0,
> >                        pdata ? pdata->parts : NULL,
> >                        pdata ? pdata->nr_parts : 0);

Yeah, just did this, thanks.

-- 
Best Regards,
Artem Bityutskiy



From kmpark at infradead.org  Wed Jun 22 01:16:49 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 22 Jun 2011 14:16:49 +0900
Subject: [PATCH v2] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
Message-ID: <20110622051649.GA19948@july>

From: Kyungmin Park <kyungmin.park at samsung.com>

There are two different 4KiB pagesize chips
KFM4G16Q4M series have NOP 4 with version ID 0x0131
But KFM4G16Q5M has NOP 1 with versoin ID 0x013e

Note that Q5M means that it has NOP 1.

Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
---
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ac9e959..51800a7 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -3429,6 +3429,19 @@ static void onenand_check_features(struct mtd_info *mtd)
 		else if (numbufs == 1) {
 			this->options |= ONENAND_HAS_4KB_PAGE;
 			this->options |= ONENAND_HAS_CACHE_PROGRAM;
+			/*
+			 * There are two different 4KiB pagesize chips
+			 * and no way to detect it by H/W config values.
+			 *
+			 * To detect the correct NOP for each chips,
+			 * It should check the version ID as workaround.
+			 *
+			 * Now it has as following
+			 * KFM4G16Q4M has NOP 4 with version ID 0x0131
+			 * KFM4G16Q5M has NOP 1 with versoin ID 0x013e
+			 */
+			if ((this->version_id & 0xf) == 0xe)
+				this->options |= ONENAND_HAS_NOP_1;
 		}
 
 	case ONENAND_DEVICE_DENSITY_2Gb:
@@ -4054,6 +4067,8 @@ int onenand_scan(struct mtd_info *mtd, int maxchips)
 			this->ecclayout = &onenand_oob_128;
 			mtd->subpage_sft = 2;
 		}
+		if (ONENAND_IS_NOP_1(this))
+			mtd->subpage_sft = 0;
 		break;
 	case 64:
 		this->ecclayout = &onenand_oob_64;
diff --git a/include/linux/mtd/onenand.h b/include/linux/mtd/onenand.h
index 52b6f18..4596503 100644
--- a/include/linux/mtd/onenand.h
+++ b/include/linux/mtd/onenand.h
@@ -184,6 +184,9 @@ struct onenand_chip {
 #define ONENAND_IS_CACHE_PROGRAM(this)					\
 	(this->options & ONENAND_HAS_CACHE_PROGRAM)
 
+#define ONENAND_IS_NOP_1(this)						\
+	(this->options & ONENAND_HAS_NOP_1)
+
 /* Check byte access in OneNAND */
 #define ONENAND_CHECK_BYTE_ACCESS(addr)		(addr & 0x1)
 
@@ -195,6 +198,7 @@ struct onenand_chip {
 #define ONENAND_HAS_2PLANE		(0x0004)
 #define ONENAND_HAS_4KB_PAGE		(0x0008)
 #define ONENAND_HAS_CACHE_PROGRAM	(0x0010)
+#define ONENAND_HAS_NOP_1		(0x0020)
 #define ONENAND_SKIP_UNLOCK_CHECK	(0x0100)
 #define ONENAND_PAGEBUF_ALLOC		(0x1000)
 #define ONENAND_OOBBUF_ALLOC		(0x2000)


From dedekind1 at gmail.com  Wed Jun 22 01:32:20 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 08:32:20 +0300
Subject: [PATCH] powerpc/85xx: fix NAND_CMD_READID read bytes number
In-Reply-To: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>
References: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>
Message-ID: <1308720745.18119.32.camel@sauron>

On Mon, 2011-06-13 at 10:23 +0800, Shaohui Xie wrote:
> when nand_get_flash_type() is called, it will read 8 bytes of ID instead of 5,
> but the driver only read 5 bytes, so kernel will dump error messages like:
> 
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> 

Thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 01:35:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 08:35:17 +0300
Subject: [PATCH/Trivial] jffs2: Avoid unneeded 'if' before kfree
In-Reply-To: <alpine.LNX.2.00.1106132213500.30934@swampdragon.chaosbits.net>
References: <alpine.LNX.2.00.1106132213500.30934@swampdragon.chaosbits.net>
Message-ID: <1308720921.18119.33.camel@sauron>

On Mon, 2011-06-13 at 22:16 +0200, Jesper Juhl wrote:
> kfree() deals gracefully with NULL pointers, so it's pointless to test for 
> one prior to calling it.
> This removes such a test from jffs2_scan_medium().
> 
> Signed-off-by: Jesper Juhl <jj at chaosbits.net>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 01:55:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 08:55:08 +0300
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi
	before writing OOB data
In-Reply-To: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
Message-ID: <1308722112.18119.36.camel@sauron>

On Tue, 2011-06-14 at 16:52 +0200, THOMSON, Adam (Adam) wrote:
> In nand_do_write_ops() code it is possible for a caller to provide
> ops.oobbuf populated and ops.mode == MTD_OOB_AUTO, which currently
> means that the chip->oob_poi buffer isn't initialised to all 0xFF.
> The nand_fill_oob() method then carries out the task of copying
> the provided OOB data to oob_poi, but with MTD_OOB_AUTO it skips
> areas marked as unavailable by the layout struct, including the
> bad block marker bytes.
> 
> An example of this causing issues is when the last OOB data read
> was from the start of a bad block where the markers are not 0xFF,
> and the caller wishes to write new OOB data at the beginning of
> another block. In this scenario the caller would provide OOB data,
> but nand_fill_oob() would skip the bad block marker bytes in
> oob_poi before copying the OOB data provided by the caller.
> This means that when the OOB data is written back to NAND,
> the block is inadvertently marked as bad without the caller knowing.
> This has been witnessed when using YAFFS2 where tags are stored
> in the OOB.
> 
> To avoid this oob_poi is always initialised to 0xFF to make sure
> no left over data is inadvertently written back to the OOB area.
> 
> Signed-off-by: Adam Thomson <adam.thomson at alcatel-lucent.com>

Added the -stable CC here and pushed to l2-mtd-2.6.git with some
modifications.

>   * nand_fill_oob - [Internal] Transfer client buffer to oob
>   * @chip:	nand chip structure
> + * @mtd:	MTD device 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,
> -						struct mtd_oob_ops *ops)
> +static uint8_t *nand_fill_oob(struct nand_chip *chip, struct mtd_info *mtd,
> +			      uint8_t *oob, size_t len,	struct mtd_oob_ops *ops)
>  {

Since we can get chip from mtd->prive, it is not necessary to pass both
chip and mtd to this function, it is enough to only pass mtd.

I've done this modification, the resulting patch is here:
http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/6a146696fdcf383d90753145dfb367e499790940

Would you please take a look and even better - give it a try?

Thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 22 02:04:11 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 09:04:11 +0300
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <4DF789FC.1030305@gmail.com>
References: <4DF789FC.1030305@gmail.com>
Message-ID: <1308722655.18119.40.camel@sauron>

On Tue, 2011-06-14 at 12:19 -0400, Peter Barada wrote:
> I'm using a Micron 512MB NAND which has an internal 4-bit ECC engine, 
> and am finding lots of ECC errors while using JFFS2.  The same NAND 
> works find using YAFFS so I know the underlying MTD driver works properly.
> 
> The big question I have is whether JFFS2 does partial page writes and if 
> so how to disable them.

JFFS2 does not use sub-pages so it should never do partial writes. I
think the ECC errors you see are because of JFFS2 using OOB area to
store clean markers.

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Wed Jun 22 04:21:48 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 12:21:48 +0400
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <1308716496.18119.8.camel@sauron>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
	<1308716496.18119.8.camel@sauron>
Message-ID: <BANLkTimc-syC35X8Tej2w3owyXZttU0wKw@mail.gmail.com>

On 6/22/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> I see a lot of checkpatch.pl warnings, could you please take a look?
>
> Also, my gcc produces warnings with this patch because you have not
> fixed up MPT parsers, e.g., like this:

Sorry, I was also busy that time and forgot about this :)

BTW: the patches should be applicable clearly to the l2-mtd at the time
I've sent them.

I'll fix all of your comments except this one:

> Could you please embrace the origin field into an anonymous union - once
> we add the of_node field they do not have to be at separate addresses. I
> mean:
>
> struct mtd_part_parser_data {
> 	union {
> 		unsigned long origin;
> 		struct device_node *of_node;
> 	};
> };

No, no and no. This data is passed to all parsers, so it should be valid for all
of them. Either we have to add a way to specify, what exactly we have provided,
or we have to leave data as separate struct fields.

-- 
With best wishes
Dmitry


From glecerf at gmail.com  Wed Jun 22 04:30:07 2011
From: glecerf at gmail.com (Guillaume LECERF)
Date: Wed, 22 Jun 2011 10:30:07 +0200
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
In-Reply-To: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
References: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
Message-ID: <BANLkTimj-1sFRG9hkcFfu0yjpUa4eeP5qA@mail.gmail.com>

Hi Mike,

2011/6/22 Mike Frysinger <vapier.adi at gmail.com>:
> the current mkfs.jffs2 util has in its --eraseblock handling:
> /* If it's less than 8KiB, they're not allowed */
> if (erase_block_size < 0x2000) {
> ? ?fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
> ? ? ? ?erase_block_size);
> ? ?erase_block_size = 0x2000;
> }
>
> but i cant seem to find documentation on where this comes from. ?it's
> not uncommon to have SPI flashes with 4KiB erase sectors, and removing
> this sanity check and allowing 4 KiB seems to produce an image that
> works OK.
>
> am i missing something ? ?or should i send a patch to drop this check ?

This has already be pointed by Fabio Giovagnini :
http://lists.infradead.org/pipermail/linux-mtd/2011-February/033992.html
He patched mkfs.jffs2 to allow "--eraseblock=0x1000" and he reported
it works ok.

AFAIK, there should be no problem removing this sanity check.
Artem, david, objections ?

-- 
Guillaume LECERF
GeeXboX developer - www.geexbox.org


From dedekind1 at gmail.com  Wed Jun 22 04:55:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 11:55:36 +0300
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <BANLkTimc-syC35X8Tej2w3owyXZttU0wKw@mail.gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
	<1308716496.18119.8.camel@sauron>
	<BANLkTimc-syC35X8Tej2w3owyXZttU0wKw@mail.gmail.com>
Message-ID: <1308732940.18119.55.camel@sauron>

On Wed, 2011-06-22 at 12:21 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/22/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > I see a lot of checkpatch.pl warnings, could you please take a look?
> >
> > Also, my gcc produces warnings with this patch because you have not
> > fixed up MPT parsers, e.g., like this:
> 
> Sorry, I was also busy that time and forgot about this :)
> 
> BTW: the patches should be applicable clearly to the l2-mtd at the time
> I've sent them.
> 
> I'll fix all of your comments except this one:
> 
> > Could you please embrace the origin field into an anonymous union - once
> > we add the of_node field they do not have to be at separate addresses. I
> > mean:
> >
> > struct mtd_part_parser_data {
> > 	union {
> > 		unsigned long origin;
> > 		struct device_node *of_node;
> > 	};
> > };
> 
> No, no and no. This data is passed to all parsers, so it should be valid for all
> of them. Either we have to add a way to specify, what exactly we have provided,
> or we have to leave data as separate struct fields.

I do not see why we should waste memory - union will work well. This is
parser-specific object and the parser should know which fields belong to
him. And this object is not shared between parsers so they cannot screw
each other. Yes, this is not the most beautiful way to go, but it is
simple enough and suits this situation, I think.

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Wed Jun 22 05:05:20 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:05:20 +0400
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <1308732940.18119.55.camel@sauron>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
	<1308716496.18119.8.camel@sauron>
	<BANLkTimc-syC35X8Tej2w3owyXZttU0wKw@mail.gmail.com>
	<1308732940.18119.55.camel@sauron>
Message-ID: <BANLkTimFJsAv+u7i_csaBrQpsORze1uWOw@mail.gmail.com>

On 6/22/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-22 at 12:21 +0400, Dmitry Eremin-Solenikov wrote:
>> On 6/22/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> > I see a lot of checkpatch.pl warnings, could you please take a look?
>> >
>> > Also, my gcc produces warnings with this patch because you have not
>> > fixed up MPT parsers, e.g., like this:
>>
>> Sorry, I was also busy that time and forgot about this :)
>>
>> BTW: the patches should be applicable clearly to the l2-mtd at the time
>> I've sent them.
>>
>> I'll fix all of your comments except this one:
>>
>> > Could you please embrace the origin field into an anonymous union - once
>> > we add the of_node field they do not have to be at separate addresses. I
>> > mean:
>> >
>> > struct mtd_part_parser_data {
>> > 	union {
>> > 		unsigned long origin;
>> > 		struct device_node *of_node;
>> > 	};
>> > };
>>
>> No, no and no. This data is passed to all parsers, so it should be valid
>> for all
>> of them. Either we have to add a way to specify, what exactly we have
>> provided,
>> or we have to leave data as separate struct fields.
>
> I do not see why we should waste memory - union will work well. This is
> parser-specific object and the parser should know which fields belong to
> him. And this object is not shared between parsers so they cannot screw
> each other. Yes, this is not the most beautiful way to go, but it is
> simple enough and suits this situation, I think.

It _is_ shared between parsers. See: driver creates one mtd_part_parser_data
instance, populates it and passes to parse_mtd_partitions (directly or
indirectly).
Then each parser uses the same object to get data. Consider what will happen
when ixp4xx driver (which currently uses origin for RedBoot) will also gain
OF support (as it's expected for all ARM-related things). It will set both
origin (for RedBoot) and of_node (for ofpart).

-- 
With best wishes
Dmitry


From dbaryshkov at gmail.com  Wed Jun 22 05:12:37 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 09:12:37 +0000 (UTC)
Subject: [PATCH v2 2/4] mtd: nand: convert printk() to pr_*()
References: <1307544227.31223.115.camel@localhost>
	<1307557519-31269-1-git-send-email-computersforpeace@gmail.com>
	<1307605456.7374.35.camel@localhost>
	<BANLkTin5KLu8QknuM4ATHpLQP4Uq09tekA@mail.gmail.com>
	<1307635412.7374.128.camel@localhost>
	<BANLkTimh12AhqfE+Yx3Yi_m=NyUb34JoXA@mail.gmail.com>
	<1308717655.18119.19.camel@sauron>
Message-ID: <itsbm4$d29$1@dough.gmane.org>

Artem Bityutskiy wrote:

> On Mon, 2011-06-13 at 11:24 -0700, Brian Norris wrote:
>> I'm a little new to the Linux device model, so I'm not sure if it's
>> safe and sensible to add lines to a driver's nand_probe function,
>> like, for plat_nand.c:
>> data->mtd.dev.driver = pdev->dev.driver;

IIUC, we should not set driver, but it might be better to consult with
more experienced DM hackers (like Greg Kroah-Hartman).

>> data->mtd.dev.init_name = dev_name(&pdev->dev);
>
> I think so, I believe struct device was added to mtd by some non-MTD guy
> to just make it complaint with one of interface changes which required
> struct device. So please, go ahead and improve that a bit.
-- 
With best wishes
Dmitry





From dedekind1 at gmail.com  Wed Jun 22 05:16:29 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 12:16:29 +0300
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <BANLkTimFJsAv+u7i_csaBrQpsORze1uWOw@mail.gmail.com>
References: <1307833922-21602-1-git-send-email-dbaryshkov@gmail.com>
	<1307833922-21602-2-git-send-email-dbaryshkov@gmail.com>
	<1308716496.18119.8.camel@sauron>
	<BANLkTimc-syC35X8Tej2w3owyXZttU0wKw@mail.gmail.com>
	<1308732940.18119.55.camel@sauron>
	<BANLkTimFJsAv+u7i_csaBrQpsORze1uWOw@mail.gmail.com>
Message-ID: <1308734194.18119.56.camel@sauron>

On Wed, 2011-06-22 at 13:05 +0400, Dmitry Eremin-Solenikov wrote:
> >> No, no and no. This data is passed to all parsers, so it should be valid
> >> for all
> >> of them. Either we have to add a way to specify, what exactly we have
> >> provided,
> >> or we have to leave data as separate struct fields.
> >
> > I do not see why we should waste memory - union will work well. This is
> > parser-specific object and the parser should know which fields belong to
> > him. And this object is not shared between parsers so they cannot screw
> > each other. Yes, this is not the most beautiful way to go, but it is
> > simple enough and suits this situation, I think.
> 
> It _is_ shared between parsers. See: driver creates one mtd_part_parser_data
> instance, populates it and passes to parse_mtd_partitions (directly or
> indirectly).
> Then each parser uses the same object to get data. Consider what will happen
> when ixp4xx driver (which currently uses origin for RedBoot) will also gain
> OF support (as it's expected for all ARM-related things). It will set both
> origin (for RedBoot) and of_node (for ofpart).

Agree, please, ignore that part of my feedback.

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Wed Jun 22 05:37:34 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:34 +0400
Subject: [PATCH V2 00/18] mtd: cleanup partition handling in OF-enabled drivers
Message-ID: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>

Changes since V1:
 * Tab-vs-space cleanup
 * 80-column cleanup
 * documented of_node parser data field
 * changed documentation for parser_data arguments

The following changes since commit 6a146696fdcf383d90753145dfb367e499790940:

  mtd: nand_base: always initialise oob_poi before writing OOB data (2011-06-22 08:50:28 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup

Dmitry Eremin-Solenikov (18):
      mtd: abstract last MTD partition parser argument
      mtd: prepare to convert of_mtd_parse_partitions to partition parser
      mtd: physmap_of: use ofpart through generic parsing
      mtd: m25p80: use ofpart through generic parsing
      mtd: fsl_elbc_nand: use ofpart through generic parsing
      mtd: fsl_upm: use ofpart through generic parsing
      mtd: mpc5121_nfc: use ofpart through generic parsing
      mtd: ndfc: use ofpart through generic parsing
      mtd: socrates_nand: use ofpart through generic parsing
      mtd: drop of_mtd_parse_partitions()
      mtd: physmap_of: move parse_obsolete_partitions to become separate parser
      mtd: physmap_of.c: use mtd_device_parse_register
      mtd: m25p80.c: use mtd_device_parse_register
      mtd: fsl_elbc_nand.c: use mtd_device_parse_register
      mtd: fsl_upm.c: use mtd_device_parse_register
      mtd: mpc5121_nfc.c: use mtd_device_parse_register
      mtd: ndfc.c: use mtd_device_parse_register
      mtd: socrates_nand.c: use mtd_device_parse_register

 drivers/mtd/afs.c                |    4 +-
 drivers/mtd/ar7part.c            |    2 +-
 drivers/mtd/cmdlinepart.c        |    4 +-
 drivers/mtd/devices/m25p80.c     |   37 ++------------
 drivers/mtd/maps/physmap_of.c    |   80 +++--------------------------
 drivers/mtd/mtdcore.c            |    6 +-
 drivers/mtd/mtdpart.c            |   15 ++++--
 drivers/mtd/nand/fsl_elbc_nand.c |   18 ++-----
 drivers/mtd/nand/fsl_upm.c       |   13 +----
 drivers/mtd/nand/mpc5121_nfc.c   |   17 +-----
 drivers/mtd/nand/ndfc.c          |   16 +-----
 drivers/mtd/nand/socrates_nand.c |   23 +-------
 drivers/mtd/ofpart.c             |  104 ++++++++++++++++++++++++++++++++++++--
 drivers/mtd/redboot.c            |   13 ++---
 include/linux/mtd/mtd.h          |    3 +-
 include/linux/mtd/partitions.h   |   36 +++++++-------
 16 files changed, 172 insertions(+), 219 deletions(-)



From dbaryshkov at gmail.com  Wed Jun 22 05:37:35 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:35 +0400
Subject: [PATCH 01/18] mtd: abstract last MTD partition parser argument
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-2-git-send-email-dbaryshkov@gmail.com>

Encapsulate last MTD partition parser argument into a separate
structure. Currently it holds only 'origin' field for RedBoot parser,
but will be extended in future to contain at least device_node for OF
devices.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/afs.c              |    4 ++--
 drivers/mtd/ar7part.c          |    2 +-
 drivers/mtd/cmdlinepart.c      |    4 ++--
 drivers/mtd/mtdcore.c          |    6 +++---
 drivers/mtd/mtdpart.c          |    7 ++++---
 drivers/mtd/redboot.c          |   13 ++++++-------
 include/linux/mtd/mtd.h        |    3 ++-
 include/linux/mtd/partitions.h |   16 ++++++++++++++--
 8 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/drivers/mtd/afs.c b/drivers/mtd/afs.c
index 302372c..89a02f6 100644
--- a/drivers/mtd/afs.c
+++ b/drivers/mtd/afs.c
@@ -162,8 +162,8 @@ afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
 }
 
 static int parse_afs_partitions(struct mtd_info *mtd,
-                         struct mtd_partition **pparts,
-                         unsigned long origin)
+				struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data)
 {
 	struct mtd_partition *parts;
 	u_int mask, off, idx, sz;
diff --git a/drivers/mtd/ar7part.c b/drivers/mtd/ar7part.c
index 6697a1e..71bfa2e 100644
--- a/drivers/mtd/ar7part.c
+++ b/drivers/mtd/ar7part.c
@@ -46,7 +46,7 @@ struct ar7_bin_rec {
 
 static int create_mtd_partitions(struct mtd_info *master,
 				 struct mtd_partition **pparts,
-				 unsigned long origin)
+				 struct mtd_part_parser_data *data)
 {
 	struct ar7_bin_rec header;
 	unsigned int offset;
diff --git a/drivers/mtd/cmdlinepart.c b/drivers/mtd/cmdlinepart.c
index be0c121..1b11f94 100644
--- a/drivers/mtd/cmdlinepart.c
+++ b/drivers/mtd/cmdlinepart.c
@@ -313,8 +313,8 @@ static int mtdpart_setup_real(char *s)
  * the first one in the chain if a NULL mtd_id is passed in.
  */
 static int parse_cmdline_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long origin)
+				    struct mtd_partition **pparts,
+				    struct mtd_part_parser_data *data)
 {
 	unsigned long offset;
 	int i;
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 1326747..e186399 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -457,7 +457,7 @@ EXPORT_SYMBOL_GPL(mtd_device_register);
  * @mtd: the MTD device to register
  * @types: the list of MTD partition probes to try, see
  *         'parse_mtd_partitions()' for more information
- * @origin: start address of MTD device, %0 unless you are sure you need this.
+ * @parser_data: MTD partition parser-specific data
  * @parts: fallback partition information to register, if parsing fails;
  *         only valid if %nr_parts > %0
  * @nr_parts: the number of partitions in parts, if zero then the full
@@ -480,14 +480,14 @@ EXPORT_SYMBOL_GPL(mtd_device_register);
  * Returns zero in case of success and a negative error code in case of failure.
  */
 int mtd_device_parse_register(struct mtd_info *mtd, const char **types,
-			      unsigned long origin,
+			      struct mtd_part_parser_data *parser_data,
 			      const struct mtd_partition *parts,
 			      int nr_parts)
 {
 	int err;
 	struct mtd_partition *real_parts;
 
-	err = parse_mtd_partitions(mtd, types, &real_parts, origin);
+	err = parse_mtd_partitions(mtd, types, &real_parts, parser_data);
 	if (err <= 0 && nr_parts) {
 		real_parts = kmemdup(parts, sizeof(*parts) * nr_parts,
 				     GFP_KERNEL);
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 2b71ccb..34d582c 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -736,7 +736,7 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  * @master: the master partition (describes whole MTD device)
  * @types: names of partition parsers to try or %NULL
  * @pparts: array of partitions found is returned here
- * @origin: MTD device start address (use %0 if unsure)
+ * @data: MTD partition parser-specific data
  *
  * This function tries to find partition on MTD device @master. It uses MTD
  * partition parsers, specified in @types. However, if @types is %NULL, then
@@ -750,7 +750,8 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  *   point to an array containing this number of &struct mtd_info objects.
  */
 int parse_mtd_partitions(struct mtd_info *master, const char **types,
-			 struct mtd_partition **pparts, unsigned long origin)
+			 struct mtd_partition **pparts,
+			 struct mtd_part_parser_data *data)
 {
 	struct mtd_part_parser *parser;
 	int ret = 0;
@@ -764,7 +765,7 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 				parser = get_partition_parser(*types);
 		if (!parser)
 			continue;
-		ret = (*parser->parse_fn)(master, pparts, origin);
+		ret = (*parser->parse_fn)(master, pparts, data);
 		if (ret > 0) {
 			printk(KERN_NOTICE "%d %s partitions found on MTD device %s\n",
 			       ret, parser->name, master->name);
diff --git a/drivers/mtd/redboot.c b/drivers/mtd/redboot.c
index 7a87d07..56e48ea 100644
--- a/drivers/mtd/redboot.c
+++ b/drivers/mtd/redboot.c
@@ -56,8 +56,8 @@ static inline int redboot_checksum(struct fis_image_desc *img)
 }
 
 static int parse_redboot_partitions(struct mtd_info *master,
-                             struct mtd_partition **pparts,
-                             unsigned long fis_origin)
+				    struct mtd_partition **pparts,
+				    struct mtd_part_parser_data *data)
 {
 	int nrparts = 0;
 	struct fis_image_desc *buf;
@@ -197,11 +197,10 @@ static int parse_redboot_partitions(struct mtd_info *master,
 			goto out;
 		}
 		new_fl->img = &buf[i];
-                if (fis_origin) {
-                        buf[i].flash_base -= fis_origin;
-                } else {
-                        buf[i].flash_base &= master->size-1;
-                }
+		if (data && data->origin)
+			buf[i].flash_base -= data->origin;
+		else
+			buf[i].flash_base &= master->size-1;
 
 		/* I'm sure the JFFS2 code has done me permanent damage.
 		 * I now think the following is _normal_
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index d28a241..b2b454b 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -323,13 +323,14 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
 	/* Kernel-side ioctl definitions */
 
 struct mtd_partition;
+struct mtd_part_parser_data;
 
 extern int mtd_device_register(struct mtd_info *master,
 			       const struct mtd_partition *parts,
 			       int nr_parts);
 extern int mtd_device_parse_register(struct mtd_info *mtd,
 			      const char **part_probe_types,
-			      unsigned long origin,
+			      struct mtd_part_parser_data *parser_data,
 			      const struct mtd_partition *defparts,
 			      int defnr_parts);
 extern int mtd_device_unregister(struct mtd_info *master);
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 1431cf2..df125fa 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -52,6 +52,16 @@ struct mtd_partition {
 
 struct mtd_info;
 
+/**
+ * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
+ * @origin: for RedBoot, start address of MTD device,
+ *					%0 unless you are sure you need this.
+ */
+struct mtd_part_parser_data {
+	unsigned long origin;
+};
+
+
 /*
  * Functions dealing with the various ways of partitioning the space
  */
@@ -60,13 +70,15 @@ struct mtd_part_parser {
 	struct list_head list;
 	struct module *owner;
 	const char *name;
-	int (*parse_fn)(struct mtd_info *, struct mtd_partition **, unsigned long);
+	int (*parse_fn)(struct mtd_info *, struct mtd_partition **,
+			struct mtd_part_parser_data *);
 };
 
 extern int register_mtd_parser(struct mtd_part_parser *parser);
 extern int deregister_mtd_parser(struct mtd_part_parser *parser);
 extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
-				struct mtd_partition **pparts, unsigned long origin);
+				struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data);
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:37 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:37 +0400
Subject: [PATCH 03/18] mtd: physmap_of: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-4-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   13 +++++--------
 1 files changed, 5 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index d251d1d..6a75743 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -165,7 +165,8 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    specifies the list of partition probers to use. If none is given then the
    default is use. These take precedence over other device tree
    information. */
-static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot", NULL };
+static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
+					"ofpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -218,6 +219,7 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	int reg_tuple_size;
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
+	struct mtd_part_parser_data ppdata;
 
 	match = of_match_device(of_flash_match, &dev->dev);
 	if (!match)
@@ -331,9 +333,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	if (err)
 		goto err_out;
 
+	ppdata.of_node = dp;
 	part_probe_types = of_get_probes(dp);
 	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, 0);
+				   &info->parts, &ppdata);
 	if (err < 0) {
 		of_free_probes(part_probe_types);
 		goto err_out;
@@ -341,12 +344,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	of_free_probes(part_probe_types);
 
 	if (err == 0) {
-		err = of_mtd_parse_partitions(&dev->dev, dp, &info->parts);
-		if (err < 0)
-			goto err_out;
-	}
-
-	if (err == 0) {
 		err = parse_obsolete_partitions(dev, info, dp);
 		if (err < 0)
 			goto err_out;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:36 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:36 +0400
Subject: [PATCH 02/18] mtd: prepare to convert of_mtd_parse_partitions to
	partition parser
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-3-git-send-email-dbaryshkov@gmail.com>

Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
1) Register ofpart parser
2) Internally don't use passed device for error printing
3) Add device_node to mtd_part_parser_data struct
4) Move of_mtd_parse_partitions from __devinit to common text section
5) add ofpart to the default list of partition parsers

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdpart.c          |    8 ++++++--
 drivers/mtd/ofpart.c           |   27 +++++++++++++++++++++++++--
 include/linux/mtd/partitions.h |    6 +++++-
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 34d582c..9e8ee05 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -729,7 +729,11 @@ EXPORT_SYMBOL_GPL(deregister_mtd_parser);
  * Do not forget to update 'parse_mtd_partitions()' kerneldoc comment if you
  * are changing this array!
  */
-static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
+static const char *default_mtd_part_types[] = {
+	"cmdlinepart",
+	"ofpart",
+	NULL
+};
 
 /**
  * parse_mtd_partitions - parse MTD partitions
@@ -741,7 +745,7 @@ static const char *default_mtd_part_types[] = {"cmdlinepart", NULL};
  * This function tries to find partition on MTD device @master. It uses MTD
  * partition parsers, specified in @types. However, if @types is %NULL, then
  * the default list of parsers is used. The default list contains only the
- * "cmdlinepart" parser ATM.
+ * "cmdlinepart" and "ofpart" parsers ATM.
  *
  * This function may return:
  * o a negative error code in case of failure
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index a996718..7c2c926 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -20,7 +20,17 @@
 #include <linux/slab.h>
 #include <linux/mtd/partitions.h>
 
-int __devinit of_mtd_parse_partitions(struct device *dev,
+static int parse_ofpart_partitions(struct mtd_info *master,
+				   struct mtd_partition **pparts,
+				   struct mtd_part_parser_data *data)
+{
+	if (!data || !data->of_node)
+		return 0;
+
+	return of_mtd_parse_partitions(NULL, data->of_node, pparts);
+}
+
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts)
 {
@@ -69,7 +79,7 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 
 	if (!i) {
 		of_node_put(pp);
-		dev_err(dev, "No valid partition found on %s\n", node->full_name);
+		pr_err("No valid partition found on %s\n", node->full_name);
 		kfree(*pparts);
 		*pparts = NULL;
 		return -EINVAL;
@@ -79,4 +89,17 @@ int __devinit of_mtd_parse_partitions(struct device *dev,
 }
 EXPORT_SYMBOL(of_mtd_parse_partitions);
 
+static struct mtd_part_parser ofpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofpart_partitions,
+	.name = "ofpart",
+};
+
+static int __init ofpart_parser_init(void)
+{
+	return register_mtd_parser(&ofpart_parser);
+}
+
+module_init(ofpart_parser_init);
+
 MODULE_LICENSE("GPL");
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index df125fa..6e724af 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -51,14 +51,18 @@ struct mtd_partition {
 
 
 struct mtd_info;
+struct device_node;
 
 /**
  * struct mtd_part_parser_data - used to pass data to MTD partition parsers.
  * @origin: for RedBoot, start address of MTD device,
  *					%0 unless you are sure you need this.
+ * @of_node: for OpenFirmware based parsers, pass device node containing
+ *					partitioning information
  */
 struct mtd_part_parser_data {
 	unsigned long origin;
+	struct device_node *of_node;
 };
 
 
@@ -86,7 +90,7 @@ struct device;
 struct device_node;
 
 #ifdef CONFIG_MTD_OF_PARTS
-int __devinit of_mtd_parse_partitions(struct device *dev,
+int of_mtd_parse_partitions(struct device *dev,
                                       struct device_node *node,
                                       struct mtd_partition **pparts);
 #else
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:38 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:38 +0400
Subject: [PATCH 04/18] mtd: m25p80: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-5-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 70d5fca..399c234 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -827,6 +827,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	unsigned			i;
 	struct mtd_partition		*parts = NULL;
 	int				nr_parts = 0;
+	struct mtd_part_parser_data	ppdata;
 
 	/* Platform data helps sort out which chip type we have, as
 	 * well as how this board partitions it.  If we don't have
@@ -928,6 +929,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	if (info->flags & M25P_NO_ERASE)
 		flash->mtd.flags |= MTD_NO_ERASE;
 
+	ppdata.of_node = spi->dev.of_node;
 	flash->mtd.dev.parent = &spi->dev;
 	flash->page_size = info->page_size;
 
@@ -968,20 +970,13 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, 0);
+	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, &ppdata);
 
 	if (nr_parts <= 0 && data && data->parts) {
 		parts = data->parts;
 		nr_parts = data->nr_parts;
 	}
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (nr_parts <= 0 && spi->dev.of_node) {
-		nr_parts = of_mtd_parse_partitions(&spi->dev,
-						   spi->dev.of_node, &parts);
-	}
-#endif
-
 	if (nr_parts > 0) {
 		for (i = 0; i < nr_parts; i++) {
 			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:39 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:39 +0400
Subject: [PATCH 05/18] mtd: fsl_elbc_nand: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-6-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |   12 ++++--------
 1 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index d4ea5fe..4d225ba 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -842,13 +842,15 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct resource res;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
-		= { "cmdlinepart", "RedBoot", NULL };
+		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
 	struct mtd_partition *parts;
 	int ret;
 	int bank;
 	struct device *dev;
 	struct device_node *node = pdev->dev.of_node;
+	struct mtd_part_parser_data ppdata;
 
+	ppdata.of_node = pdev->dev.of_node;
 	if (!fsl_lbc_ctrl_dev || !fsl_lbc_ctrl_dev->regs)
 		return -ENODEV;
 	lbc = fsl_lbc_ctrl_dev->regs;
@@ -934,16 +936,10 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, 0);
+	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, &ppdata);
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(priv->dev, node, &parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	mtd_device_register(&priv->mtd, parts, ret);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:40 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:40 +0400
Subject: [PATCH 06/18] mtd: fsl_upm: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-7-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 7c782eb..714d831 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -158,6 +158,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 {
 	int ret;
 	struct device_node *flash_np;
+	struct mtd_part_parser_data ppdata;
 
 	fun->chip.IO_ADDR_R = fun->io_base;
 	fun->chip.IO_ADDR_W = fun->io_base;
@@ -191,15 +192,9 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, 0);
+	ppdata.of_node = flash_np;
+	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, &ppdata);
 
-#ifdef CONFIG_MTD_OF_PARTS
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(fun->dev, flash_np, &fun->parts);
-		if (ret < 0)
-			goto err;
-	}
-#endif
 	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
 err:
 	of_node_put(flash_np);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:41 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:41 +0400
Subject: [PATCH 07/18] mtd: mpc5121_nfc: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-8-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 0b61367..996ee29 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -661,6 +661,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	int resettime = 0;
 	int retval = 0;
 	int rev, len;
+	struct mtd_part_parser_data ppdata;
 
 	/*
 	 * Check SoC revision. This driver supports only NFC
@@ -725,6 +726,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	}
 
 	mtd->name = "MPC5121 NAND";
+	ppdata.of_node = dn;
 	chip->dev_ready = mpc5121_nfc_dev_ready;
 	chip->cmdfunc = mpc5121_nfc_command;
 	chip->read_byte = mpc5121_nfc_read_byte;
@@ -836,11 +838,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, NULL, &parts, 0);
-#ifdef CONFIG_MTD_OF_PARTS
-	if (retval == 0)
-		retval = of_mtd_parse_partitions(dev, dn, &parts);
-#endif
+	retval = parse_mtd_partitions(mtd, NULL, &parts, &ppdata);
 	if (retval < 0) {
 		dev_err(dev, "Error parsing MTD partitions!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:42 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:42 +0400
Subject: [PATCH 08/18] mtd: ndfc: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-9-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 70c04ff..1528734 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -161,6 +161,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 {
 	struct device_node *flash_np;
 	struct nand_chip *chip = &ndfc->chip;
+	struct mtd_part_parser_data ppdata;
 	int ret;
 
 	chip->IO_ADDR_R = ndfc->ndfcbase + NDFC_DATA;
@@ -188,6 +189,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (!flash_np)
 		return -ENODEV;
 
+	ppdata->of_node = flash_np;
 	ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s",
 			dev_name(&ndfc->ofdev->dev), flash_np->name);
 	if (!ndfc->mtd.name) {
@@ -199,17 +201,10 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, 0);
+	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, &ppdata);
 	if (ret < 0)
 		goto err;
 
-	if (ret == 0) {
-		ret = of_mtd_parse_partitions(&ndfc->ofdev->dev, flash_np,
-					      &ndfc->parts);
-		if (ret < 0)
-			goto err;
-	}
-
 	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
 
 err:
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:43 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:43 +0400
Subject: [PATCH 09/18] mtd: socrates_nand: use ofpart through generic parsing
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-10-git-send-email-dbaryshkov@gmail.com>

Convert the driver to use ofpart partitions parsing through the generic
parse_mtd_partitions().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   14 +++-----------
 1 files changed, 3 insertions(+), 11 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index 9023ac8..f4f79ec 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -166,6 +166,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	int res;
 	struct mtd_partition *partitions = NULL;
 	int num_partitions = 0;
+	struct mtd_part_parser_data ppdata;
 
 	/* Allocate memory for the device structure (and zero it) */
 	host = kzalloc(sizeof(struct socrates_nand_host), GFP_KERNEL);
@@ -191,6 +192,7 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	mtd->name = "socrates_nand";
 	mtd->owner = THIS_MODULE;
 	mtd->dev.parent = &ofdev->dev;
+	ppdata.of_node = ofdev->dev.of_node;
 
 	/*should never be accessed directly */
 	nand_chip->IO_ADDR_R = (void *)0xdeadbeef;
@@ -223,22 +225,12 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, 0);
+	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, &ppdata);
 	if (num_partitions < 0) {
 		res = num_partitions;
 		goto release;
 	}
 
-	if (num_partitions == 0) {
-		num_partitions = of_mtd_parse_partitions(&ofdev->dev,
-							 ofdev->dev.of_node,
-							 &partitions);
-		if (num_partitions < 0) {
-			res = num_partitions;
-			goto release;
-		}
-	}
-
 	res = mtd_device_register(mtd, partitions, num_partitions);
 	if (!res)
 		return res;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:44 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:44 +0400
Subject: [PATCH 10/18] mtd: drop of_mtd_parse_partitions()
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-11-git-send-email-dbaryshkov@gmail.com>

All users have been converted to call of_mtd_parse_partitions through
parse_mtd_partitions() multiplexer. Drop obsolete API.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/ofpart.c           |   20 +++++++++-----------
 include/linux/mtd/partitions.h |   16 ----------------
 2 files changed, 9 insertions(+), 27 deletions(-)

diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 7c2c926..24007f3 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -24,20 +24,19 @@ static int parse_ofpart_partitions(struct mtd_info *master,
 				   struct mtd_partition **pparts,
 				   struct mtd_part_parser_data *data)
 {
-	if (!data || !data->of_node)
-		return 0;
-
-	return of_mtd_parse_partitions(NULL, data->of_node, pparts);
-}
-
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts)
-{
+	struct device_node *node;
 	const char *partname;
 	struct device_node *pp;
 	int nr_parts, i;
 
+
+	if (!data)
+		return 0;
+
+	node = data->of_node;
+	if (!node)
+		return 0;
+
 	/* First count the subnodes */
 	pp = NULL;
 	nr_parts = 0;
@@ -87,7 +86,6 @@ int of_mtd_parse_partitions(struct device *dev,
 
 	return nr_parts;
 }
-EXPORT_SYMBOL(of_mtd_parse_partitions);
 
 static struct mtd_part_parser ofpart_parser = {
 	.owner = THIS_MODULE,
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index 6e724af..c3dcf35 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -86,22 +86,6 @@ extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-struct device;
-struct device_node;
-
-#ifdef CONFIG_MTD_OF_PARTS
-int of_mtd_parse_partitions(struct device *dev,
-                                      struct device_node *node,
-                                      struct mtd_partition **pparts);
-#else
-static inline int of_mtd_parse_partitions(struct device *dev,
-					  struct device_node *node,
-					  struct mtd_partition **pparts)
-{
-	return 0;
-}
-#endif
-
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
 		      long long offset, long long length);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:45 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:45 +0400
Subject: [PATCH 11/18] mtd: physmap_of: move parse_obsolete_partitions to
	become separate parser
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-12-git-send-email-dbaryshkov@gmail.com>

Move parse_obsolete_partitions() to ofpart.c and register it as an
ofoldpart partitions parser.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   53 +----------------------------
 drivers/mtd/ofpart.c          |   75 ++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 75 insertions(+), 53 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 6a75743..55c4e2e 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -40,51 +40,6 @@ struct of_flash {
 };
 
 #define OF_FLASH_PARTS(info)	((info)->parts)
-static int parse_obsolete_partitions(struct platform_device *dev,
-				     struct of_flash *info,
-				     struct device_node *dp)
-{
-	int i, plen, nr_parts;
-	const struct {
-		__be32 offset, len;
-	} *part;
-	const char *names;
-
-	part = of_get_property(dp, "partitions", &plen);
-	if (!part)
-		return 0; /* No partitions found */
-
-	dev_warn(&dev->dev, "Device tree uses obsolete partition map binding\n");
-
-	nr_parts = plen / sizeof(part[0]);
-
-	info->parts = kzalloc(nr_parts * sizeof(*info->parts), GFP_KERNEL);
-	if (!info->parts)
-		return -ENOMEM;
-
-	names = of_get_property(dp, "partition-names", &plen);
-
-	for (i = 0; i < nr_parts; i++) {
-		info->parts[i].offset = be32_to_cpu(part->offset);
-		info->parts[i].size   = be32_to_cpu(part->len) & ~1;
-		if (be32_to_cpu(part->len) & 1) /* bit 0 set signifies read only partition */
-			info->parts[i].mask_flags = MTD_WRITEABLE;
-
-		if (names && (plen > 0)) {
-			int len = strlen(names) + 1;
-
-			info->parts[i].name = (char *)names;
-			plen -= len;
-			names += len;
-		} else {
-			info->parts[i].name = "unnamed";
-		}
-
-		part++;
-	}
-
-	return nr_parts;
-}
 
 static int of_flash_remove(struct platform_device *dev)
 {
@@ -166,7 +121,7 @@ static struct mtd_info * __devinit obsolete_probe(struct platform_device *dev,
    default is use. These take precedence over other device tree
    information. */
 static const char *part_probe_types_def[] = { "cmdlinepart", "RedBoot",
-					"ofpart", NULL };
+					"ofpart", "ofoldpart", NULL };
 static const char ** __devinit of_get_probes(struct device_node *dp)
 {
 	const char *cp;
@@ -343,12 +298,6 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 	}
 	of_free_probes(part_probe_types);
 
-	if (err == 0) {
-		err = parse_obsolete_partitions(dev, info, dp);
-		if (err < 0)
-			goto err_out;
-	}
-
 	mtd_device_register(info->cmtd, info->parts, err);
 
 	kfree(mtd_list);
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 24007f3..41c4518 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -93,9 +93,82 @@ static struct mtd_part_parser ofpart_parser = {
 	.name = "ofpart",
 };
 
+static int parse_ofoldpart_partitions(struct mtd_info *master,
+				      struct mtd_partition **pparts,
+				      struct mtd_part_parser_data *data)
+{
+	struct device_node *dp;
+	int i, plen, nr_parts;
+	const struct {
+		__be32 offset, len;
+	} *part;
+	const char *names;
+
+	if (!data)
+		return 0;
+
+	dp = data->of_node;
+	if (!dp)
+		return 0;
+
+	part = of_get_property(dp, "partitions", &plen);
+	if (!part)
+		return 0; /* No partitions found */
+
+	pr_warning("Device tree uses obsolete partition map binding: %s\n",
+			dp->full_name);
+
+	nr_parts = plen / sizeof(part[0]);
+
+	*pparts = kzalloc(nr_parts * sizeof(*(*pparts)), GFP_KERNEL);
+	if (!pparts)
+		return -ENOMEM;
+
+	names = of_get_property(dp, "partition-names", &plen);
+
+	for (i = 0; i < nr_parts; i++) {
+		(*pparts)[i].offset = be32_to_cpu(part->offset);
+		(*pparts)[i].size   = be32_to_cpu(part->len) & ~1;
+		/* bit 0 set signifies read only partition */
+		if (be32_to_cpu(part->len) & 1)
+			(*pparts)[i].mask_flags = MTD_WRITEABLE;
+
+		if (names && (plen > 0)) {
+			int len = strlen(names) + 1;
+
+			(*pparts)[i].name = (char *)names;
+			plen -= len;
+			names += len;
+		} else {
+			(*pparts)[i].name = "unnamed";
+		}
+
+		part++;
+	}
+
+	return nr_parts;
+}
+
+static struct mtd_part_parser ofoldpart_parser = {
+	.owner = THIS_MODULE,
+	.parse_fn = parse_ofoldpart_partitions,
+	.name = "ofoldpart",
+};
+
 static int __init ofpart_parser_init(void)
 {
-	return register_mtd_parser(&ofpart_parser);
+	int rc;
+	rc = register_mtd_parser(&ofpart_parser);
+	if (rc)
+		goto out;
+
+	rc = register_mtd_parser(&ofoldpart_parser);
+	if (!rc)
+		return 0;
+
+	deregister_mtd_parser(&ofoldpart_parser);
+out:
+	return rc;
 }
 
 module_init(ofpart_parser_init);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:46 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:46 +0400
Subject: [PATCH 12/18] mtd: physmap_of.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-13-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/physmap_of.c |   18 +++---------------
 1 files changed, 3 insertions(+), 15 deletions(-)

diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c
index 55c4e2e..7d65f9d 100644
--- a/drivers/mtd/maps/physmap_of.c
+++ b/drivers/mtd/maps/physmap_of.c
@@ -34,13 +34,10 @@ struct of_flash_list {
 
 struct of_flash {
 	struct mtd_info		*cmtd;
-	struct mtd_partition	*parts;
 	int list_size; /* number of elements in of_flash_list */
 	struct of_flash_list	list[0];
 };
 
-#define OF_FLASH_PARTS(info)	((info)->parts)
-
 static int of_flash_remove(struct platform_device *dev)
 {
 	struct of_flash *info;
@@ -56,11 +53,8 @@ static int of_flash_remove(struct platform_device *dev)
 		mtd_concat_destroy(info->cmtd);
 	}
 
-	if (info->cmtd) {
-		if (OF_FLASH_PARTS(info))
-			kfree(OF_FLASH_PARTS(info));
+	if (info->cmtd)
 		mtd_device_unregister(info->cmtd);
-	}
 
 	for (i = 0; i < info->list_size; i++) {
 		if (info->list[i].mtd)
@@ -290,16 +284,10 @@ static int __devinit of_flash_probe(struct platform_device *dev)
 
 	ppdata.of_node = dp;
 	part_probe_types = of_get_probes(dp);
-	err = parse_mtd_partitions(info->cmtd, part_probe_types,
-				   &info->parts, &ppdata);
-	if (err < 0) {
-		of_free_probes(part_probe_types);
-		goto err_out;
-	}
+	mtd_device_parse_register(info->cmtd, part_probe_types, &ppdata,
+			NULL, 0);
 	of_free_probes(part_probe_types);
 
-	mtd_device_register(info->cmtd, info->parts, err);
-
 	kfree(mtd_list);
 
 	return 0;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:48 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:48 +0400
Subject: [PATCH 14/18] mtd: fsl_elbc_nand.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-15-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    8 ++------
 1 files changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 4d225ba..915b4a4 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -843,7 +843,6 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl;
 	static const char *part_probe_types[]
 		= { "cmdlinepart", "RedBoot", "ofpart", NULL };
-	struct mtd_partition *parts;
 	int ret;
 	int bank;
 	struct device *dev;
@@ -936,11 +935,8 @@ static int __devinit fsl_elbc_nand_probe(struct platform_device *pdev)
 
 	/* First look for RedBoot table or partitions on the command
 	 * line, these take precedence over device tree information */
-	ret = parse_mtd_partitions(&priv->mtd, part_probe_types, &parts, &ppdata);
-	if (ret < 0)
-		goto err;
-
-	mtd_device_register(&priv->mtd, parts, ret);
+	mtd_device_parse_register(&priv->mtd, part_probe_types, &ppdata,
+				  NULL, 0);
 
 	printk(KERN_INFO "eLBC NAND device at 0x%llx, bank %d\n",
 	       (unsigned long long)res.start, priv->bank);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:47 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:47 +0400
Subject: [PATCH 13/18] mtd: m25p80.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-14-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/devices/m25p80.c |   28 +++-------------------------
 1 files changed, 3 insertions(+), 25 deletions(-)

diff --git a/drivers/mtd/devices/m25p80.c b/drivers/mtd/devices/m25p80.c
index 399c234..66a3555 100644
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -88,7 +88,6 @@ struct m25p {
 	struct spi_device	*spi;
 	struct mutex		lock;
 	struct mtd_info		mtd;
-	unsigned		partitioned:1;
 	u16			page_size;
 	u16			addr_width;
 	u8			erase_opcode;
@@ -825,8 +824,6 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	struct m25p			*flash;
 	struct flash_info		*info;
 	unsigned			i;
-	struct mtd_partition		*parts = NULL;
-	int				nr_parts = 0;
 	struct mtd_part_parser_data	ppdata;
 
 	/* Platform data helps sort out which chip type we have, as
@@ -970,28 +967,9 @@ static int __devinit m25p_probe(struct spi_device *spi)
 	/* partitions should match sector boundaries; and it may be good to
 	 * use readonly partitions for writeprotected sectors (BP2..BP0).
 	 */
-	nr_parts = parse_mtd_partitions(&flash->mtd, NULL, &parts, &ppdata);
-
-	if (nr_parts <= 0 && data && data->parts) {
-		parts = data->parts;
-		nr_parts = data->nr_parts;
-	}
-
-	if (nr_parts > 0) {
-		for (i = 0; i < nr_parts; i++) {
-			DEBUG(MTD_DEBUG_LEVEL2, "partitions[%d] = "
-			      "{.name = %s, .offset = 0x%llx, "
-			      ".size = 0x%llx (%lldKiB) }\n",
-			      i, parts[i].name,
-			      (long long)parts[i].offset,
-			      (long long)parts[i].size,
-			      (long long)(parts[i].size >> 10));
-		}
-		flash->partitioned = 1;
-	}
-
-	return mtd_device_register(&flash->mtd, parts, nr_parts) == 1 ?
-		-ENODEV : 0;
+	return mtd_device_parse_register(&flash->mtd, NULL, &ppdata,
+			data ? data->parts : NULL,
+			data ? data->nr_parts : 0);
 }
 
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:49 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:49 +0400
Subject: [PATCH 15/18] mtd: fsl_upm.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-16-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    4 +---
 1 files changed, 1 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index 714d831..da92fed 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -193,9 +193,7 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 		goto err;
 
 	ppdata.of_node = flash_np;
-	ret = parse_mtd_partitions(&fun->mtd, NULL, &fun->parts, &ppdata);
-
-	ret = mtd_device_register(&fun->mtd, fun->parts, ret);
+	ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
 err:
 	of_node_put(flash_np);
 	return ret;
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:50 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:50 +0400
Subject: [PATCH 16/18] mtd: mpc5121_nfc.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-17-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/mpc5121_nfc.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/mpc5121_nfc.c b/drivers/mtd/nand/mpc5121_nfc.c
index 996ee29..871095f 100644
--- a/drivers/mtd/nand/mpc5121_nfc.c
+++ b/drivers/mtd/nand/mpc5121_nfc.c
@@ -654,7 +654,6 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	struct mpc5121_nfc_prv *prv;
 	struct resource res;
 	struct mtd_info *mtd;
-	struct mtd_partition *parts;
 	struct nand_chip *chip;
 	unsigned long regs_paddr, regs_size;
 	const __be32 *chips_no;
@@ -838,15 +837,7 @@ static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 	dev_set_drvdata(dev, mtd);
 
 	/* Register device in MTD */
-	retval = parse_mtd_partitions(mtd, NULL, &parts, &ppdata);
-	if (retval < 0) {
-		dev_err(dev, "Error parsing MTD partitions!\n");
-		devm_free_irq(dev, prv->irq, mtd);
-		retval = -EINVAL;
-		goto error;
-	}
-
-	retval = mtd_device_register(mtd, parts, retval);
+	retval = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (retval) {
 		dev_err(dev, "Error adding MTD device!\n");
 		devm_free_irq(dev, prv->irq, mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:51 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:51 +0400
Subject: [PATCH 17/18] mtd: ndfc.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-18-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/ndfc.c |    7 +------
 1 files changed, 1 insertions(+), 6 deletions(-)

diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c
index 1528734..ee17139 100644
--- a/drivers/mtd/nand/ndfc.c
+++ b/drivers/mtd/nand/ndfc.c
@@ -42,7 +42,6 @@ struct ndfc_controller {
 	struct nand_chip chip;
 	int chip_select;
 	struct nand_hw_control ndfc_control;
-	struct mtd_partition *parts;
 };
 
 static struct ndfc_controller ndfc_ctrl[NDFC_MAX_CS];
@@ -201,11 +200,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc,
 	if (ret)
 		goto err;
 
-	ret = parse_mtd_partitions(&ndfc->mtd, NULL, &ndfc->parts, &ppdata);
-	if (ret < 0)
-		goto err;
-
-	ret = mtd_device_register(&ndfc->mtd, ndfc->parts, ret);
+	ret = mtd_device_parse_register(&ndfc->mtd, NULL, &ppdata, NULL, 0);
 
 err:
 	of_node_put(flash_np);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Wed Jun 22 05:37:52 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Wed, 22 Jun 2011 13:37:52 +0400
Subject: [PATCH 18/18] mtd: socrates_nand.c: use mtd_device_parse_register
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308735472-32640-19-git-send-email-dbaryshkov@gmail.com>

Replace custom invocations of parse_mtd_partitions and mtd_device_register
with common mtd_device_parse_register call. This would bring: standard
handling of all errors, fallback to default partitions, etc.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/socrates_nand.c |   11 +----------
 1 files changed, 1 insertions(+), 10 deletions(-)

diff --git a/drivers/mtd/nand/socrates_nand.c b/drivers/mtd/nand/socrates_nand.c
index f4f79ec..0fb24f9 100644
--- a/drivers/mtd/nand/socrates_nand.c
+++ b/drivers/mtd/nand/socrates_nand.c
@@ -164,8 +164,6 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 	struct mtd_info *mtd;
 	struct nand_chip *nand_chip;
 	int res;
-	struct mtd_partition *partitions = NULL;
-	int num_partitions = 0;
 	struct mtd_part_parser_data ppdata;
 
 	/* Allocate memory for the device structure (and zero it) */
@@ -225,17 +223,10 @@ static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 		goto out;
 	}
 
-	num_partitions = parse_mtd_partitions(mtd, NULL, &partitions, &ppdata);
-	if (num_partitions < 0) {
-		res = num_partitions;
-		goto release;
-	}
-
-	res = mtd_device_register(mtd, partitions, num_partitions);
+	res = mtd_device_parse_register(mtd, NULL, &ppdata, NULL, 0);
 	if (!res)
 		return res;
 
-release:
 	nand_release(mtd);
 
 out:
-- 
1.7.5.3



From adam.thomson at alcatel-lucent.com  Wed Jun 22 06:41:10 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Wed, 22 Jun 2011 12:41:10 +0200
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi
	before writing OOB data
In-Reply-To: <1308722112.18119.36.camel@sauron>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308722112.18119.36.camel@sauron>
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DD8D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

Artem Wrote:

>
> Added the -stable CC here and pushed to l2-mtd-2.6.git with
> some modifications.
>

This is probably my fault, but the mail previous to this had the
version which contained the stable line. That patch version (v3)did
not remove the final memset from nand_do_write_oob, as you requested.
Named both patches the same as they were pretty much indentical,
except for the memset. Didn't know the convention for patch naming
where one was going to stable, and the other to the latest so
marked the latest as upstream to differentiate.

> >   * nand_fill_oob - [Internal] Transfer client buffer to oob
> >   * @chip:  nand chip structure
> > + * @mtd:   MTD device 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,
> > -                                           struct mtd_oob_ops *ops)
> > +static uint8_t *nand_fill_oob(struct nand_chip *chip,
> struct mtd_info *mtd,
> > +                         uint8_t *oob, size_t len, struct
> mtd_oob_ops *ops)
> >  {
>
> Since we can get chip from mtd->prive, it is not necessary to
> pass both chip and mtd to this function, it is enough to only
> pass mtd.

Fair enough. Didn't spot that. :)

>
> I've done this modification, the resulting patch is here:
> http://git.infradead.org/users/dedekind/l2-mtd-2.6.git/commit/
6a146696fdcf383d90753145dfb367e499790940
>
> Would you please take a look and even better - give it a try?
>

Yep, no problem. Will run it up on target an check all still works.

> Thanks!
>
> --
> Best Regards,
> Artem Bityutskiy
>
> 

Thanks

Adam



From dedekind1 at gmail.com  Wed Jun 22 06:57:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 22 Jun 2011 13:57:04 +0300
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi
	before writing OOB data
In-Reply-To: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DD8D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308722112.18119.36.camel@sauron>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DD8D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
Message-ID: <1308740228.18119.70.camel@sauron>

On Wed, 2011-06-22 at 12:41 +0200, THOMSON, Adam (Adam) wrote:
> Artem Wrote:
> 
> >
> > Added the -stable CC here and pushed to l2-mtd-2.6.git with
> > some modifications.
> >
> 
> This is probably my fault, but the mail previous to this had the
> version which contained the stable line.

I did not figure out why you sent 2 separate patches. Usually it is one
patch which goes upstream, then GregKH and others pick it up and back
ports to various stable trees. If they have issues, they may come and
ask for help. So there should be 1 patch.

>  That patch version (v3)did
> not remove the final memset from nand_do_write_oob, as you requested.

Did I request so? I thought I just expressed a thought that the memset
is redundant and should be killed, and I thought you'd take a deeper
look and decide whether it is safe to do or not.

> Named both patches the same as they were pretty much indentical,
> except for the memset. Didn't know the convention for patch naming
> where one was going to stable, and the other to the latest so
> marked the latest as upstream to differentiate.

So do we need that memset or not? :-)

-- 
Best Regards,
Artem Bityutskiy



From adam.thomson at alcatel-lucent.com  Wed Jun 22 07:08:44 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Wed, 22 Jun 2011 13:08:44 +0200
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi
	before writing OOB data
In-Reply-To: <1308740228.18119.70.camel@sauron>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308722112.18119.36.camel@sauron>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DD8D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308740228.18119.70.camel@sauron>
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DDB3@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

Artem wrote:

> I did not figure out why you sent 2 separate patches. Usually 
> it is one patch which goes upstream, then GregKH and others 
> pick it up and back ports to various stable trees. If they 
> have issues, they may come and ask for help. So there should 
> be 1 patch.
> 
> >  That patch version (v3)did
> > not remove the final memset from nand_do_write_oob, as you 
> requested.
> 
> Did I request so? I thought I just expressed a thought that 
> the memset is redundant and should be killed, and I thought 
> you'd take a deeper look and decide whether it is safe to do or not.
> 
> > Named both patches the same as they were pretty much indentical, 
> > except for the memset. Didn't know the convention for patch naming 
> > where one was going to stable, and the other to the latest 
> so marked 
> > the latest as upstream to differentiate.
> 
> So do we need that memset or not? :-)

The original request was for a stable patch, and that would be accepted
if I provided a proper tidy fix also. To be fair it was a few weeks ago
now that that mail was sent. :-) Anyway, as it turns out the tidy fix was
almost identical, and we don't need the memset as far as I can tell
from reviewing code and from testing. Will run up your patch today to
verify your additional change, but should be fine.

> 
> --
> Best Regards,
> Artem Bityutskiy
> 
> 

Thanks

Adam

From galak at kernel.crashing.org  Wed Jun 22 07:08:49 2011
From: galak at kernel.crashing.org (Kumar Gala)
Date: Wed, 22 Jun 2011 06:08:49 -0500
Subject: [PATCH] powerpc/85xx: fix NAND_CMD_READID read bytes number
In-Reply-To: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>
References: <1307931792-30386-1-git-send-email-Shaohui.Xie@freescale.com>
Message-ID: <A930A3E6-3999-4240-A40B-03F3A9A5B481@kernel.crashing.org>


On Jun 12, 2011, at 9:23 PM, Shaohui Xie wrote:

> when nand_get_flash_type() is called, it will read 8 bytes of ID instead of 5,
> but the driver only read 5 bytes, so kernel will dump error messages like:
> 
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> fsl-lbc ffe124000.localbus: read_byte beyond end of buffer
> 
> Signed-off-by: Shaohui Xie <Shaohui.Xie at freescale.com>
> Acked-by: Scott Wood <scottwood at freescale.com>
> ---
> drivers/mtd/nand/fsl_elbc_nand.c |    6 +++---
> 1 files changed, 3 insertions(+), 3 deletions(-)

applied to merge

- k

From zonque at gmail.com  Wed Jun 22 07:39:33 2011
From: zonque at gmail.com (Daniel Mack)
Date: Wed, 22 Jun 2011 13:39:33 +0200
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
Message-ID: <BANLkTinQB-hXMRy5+BXKQSrPq=sVrorCVA@mail.gmail.com>

On Wed, Jun 22, 2011 at 5:17 AM, Lei Wen <leiwen at marvell.com> wrote:
> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
>
> Update platform driver to support this feature.
>
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? ?8 +-
> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?735 +++++++++++++++-----------
> ?9 files changed, 444 insertions(+), 338 deletions(-)

This patch doesn't apply for me on top of Linus' master branch. Which
tree are you based on currently?

[...]

> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 30689cc..259b8d5 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -92,11 +92,13 @@
> ?#define NDCB0_ADDR_CYC_SHIFT ? (16)
>
> ?/* macros for registers read/write */
> -#define nand_writel(info, off, val) ? ?\
> - ? ? ? __raw_writel((val), (info)->mmio_base + (off))
> +#define nand_writel(nand, off, val) ? ?\
> + ? ? ? __raw_writel((val), (nand)->mmio_base + (off))
>
> -#define nand_readl(info, off) ? ? ? ? ?\
> - ? ? ? __raw_readl((info)->mmio_base + (off))
> +#define nand_readl(nand, off) ? ? ? ? ?\
> + ? ? ? __raw_readl((nand)->mmio_base + (off))
> +#define get_mtd_by_info(info) ? ? ? ? ?\
> + ? ? ? (struct mtd_info *)((void *)info - sizeof(struct mtd_info))
>
> ?/* error code and state */
> ?enum {
> @@ -110,6 +112,7 @@ enum {
>
> ?enum {
> ? ? ? ?STATE_IDLE = 0,
> + ? ? ? STATE_PREPARED,
> ? ? ? ?STATE_CMD_HANDLE,
> ? ? ? ?STATE_DMA_READING,
> ? ? ? ?STATE_DMA_WRITING,
> @@ -123,63 +126,63 @@ enum {
> ?struct pxa3xx_nand_info {
> ? ? ? ?struct nand_chip ? ? ? ?nand_chip;
>
> - ? ? ? struct nand_hw_control ?controller;
> - ? ? ? struct platform_device ? *pdev;
> ? ? ? ?struct pxa3xx_nand_cmdset *cmdset;
> + ? ? ? /* page size of attached chip */
> + ? ? ? uint16_t ? ? ? ? ? ? ? ?page_size;
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? chip_select;
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? use_ecc;
> +
> + ? ? ? /* calculated from pxa3xx_nand_flash data */
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? col_addr_cycles;
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? row_addr_cycles;
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? read_id_bytes;
> +
> + ? ? ? /* cached register value */
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr0cs0;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr1cs0;
>
> + ? ? ? void ? ? ? ? ? ? ? ? ? ?*nand_data;
> +};
> +
> +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;
>
> - ? ? ? unsigned int ? ? ? ? ? ?buf_start;
> - ? ? ? unsigned int ? ? ? ? ? ?buf_count;
> -
> - ? ? ? struct mtd_info ? ? ? ? *mtd;
> ? ? ? ?/* DMA information */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_dat;
> ? ? ? ?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;
> - ? ? ? struct pxa_dma_desc ? ? *data_desc;
> + ? ? ? dma_addr_t ? ? ? ? ? ? ?data_buff_phys;
> ? ? ? ?dma_addr_t ? ? ? ? ? ? ?data_desc_addr;
> + ? ? ? struct pxa_dma_desc ? ? *data_desc;
>
> - ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
> -
> - ? ? ? /* saved column/page_addr during CMD_SEQIN */
> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_column;
> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_page_addr;
> + ? ? ? struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?command;
> + ? ? ? uint16_t ? ? ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
> + ? ? ? uint16_t ? ? ? ? ? ? ? ?oob_size;
> + ? ? ? unsigned char ? ? ? ? ? *data_buff;
> + ? ? ? unsigned char ? ? ? ? ? *oob_buff;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?buf_start;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?buf_count;
>
> ? ? ? ?/* relate to the command */
> ? ? ? ?unsigned int ? ? ? ? ? ?state;
> -
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? chip_select;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_ecc; ? ? ? ?/* use HW ECC ? */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_dma; ? ? ? ?/* use DMA ? */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? is_ready;
> -
> - ? ? ? unsigned int ? ? ? ? ? ?page_size; ? ? ?/* page size of attached chip */
> - ? ? ? unsigned int ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? retcode;
> - ? ? ? struct completion ? ? ? cmd_complete;
>
> ? ? ? ?/* generated NDCBx register values */
> + ? ? ? uint8_t ? ? ? ? ? ? ? ? total_cmds;
> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?ndcb0;
> ? ? ? ?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;
> -
> - ? ? ? unsigned int ? ?col_addr_cycles;
> - ? ? ? unsigned int ? ?row_addr_cycles;
> ?};
>
> ?static int use_dma = 1;
> @@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
> ?/* Define a default flash type setting serve as flash detecting only */
> ?#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
>
> -const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> +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)
> @@ -244,9 +247,11 @@ 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)) |
> @@ -260,26 +265,27 @@ 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 = (info->use_ecc) ? 40 : 64;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case 512:
> - ? ? ? ? ? ? ? info->oob_size = (info->use_ecc) ? 8 : 16;
> + ? ? ? ? ? ? ? nand->oob_size = (info->use_ecc) ? 8 : 16;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
> ?}
> @@ -290,185 +296,189 @@ 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 : 0;
> + ? ? ? ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
> + ? ? ? ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
> ? ? ? ?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;
>
> ? ? ? ?/* wait RUN bit in NDCR become 0 */
> - ? ? ? ndcr = nand_readl(info, NDCR);
> + ? ? ? ndcr = nand_readl(nand, NDCR);
> ? ? ? ?while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
> - ? ? ? ? ? ? ? ndcr = nand_readl(info, NDCR);
> + ? ? ? ? ? ? ? ndcr = nand_readl(nand, NDCR);
> ? ? ? ? ? ? ? ?udelay(1);
> ? ? ? ?}
>
> ? ? ? ?if (timeout <= 0) {
> ? ? ? ? ? ? ? ?ndcr &= ~NDCR_ND_RUN;
> - ? ? ? ? ? ? ? nand_writel(info, NDCR, ndcr);
> + ? ? ? ? ? ? ? nand_writel(nand, NDCR, ndcr);
> ? ? ? ?}
> ? ? ? ?/* clear status bits */
> - ? ? ? nand_writel(info, NDSR, NDSR_MASK);
> + ? ? ? nand_writel(nand, NDSR, NDSR_MASK);
> ?}
>
> -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)
> ?{
> - ? ? ? switch (info->state) {
> + ? ? ? switch (nand->state) {
> ? ? ? ?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));
> + ? ? ? ? ? ? ? __raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->data_size, 4));
> + ? ? ? ? ? ? ? if (nand->oob_size > 0)
> + ? ? ? ? ? ? ? ? ? ? ? __raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->oob_size, 4));
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?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));
> + ? ? ? ? ? ? ? __raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->data_size, 4));
> + ? ? ? ? ? ? ? if (nand->oob_size > 0)
> + ? ? ? ? ? ? ? ? ? ? ? __raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->oob_size, 4));
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?printk(KERN_ERR "%s: invalid state %d\n", __func__,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->state);

Can't you use dev_err() here?

> ? ? ? ? ? ? ? ?BUG();

Is crashing the entire kernel really necessary here?

> ? ? ? ?}
> ?}
>
> -static void start_data_dma(struct pxa3xx_nand_info *info)
> +static void start_data_dma(struct pxa3xx_nand *nand)
> ?{
> - ? ? ? struct pxa_dma_desc *desc = info->data_desc;
> - ? ? ? int dma_len = ALIGN(info->data_size + info->oob_size, 32);
> + ? ? ? struct pxa_dma_desc *desc = nand->data_desc;
> + ? ? ? 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;
>
> - ? ? ? switch (info->state) {
> + ? ? ? switch (nand->state) {
> ? ? ? ?case STATE_DMA_WRITING:
> - ? ? ? ? ? ? ? desc->dsadr = info->data_buff_phys;
> - ? ? ? ? ? ? ? desc->dtadr = info->mmio_phys + NDDB;
> + ? ? ? ? ? ? ? desc->dsadr = nand->data_buff_phys;
> + ? ? ? ? ? ? ? desc->dtadr = nand->mmio_phys + NDDB;
> ? ? ? ? ? ? ? ?desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case STATE_DMA_READING:
> - ? ? ? ? ? ? ? desc->dtadr = info->data_buff_phys;
> - ? ? ? ? ? ? ? desc->dsadr = info->mmio_phys + NDDB;
> + ? ? ? ? ? ? ? desc->dtadr = nand->data_buff_phys;
> + ? ? ? ? ? ? ? desc->dsadr = nand->mmio_phys + NDDB;
> ? ? ? ? ? ? ? ?desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?printk(KERN_ERR "%s: invalid state %d\n", __func__,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->state);
> ? ? ? ? ? ? ? ?BUG();
> ? ? ? ?}
>
> - ? ? ? DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
> - ? ? ? DDADR(info->data_dma_ch) = info->data_desc_addr;
> - ? ? ? DCSR(info->data_dma_ch) |= DCSR_RUN;
> + ? ? ? DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
> + ? ? ? DDADR(nand->data_dma_ch) = nand->data_desc_addr;
> + ? ? ? DCSR(nand->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;
> ? ? ? ?}
>
> - ? ? ? info->state = STATE_DMA_DONE;
> - ? ? ? enable_int(info, NDCR_INT_MASK);
> - ? ? ? nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
> + ? ? ? nand->state = STATE_DMA_DONE;
> + ? ? ? 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)) {
> ? ? ? ? ? ? ? ?/* whether use dma to transfer data */
> - ? ? ? ? ? ? ? if (info->use_dma) {
> - ? ? ? ? ? ? ? ? ? ? ? disable_int(info, NDCR_INT_MASK);
> - ? ? ? ? ? ? ? ? ? ? ? info->state = (status & NDSR_RDDREQ) ?
> + ? ? ? ? ? ? ? if (nand->use_dma) {
> + ? ? ? ? ? ? ? ? ? ? ? disable_int(nand, NDCR_INT_MASK);
> + ? ? ? ? ? ? ? ? ? ? ? nand->state = (status & NDSR_RDDREQ) ?
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?STATE_DMA_READING : STATE_DMA_WRITING;
> - ? ? ? ? ? ? ? ? ? ? ? start_data_dma(info);
> + ? ? ? ? ? ? ? ? ? ? ? start_data_dma(nand);
> ? ? ? ? ? ? ? ? ? ? ? ?goto NORMAL_IRQ_EXIT;
> ? ? ? ? ? ? ? ?} else {
> - ? ? ? ? ? ? ? ? ? ? ? info->state = (status & NDSR_RDDREQ) ?
> + ? ? ? ? ? ? ? ? ? ? ? nand->state = (status & NDSR_RDDREQ) ?
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?STATE_PIO_READING : STATE_PIO_WRITING;
> - ? ? ? ? ? ? ? ? ? ? ? handle_data_pio(info);
> + ? ? ? ? ? ? ? ? ? ? ? handle_data_pio(nand);
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}
> - ? ? ? 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->is_ready = 1;
> - ? ? ? ? ? ? ? info->state = STATE_READY;
> + ? ? ? if (status & ready) {
> + ? ? ? ? ? ? ? nand->is_ready = 1;
> + ? ? ? ? ? ? ? nand->state = STATE_READY;
> ? ? ? ?}
>
> ? ? ? ?if (status & NDSR_WRCMDREQ) {
> - ? ? ? ? ? ? ? nand_writel(info, NDSR, NDSR_WRCMDREQ);
> + ? ? ? ? ? ? ? nand_writel(nand, NDSR, NDSR_WRCMDREQ);
> ? ? ? ? ? ? ? ?status &= ~NDSR_WRCMDREQ;
> - ? ? ? ? ? ? ? info->state = STATE_CMD_HANDLE;
> - ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb0);
> - ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb1);
> - ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb2);
> + ? ? ? ? ? ? ? nand->state = STATE_CMD_HANDLE;
> + ? ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->ndcb0);
> + ? ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->ndcb1);
> + ? ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->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--)
> @@ -477,42 +487,49 @@ 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->is_ready ? ? ? ? ?= 0;
> - ? ? ? info->retcode ? ? ? ? ? = ERR_NONE;
> + ? ? ? nand->buf_start ? ? ? ? = 0;
> + ? ? ? nand->buf_count ? ? ? ? = 0;
> + ? ? ? nand->oob_size ? ? ? ? ?= 0;
> + ? ? ? nand->use_ecc ? ? ? ? ? = 0;
> + ? ? ? nand->is_ready ? ? ? ? ?= 0;
> + ? ? ? nand->retcode ? ? ? ? ? = ERR_NONE;
> + ? ? ? nand->data_size ? ? ? ? = 0;
> + ? ? ? nand->use_dma ? ? ? ? ? = 0;
> + ? ? ? nand->command ? ? ? ? ? = command;
>
> ? ? ? ?switch (command) {
> ? ? ? ?case NAND_CMD_READ0:
> ? ? ? ?case NAND_CMD_PAGEPROG:
> - ? ? ? ? ? ? ? info->use_ecc = 1;
> + ? ? ? ? ? ? ? nand->use_ecc = 1;
> ? ? ? ?case NAND_CMD_READOOB:
> ? ? ? ? ? ? ? ?pxa3xx_set_datasize(info);
> + ? ? ? ? ? ? ? nand->oob_buff = nand->data_buff + nand->data_size;
> + ? ? ? ? ? ? ? nand->use_dma = use_dma;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_SEQIN:
> ? ? ? ? ? ? ? ?exec_cmd = 0;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> - ? ? ? ? ? ? ? info->ndcb1 = 0;
> - ? ? ? ? ? ? ? info->ndcb2 = 0;
> + ? ? ? ? ? ? ? nand->ndcb1 = 0;
> + ? ? ? ? ? ? ? nand->ndcb2 = 0;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
>
> - ? ? ? info->ndcb0 = ndcb0;
> + ? ? ? nand->ndcb0 = ndcb0;
> ? ? ? ?addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?+ info->col_addr_cycles);
>
> @@ -521,16 +538,16 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ?case NAND_CMD_READ0:
> ? ? ? ? ? ? ? ?cmd = info->cmdset->read1;
> ? ? ? ? ? ? ? ?if (command == NAND_CMD_READOOB)
> - ? ? ? ? ? ? ? ? ? ? ? info->buf_start = mtd->writesize + column;
> + ? ? ? ? ? ? ? ? ? ? ? nand->buf_start = mtd->writesize + column;
> ? ? ? ? ? ? ? ?else
> - ? ? ? ? ? ? ? ? ? ? ? info->buf_start = column;
> + ? ? ? ? ? ? ? ? ? ? ? nand->buf_start = column;
>
> ? ? ? ? ? ? ? ?if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| addr_cycle
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (cmd & NDCB0_CMD1_MASK);
> ? ? ? ? ? ? ? ?else
> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_DBC
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| addr_cycle
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
> @@ -538,34 +555,34 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ?case NAND_CMD_SEQIN:
> ? ? ? ? ? ? ? ?/* small page addr setting */
> ? ? ? ? ? ? ? ?if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (column & 0xFF);
>
> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = 0;
> ? ? ? ? ? ? ? ?} else {
> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFF) << 16)
> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (column & 0xFFFF);
>
> ? ? ? ? ? ? ? ? ? ? ? ?if (page_addr & 0xFF0000)
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = (page_addr & 0xFF0000) >> 16;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
> ? ? ? ? ? ? ? ? ? ? ? ?else
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = 0;
> ? ? ? ? ? ? ? ?}
>
> - ? ? ? ? ? ? ? info->buf_count = mtd->writesize + mtd->oobsize;
> - ? ? ? ? ? ? ? memset(info->data_buff, 0xFF, info->buf_count);
> + ? ? ? ? ? ? ? nand->buf_count = mtd->writesize + mtd->oobsize;
> + ? ? ? ? ? ? ? memset(nand->data_buff, 0xFF, nand->buf_count);
>
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_PAGEPROG:
> - ? ? ? ? ? ? ? if (is_buf_blank(info->data_buff,
> + ? ? ? ? ? ? ? if (is_buf_blank(nand->data_buff,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(mtd->writesize + mtd->oobsize))) {
> ? ? ? ? ? ? ? ? ? ? ? ?exec_cmd = 0;
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
>
> ? ? ? ? ? ? ? ?cmd = info->cmdset->program;
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ST_ROW_EN
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_DBC
> @@ -575,37 +592,37 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ?case NAND_CMD_READID:
> ? ? ? ? ? ? ? ?cmd = info->cmdset->read_id;
> - ? ? ? ? ? ? ? info->buf_count = info->read_id_bytes;
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(3)
> + ? ? ? ? ? ? ? nand->buf_count = info->read_id_bytes;
> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(3)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>
> - ? ? ? ? ? ? ? info->data_size = 8;
> + ? ? ? ? ? ? ? nand->data_size = 8;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_STATUS:
> ? ? ? ? ? ? ? ?cmd = info->cmdset->read_status;
> - ? ? ? ? ? ? ? info->buf_count = 1;
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(4)
> + ? ? ? ? ? ? ? nand->buf_count = 1;
> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(4)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>
> - ? ? ? ? ? ? ? info->data_size = 8;
> + ? ? ? ? ? ? ? nand->data_size = 8;
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_ERASE1:
> ? ? ? ? ? ? ? ?cmd = info->cmdset->erase;
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(2)
> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(2)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(3)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_DBC
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
> - ? ? ? ? ? ? ? info->ndcb1 = page_addr;
> - ? ? ? ? ? ? ? info->ndcb2 = 0;
> + ? ? ? ? ? ? ? nand->ndcb1 = page_addr;
> + ? ? ? ? ? ? ? nand->ndcb2 = 0;
>
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_RESET:
> ? ? ? ? ? ? ? ?cmd = info->cmdset->reset;
> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(5)
> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(5)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>
> ? ? ? ? ? ? ? ?break;
> @@ -628,6 +645,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;
>
> ? ? ? ?/*
> @@ -638,20 +656,32 @@ 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);
> + ? ? ? /*
> + ? ? ? ?* There may be different NAND chip hooked to
> + ? ? ? ?* different chip select, so check whether
> + ? ? ? ?* chip select has been changed, if yes, reset the 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);
> + ? ? ? }
> +
> + ? ? ? nand->state = STATE_PREPARED;
> + ? ? ? exec_cmd = prepare_command_pool(nand, command, column, page_addr);
> ? ? ? ?if (exec_cmd) {
> - ? ? ? ? ? ? ? init_completion(&info->cmd_complete);
> - ? ? ? ? ? ? ? pxa3xx_nand_start(info);
> + ? ? ? ? ? ? ? init_completion(&nand->cmd_complete);
> + ? ? ? ? ? ? ? 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);
> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_stop(nand);
> ? ? ? ? ? ? ? ?}
> - ? ? ? ? ? ? ? info->state = STATE_IDLE;
> ? ? ? ?}
> + ? ? ? nand->state = STATE_IDLE;
> ?}
>
> ?static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> @@ -665,11 +695,12 @@ 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) {
> + ? ? ? if (nand->retcode == ERR_SBERR) {
> ? ? ? ? ? ? ? ?switch (info->use_ecc) {
> ? ? ? ? ? ? ? ?case 1:
> ? ? ? ? ? ? ? ? ? ? ? ?mtd->ecc_stats.corrected++;
> @@ -678,14 +709,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
> ? ? ? ? ? ? ? ?default:
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
> - ? ? ? } else if (info->retcode == ERR_DBERR) {
> + ? ? ? } else if (nand->retcode == ERR_DBERR) {
> ? ? ? ? ? ? ? ?/*
> ? ? ? ? ? ? ? ? * for blank page (all 0xff), HW will calculate its ECC as
> ? ? ? ? ? ? ? ? * 0, which is different from the ECC information within
> ? ? ? ? ? ? ? ? * OOB, ignore such double bit errors
> ? ? ? ? ? ? ? ? */
> ? ? ? ? ? ? ? ?if (is_buf_blank(buf, mtd->writesize))
> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
> + ? ? ? ? ? ? ? ? ? ? ? nand->retcode = ERR_NONE;
> ? ? ? ? ? ? ? ?else
> ? ? ? ? ? ? ? ? ? ? ? ?mtd->ecc_stats.failed++;
> ? ? ? ?}
> @@ -696,11 +727,12 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
> ?static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
> ? ? ? ?char retval = 0xFF;
>
> - ? ? ? if (info->buf_start < info->buf_count)
> + ? ? ? if (nand->buf_start < nand->buf_count)
> ? ? ? ? ? ? ? ?/* Has just send a new command? */
> - ? ? ? ? ? ? ? retval = info->data_buff[info->buf_start++];
> + ? ? ? ? ? ? ? retval = nand->data_buff[nand->buf_start++];
>
> ? ? ? ?return retval;
> ?}
> @@ -708,11 +740,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
> ?static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
> ? ? ? ?u16 retval = 0xFFFF;
>
> - ? ? ? if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
> - ? ? ? ? ? ? ? retval = *((u16 *)(info->data_buff+info->buf_start));
> - ? ? ? ? ? ? ? info->buf_start += 2;
> + ? ? ? if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
> + ? ? ? ? ? ? ? retval = *((u16 *)(nand->data_buff+nand->buf_start));
> + ? ? ? ? ? ? ? nand->buf_start += 2;
> ? ? ? ?}
> ? ? ? ?return retval;
> ?}
> @@ -720,20 +753,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
> ?static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> - ? ? ? int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
> + ? ? ? int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>
> - ? ? ? memcpy(buf, info->data_buff + info->buf_start, real_len);
> - ? ? ? info->buf_start += real_len;
> + ? ? ? memcpy(buf, nand->data_buff + nand->buf_start, real_len);
> + ? ? ? nand->buf_start += real_len;
> ?}
>
> ?static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
> ? ? ? ? ? ? ? ?const uint8_t *buf, int len)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
> - ? ? ? int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
> + ? ? ? int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>
> - ? ? ? memcpy(info->data_buff + info->buf_start, buf, real_len);
> - ? ? ? info->buf_start += real_len;
> + ? ? ? memcpy(nand->data_buff + nand->buf_start, buf, real_len);
> + ? ? ? nand->buf_start += real_len;
> ?}
>
> ?static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
> @@ -750,10 +785,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 {
> ? ? ? ? ? ? ? ? ? ? ? ?/*
> @@ -770,7 +806,8 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
> ?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 = 0x0; /* enable all interrupts */
>
> @@ -804,6 +841,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
> ? ? ? ?ndcr |= NDCR_SPARE_EN; /* enable spare by default */
>
> ? ? ? ?info->reg_ndcr = ndcr;
> + ? ? ? info->use_ecc = 1;
>
> ? ? ? ?pxa3xx_nand_set_timing(info, f->timing);
> ? ? ? ?return 0;
> @@ -811,15 +849,22 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>
> ?static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? uint32_t ndcr = nand_readl(info, NDCR);
> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
> + ? ? ? uint32_t ndcr = nand_readl(nand, NDCR);
> +
> + ? ? ? if (info->chip_select > 0) {
> + ? ? ? ? ? ? ? printk(KERN_ERR "We could not detect configure"
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " if more than one cs is supported!!\n");
> + ? ? ? ? ? ? ? BUG();
> + ? ? ? }
> ? ? ? ?info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
> ? ? ? ?/* set info fields needed to read id */
> ? ? ? ?info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
> ? ? ? ?info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
> ? ? ? ?info->cmdset = &default_cmdset;
>
> - ? ? ? info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> - ? ? ? info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
> + ? ? ? info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
> + ? ? ? info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
>
> ? ? ? ?return 0;
> ?}
> @@ -830,50 +875,31 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ?*/
> ?#define MAX_BUFF_SIZE ?PAGE_SIZE
>
> -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
> +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
> ?{
> - ? ? ? 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;
> + ? ? ? struct pxa3xx_nand *nand;
> + ? ? ? struct mtd_info *mtd;
>
> - ? ? ? 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;
> - ? ? ? }
> + ? ? ? if (!info)
> + ? ? ? ? ? ? ? return;
>
> - ? ? ? return 0;
> + ? ? ? nand = info->nand_data;
> + ? ? ? mtd = get_mtd_by_info(info);
> + ? ? ? kfree(mtd);
> + ? ? ? nand->info[cs] = NULL;
> ?}
>
> ?static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? struct mtd_info *mtd = info->mtd;
> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
> + ? ? ? struct mtd_info *mtd = get_mtd_by_info(info);
> ? ? ? ?struct nand_chip *chip = mtd->priv;
>
> ? ? ? ?/* use the common timing to make a try */
> - ? ? ? pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
> + ? ? ? if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
> + ? ? ? ? ? ? ? return 0;
> ? ? ? ?chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
> - ? ? ? if (info->is_ready)
> + ? ? ? if (nand->is_ready)
> ? ? ? ? ? ? ? ?return 1;
> ? ? ? ?else
> ? ? ? ? ? ? ? ?return 0;
> @@ -882,7 +908,8 @@ 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 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;
> ? ? ? ?struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
> ? ? ? ?const struct pxa3xx_nand_flash *f = NULL;
> @@ -891,27 +918,25 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?uint64_t chipsize;
> ? ? ? ?int i, ret, num;
>
> + ? ? ? nand->chip_select = info->chip_select;
> ? ? ? ?if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
> ? ? ? ? ? ? ? ?goto KEEP_CONFIG;
>
> ? ? ? ?ret = pxa3xx_nand_sensing(info);
> ? ? ? ?if (!ret) {
> - ? ? ? ? ? ? ? kfree(mtd);
> - ? ? ? ? ? ? ? info->mtd = NULL;
> - ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n");
> + ? ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
> + ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs %d!\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->chip_select);

dev_err()?

>
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
>
> ? ? ? ?chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
> - ? ? ? id = *((uint16_t *)(info->data_buff));
> + ? ? ? id = *((uint16_t *)(nand->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");
> -
> + ? ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
>
> @@ -928,14 +953,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?}
>
> ? ? ? ?if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
> - ? ? ? ? ? ? ? kfree(mtd);
> - ? ? ? ? ? ? ? info->mtd = NULL;
> + ? ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
> ? ? ? ? ? ? ? ?printk(KERN_ERR "ERROR!! flash not defined!!!\n");

Also here.

>
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
>
> - ? ? ? pxa3xx_nand_config_flash(info, f);
> + ? ? ? if (pxa3xx_nand_config_flash(info, f)) {
> + ? ? ? ? ? ? ? printk(KERN_ERR "ERROR! Configure failed\n");

And here. Giving no hint about which driver or function causes this
message makes debugging harder than it should be.

[...]

> ?#ifdef CONFIG_PM
> @@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
> ? ? ? ?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);
> + ? ? ? nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
> + ? ? ? nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
> ? ? ? ?clk_enable(info->clk);

This won't compile.



Daniel


From adrian.wenl at gmail.com  Wed Jun 22 08:21:46 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Wed, 22 Jun 2011 20:21:46 +0800
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <BANLkTinQB-hXMRy5+BXKQSrPq=sVrorCVA@mail.gmail.com>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
	<BANLkTinQB-hXMRy5+BXKQSrPq=sVrorCVA@mail.gmail.com>
Message-ID: <BANLkTimk0+2LUeo5sq8w4ohRq-qCe_2t_Q@mail.gmail.com>

Hi Daniel,

On Wed, Jun 22, 2011 at 7:39 PM, Daniel Mack <zonque at gmail.com> wrote:
> On Wed, Jun 22, 2011 at 5:17 AM, Lei Wen <leiwen at marvell.com> wrote:
>> Current pxa3xx_nand controller has two chip select which
>> both be workable. This patch enable this feature.
>>
>> Update platform driver to support this feature.
>>
>> Another notice should be taken that:
>> When you want to use this feature, you should not enable the
>> keep configuration feature, for two chip select could be
>> attached with different nand chip. The different page size
>> and timing requirement make the keep configuration impossible.
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> ---
>> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
>> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
>> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
>> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? ?8 +-
>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?735 +++++++++++++++-----------
>> ?9 files changed, 444 insertions(+), 338 deletions(-)
>
> This patch doesn't apply for me on top of Linus' master branch. Which
> tree are you based on currently?

Actually it is based on Linux 3.0-rc2 and add two patches pending to
l2-mtd-2.6.git already:

mtd: pxa3xx_nand: fix nand detection issue
mtd: pxa3xx_nand: Fix blank page ECC mismatch

>
> [...]
>
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index 30689cc..259b8d5 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -92,11 +92,13 @@
>> ?#define NDCB0_ADDR_CYC_SHIFT ? (16)
>>
>> ?/* macros for registers read/write */
>> -#define nand_writel(info, off, val) ? ?\
>> - ? ? ? __raw_writel((val), (info)->mmio_base + (off))
>> +#define nand_writel(nand, off, val) ? ?\
>> + ? ? ? __raw_writel((val), (nand)->mmio_base + (off))
>>
>> -#define nand_readl(info, off) ? ? ? ? ?\
>> - ? ? ? __raw_readl((info)->mmio_base + (off))
>> +#define nand_readl(nand, off) ? ? ? ? ?\
>> + ? ? ? __raw_readl((nand)->mmio_base + (off))
>> +#define get_mtd_by_info(info) ? ? ? ? ?\
>> + ? ? ? (struct mtd_info *)((void *)info - sizeof(struct mtd_info))
>>
>> ?/* error code and state */
>> ?enum {
>> @@ -110,6 +112,7 @@ enum {
>>
>> ?enum {
>> ? ? ? ?STATE_IDLE = 0,
>> + ? ? ? STATE_PREPARED,
>> ? ? ? ?STATE_CMD_HANDLE,
>> ? ? ? ?STATE_DMA_READING,
>> ? ? ? ?STATE_DMA_WRITING,
>> @@ -123,63 +126,63 @@ enum {
>> ?struct pxa3xx_nand_info {
>> ? ? ? ?struct nand_chip ? ? ? ?nand_chip;
>>
>> - ? ? ? struct nand_hw_control ?controller;
>> - ? ? ? struct platform_device ? *pdev;
>> ? ? ? ?struct pxa3xx_nand_cmdset *cmdset;
>> + ? ? ? /* page size of attached chip */
>> + ? ? ? uint16_t ? ? ? ? ? ? ? ?page_size;
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? chip_select;
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? use_ecc;
>> +
>> + ? ? ? /* calculated from pxa3xx_nand_flash data */
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? col_addr_cycles;
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? row_addr_cycles;
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? read_id_bytes;
>> +
>> + ? ? ? /* cached register value */
>> + ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
>> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr0cs0;
>> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr1cs0;
>>
>> + ? ? ? void ? ? ? ? ? ? ? ? ? ?*nand_data;
>> +};
>> +
>> +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;
>>
>> - ? ? ? unsigned int ? ? ? ? ? ?buf_start;
>> - ? ? ? unsigned int ? ? ? ? ? ?buf_count;
>> -
>> - ? ? ? struct mtd_info ? ? ? ? *mtd;
>> ? ? ? ?/* DMA information */
>> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_dat;
>> ? ? ? ?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;
>> - ? ? ? struct pxa_dma_desc ? ? *data_desc;
>> + ? ? ? dma_addr_t ? ? ? ? ? ? ?data_buff_phys;
>> ? ? ? ?dma_addr_t ? ? ? ? ? ? ?data_desc_addr;
>> + ? ? ? struct pxa_dma_desc ? ? *data_desc;
>>
>> - ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
>> -
>> - ? ? ? /* saved column/page_addr during CMD_SEQIN */
>> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_column;
>> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_page_addr;
>> + ? ? ? struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
>> + ? ? ? uint32_t ? ? ? ? ? ? ? ?command;
>> + ? ? ? uint16_t ? ? ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
>> + ? ? ? uint16_t ? ? ? ? ? ? ? ?oob_size;
>> + ? ? ? unsigned char ? ? ? ? ? *data_buff;
>> + ? ? ? unsigned char ? ? ? ? ? *oob_buff;
>> + ? ? ? uint32_t ? ? ? ? ? ? ? ?buf_start;
>> + ? ? ? uint32_t ? ? ? ? ? ? ? ?buf_count;
>>
>> ? ? ? ?/* relate to the command */
>> ? ? ? ?unsigned int ? ? ? ? ? ?state;
>> -
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? chip_select;
>> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_ecc; ? ? ? ?/* use HW ECC ? */
>> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_dma; ? ? ? ?/* use DMA ? */
>> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? is_ready;
>> -
>> - ? ? ? unsigned int ? ? ? ? ? ?page_size; ? ? ?/* page size of attached chip */
>> - ? ? ? unsigned int ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
>> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? retcode;
>> - ? ? ? struct completion ? ? ? cmd_complete;
>>
>> ? ? ? ?/* generated NDCBx register values */
>> + ? ? ? uint8_t ? ? ? ? ? ? ? ? total_cmds;
>> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?ndcb0;
>> ? ? ? ?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;
>> -
>> - ? ? ? unsigned int ? ?col_addr_cycles;
>> - ? ? ? unsigned int ? ?row_addr_cycles;
>> ?};
>>
>> ?static int use_dma = 1;
>> @@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
>> ?/* Define a default flash type setting serve as flash detecting only */
>> ?#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
>>
>> -const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
>> +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)
>> @@ -244,9 +247,11 @@ 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)) |
>> @@ -260,26 +265,27 @@ 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 = (info->use_ecc) ? 40 : 64;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?case 512:
>> - ? ? ? ? ? ? ? info->oob_size = (info->use_ecc) ? 8 : 16;
>> + ? ? ? ? ? ? ? nand->oob_size = (info->use_ecc) ? 8 : 16;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?}
>> ?}
>> @@ -290,185 +296,189 @@ 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 : 0;
>> + ? ? ? ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
>> + ? ? ? ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
>> ? ? ? ?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;
>>
>> ? ? ? ?/* wait RUN bit in NDCR become 0 */
>> - ? ? ? ndcr = nand_readl(info, NDCR);
>> + ? ? ? ndcr = nand_readl(nand, NDCR);
>> ? ? ? ?while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
>> - ? ? ? ? ? ? ? ndcr = nand_readl(info, NDCR);
>> + ? ? ? ? ? ? ? ndcr = nand_readl(nand, NDCR);
>> ? ? ? ? ? ? ? ?udelay(1);
>> ? ? ? ?}
>>
>> ? ? ? ?if (timeout <= 0) {
>> ? ? ? ? ? ? ? ?ndcr &= ~NDCR_ND_RUN;
>> - ? ? ? ? ? ? ? nand_writel(info, NDCR, ndcr);
>> + ? ? ? ? ? ? ? nand_writel(nand, NDCR, ndcr);
>> ? ? ? ?}
>> ? ? ? ?/* clear status bits */
>> - ? ? ? nand_writel(info, NDSR, NDSR_MASK);
>> + ? ? ? nand_writel(nand, NDSR, NDSR_MASK);
>> ?}
>>
>> -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)
>> ?{
>> - ? ? ? switch (info->state) {
>> + ? ? ? switch (nand->state) {
>> ? ? ? ?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));
>> + ? ? ? ? ? ? ? __raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->data_size, 4));
>> + ? ? ? ? ? ? ? if (nand->oob_size > 0)
>> + ? ? ? ? ? ? ? ? ? ? ? __raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->oob_size, 4));
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?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));
>> + ? ? ? ? ? ? ? __raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->data_size, 4));
>> + ? ? ? ? ? ? ? if (nand->oob_size > 0)
>> + ? ? ? ? ? ? ? ? ? ? ? __raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->oob_size, 4));
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?default:
>> ? ? ? ? ? ? ? ?printk(KERN_ERR "%s: invalid state %d\n", __func__,
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->state);
>
> Can't you use dev_err() here?

Good suggestion, I would make this change.
>
>> ? ? ? ? ? ? ? ?BUG();
>
> Is crashing the entire kernel really necessary here?
>
>> ? ? ? ?}
>> ?}
>>
>> -static void start_data_dma(struct pxa3xx_nand_info *info)
>> +static void start_data_dma(struct pxa3xx_nand *nand)
>> ?{
>> - ? ? ? struct pxa_dma_desc *desc = info->data_desc;
>> - ? ? ? int dma_len = ALIGN(info->data_size + info->oob_size, 32);
>> + ? ? ? struct pxa_dma_desc *desc = nand->data_desc;
>> + ? ? ? 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;
>>
>> - ? ? ? switch (info->state) {
>> + ? ? ? switch (nand->state) {
>> ? ? ? ?case STATE_DMA_WRITING:
>> - ? ? ? ? ? ? ? desc->dsadr = info->data_buff_phys;
>> - ? ? ? ? ? ? ? desc->dtadr = info->mmio_phys + NDDB;
>> + ? ? ? ? ? ? ? desc->dsadr = nand->data_buff_phys;
>> + ? ? ? ? ? ? ? desc->dtadr = nand->mmio_phys + NDDB;
>> ? ? ? ? ? ? ? ?desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?case STATE_DMA_READING:
>> - ? ? ? ? ? ? ? desc->dtadr = info->data_buff_phys;
>> - ? ? ? ? ? ? ? desc->dsadr = info->mmio_phys + NDDB;
>> + ? ? ? ? ? ? ? desc->dtadr = nand->data_buff_phys;
>> + ? ? ? ? ? ? ? desc->dsadr = nand->mmio_phys + NDDB;
>> ? ? ? ? ? ? ? ?desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?default:
>> ? ? ? ? ? ? ? ?printk(KERN_ERR "%s: invalid state %d\n", __func__,
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->state);
>> ? ? ? ? ? ? ? ?BUG();
>> ? ? ? ?}
>>
>> - ? ? ? DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
>> - ? ? ? DDADR(info->data_dma_ch) = info->data_desc_addr;
>> - ? ? ? DCSR(info->data_dma_ch) |= DCSR_RUN;
>> + ? ? ? DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
>> + ? ? ? DDADR(nand->data_dma_ch) = nand->data_desc_addr;
>> + ? ? ? DCSR(nand->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;
>> ? ? ? ?}
>>
>> - ? ? ? info->state = STATE_DMA_DONE;
>> - ? ? ? enable_int(info, NDCR_INT_MASK);
>> - ? ? ? nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
>> + ? ? ? nand->state = STATE_DMA_DONE;
>> + ? ? ? 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)) {
>> ? ? ? ? ? ? ? ?/* whether use dma to transfer data */
>> - ? ? ? ? ? ? ? if (info->use_dma) {
>> - ? ? ? ? ? ? ? ? ? ? ? disable_int(info, NDCR_INT_MASK);
>> - ? ? ? ? ? ? ? ? ? ? ? info->state = (status & NDSR_RDDREQ) ?
>> + ? ? ? ? ? ? ? if (nand->use_dma) {
>> + ? ? ? ? ? ? ? ? ? ? ? disable_int(nand, NDCR_INT_MASK);
>> + ? ? ? ? ? ? ? ? ? ? ? nand->state = (status & NDSR_RDDREQ) ?
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?STATE_DMA_READING : STATE_DMA_WRITING;
>> - ? ? ? ? ? ? ? ? ? ? ? start_data_dma(info);
>> + ? ? ? ? ? ? ? ? ? ? ? start_data_dma(nand);
>> ? ? ? ? ? ? ? ? ? ? ? ?goto NORMAL_IRQ_EXIT;
>> ? ? ? ? ? ? ? ?} else {
>> - ? ? ? ? ? ? ? ? ? ? ? info->state = (status & NDSR_RDDREQ) ?
>> + ? ? ? ? ? ? ? ? ? ? ? nand->state = (status & NDSR_RDDREQ) ?
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?STATE_PIO_READING : STATE_PIO_WRITING;
>> - ? ? ? ? ? ? ? ? ? ? ? handle_data_pio(info);
>> + ? ? ? ? ? ? ? ? ? ? ? handle_data_pio(nand);
>> ? ? ? ? ? ? ? ?}
>> ? ? ? ?}
>> - ? ? ? 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->is_ready = 1;
>> - ? ? ? ? ? ? ? info->state = STATE_READY;
>> + ? ? ? if (status & ready) {
>> + ? ? ? ? ? ? ? nand->is_ready = 1;
>> + ? ? ? ? ? ? ? nand->state = STATE_READY;
>> ? ? ? ?}
>>
>> ? ? ? ?if (status & NDSR_WRCMDREQ) {
>> - ? ? ? ? ? ? ? nand_writel(info, NDSR, NDSR_WRCMDREQ);
>> + ? ? ? ? ? ? ? nand_writel(nand, NDSR, NDSR_WRCMDREQ);
>> ? ? ? ? ? ? ? ?status &= ~NDSR_WRCMDREQ;
>> - ? ? ? ? ? ? ? info->state = STATE_CMD_HANDLE;
>> - ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb0);
>> - ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb1);
>> - ? ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb2);
>> + ? ? ? ? ? ? ? nand->state = STATE_CMD_HANDLE;
>> + ? ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->ndcb0);
>> + ? ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->ndcb1);
>> + ? ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->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--)
>> @@ -477,42 +487,49 @@ 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->is_ready ? ? ? ? ?= 0;
>> - ? ? ? info->retcode ? ? ? ? ? = ERR_NONE;
>> + ? ? ? nand->buf_start ? ? ? ? = 0;
>> + ? ? ? nand->buf_count ? ? ? ? = 0;
>> + ? ? ? nand->oob_size ? ? ? ? ?= 0;
>> + ? ? ? nand->use_ecc ? ? ? ? ? = 0;
>> + ? ? ? nand->is_ready ? ? ? ? ?= 0;
>> + ? ? ? nand->retcode ? ? ? ? ? = ERR_NONE;
>> + ? ? ? nand->data_size ? ? ? ? = 0;
>> + ? ? ? nand->use_dma ? ? ? ? ? = 0;
>> + ? ? ? nand->command ? ? ? ? ? = command;
>>
>> ? ? ? ?switch (command) {
>> ? ? ? ?case NAND_CMD_READ0:
>> ? ? ? ?case NAND_CMD_PAGEPROG:
>> - ? ? ? ? ? ? ? info->use_ecc = 1;
>> + ? ? ? ? ? ? ? nand->use_ecc = 1;
>> ? ? ? ?case NAND_CMD_READOOB:
>> ? ? ? ? ? ? ? ?pxa3xx_set_datasize(info);
>> + ? ? ? ? ? ? ? nand->oob_buff = nand->data_buff + nand->data_size;
>> + ? ? ? ? ? ? ? nand->use_dma = use_dma;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?case NAND_CMD_SEQIN:
>> ? ? ? ? ? ? ? ?exec_cmd = 0;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?default:
>> - ? ? ? ? ? ? ? info->ndcb1 = 0;
>> - ? ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? ? nand->ndcb1 = 0;
>> + ? ? ? ? ? ? ? nand->ndcb2 = 0;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?}
>>
>> - ? ? ? info->ndcb0 = ndcb0;
>> + ? ? ? nand->ndcb0 = ndcb0;
>> ? ? ? ?addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?+ info->col_addr_cycles);
>>
>> @@ -521,16 +538,16 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>> ? ? ? ?case NAND_CMD_READ0:
>> ? ? ? ? ? ? ? ?cmd = info->cmdset->read1;
>> ? ? ? ? ? ? ? ?if (command == NAND_CMD_READOOB)
>> - ? ? ? ? ? ? ? ? ? ? ? info->buf_start = mtd->writesize + column;
>> + ? ? ? ? ? ? ? ? ? ? ? nand->buf_start = mtd->writesize + column;
>> ? ? ? ? ? ? ? ?else
>> - ? ? ? ? ? ? ? ? ? ? ? info->buf_start = column;
>> + ? ? ? ? ? ? ? ? ? ? ? nand->buf_start = column;
>>
>> ? ? ? ? ? ? ? ?if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
>> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
>> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| addr_cycle
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (cmd & NDCB0_CMD1_MASK);
>> ? ? ? ? ? ? ? ?else
>> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
>> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_DBC
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| addr_cycle
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>> @@ -538,34 +555,34 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>> ? ? ? ?case NAND_CMD_SEQIN:
>> ? ? ? ? ? ? ? ?/* small page addr setting */
>> ? ? ? ? ? ? ? ?if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
>> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
>> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (column & 0xFF);
>>
>> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = 0;
>> ? ? ? ? ? ? ? ?} else {
>> - ? ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFF) << 16)
>> + ? ? ? ? ? ? ? ? ? ? ? nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (column & 0xFFFF);
>>
>> ? ? ? ? ? ? ? ? ? ? ? ?if (page_addr & 0xFF0000)
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = (page_addr & 0xFF0000) >> 16;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
>> ? ? ? ? ? ? ? ? ? ? ? ?else
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = 0;
>> ? ? ? ? ? ? ? ?}
>>
>> - ? ? ? ? ? ? ? info->buf_count = mtd->writesize + mtd->oobsize;
>> - ? ? ? ? ? ? ? memset(info->data_buff, 0xFF, info->buf_count);
>> + ? ? ? ? ? ? ? nand->buf_count = mtd->writesize + mtd->oobsize;
>> + ? ? ? ? ? ? ? memset(nand->data_buff, 0xFF, nand->buf_count);
>>
>> ? ? ? ? ? ? ? ?break;
>>
>> ? ? ? ?case NAND_CMD_PAGEPROG:
>> - ? ? ? ? ? ? ? if (is_buf_blank(info->data_buff,
>> + ? ? ? ? ? ? ? if (is_buf_blank(nand->data_buff,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(mtd->writesize + mtd->oobsize))) {
>> ? ? ? ? ? ? ? ? ? ? ? ?exec_cmd = 0;
>> ? ? ? ? ? ? ? ? ? ? ? ?break;
>> ? ? ? ? ? ? ? ?}
>>
>> ? ? ? ? ? ? ? ?cmd = info->cmdset->program;
>> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
>> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ST_ROW_EN
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_DBC
>> @@ -575,37 +592,37 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>>
>> ? ? ? ?case NAND_CMD_READID:
>> ? ? ? ? ? ? ? ?cmd = info->cmdset->read_id;
>> - ? ? ? ? ? ? ? info->buf_count = info->read_id_bytes;
>> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(3)
>> + ? ? ? ? ? ? ? nand->buf_count = info->read_id_bytes;
>> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(3)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>>
>> - ? ? ? ? ? ? ? info->data_size = 8;
>> + ? ? ? ? ? ? ? nand->data_size = 8;
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?case NAND_CMD_STATUS:
>> ? ? ? ? ? ? ? ?cmd = info->cmdset->read_status;
>> - ? ? ? ? ? ? ? info->buf_count = 1;
>> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(4)
>> + ? ? ? ? ? ? ? nand->buf_count = 1;
>> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(4)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>>
>> - ? ? ? ? ? ? ? info->data_size = 8;
>> + ? ? ? ? ? ? ? nand->data_size = 8;
>> ? ? ? ? ? ? ? ?break;
>>
>> ? ? ? ?case NAND_CMD_ERASE1:
>> ? ? ? ? ? ? ? ?cmd = info->cmdset->erase;
>> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(2)
>> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(2)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(3)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_DBC
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>> - ? ? ? ? ? ? ? info->ndcb1 = page_addr;
>> - ? ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? ? nand->ndcb1 = page_addr;
>> + ? ? ? ? ? ? ? nand->ndcb2 = 0;
>>
>> ? ? ? ? ? ? ? ?break;
>> ? ? ? ?case NAND_CMD_RESET:
>> ? ? ? ? ? ? ? ?cmd = info->cmdset->reset;
>> - ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(5)
>> + ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(5)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>>
>> ? ? ? ? ? ? ? ?break;
>> @@ -628,6 +645,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;
>>
>> ? ? ? ?/*
>> @@ -638,20 +656,32 @@ 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);
>> + ? ? ? /*
>> + ? ? ? ?* There may be different NAND chip hooked to
>> + ? ? ? ?* different chip select, so check whether
>> + ? ? ? ?* chip select has been changed, if yes, reset the 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);
>> + ? ? ? }
>> +
>> + ? ? ? nand->state = STATE_PREPARED;
>> + ? ? ? exec_cmd = prepare_command_pool(nand, command, column, page_addr);
>> ? ? ? ?if (exec_cmd) {
>> - ? ? ? ? ? ? ? init_completion(&info->cmd_complete);
>> - ? ? ? ? ? ? ? pxa3xx_nand_start(info);
>> + ? ? ? ? ? ? ? init_completion(&nand->cmd_complete);
>> + ? ? ? ? ? ? ? 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);
>> + ? ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_stop(nand);
>> ? ? ? ? ? ? ? ?}
>> - ? ? ? ? ? ? ? info->state = STATE_IDLE;
>> ? ? ? ?}
>> + ? ? ? nand->state = STATE_IDLE;
>> ?}
>>
>> ?static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
>> @@ -665,11 +695,12 @@ 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) {
>> + ? ? ? if (nand->retcode == ERR_SBERR) {
>> ? ? ? ? ? ? ? ?switch (info->use_ecc) {
>> ? ? ? ? ? ? ? ?case 1:
>> ? ? ? ? ? ? ? ? ? ? ? ?mtd->ecc_stats.corrected++;
>> @@ -678,14 +709,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>> ? ? ? ? ? ? ? ?default:
>> ? ? ? ? ? ? ? ? ? ? ? ?break;
>> ? ? ? ? ? ? ? ?}
>> - ? ? ? } else if (info->retcode == ERR_DBERR) {
>> + ? ? ? } else if (nand->retcode == ERR_DBERR) {
>> ? ? ? ? ? ? ? ?/*
>> ? ? ? ? ? ? ? ? * for blank page (all 0xff), HW will calculate its ECC as
>> ? ? ? ? ? ? ? ? * 0, which is different from the ECC information within
>> ? ? ? ? ? ? ? ? * OOB, ignore such double bit errors
>> ? ? ? ? ? ? ? ? */
>> ? ? ? ? ? ? ? ?if (is_buf_blank(buf, mtd->writesize))
>> - ? ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
>> + ? ? ? ? ? ? ? ? ? ? ? nand->retcode = ERR_NONE;
>> ? ? ? ? ? ? ? ?else
>> ? ? ? ? ? ? ? ? ? ? ? ?mtd->ecc_stats.failed++;
>> ? ? ? ?}
>> @@ -696,11 +727,12 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>> ?static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>> ?{
>> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
>> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
>> ? ? ? ?char retval = 0xFF;
>>
>> - ? ? ? if (info->buf_start < info->buf_count)
>> + ? ? ? if (nand->buf_start < nand->buf_count)
>> ? ? ? ? ? ? ? ?/* Has just send a new command? */
>> - ? ? ? ? ? ? ? retval = info->data_buff[info->buf_start++];
>> + ? ? ? ? ? ? ? retval = nand->data_buff[nand->buf_start++];
>>
>> ? ? ? ?return retval;
>> ?}
>> @@ -708,11 +740,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>> ?static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>> ?{
>> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
>> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
>> ? ? ? ?u16 retval = 0xFFFF;
>>
>> - ? ? ? if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
>> - ? ? ? ? ? ? ? retval = *((u16 *)(info->data_buff+info->buf_start));
>> - ? ? ? ? ? ? ? info->buf_start += 2;
>> + ? ? ? if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
>> + ? ? ? ? ? ? ? retval = *((u16 *)(nand->data_buff+nand->buf_start));
>> + ? ? ? ? ? ? ? nand->buf_start += 2;
>> ? ? ? ?}
>> ? ? ? ?return retval;
>> ?}
>> @@ -720,20 +753,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>> ?static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>> ?{
>> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
>> - ? ? ? int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? ? int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>>
>> - ? ? ? memcpy(buf, info->data_buff + info->buf_start, real_len);
>> - ? ? ? info->buf_start += real_len;
>> + ? ? ? memcpy(buf, nand->data_buff + nand->buf_start, real_len);
>> + ? ? ? nand->buf_start += real_len;
>> ?}
>>
>> ?static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
>> ? ? ? ? ? ? ? ?const uint8_t *buf, int len)
>> ?{
>> ? ? ? ?struct pxa3xx_nand_info *info = mtd->priv;
>> - ? ? ? int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? ? int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>>
>> - ? ? ? memcpy(info->data_buff + info->buf_start, buf, real_len);
>> - ? ? ? info->buf_start += real_len;
>> + ? ? ? memcpy(nand->data_buff + nand->buf_start, buf, real_len);
>> + ? ? ? nand->buf_start += real_len;
>> ?}
>>
>> ?static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
>> @@ -750,10 +785,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 {
>> ? ? ? ? ? ? ? ? ? ? ? ?/*
>> @@ -770,7 +806,8 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
>> ?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 = 0x0; /* enable all interrupts */
>>
>> @@ -804,6 +841,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>> ? ? ? ?ndcr |= NDCR_SPARE_EN; /* enable spare by default */
>>
>> ? ? ? ?info->reg_ndcr = ndcr;
>> + ? ? ? info->use_ecc = 1;
>>
>> ? ? ? ?pxa3xx_nand_set_timing(info, f->timing);
>> ? ? ? ?return 0;
>> @@ -811,15 +849,22 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>>
>> ?static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
>> ?{
>> - ? ? ? uint32_t ndcr = nand_readl(info, NDCR);
>> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? ? uint32_t ndcr = nand_readl(nand, NDCR);
>> +
>> + ? ? ? if (info->chip_select > 0) {
>> + ? ? ? ? ? ? ? printk(KERN_ERR "We could not detect configure"
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? " if more than one cs is supported!!\n");
>> + ? ? ? ? ? ? ? BUG();
>> + ? ? ? }
>> ? ? ? ?info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
>> ? ? ? ?/* set info fields needed to read id */
>> ? ? ? ?info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
>> ? ? ? ?info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
>> ? ? ? ?info->cmdset = &default_cmdset;
>>
>> - ? ? ? info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
>> - ? ? ? info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
>> + ? ? ? info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
>> + ? ? ? info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
>>
>> ? ? ? ?return 0;
>> ?}
>> @@ -830,50 +875,31 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
>> ?*/
>> ?#define MAX_BUFF_SIZE ?PAGE_SIZE
>>
>> -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
>> +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
>> ?{
>> - ? ? ? 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;
>> + ? ? ? struct pxa3xx_nand *nand;
>> + ? ? ? struct mtd_info *mtd;
>>
>> - ? ? ? 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;
>> - ? ? ? }
>> + ? ? ? if (!info)
>> + ? ? ? ? ? ? ? return;
>>
>> - ? ? ? return 0;
>> + ? ? ? nand = info->nand_data;
>> + ? ? ? mtd = get_mtd_by_info(info);
>> + ? ? ? kfree(mtd);
>> + ? ? ? nand->info[cs] = NULL;
>> ?}
>>
>> ?static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
>> ?{
>> - ? ? ? struct mtd_info *mtd = info->mtd;
>> + ? ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? ? struct mtd_info *mtd = get_mtd_by_info(info);
>> ? ? ? ?struct nand_chip *chip = mtd->priv;
>>
>> ? ? ? ?/* use the common timing to make a try */
>> - ? ? ? pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
>> + ? ? ? if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
>> + ? ? ? ? ? ? ? return 0;
>> ? ? ? ?chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
>> - ? ? ? if (info->is_ready)
>> + ? ? ? if (nand->is_ready)
>> ? ? ? ? ? ? ? ?return 1;
>> ? ? ? ?else
>> ? ? ? ? ? ? ? ?return 0;
>> @@ -882,7 +908,8 @@ 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 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;
>> ? ? ? ?struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
>> ? ? ? ?const struct pxa3xx_nand_flash *f = NULL;
>> @@ -891,27 +918,25 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>> ? ? ? ?uint64_t chipsize;
>> ? ? ? ?int i, ret, num;
>>
>> + ? ? ? nand->chip_select = info->chip_select;
>> ? ? ? ?if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
>> ? ? ? ? ? ? ? ?goto KEEP_CONFIG;
>>
>> ? ? ? ?ret = pxa3xx_nand_sensing(info);
>> ? ? ? ?if (!ret) {
>> - ? ? ? ? ? ? ? kfree(mtd);
>> - ? ? ? ? ? ? ? info->mtd = NULL;
>> - ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n");
>> + ? ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
>> + ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs %d!\n",
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->chip_select);
>
> dev_err()?
>
>>
>> ? ? ? ? ? ? ? ?return -EINVAL;
>> ? ? ? ?}
>>
>> ? ? ? ?chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
>> - ? ? ? id = *((uint16_t *)(info->data_buff));
>> + ? ? ? id = *((uint16_t *)(nand->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");
>> -
>> + ? ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
>> ? ? ? ? ? ? ? ?return -EINVAL;
>> ? ? ? ?}
>>
>> @@ -928,14 +953,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>> ? ? ? ?}
>>
>> ? ? ? ?if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
>> - ? ? ? ? ? ? ? kfree(mtd);
>> - ? ? ? ? ? ? ? info->mtd = NULL;
>> + ? ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
>> ? ? ? ? ? ? ? ?printk(KERN_ERR "ERROR!! flash not defined!!!\n");
>
> Also here.
>
>>
>> ? ? ? ? ? ? ? ?return -EINVAL;
>> ? ? ? ?}
>>
>> - ? ? ? pxa3xx_nand_config_flash(info, f);
>> + ? ? ? if (pxa3xx_nand_config_flash(info, f)) {
>> + ? ? ? ? ? ? ? printk(KERN_ERR "ERROR! Configure failed\n");
>
> And here. Giving no hint about which driver or function causes this
> message makes debugging harder than it should be.
>
> [...]
>
>> ?#ifdef CONFIG_PM
>> @@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
>> ? ? ? ?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);
>> + ? ? ? nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
>> + ? ? ? nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
>> ? ? ? ?clk_enable(info->clk);
>
> This won't compile.

Could you post your build log?

Thanks,
Lei


From zonque at gmail.com  Wed Jun 22 09:06:52 2011
From: zonque at gmail.com (Daniel Mack)
Date: Wed, 22 Jun 2011 15:06:52 +0200
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <BANLkTimk0+2LUeo5sq8w4ohRq-qCe_2t_Q@mail.gmail.com>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
	<BANLkTinQB-hXMRy5+BXKQSrPq=sVrorCVA@mail.gmail.com>
	<BANLkTimk0+2LUeo5sq8w4ohRq-qCe_2t_Q@mail.gmail.com>
Message-ID: <BANLkTim54jEKmxAQFNMGCyWwAu+FhVu0KA@mail.gmail.com>

Hi Lei,

On Wed, Jun 22, 2011 at 2:21 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
> Hi Daniel,
>
> On Wed, Jun 22, 2011 at 7:39 PM, Daniel Mack <zonque at gmail.com> wrote:
>> On Wed, Jun 22, 2011 at 5:17 AM, Lei Wen <leiwen at marvell.com> wrote:
>>> Current pxa3xx_nand controller has two chip select which
>>> both be workable. This patch enable this feature.
>>>
>>> Update platform driver to support this feature.
>>>
>>> Another notice should be taken that:
>>> When you want to use this feature, you should not enable the
>>> keep configuration feature, for two chip select could be
>>> attached with different nand chip. The different page size
>>> and timing requirement make the keep configuration impossible.
>>>
>>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>>> ---
>>> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>>> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
>>> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
>>> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
>>> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
>>> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
>>> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? ?8 +-
>>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?735 +++++++++++++++-----------
>>> ?9 files changed, 444 insertions(+), 338 deletions(-)
>>
>> This patch doesn't apply for me on top of Linus' master branch. Which
>> tree are you based on currently?
>
> Actually it is based on Linux 3.0-rc2 and add two patches pending to
> l2-mtd-2.6.git already:
>
> mtd: pxa3xx_nand: fix nand detection issue
> mtd: pxa3xx_nand: Fix blank page ECC mismatch

I have a similar setup, also with those two patches on top, but
applying your patch gives me:

Applying: MTD: pxa3xx_nand: enable multiple chip select support
error: patch failed: drivers/mtd/nand/pxa3xx_nand.c:477
error: drivers/mtd/nand/pxa3xx_nand.c: patch does not apply
Patch failed at 0001 MTD: pxa3xx_nand: enable multiple chip select support
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".

Could you push your branch somewhere?

>>> ?#ifdef CONFIG_PM
>>> @@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
>>> ? ? ? ?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);
>>> + ? ? ? nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
>>> + ? ? ? nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
>>> ? ? ? ?clk_enable(info->clk);
>>
>> This won't compile.
>
> Could you post your build log?

I didn't compile it because I couldn't, but "nand" is certainly
undefined in this context now. Did you compile and test this code with
"CONFIG_PM=y"?


Thanks,
Daniel


From grinberg at compulab.co.il  Wed Jun 22 09:45:11 2011
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Wed, 22 Jun 2011 16:45:11 +0300
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
Message-ID: <4E01F1E7.5010707@compulab.co.il>

Hi Lei,


Some comments from a quick look...


On 06/22/11 06:17, Lei Wen wrote:

> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
>
> Update platform driver to support this feature.
>
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.

You should _also_ put this comment inside the pxa3xx_nand.h
may be even inside the pxa3xx_nand_platform_data structure,
so people would not have to search the git log to find this problem.

> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
>  arch/arm/mach-mmp/aspenite.c                 |    5 +-
>  arch/arm/mach-pxa/cm-x300.c                  |    5 +-
>  arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
>  arch/arm/mach-pxa/littleton.c                |    5 +-
>  arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
>  arch/arm/mach-pxa/raumfeld.c                 |    5 +-
>  arch/arm/mach-pxa/zylonite.c                 |    5 +-
>  arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    8 +-
>  drivers/mtd/nand/pxa3xx_nand.c               |  735 +++++++++++++++-----------
>  9 files changed, 444 insertions(+), 338 deletions(-)
>
> diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
> index 06b5fa8..b6589d6 100644
> --- a/arch/arm/mach-mmp/aspenite.c
> +++ b/arch/arm/mach-mmp/aspenite.c
> @@ -167,8 +167,9 @@ 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),
> +	.cs_num = 1,
> +	.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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
> index b2248e7..d67eb7b 100644
> --- a/arch/arm/mach-pxa/cm-x300.c
> +++ b/arch/arm/mach-pxa/cm-x300.c
> @@ -423,8 +423,9 @@ 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),
> +	.cs_num		= 1,
> +	.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 3f9be41..ff7a07b 100644
> --- a/arch/arm/mach-pxa/colibri-pxa3xx.c
> +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
> @@ -139,8 +139,9 @@ 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),
> +	.cs_num		= 1,
> +	.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 e5e326d..6eaf852 100644
> --- a/arch/arm/mach-pxa/littleton.c
> +++ b/arch/arm/mach-pxa/littleton.c
> @@ -325,8 +325,9 @@ 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),
> +	.cs_num		= 1,
> +	.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 b5a8fd3..e7ce135 100644
> --- a/arch/arm/mach-pxa/mxm8x10.c
> +++ b/arch/arm/mach-pxa/mxm8x10.c
> @@ -389,10 +389,11 @@ 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,
> +	.cs_num		= 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 d130f77..a54846d 100644
> --- a/arch/arm/mach-pxa/raumfeld.c
> +++ b/arch/arm/mach-pxa/raumfeld.c
> @@ -349,8 +349,9 @@ 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),
> +	.cs_num		= 1,
> +	.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 5821185..ea4752a 100644
> --- a/arch/arm/mach-pxa/zylonite.c
> +++ b/arch/arm/mach-pxa/zylonite.c
> @@ -366,8 +366,9 @@ 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),
> +	.cs_num		= 1,
> +	.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 442301f..34a3f52 100644
> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> @@ -41,6 +41,8 @@ struct pxa3xx_nand_flash {
>  	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
>  };
>  
> +/* The max num of chip select current support */

/* The maximum number of chip selects currently supported */

> +#define NUM_CHIP_SELECT		(2)
>  struct pxa3xx_nand_platform_data {
>  
>  	/* the data flash bus is shared between the Static Memory
> @@ -52,8 +54,10 @@ 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;
> +	/* indicate how many chip select would be used for this platform */

/* indicate how many chip selects will be used */

> +	int	cs_num;

This name is too confusing, I think even num_cs is better or cs_count?
Also, may be align it with the others?

> +	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
> +	unsigned int				nr_parts[NUM_CHIP_SELECT];
>  
>  	const struct pxa3xx_nand_flash * 	flash;
>  	size_t					num_flash;
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index 30689cc..259b8d5 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -92,11 +92,13 @@
>  #define NDCB0_ADDR_CYC_SHIFT	(16)
>  
>  /* macros for registers read/write */
> -#define nand_writel(info, off, val)	\
> -	__raw_writel((val), (info)->mmio_base + (off))
> +#define nand_writel(nand, off, val)	\
> +	__raw_writel((val), (nand)->mmio_base + (off))
>  
> -#define nand_readl(info, off)		\
> -	__raw_readl((info)->mmio_base + (off))
> +#define nand_readl(nand, off)		\
> +	__raw_readl((nand)->mmio_base + (off))
> +#define get_mtd_by_info(info)		\
> +	(struct mtd_info *)((void *)info - sizeof(struct mtd_info))
>  
>  /* error code and state */
>  enum {
> @@ -110,6 +112,7 @@ enum {
>  
>  enum {
>  	STATE_IDLE = 0,
> +	STATE_PREPARED,
>  	STATE_CMD_HANDLE,
>  	STATE_DMA_READING,
>  	STATE_DMA_WRITING,
> @@ -123,63 +126,63 @@ enum {
>  struct pxa3xx_nand_info {
>  	struct nand_chip	nand_chip;
>  
> -	struct nand_hw_control	controller;
> -	struct platform_device	 *pdev;
>  	struct pxa3xx_nand_cmdset *cmdset;
> +	/* page size of attached chip */
> +	uint16_t		page_size;
> +	uint8_t			chip_select;
> +	uint8_t			use_ecc;
> +
> +	/* calculated from pxa3xx_nand_flash data */
> +	uint8_t			col_addr_cycles;
> +	uint8_t			row_addr_cycles;
> +	uint8_t			read_id_bytes;
> +
> +	/* cached register value */
> +	uint32_t		reg_ndcr;
> +	uint32_t		ndtr0cs0;
> +	uint32_t		ndtr1cs0;
>  
> +	void			*nand_data;
> +};
> +
> +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;

please, align

>  
> -	unsigned int 		buf_start;
> -	unsigned int		buf_count;
> -
> -	struct mtd_info         *mtd;
>  	/* DMA information */
>  	int			drcmr_dat;
>  	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;
> -	struct pxa_dma_desc	*data_desc;
> +	dma_addr_t		data_buff_phys;
>  	dma_addr_t 		data_desc_addr;
> +	struct pxa_dma_desc	*data_desc;
>  
> -	uint32_t		reg_ndcr;
> -
> -	/* saved column/page_addr during CMD_SEQIN */
> -	int			seqin_column;
> -	int			seqin_page_addr;
> +	struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
> +	uint32_t		command;
> +	uint16_t		data_size;	/* data size in FIFO */
> +	uint16_t		oob_size;
> +	unsigned char		*data_buff;
> +	unsigned char		*oob_buff;
> +	uint32_t		buf_start;
> +	uint32_t		buf_count;
>  
>  	/* relate to the command */
>  	unsigned int		state;
> -
> +	uint8_t			chip_select;
>  	int			use_ecc;	/* use HW ECC ? */
>  	int			use_dma;	/* use DMA ? */
>  	int			is_ready;
> -
> -	unsigned int		page_size;	/* page size of attached chip */
> -	unsigned int		data_size;	/* data size in FIFO */
>  	int 			retcode;
> -	struct completion 	cmd_complete;
>  
>  	/* generated NDCBx register values */
> +	uint8_t			total_cmds;
>  	uint32_t		ndcb0;
>  	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;
> -
> -	unsigned int	col_addr_cycles;
> -	unsigned int	row_addr_cycles;
>  };

It looks like if you switch the names of the structures above,
then the patch will be much shorter and cleaner,
but will it make structures meaning confusion?

>  
>  static int use_dma = 1;
> @@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
>  /* Define a default flash type setting serve as flash detecting only */
>  #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
>  
> -const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> +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)
> @@ -244,9 +247,11 @@ 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)) |
> @@ -260,26 +265,27 @@ 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 = (info->use_ecc) ? 40 : 64;
>  		break;
>  	case 512:
> -		info->oob_size = (info->use_ecc) ? 8 : 16;
> +		nand->oob_size = (info->use_ecc) ? 8 : 16;
>  		break;
>  	}
>  }
> @@ -290,185 +296,189 @@ 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 : 0;
> +	ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
> +	ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
>  	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;
>  
>  	/* wait RUN bit in NDCR become 0 */
> -	ndcr = nand_readl(info, NDCR);
> +	ndcr = nand_readl(nand, NDCR);
>  	while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
> -		ndcr = nand_readl(info, NDCR);
> +		ndcr = nand_readl(nand, NDCR);
>  		udelay(1);
>  	}
>  
>  	if (timeout <= 0) {
>  		ndcr &= ~NDCR_ND_RUN;
> -		nand_writel(info, NDCR, ndcr);
> +		nand_writel(nand, NDCR, ndcr);
>  	}
>  	/* clear status bits */
> -	nand_writel(info, NDSR, NDSR_MASK);
> +	nand_writel(nand, NDSR, NDSR_MASK);
>  }
>  
> -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)
>  {
> -	switch (info->state) {
> +	switch (nand->state) {
>  	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));
> +		__raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
> +				DIV_ROUND_UP(nand->data_size, 4));
> +		if (nand->oob_size > 0)
> +			__raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
> +					DIV_ROUND_UP(nand->oob_size, 4));
>  		break;
>  	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));
> +		__raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
> +				DIV_ROUND_UP(nand->data_size, 4));
> +		if (nand->oob_size > 0)
> +			__raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
> +					DIV_ROUND_UP(nand->oob_size, 4));
>  		break;
>  	default:
>  		printk(KERN_ERR "%s: invalid state %d\n", __func__,
> -				info->state);
> +				nand->state);
>  		BUG();
>  	}
>  }
>  
> -static void start_data_dma(struct pxa3xx_nand_info *info)
> +static void start_data_dma(struct pxa3xx_nand *nand)
>  {
> -	struct pxa_dma_desc *desc = info->data_desc;
> -	int dma_len = ALIGN(info->data_size + info->oob_size, 32);
> +	struct pxa_dma_desc *desc = nand->data_desc;
> +	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;
>  
> -	switch (info->state) {
> +	switch (nand->state) {
>  	case STATE_DMA_WRITING:
> -		desc->dsadr = info->data_buff_phys;
> -		desc->dtadr = info->mmio_phys + NDDB;
> +		desc->dsadr = nand->data_buff_phys;
> +		desc->dtadr = nand->mmio_phys + NDDB;
>  		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
>  		break;
>  	case STATE_DMA_READING:
> -		desc->dtadr = info->data_buff_phys;
> -		desc->dsadr = info->mmio_phys + NDDB;
> +		desc->dtadr = nand->data_buff_phys;
> +		desc->dsadr = nand->mmio_phys + NDDB;
>  		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
>  		break;
>  	default:
>  		printk(KERN_ERR "%s: invalid state %d\n", __func__,
> -				info->state);
> +				nand->state);
>  		BUG();
>  	}
>  
> -	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
> -	DDADR(info->data_dma_ch) = info->data_desc_addr;
> -	DCSR(info->data_dma_ch) |= DCSR_RUN;
> +	DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
> +	DDADR(nand->data_dma_ch) = nand->data_desc_addr;
> +	DCSR(nand->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;
>  	}
>  
> -	info->state = STATE_DMA_DONE;
> -	enable_int(info, NDCR_INT_MASK);
> -	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
> +	nand->state = STATE_DMA_DONE;
> +	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;

This is confusing... do you use to ?: operator for differentiating between
cs = 0 and cs = 1?
I think this is a bad idea.
Moreover, the use of ?: is discouraged among the kernel.

> +	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)) {
>  		/* whether use dma to transfer data */
> -		if (info->use_dma) {
> -			disable_int(info, NDCR_INT_MASK);
> -			info->state = (status & NDSR_RDDREQ) ?
> +		if (nand->use_dma) {
> +			disable_int(nand, NDCR_INT_MASK);
> +			nand->state = (status & NDSR_RDDREQ) ?
>  				      STATE_DMA_READING : STATE_DMA_WRITING;
> -			start_data_dma(info);
> +			start_data_dma(nand);
>  			goto NORMAL_IRQ_EXIT;
>  		} else {
> -			info->state = (status & NDSR_RDDREQ) ?
> +			nand->state = (status & NDSR_RDDREQ) ?
>  				      STATE_PIO_READING : STATE_PIO_WRITING;
> -			handle_data_pio(info);
> +			handle_data_pio(nand);
>  		}
>  	}
> -	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->is_ready = 1;
> -		info->state = STATE_READY;
> +	if (status & ready) {
> +		nand->is_ready = 1;
> +		nand->state = STATE_READY;
>  	}
>  
>  	if (status & NDSR_WRCMDREQ) {
> -		nand_writel(info, NDSR, NDSR_WRCMDREQ);
> +		nand_writel(nand, NDSR, NDSR_WRCMDREQ);
>  		status &= ~NDSR_WRCMDREQ;
> -		info->state = STATE_CMD_HANDLE;
> -		nand_writel(info, NDCB0, info->ndcb0);
> -		nand_writel(info, NDCB0, info->ndcb1);
> -		nand_writel(info, NDCB0, info->ndcb2);
> +		nand->state = STATE_CMD_HANDLE;
> +		nand_writel(nand, NDCB0, nand->ndcb0);
> +		nand_writel(nand, NDCB0, nand->ndcb1);
> +		nand_writel(nand, NDCB0, nand->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--)
> @@ -477,42 +487,49 @@ 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;

This one is confusing too...
Besides, you don't need the parenthesis.

>  	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->is_ready		= 0;
> -	info->retcode		= ERR_NONE;
> +	nand->buf_start		= 0;
> +	nand->buf_count		= 0;
> +	nand->oob_size		= 0;
> +	nand->use_ecc		= 0;
> +	nand->is_ready		= 0;
> +	nand->retcode		= ERR_NONE;
> +	nand->data_size		= 0;
> +	nand->use_dma		= 0;
> +	nand->command		= command;
>  
>  	switch (command) {
>  	case NAND_CMD_READ0:
>  	case NAND_CMD_PAGEPROG:
> -		info->use_ecc = 1;
> +		nand->use_ecc = 1;
>  	case NAND_CMD_READOOB:
>  		pxa3xx_set_datasize(info);
> +		nand->oob_buff = nand->data_buff + nand->data_size;
> +		nand->use_dma = use_dma;
>  		break;
>  	case NAND_CMD_SEQIN:
>  		exec_cmd = 0;
>  		break;
>  	default:
> -		info->ndcb1 = 0;
> -		info->ndcb2 = 0;
> +		nand->ndcb1 = 0;
> +		nand->ndcb2 = 0;
>  		break;
>  	}
>  
> -	info->ndcb0 = ndcb0;
> +	nand->ndcb0 = ndcb0;
>  	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
>  				    + info->col_addr_cycles);
>  
> @@ -521,16 +538,16 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>  	case NAND_CMD_READ0:
>  		cmd = info->cmdset->read1;
>  		if (command == NAND_CMD_READOOB)
> -			info->buf_start = mtd->writesize + column;
> +			nand->buf_start = mtd->writesize + column;
>  		else
> -			info->buf_start = column;
> +			nand->buf_start = column;
>  
>  		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
> -			info->ndcb0 |= NDCB0_CMD_TYPE(0)
> +			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
>  					| addr_cycle
>  					| (cmd & NDCB0_CMD1_MASK);
>  		else
> -			info->ndcb0 |= NDCB0_CMD_TYPE(0)
> +			nand->ndcb0 |= NDCB0_CMD_TYPE(0)
>  					| NDCB0_DBC
>  					| addr_cycle
>  					| cmd;
> @@ -538,34 +555,34 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>  	case NAND_CMD_SEQIN:
>  		/* small page addr setting */
>  		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
> -			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
> +			nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
>  					| (column & 0xFF);
>  
> -			info->ndcb2 = 0;
> +			nand->ndcb2 = 0;
>  		} else {
> -			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
> +			nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
>  					| (column & 0xFFFF);
>  
>  			if (page_addr & 0xFF0000)
> -				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
> +				nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
>  			else
> -				info->ndcb2 = 0;
> +				nand->ndcb2 = 0;
>  		}
>  
> -		info->buf_count = mtd->writesize + mtd->oobsize;
> -		memset(info->data_buff, 0xFF, info->buf_count);
> +		nand->buf_count = mtd->writesize + mtd->oobsize;
> +		memset(nand->data_buff, 0xFF, nand->buf_count);
>  
>  		break;
>  
>  	case NAND_CMD_PAGEPROG:
> -		if (is_buf_blank(info->data_buff,
> +		if (is_buf_blank(nand->data_buff,
>  					(mtd->writesize + mtd->oobsize))) {
>  			exec_cmd = 0;
>  			break;
>  		}
>  
>  		cmd = info->cmdset->program;
> -		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
> +		nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
>  				| NDCB0_AUTO_RS
>  				| NDCB0_ST_ROW_EN
>  				| NDCB0_DBC
> @@ -575,37 +592,37 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>  
>  	case NAND_CMD_READID:
>  		cmd = info->cmdset->read_id;
> -		info->buf_count = info->read_id_bytes;
> -		info->ndcb0 |= NDCB0_CMD_TYPE(3)
> +		nand->buf_count = info->read_id_bytes;
> +		nand->ndcb0 |= NDCB0_CMD_TYPE(3)
>  				| NDCB0_ADDR_CYC(1)
>  				| cmd;
>  
> -		info->data_size = 8;
> +		nand->data_size = 8;
>  		break;
>  	case NAND_CMD_STATUS:
>  		cmd = info->cmdset->read_status;
> -		info->buf_count = 1;
> -		info->ndcb0 |= NDCB0_CMD_TYPE(4)
> +		nand->buf_count = 1;
> +		nand->ndcb0 |= NDCB0_CMD_TYPE(4)
>  				| NDCB0_ADDR_CYC(1)
>  				| cmd;
>  
> -		info->data_size = 8;
> +		nand->data_size = 8;
>  		break;
>  
>  	case NAND_CMD_ERASE1:
>  		cmd = info->cmdset->erase;
> -		info->ndcb0 |= NDCB0_CMD_TYPE(2)
> +		nand->ndcb0 |= NDCB0_CMD_TYPE(2)
>  				| NDCB0_AUTO_RS
>  				| NDCB0_ADDR_CYC(3)
>  				| NDCB0_DBC
>  				| cmd;
> -		info->ndcb1 = page_addr;
> -		info->ndcb2 = 0;
> +		nand->ndcb1 = page_addr;
> +		nand->ndcb2 = 0;
>  
>  		break;
>  	case NAND_CMD_RESET:
>  		cmd = info->cmdset->reset;
> -		info->ndcb0 |= NDCB0_CMD_TYPE(5)
> +		nand->ndcb0 |= NDCB0_CMD_TYPE(5)
>  				| cmd;
>  
>  		break;
> @@ -628,6 +645,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;
>  
>  	/*
> @@ -638,20 +656,32 @@ 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);
> +	/*
> +	 * There may be different NAND chip hooked to
> +	 * different chip select, so check whether
> +	 * chip select has been changed, if yes, reset the 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);
> +	}
> +
> +	nand->state = STATE_PREPARED;
> +	exec_cmd = prepare_command_pool(nand, command, column, page_addr);
>  	if (exec_cmd) {
> -		init_completion(&info->cmd_complete);
> -		pxa3xx_nand_start(info);
> +		init_completion(&nand->cmd_complete);
> +		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);
> +			pxa3xx_nand_stop(nand);
>  		}
> -		info->state = STATE_IDLE;
>  	}
> +	nand->state = STATE_IDLE;
>  }
>  
>  static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> @@ -665,11 +695,12 @@ 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) {
> +	if (nand->retcode == ERR_SBERR) {
>  		switch (info->use_ecc) {
>  		case 1:
>  			mtd->ecc_stats.corrected++;
> @@ -678,14 +709,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>  		default:
>  			break;
>  		}
> -	} else if (info->retcode == ERR_DBERR) {
> +	} else if (nand->retcode == ERR_DBERR) {
>  		/*
>  		 * for blank page (all 0xff), HW will calculate its ECC as
>  		 * 0, which is different from the ECC information within
>  		 * OOB, ignore such double bit errors
>  		 */
>  		if (is_buf_blank(buf, mtd->writesize))
> -			info->retcode = ERR_NONE;
> +			nand->retcode = ERR_NONE;
>  		else
>  			mtd->ecc_stats.failed++;
>  	}
> @@ -696,11 +727,12 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>  static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>  {
>  	struct pxa3xx_nand_info *info = mtd->priv;
> +	struct pxa3xx_nand *nand = info->nand_data;
>  	char retval = 0xFF;
>  
> -	if (info->buf_start < info->buf_count)
> +	if (nand->buf_start < nand->buf_count)
>  		/* Has just send a new command? */
> -		retval = info->data_buff[info->buf_start++];
> +		retval = nand->data_buff[nand->buf_start++];
>  
>  	return retval;
>  }
> @@ -708,11 +740,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>  static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>  {
>  	struct pxa3xx_nand_info *info = mtd->priv;
> +	struct pxa3xx_nand *nand = info->nand_data;
>  	u16 retval = 0xFFFF;
>  
> -	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
> -		retval = *((u16 *)(info->data_buff+info->buf_start));
> -		info->buf_start += 2;
> +	if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
> +		retval = *((u16 *)(nand->data_buff+nand->buf_start));
> +		nand->buf_start += 2;
>  	}
>  	return retval;
>  }
> @@ -720,20 +753,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>  static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>  {
>  	struct pxa3xx_nand_info *info = mtd->priv;
> -	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
> +	struct pxa3xx_nand *nand = info->nand_data;
> +	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>  
> -	memcpy(buf, info->data_buff + info->buf_start, real_len);
> -	info->buf_start += real_len;
> +	memcpy(buf, nand->data_buff + nand->buf_start, real_len);
> +	nand->buf_start += real_len;
>  }
>  
>  static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
>  		const uint8_t *buf, int len)
>  {
>  	struct pxa3xx_nand_info *info = mtd->priv;
> -	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
> +	struct pxa3xx_nand *nand = info->nand_data;
> +	int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>  
> -	memcpy(info->data_buff + info->buf_start, buf, real_len);
> -	info->buf_start += real_len;
> +	memcpy(nand->data_buff + nand->buf_start, buf, real_len);
> +	nand->buf_start += real_len;
>  }
>  
>  static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
> @@ -750,10 +785,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 {
>  			/*
> @@ -770,7 +806,8 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
>  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 = 0x0; /* enable all interrupts */
>  
> @@ -804,6 +841,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>  	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
>  
>  	info->reg_ndcr = ndcr;
> +	info->use_ecc = 1;
>  
>  	pxa3xx_nand_set_timing(info, f->timing);
>  	return 0;
> @@ -811,15 +849,22 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>  
>  static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
>  {
> -	uint32_t ndcr = nand_readl(info, NDCR);
> +	struct pxa3xx_nand *nand = info->nand_data;
> +	uint32_t ndcr = nand_readl(nand, NDCR);
> +
> +	if (info->chip_select > 0) {
> +		printk(KERN_ERR "We could not detect configure"
> +				" if more than one cs is supported!!\n");
> +		BUG();

like Daniel already noticed, may be dev_err() is enough?

> +	}
>  	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
>  	/* set info fields needed to read id */
>  	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
>  	info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
>  	info->cmdset = &default_cmdset;
>  
> -	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> -	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
> +	info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
> +	info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
>  
>  	return 0;
>  }
> @@ -830,50 +875,31 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
>   */
>  #define MAX_BUFF_SIZE	PAGE_SIZE
>  
> -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
> +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
>  {
> -	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;
> +	struct pxa3xx_nand *nand;
> +	struct mtd_info *mtd;
>  
> -	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;
> -	}
> +	if (!info)
> +		return;
>  
> -	return 0;
> +	nand = info->nand_data;
> +	mtd = get_mtd_by_info(info);
> +	kfree(mtd);
> +	nand->info[cs] = NULL;
>  }
>  
>  static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
>  {
> -	struct mtd_info *mtd = info->mtd;
> +	struct pxa3xx_nand *nand = info->nand_data;
> +	struct mtd_info *mtd = get_mtd_by_info(info);
>  	struct nand_chip *chip = mtd->priv;
>  
>  	/* use the common timing to make a try */
> -	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
> +	if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
> +		return 0;
>  	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
> -	if (info->is_ready)
> +	if (nand->is_ready)
>  		return 1;
>  	else
>  		return 0;

I think it is time to change this function return convention to propagate
errors and not just 0 or 1, (may be in separate patch) what do you think?

> @@ -882,7 +908,8 @@ 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 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;
>  	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
>  	const struct pxa3xx_nand_flash *f = NULL;
> @@ -891,27 +918,25 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>  	uint64_t chipsize;
>  	int i, ret, num;
>  
> +	nand->chip_select = info->chip_select;
>  	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
>  		goto KEEP_CONFIG;
>  
>  	ret = pxa3xx_nand_sensing(info);
>  	if (!ret) {
> -		kfree(mtd);
> -		info->mtd = NULL;
> -		printk(KERN_INFO "There is no nand chip on cs 0!\n");
> +		free_cs_resource(info, nand->chip_select);
> +		printk(KERN_INFO "There is no nand chip on cs %d!\n",
> +				nand->chip_select);
>  
>  		return -EINVAL;
>  	}
>  
>  	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
> -	id = *((uint16_t *)(info->data_buff));
> +	id = *((uint16_t *)(nand->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");

Is this warning no longer needed?

> -
> +		free_cs_resource(info, nand->chip_select);
>  		return -EINVAL;
>  	}
>  
> @@ -928,14 +953,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>  	}
>  
>  	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
> -		kfree(mtd);
> -		info->mtd = NULL;
> +		free_cs_resource(info, nand->chip_select);
>  		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
>  
>  		return -EINVAL;
>  	}
>  
> -	pxa3xx_nand_config_flash(info, f);
> +	if (pxa3xx_nand_config_flash(info, f)) {
> +		printk(KERN_ERR "ERROR! Configure failed\n");
> +		return -EINVAL;
> +	}

Although, the pxa3xx_nand_config_flash() returns only 0 or -EINVAL,
it is better to propagate its return value.

>  	pxa3xx_flash_ids[0].name = f->name;
>  	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
>  	pxa3xx_flash_ids[0].pagesize = f->page_size;
> @@ -950,13 +977,13 @@ KEEP_CONFIG:
>  	if (nand_scan_ident(mtd, 1, def))
>  		return -ENODEV;
>  	/* calculate addressing information */
> +	nand->oob_buff = nand->data_buff + mtd->writesize;
>  	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
> -	info->oob_buff = info->data_buff + mtd->writesize;
>  	if ((mtd->size >> chip->page_shift) > 65536)
>  		info->row_addr_cycles = 3;
>  	else
>  		info->row_addr_cycles = 2;
> -	mtd->name = mtd_names[0];
> +	mtd->name = mtd_names[nand->chip_select];
>  	chip->ecc.mode = NAND_ECC_HW;
>  	chip->ecc.size = info->page_size;
>  
> @@ -967,51 +994,33 @@ KEEP_CONFIG:
>  	return nand_scan_tail(mtd);
>  }
>  
> -static
> -struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> +static int alloc_nand_resource(struct platform_device *pdev)
>  {
> +	struct pxa3xx_nand_platform_data *pdata;
>  	struct pxa3xx_nand_info *info;
>  	struct nand_chip *chip;
>  	struct mtd_info *mtd;
> +	struct pxa3xx_nand *nand;
>  	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) {
> +	pdata = pdev->dev.platform_data;
> +	nand = kzalloc(sizeof(struct mtd_info)
> +			+ sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
> +	if (!nand) {
>  		dev_err(&pdev->dev, "failed to allocate memory\n");
> -		return NULL;
> +		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->controller        = &info->controller;
> -	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;
> -
> -	spin_lock_init(&chip->controller->lock);
> -	init_waitqueue_head(&chip->controller->wq);
> -	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) {
> @@ -1019,7 +1028,7 @@ struct pxa3xx_nand_info *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) {
> @@ -1027,7 +1036,7 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
>  		ret = -ENXIO;
>  		goto fail_put_clk;
>  	}
> -	info->drcmr_cmd = r->start;
> +	nand->drcmr_cmd = r->start;
>  
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq < 0) {
> @@ -1050,81 +1059,147 @@ struct pxa3xx_nand_info *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);
>  
>  	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_io;
> +	}
> +
> +	platform_set_drvdata(pdev, nand);
> +
> +	spin_lock_init(&nand->controller.lock);
> +	init_waitqueue_head(&nand->controller.wq);
> +	for (cs = 0; cs < pdata->cs_num; 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;
>  	}
>  
> -	platform_set_drvdata(pdev, info);
> +	if (use_dma == 0) {
> +		nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
> +		if (nand->data_buff == NULL) {
> +			ret = -ENOMEM;
> +			goto fail_free_buf;
> +		}
> +		goto success_exit;
> +	}
>  
> -	return info;
> +	nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
> +			&nand->data_buff_phys, GFP_KERNEL);
> +	if (nand->data_buff == NULL) {
> +		dev_err(&pdev->dev, "failed to allocate dma buffer\n");
> +		ret = -ENOMEM;
> +		goto fail_free_buf;
> +	}
>  
> +	nand->data_desc = (void *)nand->data_buff + data_desc_offset;
> +	nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
> +	nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
> +			pxa3xx_nand_data_dma_irq, nand);
> +	if (nand->data_dma_ch < 0) {
> +		dev_err(&pdev->dev, "failed to request data dma\n");
> +		ret = -ENXIO;
> +		goto fail_free_dma_buf;
> +	}
> +success_exit:
> +	return 0;
> +
> +fail_free_dma_buf:
> +	dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
> +			nand->data_buff, nand->data_buff_phys);
>  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);
> +	for (cs = 0; cs < pdata->cs_num; cs++) {
> +		info = nand->info[cs];
> +		free_cs_resource(info, cs);
> +	}
> +fail_free_irq:
> +	free_irq(irq, nand);
>  fail_free_io:
> -	iounmap(info->mmio_base);
> +	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);
> -	return NULL;
> +	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_platform_data *pdata;
> +	struct pxa3xx_nand_info *info;
> +	struct mtd_info *mtd;
>  	struct resource *r;
> -	int irq;
> +	int irq, cs;
>  
>  	platform_set_drvdata(pdev, NULL);
> +	pdata = pdev->dev.platform_data;
>  
>  	irq = platform_get_irq(pdev, 0);
>  	if (irq >= 0)
> -		free_irq(irq, info);
> +		free_irq(irq, nand);
>  	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);
> +		pxa_free_dma(nand->data_dma_ch);
> +		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
> +				nand->data_buff, nand->data_buff_phys);
>  	} else
> -		kfree(info->data_buff);
> +		kfree(nand->data_buff);
>  
> -	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);
> +	clk_disable(nand->clk);
> +	clk_put(nand->clk);
>  
> -	if (mtd) {
> +	for (cs = 0; cs < pdata->cs_num; cs++) {
> +		info = nand->info[cs];
> +		if (!info)
> +			continue;
> +		mtd = get_mtd_by_info(info);
>  		mtd_device_unregister(mtd);
> -		kfree(mtd);
> +		free_cs_resource(info, cs);
>  	}
>  	return 0;
>  }
> @@ -1134,34 +1209,54 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
>  	struct pxa3xx_nand_platform_data *pdata;
>  	struct pxa3xx_nand_info *info;
>  
> +	struct pxa3xx_nand *nand;
> +	struct mtd_info *mtd;
> +	int cs, ret, nr_parts, probe_success;
> +
> +	probe_success = 0;

Can this be done along with declaration?

>  	pdata = pdev->dev.platform_data;
>  	if (!pdata) {
>  		dev_err(&pdev->dev, "no platform data defined\n");
>  		return -ENODEV;
>  	}
>  
> -	info = alloc_nand_resource(pdev);
> -	if (info == NULL)
> +	ret = alloc_nand_resource(pdev);
> +	if (ret)
>  		return -ENOMEM;

Why not propagate the return value of alloc_nand_resource()?

>  
> -	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 < pdata->cs_num; cs++) {
> +		info = nand->info[cs];
> +		mtd = get_mtd_by_info(info);
> +		if (pxa3xx_nand_scan(mtd)) {
> +			dev_err(&pdev->dev, "failed to scan nand\n");

I think, it would be useful also to print here the return value of pxa3xx_nand_scan().

> +			continue;
> +		}
> +
> +		ret = 0;
> +		nr_parts = 0;
> +		if (mtd_has_cmdlinepart()) {
> +			const char *probes[] = { "cmdlinepart", NULL };
> +			struct mtd_partition *parts;
>  
> -	if (mtd_has_cmdlinepart()) {
> -		const char *probes[] = { "cmdlinepart", NULL };
> -		struct mtd_partition *parts;
> -		int nr_parts;
> +			nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
>  
> -		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
> +			if (nr_parts)
> +				ret = mtd_device_register(mtd, parts, nr_parts);
> +		}
>  
> -		if (nr_parts)
> -			return mtd_device_register(info->mtd, parts, nr_parts);
> +		if (!nr_parts)
> +			ret = mtd_device_register(mtd, pdata->parts[cs],
> +					pdata->nr_parts[cs]);
> +		if (!ret)
> +			probe_success = 1;
>  	}
>  
> -	return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
> +	if (!probe_success) {
> +		pxa3xx_nand_remove(pdev);
> +		return -ENODEV;
> +	} else

You don't need this else statement

> +		return 0;
>  }
>  
>  #ifdef CONFIG_PM
> @@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
>  	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);
> +	nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
> +	nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
>  	clk_enable(info->clk);
>  
>  	return 0;

I won't be able to test the patch in the near future, sorry...

-- 
Regards,
Igor.



From peter.barada at gmail.com  Wed Jun 22 11:28:54 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Wed, 22 Jun 2011 11:28:54 -0400
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <1308722655.18119.40.camel@sauron>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
Message-ID: <4E020A36.6070708@gmail.com>

On 06/22/2011 02:04 AM, Artem Bityutskiy wrote:
> On Tue, 2011-06-14 at 12:19 -0400, Peter Barada wrote:
>> I'm using a Micron 512MB NAND which has an internal 4-bit ECC engine,
>> and am finding lots of ECC errors while using JFFS2.  The same NAND
>> works find using YAFFS so I know the underlying MTD driver works properly.
>>
>> The big question I have is whether JFFS2 does partial page writes and if
>> so how to disable them.
> JFFS2 does not use sub-pages so it should never do partial writes. I
> think the ECC errors you see are because of JFFS2 using OOB area to
> store clean markers.
Sorry for using the wrong terminology - I assumed a "partial write" is 
where data/oob information is written into a page multiple times.

Yes, the issue I'm seeing is that JFFS2 writes into the OOB area into
bytes that perturb the ECC, then writes data (w/o OOB) and the next read 
fails.  Googling around I see GETECCLAYOUT is now obsolete, so it 
doesn't look like extending the structure returned from it is not the 
way to go.

I'm thinking a new ioctl (and data in the kernel accessible to the NAND 
FS layers) is needed (GETOOBLAYOUT?) that returns the oobfree array, as 
well as other arrays in a structure:
1) which OOB bytes perturb the data ECCs,
2) which OOB bytes are ECC'd (within the OOB area and separate from the 
data ECCs).

I think given the new large-sized NAND that these lists will have to be 
dynamic (and another GETOOBLAYOUTSIZE ioctl call to return its size) to 
prevent moving massive structure to userspace).

Then userspace can figure out:

1) what bytes can be written in the OOB.
2) what bytes in the OOB can only be written as part of a data write (or 
sub-page write)
3) if no OOB bytes are internally ECC'd(outside of those covered by a 
data area ECC) then the code needs to either use an ECC as part of the 
data written to the OOB, or use a bitflip-friendly way to compare the 
returned data - unless the OOB data it wants to write is part of a data 
area write.

In my initial attempt to solve this I ran into the issue (in 
linux-2.6.32) that nand_transfer_oob/nand_fill_oob make the assumption 
that chip->ecc.layout->oobfree is *always* zero terminated (I needed 
eight entries to describe my OOB area).  I'll put together a patch 
against the latest kernel and send it along.

Thoughts?

-- 
Peter Barada
peter.barada at gmail.com



From adam.thomson at alcatel-lucent.com  Wed Jun 22 11:40:09 2011
From: adam.thomson at alcatel-lucent.com (THOMSON, Adam (Adam))
Date: Wed, 22 Jun 2011 17:40:09 +0200
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi
	before writing OOB data
In-Reply-To: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DDB3@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308722112.18119.36.camel@sauron>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DD8D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308740228.18119.70.camel@sauron>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DDB3@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
Message-ID: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DF22@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>

Adam Thomson Wrote:
> 
> The original request was for a stable patch, and that would 
> be accepted if I provided a proper tidy fix also. To be fair 
> it was a few weeks ago now that that mail was sent. :-) 
> Anyway, as it turns out the tidy fix was almost identical, 
> and we don't need the memset as far as I can tell from 
> reviewing code and from testing. Will run up your patch today 
> to verify your additional change, but should be fine.
> 

Have tested the updated patch on hardware, and all seems good.
No problems with OOB corruption, and mtd tests run without failure.

Thanks

Adam

From computersforpeace at gmail.com  Wed Jun 22 12:49:16 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:16 -0700
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-1-git-send-email-computersforpeace@gmail.com>

Hello,

I think this should be the last version necessary for this particular patch
series...

This series adds, changes, and deprecates several nanddump options, helping make
nanddump a closer inverse to nandwrite. This is mostly a preparation for the
next release, when several defaults might change. A short list of the planned
changes:

 * unify bad block methods under `--bb=METHOD', deprecating old ones
 * kill --omitbad in favor of --bb=skipbad
 * skip bad blocks by default (i.e., --bb=skipbad)
 * do not dump OOB by default (--omitoob)
 * add `--oob' to force dumping OOB

Please let me know when these are accepted and the 1.4.5 release is made, so I
can send a proper patchset to clean this all up as planned for the 1.4.6
release.

BTW, is each utility supposed to have its own version? (e.g., nanddump has
version 1.30?) Should these versions be kept in any kind of sync with the
mtd-utils revision tags? And does Artem take care of this stuff?

Thanks,
Brian

Brian Norris (7):
  nanddump: add --bb=METHOD option
  nanddump: remove --skipbad, leaving --bb=skipbad
  nanddump: update help message for BB method changes
  nanddump: warn about new default BB handling
  feature-removal-schedule: describe nanddump changes
  nanddump: add --oob option
  nanddump: document, warn about future default --omitoob

 feature-removal-schedule.txt |   37 ++++++++++++
 nanddump.c                   |  132 +++++++++++++++++++++++++++++++-----------
 2 files changed, 134 insertions(+), 35 deletions(-)




From computersforpeace at gmail.com  Wed Jun 22 12:49:17 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:17 -0700
Subject: [PATCH v3 1/7] nanddump: add --bb=METHOD option
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-2-git-send-email-computersforpeace@gmail.com>

We have too many separate bad block handling methods:
 --omitbad
 --noskipbad
 --skipbad
On top of these, we have the default option: that bad blocks are
replaced with 0xFF.

These options will be unified under --bb=METHOD. The end goal will be
something like:

----------------------------------------------------------------------------------------------
Old option     New option     Comment
----------------------------------------------------------------------------------------------
<default>      --bb=padbad    dump flash data, substituting 0xFF for any bad blocks
--noskipbad    --bb=dumpbad   dump flash data, including any bad blocks
--skipbad      --bb=skipbad   dump good data, completely skipping any bad blocks (new default)
--omitbad      N/A            very similar to `skipbad' (DEPRECTATED)

The BB options are all mutually exclusive, so we check that we do not
have more than one BB option explicitly enabled on the command line by
tracking whether or not a BB method has been set by the user.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   67 ++++++++++++++++++++++++++++++++++++++++-------------------
 1 files changed, 45 insertions(+), 22 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index c9d7e8b..08f8964 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -88,21 +88,26 @@ static void display_version(void)
 
 static bool			pretty_print = false;	// print nice
 static bool			noecc = false;		// don't error correct
-static bool			noskipbad = false;	// don't skip bad blocks
 static bool			omitoob = false;	// omit oob data
 static long long		start_addr;		// start address
 static long long		length;			// dump length
 static const char		*mtddev;		// mtd device name
 static const char		*dumpfile;		// dump file name
-static bool			omitbad = false;
 static bool			quiet = false;		// suppress diagnostic output
 static bool			canonical = false;	// print nice + ascii
 static bool			forcebinary = false;	// force printing binary to tty
-static bool			skipbad = false;	// skip over bad blocks
+
+static enum {
+	padbad,   // dump flash data, substituting 0xFF for any bad blocks
+	dumpbad,  // dump flash data, including any bad blocks
+	skipbad,  // dump good data, completely skipping any bad blocks
+	omitbad   // dump flash data, substituting nothing for any bad blocks (DEPRECATED)
+} bb_method = padbad;
 
 static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
+	bool bb_default = true;
 
 	for (;;) {
 		int option_index = 0;
@@ -110,6 +115,7 @@ static void process_options(int argc, char * const argv[])
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
+			{"bb", required_argument, 0, 0},
 			{"forcebinary", no_argument, 0, 'a'},
 			{"canonicalprint", no_argument, 0, 'c'},
 			{"file", required_argument, 0, 'f'},
@@ -140,10 +146,28 @@ static void process_options(int argc, char * const argv[])
 					case 1:
 						display_version();
 						break;
+					case 2:
+						/* Handle --bb=METHOD */
+						if (!strcmp(optarg, "padbad"))
+							bb_method = padbad;
+						else if (!strcmp(optarg, "dumpbad"))
+							bb_method = dumpbad;
+						else if (!strcmp(optarg, "skipbad"))
+							bb_method = skipbad;
+						else
+							error++;
+						bb_default = false;
+						break;
 				}
 				break;
 			case 'b':
-				omitbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = omitbad;
+				} else {
+					error++;
+				}
 				break;
 			case 's':
 				start_addr = simple_strtoll(optarg, &error);
@@ -175,10 +199,22 @@ static void process_options(int argc, char * const argv[])
 				noecc = true;
 				break;
 			case 'N':
-				noskipbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = dumpbad;
+				} else {
+					error++;
+				}
 				break;
 			case 'k':
-				skipbad = true;
+				/* Check if bb_method was already set explicitly */
+				if (bb_default) {
+					bb_default = false;
+					bb_method = skipbad;
+				} else {
+					error++;
+				}
 				break;
 			case '?':
 				error++;
@@ -206,19 +242,6 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (noskipbad && skipbad) {
-		fprintf(stderr, "The noskipbad and skipbad options are "
-				"mutually-exclusive.\n"
-				"Choose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
-	if (omitbad && skipbad) {
-		fprintf(stderr, "The omitbad and skipbad options are mutually-"
-				"exclusive.\nChoose one or the other.\n");
-		exit(EXIT_FAILURE);
-	}
-
 	if ((argc - optind) != 1 || error)
 		display_help();
 
@@ -416,7 +439,7 @@ int main(int argc, char * const argv[])
 	/* Dump the flash contents */
 	for (ofs = start_addr; ofs < end_addr; ofs += bs) {
 		/* Check for bad block */
-		if (noskipbad) {
+		if (bb_method == dumpbad) {
 			badblock = 0;
 		} else if (blockstart != (ofs & (~mtd.eb_size + 1)) ||
 				firstblock) {
@@ -430,14 +453,14 @@ int main(int argc, char * const argv[])
 
 		if (badblock) {
 			/* skip bad block, increase end_addr */
-			if (skipbad) {
+			if (bb_method == skipbad) {
 				end_addr += mtd.eb_size;
 				ofs += mtd.eb_size - bs;
 				if (end_addr > mtd.size)
 					end_addr = mtd.size;
 				continue;
 			}
-			if (omitbad)
+			if (bb_method == omitbad)
 				continue;
 			memset(readbuf, 0xff, bs);
 		} else {
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:49:18 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:18 -0700
Subject: [PATCH v3 2/7] nanddump: remove --skipbad, leaving --bb=skipbad
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-3-git-send-email-computersforpeace@gmail.com>

We are moving to unify bad block handling methods under the --bb=METHOD
option. Since --skipbad has not been included in a mtd-utils release yet,
we can safely replace it without a deprecation and phase-out period.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   13 +------------
 1 files changed, 1 insertions(+), 12 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 08f8964..d2e2e8f 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -51,7 +51,6 @@ static void display_help(void)
 "-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
-"-k         --skipbad            Skip over bad blocks (see below)\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
 "-N         --noskipbad          Read without bad block skipping\n"
@@ -111,7 +110,7 @@ static void process_options(int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "bs:f:l:opqnNcak";
+		static const char *short_options = "bs:f:l:opqnNca";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
@@ -126,7 +125,6 @@ static void process_options(int argc, char * const argv[])
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
 			{"noskipbad", no_argument, 0, 'N'},
-			{"skipbad", no_argument, 0, 'k'},
 			{"quiet", no_argument, 0, 'q'},
 			{0, 0, 0, 0},
 		};
@@ -207,15 +205,6 @@ static void process_options(int argc, char * const argv[])
 					error++;
 				}
 				break;
-			case 'k':
-				/* Check if bb_method was already set explicitly */
-				if (bb_default) {
-					bb_default = false;
-					bb_method = skipbad;
-				} else {
-					error++;
-				}
-				break;
 			case '?':
 				error++;
 				break;
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:49:19 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:19 -0700
Subject: [PATCH v3 3/7] nanddump: update help message for BB method
 changes
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-4-git-send-email-computersforpeace@gmail.com>

--noskipbad will soon be replaced by --bb=dumpbad, and --omitbad is being
removed entirely in favor of --bb=skipbad.

This patch adds warnings when using inappropriate configurations and adds
info to the help message. Please plan to migrate to the new usages shortly.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   32 +++++++++++++++++++++++++-------
 1 files changed, 25 insertions(+), 7 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index d2e2e8f..103ad06 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -47,23 +47,35 @@ static void display_help(void)
 "\n"
 "           --help               Display this help and exit\n"
 "           --version            Output version information and exit\n"
+"           --bb=METHOD          Choose bad block handling method (see below).\n"
 "-a         --forcebinary        Force printing of binary data to tty\n"
-"-b         --omitbad            Omit bad blocks from the dump\n"
 "-c         --canonicalprint     Print canonical Hex+ASCII dump\n"
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"-N         --noskipbad          Read without bad block skipping\n"
 "-o         --omitoob            Omit oob data\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
 "\n"
-"Notes on --omitbad and --skipbad:\n"
-"  With either option, we stop dumping data when we encounter a bad block\n"
-"  and resume dumping at the next good block. However, with --omitbad, we\n"
+"--bb=METHOD, where METHOD can be `padbad', `dumpbad', or `skipbad':\n"
+"    padbad:  dump flash data, substituting 0xFF for any bad blocks (default)\n"
+"    dumpbad: dump flash data, including any bad blocks\n"
+"    skipbad: dump good data, completely skipping any bad blocks\n"
+"\n"
+"Deprecated options:\n"
+"The following options are being replaced by --bb=METHOD flags or being\n"
+"removed entirely. Do not continue to use these options.\n"
+"-b         --omitbad            Omit bad blocks from the dump (DEPRECATED)\n"
+"-N         --noskipbad          Read without bad block skipping\n"
+"\n"
+"Notes on --omitbad and --bb=skipbad:\n"
+"* `omitbad' and `skipbad' are very similar; we are deprecating `--omitbad'\n"
+"  in favor of `--bb=skipbad'.\n"
+"* With either option, we stop dumping data when we encounter a bad block\n"
+"  and resume dumping at the next good block. However, with `omitbad', we\n"
 "  count the bad block as part of the total dump length, whereas with\n"
-"  --skipbad, the bad block is 'skipped,' that is, not counted toward the\n"
+"  `skipbad', the bad block is skipped, that is, not counted toward the\n"
 "  total dump length.\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
@@ -120,7 +132,7 @@ static void process_options(int argc, char * const argv[])
 			{"file", required_argument, 0, 'f'},
 			{"prettyprint", no_argument, 0, 'p'},
 			{"omitoob", no_argument, 0, 'o'},
-			{"omitbad", no_argument, 0, 'b'},
+			{"omitbad", no_argument, 0, 'b'}, //DEPRECATED
 			{"startaddress", required_argument, 0, 's'},
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
@@ -163,6 +175,9 @@ static void process_options(int argc, char * const argv[])
 				if (bb_default) {
 					bb_default = false;
 					bb_method = omitbad;
+					warnmsg("--omitbad is being deprecated in favor of --bb=skipbad.\n"
+						"  --omitbad will not be available in future releases.\n"
+						"  Please update your usage accordingly.");
 				} else {
 					error++;
 				}
@@ -201,6 +216,9 @@ static void process_options(int argc, char * const argv[])
 				if (bb_default) {
 					bb_default = false;
 					bb_method = dumpbad;
+					warnmsg("--noskipbad is being deprecated in favor of --bb=dumpbad.\n"
+						"  --noskipbad will not be available in future releases.\n"
+						"  Please update your usage accordingly.");
 				} else {
 					error++;
 				}
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:49:20 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:20 -0700
Subject: [PATCH v3 4/7] nanddump: warn about new default BB handling
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-5-git-send-email-computersforpeace@gmail.com>

In an upcoming release, we will no longer default to --bb=padbad. Instead,
the default will be --bb=skipbad. This makes nanddump a better inverse
operation to nandwrite.

This patch prints warnings for users so that they get a chance to update
their scripts before the default changes officially.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 103ad06..b6307cf 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -249,6 +249,11 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
+	if (bb_default)
+		warnmsg("you did not specify a default bad-block handling\n"
+			"  method. In future versions, the default will change to\n"
+			"  --bb=skipbad. Use \"nanddump --help\" for more information.");
+
 	if ((argc - optind) != 1 || error)
 		display_help();
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:49:21 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:21 -0700
Subject: [PATCH v3 5/7] feature-removal-schedule: describe nanddump
 changes
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-6-git-send-email-computersforpeace@gmail.com>

Include a few notes about the edited options and new defaults for bad
block handling in nanddump.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |   26 ++++++++++++++++++++++++++
 1 files changed, 26 insertions(+), 0 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index a5980f7..f9910f1 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -40,3 +40,29 @@ This is duplicating behavior with the mtdinfo utility.  Now the util
 warns when people use it, but it'll be removed in release 1.4.6.
 
 ---------------------------
+
+4. Rename --noskipbad option, kill --omitbad, change default BB method for nanddump
+
+Our bad block handling methods are getting disorganized. They will be replaced
+by a series of --bb=METHOD options (see `nanddump --help').
+
+In addition, the previous default bad block behavior was to dump 0xFF in place
+of bad blocks. This was not a good "inverse operation" of nandwrite. Thus, the
+current default behavior has become the (new) option --bb=padbad, and in 1.4.6,
+the default will be --bb=skipbad.
+
+The new `--bb=METHOD' options are included in this release, but all feature
+removals and changed defaults will occur in 1.4.6. For now, there are
+appropriate deprecation warning messages and an alert telling about the
+soon-to-be-default settings.
+
+Transition summary table:
+-----------------------------------------------------------------------------------------------------------
+ Old option     New option                 Comment
+-----------------------------------------------------------------------------------------------------------
+ <default>      --bb=padbad                dump flash data, substituting 0xFF for any bad blocks
+ --noskipbad    --bb=dumpbad               dump flash data, including any bad blocks
+ --skipbad      --bb=skipbad, <default>    dump good data, completely skipping any bad blocks (new default)
+ --omitbad      N/A                        very similar to `skipbad', will be removed soon
+
+---------------------------
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:49:22 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:22 -0700
Subject: [PATCH v3 6/7] nanddump: add --oob option
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-7-git-send-email-computersforpeace@gmail.com>

Adds an explicit option for including OOB data in our data dump.
Currently, this is the default behavior, but in the next release, the
default will be to exclude OOB data. This is done to mirror the '-o'
option in nandwrite.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index b6307cf..e19a45f 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -54,6 +54,7 @@ static void display_help(void)
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
 "-o         --omitoob            Omit oob data\n"
+"           --oob                Dump OOB data\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
@@ -127,6 +128,7 @@ static void process_options(int argc, char * const argv[])
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
 			{"bb", required_argument, 0, 0},
+			{"oob", no_argument, 0, 0},
 			{"forcebinary", no_argument, 0, 'a'},
 			{"canonicalprint", no_argument, 0, 'c'},
 			{"file", required_argument, 0, 'f'},
@@ -168,6 +170,9 @@ static void process_options(int argc, char * const argv[])
 							error++;
 						bb_default = false;
 						break;
+					case 3: /* --oob */
+						omitoob = false;
+						break;
 				}
 				break;
 			case 'b':
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:49:23 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:49:23 -0700
Subject: [PATCH v3 7/7] nanddump: document, warn about future default --omitoob
In-Reply-To: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
Message-ID: <1308761363-16512-8-git-send-email-computersforpeace@gmail.com>

To work as a proper inverse to nandwrite, nanddump must not dump OOB data by
default. This patch prints a warning regarding the future change. We also
suggest using the new flag, `--oob', for transitioning to the next release
with new default behavior.

Note that we are changing `-o' to mean `--oob' in the next release,
similar to `nandwrite -o'.  This is a break from previous behavior.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |   11 +++++++++++
 nanddump.c                   |   34 ++++++++++++++++++++++++++++------
 2 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index f9910f1..338bc08 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -66,3 +66,14 @@ Transition summary table:
  --omitbad      N/A                        very similar to `skipbad', will be removed soon
 
 ---------------------------
+
+5. nanddump will not dump OOB by default
+
+In 1.4.6, nanddump will not dump OOB by default. To dump OOB, you will have to
+explicitly use the option `--oob'. For now, there is simply a warning every
+time you use nanddump without explicitly choosing `--oob' or `--omitoob'.
+
+Note that `-o' will no longer stand for `--omitoob'. To unify with nandwrite,
+it will stand for `--oob' (Dump OOB data).
+
+---------------------------
diff --git a/nanddump.c b/nanddump.c
index e19a45f..54cb1af 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -53,8 +53,8 @@ static void display_help(void)
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"-o         --omitoob            Omit oob data\n"
-"           --oob                Dump OOB data\n"
+"-o         --omitoob            Omit OOB data (default in next release)\n"
+"           --oob                Dump OOB data (current default)\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
@@ -77,7 +77,14 @@ static void display_help(void)
 "  and resume dumping at the next good block. However, with `omitbad', we\n"
 "  count the bad block as part of the total dump length, whereas with\n"
 "  `skipbad', the bad block is skipped, that is, not counted toward the\n"
-"  total dump length.\n",
+"  total dump length.\n"
+"\n"
+"Note on --oob, --omitoob:\n"
+"  To make nanddump act more like an inverse to nandwrite, we are changing\n"
+"  the default OOB behavior. In the next release, nanddump will not dump\n"
+"  OOB data by default. We will leave both the `--omitoob' and `--oob'\n"
+"  options, but to mirror nandwrite, the short option `-o' will then stand\n"
+"  for `--oob', not `--omitoob'. Please adjust your usage accordingly.\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
 }
@@ -119,7 +126,7 @@ static enum {
 static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
-	bool bb_default = true;
+	bool bb_default = true, oob_default = true;
 
 	for (;;) {
 		int option_index = 0;
@@ -171,7 +178,12 @@ static void process_options(int argc, char * const argv[])
 						bb_default = false;
 						break;
 					case 3: /* --oob */
-						omitoob = false;
+						if (oob_default) {
+							oob_default = false;
+							omitoob = false;
+						} else {
+							errmsg_die("--oob and --oomitoob are mutually exclusive");
+						}
 						break;
 				}
 				break;
@@ -200,7 +212,12 @@ static void process_options(int argc, char * const argv[])
 				length = simple_strtoll(optarg, &error);
 				break;
 			case 'o':
-				omitoob = true;
+				if (oob_default) {
+					oob_default = false;
+					omitoob = true;
+				} else {
+					errmsg_die("--oob and --oomitoob are mutually exclusive");
+				}
 				break;
 			case 'a':
 				forcebinary = true;
@@ -259,6 +276,11 @@ static void process_options(int argc, char * const argv[])
 			"  method. In future versions, the default will change to\n"
 			"  --bb=skipbad. Use \"nanddump --help\" for more information.");
 
+	if (oob_default)
+		warnmsg("in next release, nanddump will not dump OOB\n"
+			"  by default. Use `nanddump --oob' explicitly to ensure\n"
+			"  it is dumped.");
+
 	if ((argc - optind) != 1 || error)
 		display_help();
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 22 12:53:21 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 22 Jun 2011 09:53:21 -0700
Subject: nanddump badblock options
In-Reply-To: <1308717762.18119.21.camel@sauron>
References: <1307563284-32416-1-git-send-email-computersforpeace@gmail.com>
	<1307608004.7374.56.camel@localhost>
	<BANLkTimU-fzEj6ByC9X6DX=tUQ0ay_eYrQ@mail.gmail.com>
	<1308717762.18119.21.camel@sauron>
Message-ID: <BANLkTimps-inQVa2Vn3kdjTnoauqaE0vtw@mail.gmail.com>

On Tue, Jun 21, 2011 at 9:42 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> Yes, I think so. Just invent a sensible "deprecation period" plan and go
> ahead with unifying them.
>
> Thanks!

OK, I sent my v3 patch set just now. I think I documented my plan well
enough in the patch set, so let me know how that looks.

Thanks,
Brian


From ivan.djelic at parrot.com  Wed Jun 22 13:07:47 2011
From: ivan.djelic at parrot.com (Ivan Djelic)
Date: Wed, 22 Jun 2011 19:07:47 +0200
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <4E020A36.6070708@gmail.com>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
	<4E020A36.6070708@gmail.com>
Message-ID: <20110622170747.GC25928@parrot.com>

On Wed, Jun 22, 2011 at 04:28:54PM +0100, Peter Barada wrote:
(...)
> 
> I'm thinking a new ioctl (and data in the kernel accessible to the NAND 
> FS layers) is needed (GETOOBLAYOUT?) that returns the oobfree array, as 
> well as other arrays in a structure:
> 1) which OOB bytes perturb the data ECCs,
> 2) which OOB bytes are ECC'd (within the OOB area and separate from the 
> data ECCs).
> 
> I think given the new large-sized NAND that these lists will have to be 
> dynamic (and another GETOOBLAYOUTSIZE ioctl call to return its size) to 
> prevent moving massive structure to userspace).
> 
> Then userspace can figure out:
> 
> 1) what bytes can be written in the OOB.
> 2) what bytes in the OOB can only be written as part of a data write (or 
> sub-page write)
> 3) if no OOB bytes are internally ECC'd(outside of those covered by a 
> data area ECC) then the code needs to either use an ECC as part of the 
> data written to the OOB, or use a bitflip-friendly way to compare the 
> returned data - unless the OOB data it wants to write is part of a data 
> area write.
> 
> In my initial attempt to solve this I ran into the issue (in 
> linux-2.6.32) that nand_transfer_oob/nand_fill_oob make the assumption 
> that chip->ecc.layout->oobfree is *always* zero terminated (I needed 
> eight entries to describe my OOB area).  I'll put together a patch 
> against the latest kernel and send it along.
> 
> Thoughts?

On one hand it sure would be nice (and a bit complicated) to accurately
describe OOB write constraints, for easier JFFS2/YAFFS2 integration.
On the other hand, I am not sure such a complication is really worth the
trouble, given that on next nand generation:
- OOB areas will not be usable anymore for metadata storage (8-bit ecc leaves
  only 6 spare bytes out of 64)
- partial writes will probably be limited to 1 (like in MLC), meaning that
  JFFS2 clean marking step will be forbidden anyway
Furthermore, userspace will probably need to handle case 3) anyway (no
protected oob bytes) to stay portable...

--
Ivan


From peter.barada at gmail.com  Wed Jun 22 15:17:33 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Wed, 22 Jun 2011 15:17:33 -0400
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <20110622170747.GC25928@parrot.com>
References: <4DF789FC.1030305@gmail.com>
	<1308722655.18119.40.camel@sauron>	<4E020A36.6070708@gmail.com>
	<20110622170747.GC25928@parrot.com>
Message-ID: <4E023FCD.9010800@gmail.com>

On 06/22/2011 01:07 PM, Ivan Djelic wrote:
>
> On one hand it sure would be nice (and a bit complicated) to accurately
> describe OOB write constraints, for easier JFFS2/YAFFS2 integration.
> On the other hand, I am not sure such a complication is really worth the
> trouble, given that on next nand generation:
> - OOB areas will not be usable anymore for metadata storage (8-bit ecc leaves
>    only 6 spare bytes out of 64)
> - partial writes will probably be limited to 1 (like in MLC), meaning that
>    JFFS2 clean marking step will be forbidden anyway
> Furthermore, userspace will probably need to handle case 3) anyway (no
> protected oob bytes) to stay portable...
>
SLC parts (including this one) look to be around for a while, as well as 
the products they are already in.  So I think the issue of JFFS2's 
cleanmarker in the context of this Micron NAND needs to be solved, 
preferably in a general way so the next oddball NAND chip that comes 
along doesn't cause MTD, mtd-utils, JFFS2 (and other NAND FS) fits.

Does UBIFS do any of the "partial writes" (i.e. write OOB/data area 
multiple times) as JFFS2 does?



-- 
Peter Barada
peter.barada at gmail.com



From ivan.djelic at parrot.com  Wed Jun 22 16:06:21 2011
From: ivan.djelic at parrot.com (Ivan Djelic)
Date: Wed, 22 Jun 2011 22:06:21 +0200
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <4E023FCD.9010800@gmail.com>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
	<4E020A36.6070708@gmail.com> <20110622170747.GC25928@parrot.com>
	<4E023FCD.9010800@gmail.com>
Message-ID: <20110622200621.GA26973@parrot.com>

On Wed, Jun 22, 2011 at 08:17:33PM +0100, Peter Barada wrote:
> On 06/22/2011 01:07 PM, Ivan Djelic wrote:
> >
> > On one hand it sure would be nice (and a bit complicated) to accurately
> > describe OOB write constraints, for easier JFFS2/YAFFS2 integration.
> > On the other hand, I am not sure such a complication is really worth the
> > trouble, given that on next nand generation:
> > - OOB areas will not be usable anymore for metadata storage (8-bit ecc leaves
> >    only 6 spare bytes out of 64)
> > - partial writes will probably be limited to 1 (like in MLC), meaning that
> >    JFFS2 clean marking step will be forbidden anyway
> > Furthermore, userspace will probably need to handle case 3) anyway (no
> > protected oob bytes) to stay portable...
> >
> SLC parts (including this one) look to be around for a while, as well as 
> the products they are already in.  So I think the issue of JFFS2's 
> cleanmarker in the context of this Micron NAND needs to be solved, 
> preferably in a general way so the next oddball NAND chip that comes 
> along doesn't cause MTD, mtd-utils, JFFS2 (and other NAND FS) fits.
> 
> Does UBIFS do any of the "partial writes" (i.e. write OOB/data area 
> multiple times) as JFFS2 does?
 
No it doesn't. UBIFS relies on UBI, which itself does not rely on oob for
storing metadata. BTW, have you considered using UBIFS instead of JFFS2/YAFFS2?

--
Ivan


From adrian.wenl at gmail.com  Thu Jun 23 02:22:11 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Thu, 23 Jun 2011 14:22:11 +0800
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <BANLkTim54jEKmxAQFNMGCyWwAu+FhVu0KA@mail.gmail.com>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
	<BANLkTinQB-hXMRy5+BXKQSrPq=sVrorCVA@mail.gmail.com>
	<BANLkTimk0+2LUeo5sq8w4ohRq-qCe_2t_Q@mail.gmail.com>
	<BANLkTim54jEKmxAQFNMGCyWwAu+FhVu0KA@mail.gmail.com>
Message-ID: <BANLkTinsw59F-X2LFrdu3Xtau5xY-=CSnA@mail.gmail.com>

Hi Daniel,

On Wed, Jun 22, 2011 at 9:06 PM, Daniel Mack <zonque at gmail.com> wrote:
> Hi Lei,
>
> On Wed, Jun 22, 2011 at 2:21 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
>> Hi Daniel,
>>
>> On Wed, Jun 22, 2011 at 7:39 PM, Daniel Mack <zonque at gmail.com> wrote:
>>> On Wed, Jun 22, 2011 at 5:17 AM, Lei Wen <leiwen at marvell.com> wrote:
>>>> Current pxa3xx_nand controller has two chip select which
>>>> both be workable. This patch enable this feature.
>>>>
>>>> Update platform driver to support this feature.
>>>>
>>>> Another notice should be taken that:
>>>> When you want to use this feature, you should not enable the
>>>> keep configuration feature, for two chip select could be
>>>> attached with different nand chip. The different page size
>>>> and timing requirement make the keep configuration impossible.
>>>>
>>>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>>>> ---
>>>> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>>>> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
>>>> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
>>>> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
>>>> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
>>>> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
>>>> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>>>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? ?8 +-
>>>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?735 +++++++++++++++-----------
>>>> ?9 files changed, 444 insertions(+), 338 deletions(-)
>>>
>>> This patch doesn't apply for me on top of Linus' master branch. Which
>>> tree are you based on currently?
>>
>> Actually it is based on Linux 3.0-rc2 and add two patches pending to
>> l2-mtd-2.6.git already:
>>
>> mtd: pxa3xx_nand: fix nand detection issue
>> mtd: pxa3xx_nand: Fix blank page ECC mismatch
>
> I have a similar setup, also with those two patches on top, but
> applying your patch gives me:
>
> Applying: MTD: pxa3xx_nand: enable multiple chip select support
> error: patch failed: drivers/mtd/nand/pxa3xx_nand.c:477
> error: drivers/mtd/nand/pxa3xx_nand.c: patch does not apply
> Patch failed at 0001 MTD: pxa3xx_nand: enable multiple chip select support
> 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".
>
> Could you push your branch somewhere?
>
>>>> ?#ifdef CONFIG_PM
>>>> @@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
>>>> ? ? ? ?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);
>>>> + ? ? ? nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
>>>> + ? ? ? nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
>>>> ? ? ? ?clk_enable(info->clk);
>>>
>>> This won't compile.
>>
>> Could you post your build log?
>
> I didn't compile it because I couldn't, but "nand" is certainly
> undefined in this context now. Did you compile and test this code with
> "CONFIG_PM=y"?

You're right, I haven't take open PM config...
I would rebase this patch over l2-mtd-2.6.git for next post.

Thanks,
Lei


From adrian.wenl at gmail.com  Thu Jun 23 02:35:31 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Thu, 23 Jun 2011 14:35:31 +0800
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <4E01F1E7.5010707@compulab.co.il>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>
	<4E01F1E7.5010707@compulab.co.il>
Message-ID: <BANLkTi=YFeVYfsp+68OA_vCF6LnJpqF-ag@mail.gmail.com>

Hi Igor,

On Wed, Jun 22, 2011 at 9:45 PM, Igor Grinberg <grinberg at compulab.co.il> wrote:
> Hi Lei,
>
>
> Some comments from a quick look...
>
>
> On 06/22/11 06:17, Lei Wen wrote:
>
>> Current pxa3xx_nand controller has two chip select which
>> both be workable. This patch enable this feature.
>>
>> Update platform driver to support this feature.
>>
>> Another notice should be taken that:
>> When you want to use this feature, you should not enable the
>> keep configuration feature, for two chip select could be
>> attached with different nand chip. The different page size
>> and timing requirement make the keep configuration impossible.
>
> You should _also_ put this comment inside the pxa3xx_nand.h
> may be even inside the pxa3xx_nand_platform_data structure,
> so people would not have to search the git log to find this problem.

How about just throw out a BUG() to force people cannot set keep_config
when supported cs num more than 1? Also appended with the comments above?

>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> ---
>> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
>> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
>> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
>> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? ?8 +-
>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?735 +++++++++++++++-----------
>> ?9 files changed, 444 insertions(+), 338 deletions(-)
>>
>> diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
>> index 06b5fa8..b6589d6 100644
>> --- a/arch/arm/mach-mmp/aspenite.c
>> +++ b/arch/arm/mach-mmp/aspenite.c
>> @@ -167,8 +167,9 @@ 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),
>> + ? ? .cs_num = 1,
>> + ? ? .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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
>> index b2248e7..d67eb7b 100644
>> --- a/arch/arm/mach-pxa/cm-x300.c
>> +++ b/arch/arm/mach-pxa/cm-x300.c
>> @@ -423,8 +423,9 @@ 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),
>> + ? ? .cs_num ? ? ? ? = 1,
>> + ? ? .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 3f9be41..ff7a07b 100644
>> --- a/arch/arm/mach-pxa/colibri-pxa3xx.c
>> +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
>> @@ -139,8 +139,9 @@ 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),
>> + ? ? .cs_num ? ? ? ? = 1,
>> + ? ? .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 e5e326d..6eaf852 100644
>> --- a/arch/arm/mach-pxa/littleton.c
>> +++ b/arch/arm/mach-pxa/littleton.c
>> @@ -325,8 +325,9 @@ 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),
>> + ? ? .cs_num ? ? ? ? = 1,
>> + ? ? .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 b5a8fd3..e7ce135 100644
>> --- a/arch/arm/mach-pxa/mxm8x10.c
>> +++ b/arch/arm/mach-pxa/mxm8x10.c
>> @@ -389,10 +389,11 @@ 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,
>> + ? ? .cs_num ? ? ? ? = 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 d130f77..a54846d 100644
>> --- a/arch/arm/mach-pxa/raumfeld.c
>> +++ b/arch/arm/mach-pxa/raumfeld.c
>> @@ -349,8 +349,9 @@ 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),
>> + ? ? .cs_num ? ? ? ? = 1,
>> + ? ? .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 5821185..ea4752a 100644
>> --- a/arch/arm/mach-pxa/zylonite.c
>> +++ b/arch/arm/mach-pxa/zylonite.c
>> @@ -366,8 +366,9 @@ 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),
>> + ? ? .cs_num ? ? ? ? = 1,
>> + ? ? .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 442301f..34a3f52 100644
>> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>> @@ -41,6 +41,8 @@ struct pxa3xx_nand_flash {
>> ? ? ? struct pxa3xx_nand_timing *timing; ? ? ?/* NAND Flash timing */
>> ?};
>>
>> +/* The max num of chip select current support */
>
> /* The maximum number of chip selects currently supported */
>
>> +#define NUM_CHIP_SELECT ? ? ? ? ? ? ?(2)
>> ?struct pxa3xx_nand_platform_data {
>>
>> ? ? ? /* the data flash bus is shared between the Static Memory
>> @@ -52,8 +54,10 @@ 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;
>> + ? ? /* indicate how many chip select would be used for this platform */
>
> /* indicate how many chip selects will be used */
>
>> + ? ? int ? ? cs_num;
>
> This name is too confusing, I think even num_cs is better or cs_count?
> Also, may be align it with the others?

 I prefer the num_cs.

>
>> + ? ? const struct mtd_partition ? ? ? ? ? ? ?*parts[NUM_CHIP_SELECT];
>> + ? ? unsigned int ? ? ? ? ? ? ? ? ? ? ? ? ? ?nr_parts[NUM_CHIP_SELECT];
>>
>> ? ? ? const struct pxa3xx_nand_flash * ? ? ? ?flash;
>> ? ? ? size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash;
>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>> index 30689cc..259b8d5 100644
>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>> +++ b/drivers/mtd/nand/pxa3xx_nand.c
>> @@ -92,11 +92,13 @@
>> ?#define NDCB0_ADDR_CYC_SHIFT (16)
>>
>> ?/* macros for registers read/write */
>> -#define nand_writel(info, off, val) ?\
>> - ? ? __raw_writel((val), (info)->mmio_base + (off))
>> +#define nand_writel(nand, off, val) ?\
>> + ? ? __raw_writel((val), (nand)->mmio_base + (off))
>>
>> -#define nand_readl(info, off) ? ? ? ? ? ? ? ?\
>> - ? ? __raw_readl((info)->mmio_base + (off))
>> +#define nand_readl(nand, off) ? ? ? ? ? ? ? ?\
>> + ? ? __raw_readl((nand)->mmio_base + (off))
>> +#define get_mtd_by_info(info) ? ? ? ? ? ? ? ?\
>> + ? ? (struct mtd_info *)((void *)info - sizeof(struct mtd_info))
>>
>> ?/* error code and state */
>> ?enum {
>> @@ -110,6 +112,7 @@ enum {
>>
>> ?enum {
>> ? ? ? STATE_IDLE = 0,
>> + ? ? STATE_PREPARED,
>> ? ? ? STATE_CMD_HANDLE,
>> ? ? ? STATE_DMA_READING,
>> ? ? ? STATE_DMA_WRITING,
>> @@ -123,63 +126,63 @@ enum {
>> ?struct pxa3xx_nand_info {
>> ? ? ? struct nand_chip ? ? ? ?nand_chip;
>>
>> - ? ? struct nand_hw_control ?controller;
>> - ? ? struct platform_device ? *pdev;
>> ? ? ? struct pxa3xx_nand_cmdset *cmdset;
>> + ? ? /* page size of attached chip */
>> + ? ? uint16_t ? ? ? ? ? ? ? ?page_size;
>> + ? ? uint8_t ? ? ? ? ? ? ? ? chip_select;
>> + ? ? uint8_t ? ? ? ? ? ? ? ? use_ecc;
>> +
>> + ? ? /* calculated from pxa3xx_nand_flash data */
>> + ? ? uint8_t ? ? ? ? ? ? ? ? col_addr_cycles;
>> + ? ? uint8_t ? ? ? ? ? ? ? ? row_addr_cycles;
>> + ? ? uint8_t ? ? ? ? ? ? ? ? read_id_bytes;
>> +
>> + ? ? /* cached register value */
>> + ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
>> + ? ? uint32_t ? ? ? ? ? ? ? ?ndtr0cs0;
>> + ? ? uint32_t ? ? ? ? ? ? ? ?ndtr1cs0;
>>
>> + ? ? void ? ? ? ? ? ? ? ? ? ?*nand_data;
>> +};
>> +
>> +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;
>
> please, align

Do you still mean cs_num? What this comment refer to?

>
>>
>> - ? ? unsigned int ? ? ? ? ? ?buf_start;
>> - ? ? unsigned int ? ? ? ? ? ?buf_count;
>> -
>> - ? ? struct mtd_info ? ? ? ? *mtd;
>> ? ? ? /* DMA information */
>> ? ? ? int ? ? ? ? ? ? ? ? ? ? drcmr_dat;
>> ? ? ? 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;
>> - ? ? struct pxa_dma_desc ? ? *data_desc;
>> + ? ? dma_addr_t ? ? ? ? ? ? ?data_buff_phys;
>> ? ? ? dma_addr_t ? ? ? ? ? ? ?data_desc_addr;
>> + ? ? struct pxa_dma_desc ? ? *data_desc;
>>
>> - ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
>> -
>> - ? ? /* saved column/page_addr during CMD_SEQIN */
>> - ? ? int ? ? ? ? ? ? ? ? ? ? seqin_column;
>> - ? ? int ? ? ? ? ? ? ? ? ? ? seqin_page_addr;
>> + ? ? struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
>> + ? ? uint32_t ? ? ? ? ? ? ? ?command;
>> + ? ? uint16_t ? ? ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
>> + ? ? uint16_t ? ? ? ? ? ? ? ?oob_size;
>> + ? ? unsigned char ? ? ? ? ? *data_buff;
>> + ? ? unsigned char ? ? ? ? ? *oob_buff;
>> + ? ? uint32_t ? ? ? ? ? ? ? ?buf_start;
>> + ? ? uint32_t ? ? ? ? ? ? ? ?buf_count;
>>
>> ? ? ? /* relate to the command */
>> ? ? ? unsigned int ? ? ? ? ? ?state;
>> -
>> + ? ? uint8_t ? ? ? ? ? ? ? ? chip_select;
>> ? ? ? int ? ? ? ? ? ? ? ? ? ? use_ecc; ? ? ? ?/* use HW ECC ? */
>> ? ? ? int ? ? ? ? ? ? ? ? ? ? use_dma; ? ? ? ?/* use DMA ? */
>> ? ? ? int ? ? ? ? ? ? ? ? ? ? is_ready;
>> -
>> - ? ? unsigned int ? ? ? ? ? ?page_size; ? ? ?/* page size of attached chip */
>> - ? ? unsigned int ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
>> ? ? ? int ? ? ? ? ? ? ? ? ? ? retcode;
>> - ? ? struct completion ? ? ? cmd_complete;
>>
>> ? ? ? /* generated NDCBx register values */
>> + ? ? uint8_t ? ? ? ? ? ? ? ? total_cmds;
>> ? ? ? uint32_t ? ? ? ? ? ? ? ?ndcb0;
>> ? ? ? 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;
>> -
>> - ? ? unsigned int ? ?col_addr_cycles;
>> - ? ? unsigned int ? ?row_addr_cycles;
>> ?};
>
> It looks like if you switch the names of the structures above,
> then the patch will be much shorter and cleaner,
> but will it make structures meaning confusion?

Could you elaborate more about this? Do you means no need to create a seperated
structure?

>
>>
>> ?static int use_dma = 1;
>> @@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
>> ?/* Define a default flash type setting serve as flash detecting only */
>> ?#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
>>
>> -const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
>> +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)
>> @@ -244,9 +247,11 @@ 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)) |
>> @@ -260,26 +265,27 @@ 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 = (info->use_ecc) ? 40 : 64;
>> ? ? ? ? ? ? ? break;
>> ? ? ? case 512:
>> - ? ? ? ? ? ? info->oob_size = (info->use_ecc) ? 8 : 16;
>> + ? ? ? ? ? ? nand->oob_size = (info->use_ecc) ? 8 : 16;
>> ? ? ? ? ? ? ? break;
>> ? ? ? }
>> ?}
>> @@ -290,185 +296,189 @@ 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 : 0;
>> + ? ? ndcr |= nand->use_ecc ? NDCR_ECC_EN : 0;
>> + ? ? ndcr |= nand->use_dma ? NDCR_DMA_EN : 0;
>> ? ? ? 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;
>>
>> ? ? ? /* wait RUN bit in NDCR become 0 */
>> - ? ? ndcr = nand_readl(info, NDCR);
>> + ? ? ndcr = nand_readl(nand, NDCR);
>> ? ? ? while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
>> - ? ? ? ? ? ? ndcr = nand_readl(info, NDCR);
>> + ? ? ? ? ? ? ndcr = nand_readl(nand, NDCR);
>> ? ? ? ? ? ? ? udelay(1);
>> ? ? ? }
>>
>> ? ? ? if (timeout <= 0) {
>> ? ? ? ? ? ? ? ndcr &= ~NDCR_ND_RUN;
>> - ? ? ? ? ? ? nand_writel(info, NDCR, ndcr);
>> + ? ? ? ? ? ? nand_writel(nand, NDCR, ndcr);
>> ? ? ? }
>> ? ? ? /* clear status bits */
>> - ? ? nand_writel(info, NDSR, NDSR_MASK);
>> + ? ? nand_writel(nand, NDSR, NDSR_MASK);
>> ?}
>>
>> -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)
>> ?{
>> - ? ? switch (info->state) {
>> + ? ? switch (nand->state) {
>> ? ? ? 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));
>> + ? ? ? ? ? ? __raw_writesl(nand->mmio_base + NDDB, nand->data_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->data_size, 4));
>> + ? ? ? ? ? ? if (nand->oob_size > 0)
>> + ? ? ? ? ? ? ? ? ? ? __raw_writesl(nand->mmio_base + NDDB, nand->oob_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->oob_size, 4));
>> ? ? ? ? ? ? ? break;
>> ? ? ? 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));
>> + ? ? ? ? ? ? __raw_readsl(nand->mmio_base + NDDB, nand->data_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->data_size, 4));
>> + ? ? ? ? ? ? if (nand->oob_size > 0)
>> + ? ? ? ? ? ? ? ? ? ? __raw_readsl(nand->mmio_base + NDDB, nand->oob_buff,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? DIV_ROUND_UP(nand->oob_size, 4));
>> ? ? ? ? ? ? ? break;
>> ? ? ? default:
>> ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->state);
>> ? ? ? ? ? ? ? BUG();
>> ? ? ? }
>> ?}
>>
>> -static void start_data_dma(struct pxa3xx_nand_info *info)
>> +static void start_data_dma(struct pxa3xx_nand *nand)
>> ?{
>> - ? ? struct pxa_dma_desc *desc = info->data_desc;
>> - ? ? int dma_len = ALIGN(info->data_size + info->oob_size, 32);
>> + ? ? struct pxa_dma_desc *desc = nand->data_desc;
>> + ? ? 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;
>>
>> - ? ? switch (info->state) {
>> + ? ? switch (nand->state) {
>> ? ? ? case STATE_DMA_WRITING:
>> - ? ? ? ? ? ? desc->dsadr = info->data_buff_phys;
>> - ? ? ? ? ? ? desc->dtadr = info->mmio_phys + NDDB;
>> + ? ? ? ? ? ? desc->dsadr = nand->data_buff_phys;
>> + ? ? ? ? ? ? desc->dtadr = nand->mmio_phys + NDDB;
>> ? ? ? ? ? ? ? desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
>> ? ? ? ? ? ? ? break;
>> ? ? ? case STATE_DMA_READING:
>> - ? ? ? ? ? ? desc->dtadr = info->data_buff_phys;
>> - ? ? ? ? ? ? desc->dsadr = info->mmio_phys + NDDB;
>> + ? ? ? ? ? ? desc->dtadr = nand->data_buff_phys;
>> + ? ? ? ? ? ? desc->dsadr = nand->mmio_phys + NDDB;
>> ? ? ? ? ? ? ? desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
>> ? ? ? ? ? ? ? break;
>> ? ? ? default:
>> ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->state);
>> ? ? ? ? ? ? ? BUG();
>> ? ? ? }
>>
>> - ? ? DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
>> - ? ? DDADR(info->data_dma_ch) = info->data_desc_addr;
>> - ? ? DCSR(info->data_dma_ch) |= DCSR_RUN;
>> + ? ? DRCMR(nand->drcmr_dat) = DRCMR_MAPVLD | nand->data_dma_ch;
>> + ? ? DDADR(nand->data_dma_ch) = nand->data_desc_addr;
>> + ? ? DCSR(nand->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;
>> ? ? ? }
>>
>> - ? ? info->state = STATE_DMA_DONE;
>> - ? ? enable_int(info, NDCR_INT_MASK);
>> - ? ? nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
>> + ? ? nand->state = STATE_DMA_DONE;
>> + ? ? 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;
>
> This is confusing... do you use to ?: operator for differentiating between
> cs = 0 and cs = 1?
> I think this is a bad idea.
> Moreover, the use of ?: is discouraged among the kernel.

I could use if/else to replace this statement.

>
>> + ? ? 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)) {
>> ? ? ? ? ? ? ? /* whether use dma to transfer data */
>> - ? ? ? ? ? ? if (info->use_dma) {
>> - ? ? ? ? ? ? ? ? ? ? disable_int(info, NDCR_INT_MASK);
>> - ? ? ? ? ? ? ? ? ? ? info->state = (status & NDSR_RDDREQ) ?
>> + ? ? ? ? ? ? if (nand->use_dma) {
>> + ? ? ? ? ? ? ? ? ? ? disable_int(nand, NDCR_INT_MASK);
>> + ? ? ? ? ? ? ? ? ? ? nand->state = (status & NDSR_RDDREQ) ?
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? STATE_DMA_READING : STATE_DMA_WRITING;
>> - ? ? ? ? ? ? ? ? ? ? start_data_dma(info);
>> + ? ? ? ? ? ? ? ? ? ? start_data_dma(nand);
>> ? ? ? ? ? ? ? ? ? ? ? goto NORMAL_IRQ_EXIT;
>> ? ? ? ? ? ? ? } else {
>> - ? ? ? ? ? ? ? ? ? ? info->state = (status & NDSR_RDDREQ) ?
>> + ? ? ? ? ? ? ? ? ? ? nand->state = (status & NDSR_RDDREQ) ?
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? STATE_PIO_READING : STATE_PIO_WRITING;
>> - ? ? ? ? ? ? ? ? ? ? handle_data_pio(info);
>> + ? ? ? ? ? ? ? ? ? ? handle_data_pio(nand);
>> ? ? ? ? ? ? ? }
>> ? ? ? }
>> - ? ? 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->is_ready = 1;
>> - ? ? ? ? ? ? info->state = STATE_READY;
>> + ? ? if (status & ready) {
>> + ? ? ? ? ? ? nand->is_ready = 1;
>> + ? ? ? ? ? ? nand->state = STATE_READY;
>> ? ? ? }
>>
>> ? ? ? if (status & NDSR_WRCMDREQ) {
>> - ? ? ? ? ? ? nand_writel(info, NDSR, NDSR_WRCMDREQ);
>> + ? ? ? ? ? ? nand_writel(nand, NDSR, NDSR_WRCMDREQ);
>> ? ? ? ? ? ? ? status &= ~NDSR_WRCMDREQ;
>> - ? ? ? ? ? ? info->state = STATE_CMD_HANDLE;
>> - ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb0);
>> - ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb1);
>> - ? ? ? ? ? ? nand_writel(info, NDCB0, info->ndcb2);
>> + ? ? ? ? ? ? nand->state = STATE_CMD_HANDLE;
>> + ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->ndcb0);
>> + ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->ndcb1);
>> + ? ? ? ? ? ? nand_writel(nand, NDCB0, nand->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--)
>> @@ -477,42 +487,49 @@ 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;
>
> This one is confusing too...
> Besides, you don't need the parenthesis.

Got that. I would fix it.

>
>> ? ? ? 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->is_ready ? ? ? ? ?= 0;
>> - ? ? info->retcode ? ? ? ? ? = ERR_NONE;
>> + ? ? nand->buf_start ? ? ? ? = 0;
>> + ? ? nand->buf_count ? ? ? ? = 0;
>> + ? ? nand->oob_size ? ? ? ? ?= 0;
>> + ? ? nand->use_ecc ? ? ? ? ? = 0;
>> + ? ? nand->is_ready ? ? ? ? ?= 0;
>> + ? ? nand->retcode ? ? ? ? ? = ERR_NONE;
>> + ? ? nand->data_size ? ? ? ? = 0;
>> + ? ? nand->use_dma ? ? ? ? ? = 0;
>> + ? ? nand->command ? ? ? ? ? = command;
>>
>> ? ? ? switch (command) {
>> ? ? ? case NAND_CMD_READ0:
>> ? ? ? case NAND_CMD_PAGEPROG:
>> - ? ? ? ? ? ? info->use_ecc = 1;
>> + ? ? ? ? ? ? nand->use_ecc = 1;
>> ? ? ? case NAND_CMD_READOOB:
>> ? ? ? ? ? ? ? pxa3xx_set_datasize(info);
>> + ? ? ? ? ? ? nand->oob_buff = nand->data_buff + nand->data_size;
>> + ? ? ? ? ? ? nand->use_dma = use_dma;
>> ? ? ? ? ? ? ? break;
>> ? ? ? case NAND_CMD_SEQIN:
>> ? ? ? ? ? ? ? exec_cmd = 0;
>> ? ? ? ? ? ? ? break;
>> ? ? ? default:
>> - ? ? ? ? ? ? info->ndcb1 = 0;
>> - ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? nand->ndcb1 = 0;
>> + ? ? ? ? ? ? nand->ndcb2 = 0;
>> ? ? ? ? ? ? ? break;
>> ? ? ? }
>>
>> - ? ? info->ndcb0 = ndcb0;
>> + ? ? nand->ndcb0 = ndcb0;
>> ? ? ? addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + info->col_addr_cycles);
>>
>> @@ -521,16 +538,16 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>> ? ? ? case NAND_CMD_READ0:
>> ? ? ? ? ? ? ? cmd = info->cmdset->read1;
>> ? ? ? ? ? ? ? if (command == NAND_CMD_READOOB)
>> - ? ? ? ? ? ? ? ? ? ? info->buf_start = mtd->writesize + column;
>> + ? ? ? ? ? ? ? ? ? ? nand->buf_start = mtd->writesize + column;
>> ? ? ? ? ? ? ? else
>> - ? ? ? ? ? ? ? ? ? ? info->buf_start = column;
>> + ? ? ? ? ? ? ? ? ? ? nand->buf_start = column;
>>
>> ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
>> - ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
>> + ? ? ? ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | addr_cycle
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (cmd & NDCB0_CMD1_MASK);
>> ? ? ? ? ? ? ? else
>> - ? ? ? ? ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0)
>> + ? ? ? ? ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_DBC
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | addr_cycle
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
>> @@ -538,34 +555,34 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>> ? ? ? case NAND_CMD_SEQIN:
>> ? ? ? ? ? ? ? /* small page addr setting */
>> ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
>> - ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
>> + ? ? ? ? ? ? ? ? ? ? nand->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (column & 0xFF);
>>
>> - ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = 0;
>> ? ? ? ? ? ? ? } else {
>> - ? ? ? ? ? ? ? ? ? ? info->ndcb1 = ((page_addr & 0xFFFF) << 16)
>> + ? ? ? ? ? ? ? ? ? ? nand->ndcb1 = ((page_addr & 0xFFFF) << 16)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | (column & 0xFFFF);
>>
>> ? ? ? ? ? ? ? ? ? ? ? if (page_addr & 0xFF0000)
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = (page_addr & 0xFF0000) >> 16;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = (page_addr & 0xFF0000) >> 16;
>> ? ? ? ? ? ? ? ? ? ? ? else
>> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->ndcb2 = 0;
>> ? ? ? ? ? ? ? }
>>
>> - ? ? ? ? ? ? info->buf_count = mtd->writesize + mtd->oobsize;
>> - ? ? ? ? ? ? memset(info->data_buff, 0xFF, info->buf_count);
>> + ? ? ? ? ? ? nand->buf_count = mtd->writesize + mtd->oobsize;
>> + ? ? ? ? ? ? memset(nand->data_buff, 0xFF, nand->buf_count);
>>
>> ? ? ? ? ? ? ? break;
>>
>> ? ? ? case NAND_CMD_PAGEPROG:
>> - ? ? ? ? ? ? if (is_buf_blank(info->data_buff,
>> + ? ? ? ? ? ? if (is_buf_blank(nand->data_buff,
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? (mtd->writesize + mtd->oobsize))) {
>> ? ? ? ? ? ? ? ? ? ? ? exec_cmd = 0;
>> ? ? ? ? ? ? ? ? ? ? ? break;
>> ? ? ? ? ? ? ? }
>>
>> ? ? ? ? ? ? ? cmd = info->cmdset->program;
>> - ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
>> + ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(0x1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_AUTO_RS
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ST_ROW_EN
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_DBC
>> @@ -575,37 +592,37 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>>
>> ? ? ? case NAND_CMD_READID:
>> ? ? ? ? ? ? ? cmd = info->cmdset->read_id;
>> - ? ? ? ? ? ? info->buf_count = info->read_id_bytes;
>> - ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(3)
>> + ? ? ? ? ? ? nand->buf_count = info->read_id_bytes;
>> + ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(3)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ADDR_CYC(1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
>>
>> - ? ? ? ? ? ? info->data_size = 8;
>> + ? ? ? ? ? ? nand->data_size = 8;
>> ? ? ? ? ? ? ? break;
>> ? ? ? case NAND_CMD_STATUS:
>> ? ? ? ? ? ? ? cmd = info->cmdset->read_status;
>> - ? ? ? ? ? ? info->buf_count = 1;
>> - ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(4)
>> + ? ? ? ? ? ? nand->buf_count = 1;
>> + ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(4)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ADDR_CYC(1)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
>>
>> - ? ? ? ? ? ? info->data_size = 8;
>> + ? ? ? ? ? ? nand->data_size = 8;
>> ? ? ? ? ? ? ? break;
>>
>> ? ? ? case NAND_CMD_ERASE1:
>> ? ? ? ? ? ? ? cmd = info->cmdset->erase;
>> - ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(2)
>> + ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(2)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_AUTO_RS
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_ADDR_CYC(3)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | NDCB0_DBC
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
>> - ? ? ? ? ? ? info->ndcb1 = page_addr;
>> - ? ? ? ? ? ? info->ndcb2 = 0;
>> + ? ? ? ? ? ? nand->ndcb1 = page_addr;
>> + ? ? ? ? ? ? nand->ndcb2 = 0;
>>
>> ? ? ? ? ? ? ? break;
>> ? ? ? case NAND_CMD_RESET:
>> ? ? ? ? ? ? ? cmd = info->cmdset->reset;
>> - ? ? ? ? ? ? info->ndcb0 |= NDCB0_CMD_TYPE(5)
>> + ? ? ? ? ? ? nand->ndcb0 |= NDCB0_CMD_TYPE(5)
>> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | cmd;
>>
>> ? ? ? ? ? ? ? break;
>> @@ -628,6 +645,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;
>>
>> ? ? ? /*
>> @@ -638,20 +656,32 @@ 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);
>> + ? ? /*
>> + ? ? ?* There may be different NAND chip hooked to
>> + ? ? ?* different chip select, so check whether
>> + ? ? ?* chip select has been changed, if yes, reset the 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);
>> + ? ? }
>> +
>> + ? ? nand->state = STATE_PREPARED;
>> + ? ? exec_cmd = prepare_command_pool(nand, command, column, page_addr);
>> ? ? ? if (exec_cmd) {
>> - ? ? ? ? ? ? init_completion(&info->cmd_complete);
>> - ? ? ? ? ? ? pxa3xx_nand_start(info);
>> + ? ? ? ? ? ? init_completion(&nand->cmd_complete);
>> + ? ? ? ? ? ? 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);
>> + ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_stop(nand);
>> ? ? ? ? ? ? ? }
>> - ? ? ? ? ? ? info->state = STATE_IDLE;
>> ? ? ? }
>> + ? ? nand->state = STATE_IDLE;
>> ?}
>>
>> ?static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
>> @@ -665,11 +695,12 @@ 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) {
>> + ? ? if (nand->retcode == ERR_SBERR) {
>> ? ? ? ? ? ? ? switch (info->use_ecc) {
>> ? ? ? ? ? ? ? case 1:
>> ? ? ? ? ? ? ? ? ? ? ? mtd->ecc_stats.corrected++;
>> @@ -678,14 +709,14 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>> ? ? ? ? ? ? ? default:
>> ? ? ? ? ? ? ? ? ? ? ? break;
>> ? ? ? ? ? ? ? }
>> - ? ? } else if (info->retcode == ERR_DBERR) {
>> + ? ? } else if (nand->retcode == ERR_DBERR) {
>> ? ? ? ? ? ? ? /*
>> ? ? ? ? ? ? ? ?* for blank page (all 0xff), HW will calculate its ECC as
>> ? ? ? ? ? ? ? ?* 0, which is different from the ECC information within
>> ? ? ? ? ? ? ? ?* OOB, ignore such double bit errors
>> ? ? ? ? ? ? ? ?*/
>> ? ? ? ? ? ? ? if (is_buf_blank(buf, mtd->writesize))
>> - ? ? ? ? ? ? ? ? ? ? info->retcode = ERR_NONE;
>> + ? ? ? ? ? ? ? ? ? ? nand->retcode = ERR_NONE;
>> ? ? ? ? ? ? ? else
>> ? ? ? ? ? ? ? ? ? ? ? mtd->ecc_stats.failed++;
>> ? ? ? }
>> @@ -696,11 +727,12 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>> ?static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>> ?{
>> ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
>> + ? ? struct pxa3xx_nand *nand = info->nand_data;
>> ? ? ? char retval = 0xFF;
>>
>> - ? ? if (info->buf_start < info->buf_count)
>> + ? ? if (nand->buf_start < nand->buf_count)
>> ? ? ? ? ? ? ? /* Has just send a new command? */
>> - ? ? ? ? ? ? retval = info->data_buff[info->buf_start++];
>> + ? ? ? ? ? ? retval = nand->data_buff[nand->buf_start++];
>>
>> ? ? ? return retval;
>> ?}
>> @@ -708,11 +740,12 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>> ?static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>> ?{
>> ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
>> + ? ? struct pxa3xx_nand *nand = info->nand_data;
>> ? ? ? u16 retval = 0xFFFF;
>>
>> - ? ? if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
>> - ? ? ? ? ? ? retval = *((u16 *)(info->data_buff+info->buf_start));
>> - ? ? ? ? ? ? info->buf_start += 2;
>> + ? ? if (!(nand->buf_start & 0x01) && nand->buf_start < nand->buf_count) {
>> + ? ? ? ? ? ? retval = *((u16 *)(nand->data_buff+nand->buf_start));
>> + ? ? ? ? ? ? nand->buf_start += 2;
>> ? ? ? }
>> ? ? ? return retval;
>> ?}
>> @@ -720,20 +753,22 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>> ?static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
>> ?{
>> ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
>> - ? ? int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>> + ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>>
>> - ? ? memcpy(buf, info->data_buff + info->buf_start, real_len);
>> - ? ? info->buf_start += real_len;
>> + ? ? memcpy(buf, nand->data_buff + nand->buf_start, real_len);
>> + ? ? nand->buf_start += real_len;
>> ?}
>>
>> ?static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
>> ? ? ? ? ? ? ? const uint8_t *buf, int len)
>> ?{
>> ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
>> - ? ? int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>> + ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? int real_len = min_t(size_t, len, nand->buf_count - nand->buf_start);
>>
>> - ? ? memcpy(info->data_buff + info->buf_start, buf, real_len);
>> - ? ? info->buf_start += real_len;
>> + ? ? memcpy(nand->data_buff + nand->buf_start, buf, real_len);
>> + ? ? nand->buf_start += real_len;
>> ?}
>>
>> ?static int pxa3xx_nand_verify_buf(struct mtd_info *mtd,
>> @@ -750,10 +785,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 {
>> ? ? ? ? ? ? ? ? ? ? ? /*
>> @@ -770,7 +806,8 @@ static int pxa3xx_nand_waitfunc(struct mtd_info *mtd, struct nand_chip *this)
>> ?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 = 0x0; /* enable all interrupts */
>>
>> @@ -804,6 +841,7 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>> ? ? ? ndcr |= NDCR_SPARE_EN; /* enable spare by default */
>>
>> ? ? ? info->reg_ndcr = ndcr;
>> + ? ? info->use_ecc = 1;
>>
>> ? ? ? pxa3xx_nand_set_timing(info, f->timing);
>> ? ? ? return 0;
>> @@ -811,15 +849,22 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
>>
>> ?static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
>> ?{
>> - ? ? uint32_t ndcr = nand_readl(info, NDCR);
>> + ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? uint32_t ndcr = nand_readl(nand, NDCR);
>> +
>> + ? ? if (info->chip_select > 0) {
>> + ? ? ? ? ? ? printk(KERN_ERR "We could not detect configure"
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? " if more than one cs is supported!!\n");
>> + ? ? ? ? ? ? BUG();
>
> like Daniel already noticed, may be dev_err() is enough?
Would change to dev_err();

>
>> + ? ? }
>> ? ? ? info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
>> ? ? ? /* set info fields needed to read id */
>> ? ? ? info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
>> ? ? ? info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
>> ? ? ? info->cmdset = &default_cmdset;
>>
>> - ? ? info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
>> - ? ? info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
>> + ? ? info->ndtr0cs0 = nand_readl(nand, NDTR0CS0);
>> + ? ? info->ndtr1cs0 = nand_readl(nand, NDTR1CS0);
>>
>> ? ? ? return 0;
>> ?}
>> @@ -830,50 +875,31 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
>> ? */
>> ?#define MAX_BUFF_SIZE ? ? ? ?PAGE_SIZE
>>
>> -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
>> +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
>> ?{
>> - ? ? 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;
>> + ? ? struct pxa3xx_nand *nand;
>> + ? ? struct mtd_info *mtd;
>>
>> - ? ? 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;
>> - ? ? }
>> + ? ? if (!info)
>> + ? ? ? ? ? ? return;
>>
>> - ? ? return 0;
>> + ? ? nand = info->nand_data;
>> + ? ? mtd = get_mtd_by_info(info);
>> + ? ? kfree(mtd);
>> + ? ? nand->info[cs] = NULL;
>> ?}
>>
>> ?static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
>> ?{
>> - ? ? struct mtd_info *mtd = info->mtd;
>> + ? ? struct pxa3xx_nand *nand = info->nand_data;
>> + ? ? struct mtd_info *mtd = get_mtd_by_info(info);
>> ? ? ? struct nand_chip *chip = mtd->priv;
>>
>> ? ? ? /* use the common timing to make a try */
>> - ? ? pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
>> + ? ? if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
>> + ? ? ? ? ? ? return 0;
>> ? ? ? chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
>> - ? ? if (info->is_ready)
>> + ? ? if (nand->is_ready)
>> ? ? ? ? ? ? ? return 1;
>> ? ? ? else
>> ? ? ? ? ? ? ? return 0;
>
> I think it is time to change this function return convention to propagate
> errors and not just 0 or 1, (may be in separate patch) what do you think?

How about return 0 when sensing the READY signal, or return -ENODEV?

>
>> @@ -882,7 +908,8 @@ 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 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;
>> ? ? ? struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
>> ? ? ? const struct pxa3xx_nand_flash *f = NULL;
>> @@ -891,27 +918,25 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>> ? ? ? uint64_t chipsize;
>> ? ? ? int i, ret, num;
>>
>> + ? ? nand->chip_select = info->chip_select;
>> ? ? ? if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
>> ? ? ? ? ? ? ? goto KEEP_CONFIG;
>>
>> ? ? ? ret = pxa3xx_nand_sensing(info);
>> ? ? ? if (!ret) {
>> - ? ? ? ? ? ? kfree(mtd);
>> - ? ? ? ? ? ? info->mtd = NULL;
>> - ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n");
>> + ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
>> + ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs %d!\n",
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->chip_select);
>>
>> ? ? ? ? ? ? ? return -EINVAL;
>> ? ? ? }
>>
>> ? ? ? chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
>> - ? ? id = *((uint16_t *)(info->data_buff));
>> + ? ? id = *((uint16_t *)(nand->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");
>
> Is this warning no longer needed?
Would readd it in the next post.

>
>> -
>> + ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
>> ? ? ? ? ? ? ? return -EINVAL;
>> ? ? ? }
>>
>> @@ -928,14 +953,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>> ? ? ? }
>>
>> ? ? ? if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
>> - ? ? ? ? ? ? kfree(mtd);
>> - ? ? ? ? ? ? info->mtd = NULL;
>> + ? ? ? ? ? ? free_cs_resource(info, nand->chip_select);
>> ? ? ? ? ? ? ? printk(KERN_ERR "ERROR!! flash not defined!!!\n");
>>
>> ? ? ? ? ? ? ? return -EINVAL;
>> ? ? ? }
>>
>> - ? ? pxa3xx_nand_config_flash(info, f);
>> + ? ? if (pxa3xx_nand_config_flash(info, f)) {
>> + ? ? ? ? ? ? printk(KERN_ERR "ERROR! Configure failed\n");
>> + ? ? ? ? ? ? return -EINVAL;
>> + ? ? }
>
> Although, the pxa3xx_nand_config_flash() returns only 0 or -EINVAL,
> it is better to propagate its return value.

Ok, would apply this.

>
>> ? ? ? pxa3xx_flash_ids[0].name = f->name;
>> ? ? ? pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
>> ? ? ? pxa3xx_flash_ids[0].pagesize = f->page_size;
>> @@ -950,13 +977,13 @@ KEEP_CONFIG:
>> ? ? ? if (nand_scan_ident(mtd, 1, def))
>> ? ? ? ? ? ? ? return -ENODEV;
>> ? ? ? /* calculate addressing information */
>> + ? ? nand->oob_buff = nand->data_buff + mtd->writesize;
>> ? ? ? info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
>> - ? ? info->oob_buff = info->data_buff + mtd->writesize;
>> ? ? ? if ((mtd->size >> chip->page_shift) > 65536)
>> ? ? ? ? ? ? ? info->row_addr_cycles = 3;
>> ? ? ? else
>> ? ? ? ? ? ? ? info->row_addr_cycles = 2;
>> - ? ? mtd->name = mtd_names[0];
>> + ? ? mtd->name = mtd_names[nand->chip_select];
>> ? ? ? chip->ecc.mode = NAND_ECC_HW;
>> ? ? ? chip->ecc.size = info->page_size;
>>
>> @@ -967,51 +994,33 @@ KEEP_CONFIG:
>> ? ? ? return nand_scan_tail(mtd);
>> ?}
>>
>> -static
>> -struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
>> +static int alloc_nand_resource(struct platform_device *pdev)
>> ?{
>> + ? ? struct pxa3xx_nand_platform_data *pdata;
>> ? ? ? struct pxa3xx_nand_info *info;
>> ? ? ? struct nand_chip *chip;
>> ? ? ? struct mtd_info *mtd;
>> + ? ? struct pxa3xx_nand *nand;
>> ? ? ? 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) {
>> + ? ? pdata = pdev->dev.platform_data;
>> + ? ? nand = kzalloc(sizeof(struct mtd_info)
>> + ? ? ? ? ? ? ? ? ? ? + sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
>> + ? ? if (!nand) {
>> ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to allocate memory\n");
>> - ? ? ? ? ? ? return NULL;
>> + ? ? ? ? ? ? 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->controller ? ? ? ?= &info->controller;
>> - ? ? 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;
>> -
>> - ? ? spin_lock_init(&chip->controller->lock);
>> - ? ? init_waitqueue_head(&chip->controller->wq);
>> - ? ? 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) {
>> @@ -1019,7 +1028,7 @@ struct pxa3xx_nand_info *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) {
>> @@ -1027,7 +1036,7 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
>> ? ? ? ? ? ? ? ret = -ENXIO;
>> ? ? ? ? ? ? ? goto fail_put_clk;
>> ? ? ? }
>> - ? ? info->drcmr_cmd = r->start;
>> + ? ? nand->drcmr_cmd = r->start;
>>
>> ? ? ? irq = platform_get_irq(pdev, 0);
>> ? ? ? if (irq < 0) {
>> @@ -1050,81 +1059,147 @@ struct pxa3xx_nand_info *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);
>>
>> ? ? ? 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_io;
>> + ? ? }
>> +
>> + ? ? platform_set_drvdata(pdev, nand);
>> +
>> + ? ? spin_lock_init(&nand->controller.lock);
>> + ? ? init_waitqueue_head(&nand->controller.wq);
>> + ? ? for (cs = 0; cs < pdata->cs_num; 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;
>> ? ? ? }
>>
>> - ? ? platform_set_drvdata(pdev, info);
>> + ? ? if (use_dma == 0) {
>> + ? ? ? ? ? ? nand->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
>> + ? ? ? ? ? ? if (nand->data_buff == NULL) {
>> + ? ? ? ? ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? ? ? ? ? goto fail_free_buf;
>> + ? ? ? ? ? ? }
>> + ? ? ? ? ? ? goto success_exit;
>> + ? ? }
>>
>> - ? ? return info;
>> + ? ? nand->data_buff = dma_alloc_coherent(&pdev->dev, MAX_BUFF_SIZE,
>> + ? ? ? ? ? ? ? ? ? ? &nand->data_buff_phys, GFP_KERNEL);
>> + ? ? if (nand->data_buff == NULL) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "failed to allocate dma buffer\n");
>> + ? ? ? ? ? ? ret = -ENOMEM;
>> + ? ? ? ? ? ? goto fail_free_buf;
>> + ? ? }
>>
>> + ? ? nand->data_desc = (void *)nand->data_buff + data_desc_offset;
>> + ? ? nand->data_desc_addr = nand->data_buff_phys + data_desc_offset;
>> + ? ? nand->data_dma_ch = pxa_request_dma("nand-data", DMA_PRIO_LOW,
>> + ? ? ? ? ? ? ? ? ? ? pxa3xx_nand_data_dma_irq, nand);
>> + ? ? if (nand->data_dma_ch < 0) {
>> + ? ? ? ? ? ? dev_err(&pdev->dev, "failed to request data dma\n");
>> + ? ? ? ? ? ? ret = -ENXIO;
>> + ? ? ? ? ? ? goto fail_free_dma_buf;
>> + ? ? }
>> +success_exit:
>> + ? ? return 0;
>> +
>> +fail_free_dma_buf:
>> + ? ? dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
>> + ? ? ? ? ? ? ? ? ? ? nand->data_buff, nand->data_buff_phys);
>> ?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);
>> + ? ? for (cs = 0; cs < pdata->cs_num; cs++) {
>> + ? ? ? ? ? ? info = nand->info[cs];
>> + ? ? ? ? ? ? free_cs_resource(info, cs);
>> + ? ? }
>> +fail_free_irq:
>> + ? ? free_irq(irq, nand);
>> ?fail_free_io:
>> - ? ? iounmap(info->mmio_base);
>> + ? ? 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);
>> - ? ? return NULL;
>> + ? ? 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_platform_data *pdata;
>> + ? ? struct pxa3xx_nand_info *info;
>> + ? ? struct mtd_info *mtd;
>> ? ? ? struct resource *r;
>> - ? ? int irq;
>> + ? ? int irq, cs;
>>
>> ? ? ? platform_set_drvdata(pdev, NULL);
>> + ? ? pdata = pdev->dev.platform_data;
>>
>> ? ? ? irq = platform_get_irq(pdev, 0);
>> ? ? ? if (irq >= 0)
>> - ? ? ? ? ? ? free_irq(irq, info);
>> + ? ? ? ? ? ? free_irq(irq, nand);
>> ? ? ? 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);
>> + ? ? ? ? ? ? pxa_free_dma(nand->data_dma_ch);
>> + ? ? ? ? ? ? dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? nand->data_buff, nand->data_buff_phys);
>> ? ? ? } else
>> - ? ? ? ? ? ? kfree(info->data_buff);
>> + ? ? ? ? ? ? kfree(nand->data_buff);
>>
>> - ? ? 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);
>> + ? ? clk_disable(nand->clk);
>> + ? ? clk_put(nand->clk);
>>
>> - ? ? if (mtd) {
>> + ? ? for (cs = 0; cs < pdata->cs_num; cs++) {
>> + ? ? ? ? ? ? info = nand->info[cs];
>> + ? ? ? ? ? ? if (!info)
>> + ? ? ? ? ? ? ? ? ? ? continue;
>> + ? ? ? ? ? ? mtd = get_mtd_by_info(info);
>> ? ? ? ? ? ? ? mtd_device_unregister(mtd);
>> - ? ? ? ? ? ? kfree(mtd);
>> + ? ? ? ? ? ? free_cs_resource(info, cs);
>> ? ? ? }
>> ? ? ? return 0;
>> ?}
>> @@ -1134,34 +1209,54 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
>> ? ? ? struct pxa3xx_nand_platform_data *pdata;
>> ? ? ? struct pxa3xx_nand_info *info;
>>
>> + ? ? struct pxa3xx_nand *nand;
>> + ? ? struct mtd_info *mtd;
>> + ? ? int cs, ret, nr_parts, probe_success;
>> +
>> + ? ? probe_success = 0;
>
> Can this be done along with declaration?
Ok, would apply to the next post.

>
>> ? ? ? pdata = pdev->dev.platform_data;
>> ? ? ? if (!pdata) {
>> ? ? ? ? ? ? ? dev_err(&pdev->dev, "no platform data defined\n");
>> ? ? ? ? ? ? ? return -ENODEV;
>> ? ? ? }
>>
>> - ? ? info = alloc_nand_resource(pdev);
>> - ? ? if (info == NULL)
>> + ? ? ret = alloc_nand_resource(pdev);
>> + ? ? if (ret)
>> ? ? ? ? ? ? ? return -ENOMEM;
>
> Why not propagate the return value of alloc_nand_resource()?

Would apply propagate error to the next post.

>
>>
>> - ? ? 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 < pdata->cs_num; cs++) {
>> + ? ? ? ? ? ? info = nand->info[cs];
>> + ? ? ? ? ? ? mtd = get_mtd_by_info(info);
>> + ? ? ? ? ? ? if (pxa3xx_nand_scan(mtd)) {
>> + ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
>
> I think, it would be useful also to print here the return value of pxa3xx_nand_scan().
Ok, would apply to the next post

>
>> + ? ? ? ? ? ? ? ? ? ? continue;
>> + ? ? ? ? ? ? }
>> +
>> + ? ? ? ? ? ? ret = 0;
>> + ? ? ? ? ? ? nr_parts = 0;
>> + ? ? ? ? ? ? if (mtd_has_cmdlinepart()) {
>> + ? ? ? ? ? ? ? ? ? ? const char *probes[] = { "cmdlinepart", NULL };
>> + ? ? ? ? ? ? ? ? ? ? struct mtd_partition *parts;
>>
>> - ? ? if (mtd_has_cmdlinepart()) {
>> - ? ? ? ? ? ? const char *probes[] = { "cmdlinepart", NULL };
>> - ? ? ? ? ? ? struct mtd_partition *parts;
>> - ? ? ? ? ? ? int nr_parts;
>> + ? ? ? ? ? ? ? ? ? ? nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
>>
>> - ? ? ? ? ? ? nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
>> + ? ? ? ? ? ? ? ? ? ? if (nr_parts)
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ret = mtd_device_register(mtd, parts, nr_parts);
>> + ? ? ? ? ? ? }
>>
>> - ? ? ? ? ? ? if (nr_parts)
>> - ? ? ? ? ? ? ? ? ? ? return mtd_device_register(info->mtd, parts, nr_parts);
>> + ? ? ? ? ? ? if (!nr_parts)
>> + ? ? ? ? ? ? ? ? ? ? ret = mtd_device_register(mtd, pdata->parts[cs],
>> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? pdata->nr_parts[cs]);
>> + ? ? ? ? ? ? if (!ret)
>> + ? ? ? ? ? ? ? ? ? ? probe_success = 1;
>> ? ? ? }
>>
>> - ? ? return mtd_device_register(info->mtd, pdata->parts, pdata->nr_parts);
>> + ? ? if (!probe_success) {
>> + ? ? ? ? ? ? pxa3xx_nand_remove(pdev);
>> + ? ? ? ? ? ? return -ENODEV;
>> + ? ? } else
>
> You don't need this else statement

Would apply to the next post.

>
>> + ? ? ? ? ? ? return 0;
>> ?}
>>
>> ?#ifdef CONFIG_PM
>> @@ -1183,8 +1278,8 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
>> ? ? ? 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);
>> + ? ? nand_writel(nand, NDTR0CS0, info->ndtr0cs0);
>> + ? ? nand_writel(nand, NDTR1CS0, info->ndtr1cs0);
>> ? ? ? clk_enable(info->clk);
>>
>> ? ? ? return 0;
>
> I won't be able to test the patch in the near future, sorry...
>

Thanks for comments.

Best regards,
Lei


From dedekind1 at gmail.com  Thu Jun 23 03:56:32 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 10:56:32 +0300
Subject: [PATCH V2 00/18] mtd: cleanup partition handling in OF-enabled
	drivers
In-Reply-To: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
References: <1308735472-32640-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308815796.18119.93.camel@sauron>

On Wed, 2011-06-22 at 13:37 +0400, Dmitry Eremin-Solenikov wrote:
> Changes since V1:
>  * Tab-vs-space cleanup
>  * 80-column cleanup
>  * documented of_node parser data field
>  * changed documentation for parser_data arguments

Pushed to l2-mtd-2.6.git, thanks for good cleanups.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 04:22:53 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 11:22:53 +0300
Subject: [PATCH upstream] nand: nand_base: Always initialise oob_poi
	before writing OOB data
In-Reply-To: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DF22@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
References: <E14CAA9D00C5044EACE0C59FC2A1C7F5059AACE12D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308722112.18119.36.camel@sauron>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DD8D@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<1308740228.18119.70.camel@sauron>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DDB3@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
	<E14CAA9D00C5044EACE0C59FC2A1C7F5059AB4DF22@FRMRSSXCHMBSC1.dc-m.alcatel-lucent.com>
Message-ID: <1308817376.18119.94.camel@sauron>

On Wed, 2011-06-22 at 17:40 +0200, THOMSON, Adam (Adam) wrote:
> Adam Thomson Wrote:
> > 
> > The original request was for a stable patch, and that would 
> > be accepted if I provided a proper tidy fix also. To be fair 
> > it was a few weeks ago now that that mail was sent. :-) 
> > Anyway, as it turns out the tidy fix was almost identical, 
> > and we don't need the memset as far as I can tell from 
> > reviewing code and from testing. Will run up your patch today 
> > to verify your additional change, but should be fine.
> > 
> 
> Have tested the updated patch on hardware, and all seems good.
> No problems with OOB corruption, and mtd tests run without failure.

Thank you!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 04:31:25 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 11:31:25 +0300
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <0A40042D85E7C84DB443060EC44B3FD32A7208F91B@dekaexchange07.deka.local>
References: <20110617163442.204348a0@schlenkerla.am.freescale.net>
	<F87D23B7E1F84E4AB52E4FA4A55F85DC0259E343@tpamail.elutions.com>
	<0A40042D85E7C84DB443060EC44B3FD32A7208F91B@dekaexchange07.deka.local>
Message-ID: <1308817889.18119.98.camel@sauron>

On Mon, 2011-06-20 at 07:22 -0400, Atlant Schmidt wrote:
> 
>   As far as I know (and I'm sure the list will correct
>   me if I'm wrong! ;-) ), neither UBI nor UBIFS nor any
>   Linux layer provides this routine scrubbing; you have
>   to code it up yourself, probably by accessing the
>   device at the UBI (underlying block device/LEB) layer. 

UBI will scrub all LEBs with bit-flips once they are read.
But if you have bit-flips in an LEB and it is never read, it will never
be scrubbed. And erasures of the neighboring PEBs may turn bit-flips
into hard errors.

To force scrubbing, the easies way is to just read all volumes, like

dd if=/dev/ubi0_i of=/dev/null bs=4096

for each i.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 04:35:46 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 11:35:46 +0300
Subject: NAND BBT corruption on MPC83xx
In-Reply-To: <BANLkTi=L8CqtTt=+sJ-CHVyXyTsxTR_o8Q@mail.gmail.com>
References: <BANLkTi=L8CqtTt=+sJ-CHVyXyTsxTR_o8Q@mail.gmail.com>
Message-ID: <1308818150.18119.102.camel@sauron>

On Wed, 2011-06-15 at 15:48 -0400, Matthew L. Creech wrote:
> Hi, I'm not sure whether this list or the U-Boot list is more
> appropriate, but figured I'd start here and see if anyone can help.
> 
> We've gotten some devices back from the field which all suffer from
> this same problem on bootup when attaching UBI (these messages are
> from U-Boot):
> 
> 
> ...
> Bad block table found at page 524224, version 0x01
> Bad block table found at page 524160, version 0x01
> nand_bbt: ECC error while reading bad block table
> ...(long stream of bogus bad blocks)...
> UBI: attaching mtd1 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: vtbl_check: volume table check failed: record 0, error 9
> UBI error: ubi_init: cannot attach mtd1
> UBI error: ubi_init: UBI error: cannot initialize UBI, error -22
> UBI init error -22
> 
> A full console dump is here:
> 
> http://mcreech.com/work/bbt-ecc-error.txt
> 
> Question #1: Is the UBI error here attributable to the blocks which
> are wrongly marked as bad?  I would assume that it's a red herring,
> and I should focus on figuring out how the BBT got corrupted, but
> figured I'd check first.

UBI prints error messages if a block is marked bad, and they should go
to syslog. If you are able to access the syslog - you can see if
anything was marked as bad by UBI. But I really doubt this is UBI to
blame.

This might be BBT stuff - I never used on-flash BBT and when I look at
the code - I do not trust it...

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 04:46:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 11:46:52 +0300
Subject: Problem with clean markers/partial writes on Micron 4-bit ECC NAND
In-Reply-To: <4DFB9458.1030304@gmail.com>
References: <4DFB9458.1030304@gmail.com>
Message-ID: <1308818817.18119.103.camel@sauron>

On Fri, 2011-06-17 at 13:52 -0400, Peter Barada wrote:
> I'm using a 2K page Micron NAND that has an internal 4-bit ECC engine.
> 
> The Micron NAND chip uses 8-bytes per 512 bytes of main data area + 4 
> bytes of the OOB.  This allows the 32 bytes of ECC to correct 2048 bytes 
> of the main data area and 16 bytes of the OOB area.
> 
> The problem I'm running into with JFFS2 is that empty flash is first 
> marked with a clean marker into the OOB, and then a 2nd write to the 
> main data area is done (w/o an intervening erase) to that page with data 
> which corrupts the ECCs that were first modified by writing the cleanmarker.

I remember someone sent patches to teach JFFS2 to avoid using clean
markers, but I do not remembers the details and whether the patches made
it into the mainline.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 04:52:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 11:52:40 +0300
Subject: NAND OOB data.
In-Reply-To: <F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
References: <F9C551623D2CBB4C9488801D14F864C6034536@ex-mb1.corp.adtran.com>
	<0A40042D85E7C84DB443060EC44B3FD32A7208F91A@dekaexchange07.deka.local>
	<F9C551623D2CBB4C9488801D14F864C6036086@ex-mb1.corp.adtran.com>
Message-ID: <1308819164.18119.106.camel@sauron>

On Mon, 2011-06-20 at 17:53 +0000, ANDY KENNEDY wrote:
> > -----Original Message-----
> > From: Atlant Schmidt [mailto:aschmidt at dekaresearch.com]
> > Sent: Monday, June 20, 2011 6:14 AM
> > To: ANDY KENNEDY; linux-mtd at lists.infradead.org
> > Subject: RE: NAND OOB data.
> > 
> > Andy:
> > 
> >   If you don't have the old bad block information saved
> >   away somewhere (a bad block table, a scrap of paper,
> >   etc.), then you *CAN'T* completely recover from this
> >   situation; the original bad block data for that chip
> >   is probably irretrievably lost.*
> 
> All the other boards apparently are all good (is that normal?), but,
> I'm not worried about the NAND having KNOWN bad blocks as this board
> is supposed to be mine.

I think someone implemented an utility or ioctl for this, probably
Matthew Castet, but I asked for some more improvements or something, and
he disappeared. Try to find the thread, may be you can continue his
work.

But in general, I think the ideal way would be:

1. be able to distinguish between factory-marked and user-marked bad
blocks.
2. allow unmarking user-marked bad blocks, but not factory marked.

Not sure this is always possible, though.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 05:14:01 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 12:14:01 +0300
Subject: "warning!: only 995 of 1984 eraseblocks have valid erase counter"
In-Reply-To: <o4krv69m77vomji84cs3flljf6obpgfgcs@4ax.com>
References: <o4krv69m77vomji84cs3flljf6obpgfgcs@4ax.com>
Message-ID: <1308820444.19443.0.camel@sauron>

On Sun, 2011-06-19 at 12:37 +0200, Gilles wrote:
> Hello
> 
> 	After "make" built rootfs.ubifs, I ran ubinize before uploading the
> file to a web server.
> 
> I then downloaded that file on a uClinux appliance, and ran the
> following command to format /dev/mtd2 with the image:
> =========
> ubiformat /dev/mtd2 -s 512 -f rootfs.ubi.img
> =========
> 
> This command triggers the following warning:
> =========
> ...
> libscan: scanning eraseblock 1982 -- 99 % complete  MTD_ioctl
> MTD_read
> libscan: scanning eraseblock 1983 -- 100 % complete  MTD_ioctl
> MTD_read
> 
> ubiformat: 995 eraseblocks have valid erase counter, mean value is 14
> ubiformat: 989 eraseblocks are supposedly empty
> ubiformat: warning!: only 995 of 1984 eraseblocks have valid erase
> counter
> ubiformat: mean erase counter 14 will be used for the rest of
> eraseblock
> ubiformat: continue? (yes/no)
> =========
> 
> Running just "ubiformat /dev/mtd2 -s 512" triggers the same warning.
> 
> I don't know what the warning really means, and what the consequences
> are when answering "yes". Could someone tell me?

I think it is self-explanatory. Please, ask specific question. WRT to
consequences - it should not be critical.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 05:18:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 12:18:47 +0300
Subject: Claiming back space from NAND?
In-Reply-To: <lv5sv610ivu2a8de8nmdl652jsvv5p1s0r@4ax.com>
References: <lv5sv610ivu2a8de8nmdl652jsvv5p1s0r@4ax.com>
Message-ID: <1308820731.19443.3.camel@sauron>

On Sun, 2011-06-19 at 17:39 +0200, Gilles wrote:
> Hello,
> 
> 	After booting up a new kernel with the root filesystem on the second
> partition in the NAND, I notice that the 248MiB partition is down to
> only 225MiB.
> 
> I understand that Ubifs uses some space for journaling, but does it
> really need that much space? Is it possible to reclaim some space?

First of all, start with this:
http://www.linux-mtd.infradead.org/faq/ubifs.html#L_df_report

Also, yes, there is room for optimization but it requires some work.

-- 
Best Regards,
Artem Bityutskiy



From gilles.ganault at free.fr  Thu Jun 23 05:19:08 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 23 Jun 2011 11:19:08 +0200
Subject: "warning!: only 995 of 1984 eraseblocks have valid erase counter"
References: <o4krv69m77vomji84cs3flljf6obpgfgcs@4ax.com>
	<1308820444.19443.0.camel@sauron>
Message-ID: <2016071dvg4slfufk95id9ov68n2kvbp4j@4ax.com>

On Thu, 23 Jun 2011 12:14:01 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>I think it is self-explanatory. Please, ask specific question. WRT to
>consequences - it should not be critical.

I went ahead, answered yes, and it seems to work OK, but I was curious
to understand what the message really means.

Before reflashing memory with an image, does ubiformat always warn the
user that the empty blocks after the image will have their erase
counter set to the average computed from the used blocks, regardless
of their actual usage so far?

It's just for my education. Thank you.



From gilles.ganault at free.fr  Thu Jun 23 05:48:53 2011
From: gilles.ganault at free.fr (Gilles)
Date: Thu, 23 Jun 2011 11:48:53 +0200
Subject: Claiming back space from NAND?
References: <lv5sv610ivu2a8de8nmdl652jsvv5p1s0r@4ax.com>
	<1308820731.19443.3.camel@sauron>
Message-ID: <qv2607t8ostnegbbsucumn80aulser2jli@4ax.com>

On Thu, 23 Jun 2011 12:18:47 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>First of all, start with this:
>http://www.linux-mtd.infradead.org/faq/ubifs.html#L_df_report
>
>Also, yes, there is room for optimization but it requires some work.

Thanks for the info.



From grinberg at compulab.co.il  Thu Jun 23 06:44:16 2011
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Thu, 23 Jun 2011 13:44:16 +0300
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <BANLkTi=YFeVYfsp+68OA_vCF6LnJpqF-ag@mail.gmail.com>
References: <1308712645-5986-1-git-send-email-leiwen@marvell.com>	<4E01F1E7.5010707@compulab.co.il>
	<BANLkTi=YFeVYfsp+68OA_vCF6LnJpqF-ag@mail.gmail.com>
Message-ID: <4E031900.50108@compulab.co.il>

Hi Lei,

On 06/23/11 09:35, Lei Wen wrote:
> Hi Igor,
>
> On Wed, Jun 22, 2011 at 9:45 PM, Igor Grinberg <grinberg at compulab.co.il> wrote:
>> On 06/22/11 06:17, Lei Wen wrote:
>>> Current pxa3xx_nand controller has two chip select which
>>> both be workable. This patch enable this feature.
>>>
>>> Update platform driver to support this feature.
>>>
>>> Another notice should be taken that:
>>> When you want to use this feature, you should not enable the
>>> keep configuration feature, for two chip select could be
>>> attached with different nand chip. The different page size
>>> and timing requirement make the keep configuration impossible.
>> You should _also_ put this comment inside the pxa3xx_nand.h
>> may be even inside the pxa3xx_nand_platform_data structure,
>> so people would not have to search the git log to find this problem.
> How about just throw out a BUG() to force people cannot set keep_config
> when supported cs num more than 1? Also appended with the comments above?

I don't think BUG() is a good idea, instead what you can do
is force the user of the _new_ feature to _not_ use the keep_config
by overriding the keep_config to 0 and printing a warning
that keep_config is prohibited with multiple chip selects feature and
that it will be disabled.
Of course you will still need to put a comment inside the pxa3xx_nand.h.

>>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>>> ---
>>>  arch/arm/mach-mmp/aspenite.c                 |    5 +-
>>>  arch/arm/mach-pxa/cm-x300.c                  |    5 +-
>>>  arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
>>>  arch/arm/mach-pxa/littleton.c                |    5 +-
>>>  arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
>>>  arch/arm/mach-pxa/raumfeld.c                 |    5 +-
>>>  arch/arm/mach-pxa/zylonite.c                 |    5 +-
>>>  arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |    8 +-
>>>  drivers/mtd/nand/pxa3xx_nand.c               |  735 +++++++++++++++-----------
>>>  9 files changed, 444 insertions(+), 338 deletions(-)

[...]

>>> diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>>> index 442301f..34a3f52 100644
>>> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>>> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
>>> @@ -41,6 +41,8 @@ struct pxa3xx_nand_flash {
>>>       struct pxa3xx_nand_timing *timing;      /* NAND Flash timing */
>>>  };
>>>
>>> +/* The max num of chip select current support */
>> /* The maximum number of chip selects currently supported */
>>
>>> +#define NUM_CHIP_SELECT              (2)
>>>  struct pxa3xx_nand_platform_data {
>>>
>>>       /* the data flash bus is shared between the Static Memory
>>> @@ -52,8 +54,10 @@ 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;
>>> +     /* indicate how many chip select would be used for this platform */
>> /* indicate how many chip selects will be used */
>>
>>> +     int     cs_num;
>> This name is too confusing, I think even num_cs is better or cs_count?
>> Also, may be align it with the others?
>  I prefer the num_cs.

Good.

>>> +     const struct mtd_partition              *parts[NUM_CHIP_SELECT];
>>> +     unsigned int                            nr_parts[NUM_CHIP_SELECT];
>>>
>>>       const struct pxa3xx_nand_flash *        flash;
>>>       size_t                                  num_flash;
>>> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
>>> index 30689cc..259b8d5 100644
>>> --- a/drivers/mtd/nand/pxa3xx_nand.c
>>> +++ b/drivers/mtd/nand/pxa3xx_nand.c

[...]

>>> @@ -123,63 +126,63 @@ enum {
>>>  struct pxa3xx_nand_info {
>>>       struct nand_chip        nand_chip;
>>>
>>> -     struct nand_hw_control  controller;
>>> -     struct platform_device   *pdev;
>>>       struct pxa3xx_nand_cmdset *cmdset;
>>> +     /* page size of attached chip */
>>> +     uint16_t                page_size;
>>> +     uint8_t                 chip_select;
>>> +     uint8_t                 use_ecc;
>>> +
>>> +     /* calculated from pxa3xx_nand_flash data */
>>> +     uint8_t                 col_addr_cycles;
>>> +     uint8_t                 row_addr_cycles;
>>> +     uint8_t                 read_id_bytes;
>>> +
>>> +     /* cached register value */
>>> +     uint32_t                reg_ndcr;
>>> +     uint32_t                ndtr0cs0;
>>> +     uint32_t                ndtr1cs0;
>>>
>>> +     void                    *nand_data;
>>> +};
>>> +
>>> +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;
>> please, align
> Do you still mean cs_num? What this comment refer to?

No, I mean the white space before *pdev - it is not aligned with all others

>>> -     unsigned int            buf_start;
>>> -     unsigned int            buf_count;
>>> -
>>> -     struct mtd_info         *mtd;
>>>       /* DMA information */
>>>       int                     drcmr_dat;
>>>       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;
>>> -     struct pxa_dma_desc     *data_desc;
>>> +     dma_addr_t              data_buff_phys;
>>>       dma_addr_t              data_desc_addr;
>>> +     struct pxa_dma_desc     *data_desc;
>>>
>>> -     uint32_t                reg_ndcr;
>>> -
>>> -     /* saved column/page_addr during CMD_SEQIN */
>>> -     int                     seqin_column;
>>> -     int                     seqin_page_addr;
>>> +     struct pxa3xx_nand_info *info[NUM_CHIP_SELECT];
>>> +     uint32_t                command;
>>> +     uint16_t                data_size;      /* data size in FIFO */
>>> +     uint16_t                oob_size;
>>> +     unsigned char           *data_buff;
>>> +     unsigned char           *oob_buff;
>>> +     uint32_t                buf_start;
>>> +     uint32_t                buf_count;
>>>
>>>       /* relate to the command */
>>>       unsigned int            state;
>>> -
>>> +     uint8_t                 chip_select;
>>>       int                     use_ecc;        /* use HW ECC ? */
>>>       int                     use_dma;        /* use DMA ? */
>>>       int                     is_ready;
>>> -
>>> -     unsigned int            page_size;      /* page size of attached chip */
>>> -     unsigned int            data_size;      /* data size in FIFO */
>>>       int                     retcode;
>>> -     struct completion       cmd_complete;
>>>
>>>       /* generated NDCBx register values */
>>> +     uint8_t                 total_cmds;
>>>       uint32_t                ndcb0;
>>>       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;
>>> -
>>> -     unsigned int    col_addr_cycles;
>>> -     unsigned int    row_addr_cycles;
>>>  };
>> It looks like if you switch the names of the structures above,
>> then the patch will be much shorter and cleaner,
>> but will it make structures meaning confusion?
> Could you elaborate more about this? Do you means no need to create a seperated
> structure?

No, if you have 2 chips, then certainly you'd better have a separate
structure for the chip description.

What I was wondering, is that there are many places in the patch where
you change the "info" to "nand", may be this can be avoided if you keep
the structure that describes the controller ("pxa3xx_nand" in the patch)
named "pxa3xx_nand_info" and the new structure that describes the chip
will be named something else like pxa3xx_nand_chip or anything like this.
This way, your patch will not have to change the "info" to "nand" in many
places (or maybe even all places) and will be much shorter and will include
only functional changes.



[...]

>>>  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;
>> This is confusing... do you use to ?: operator for differentiating between
>> cs = 0 and cs = 1?
>> I think this is a bad idea.
>> Moreover, the use of ?: is discouraged among the kernel.
> I could use if/else to replace this statement.

or switch, what ever you like, but please, don't leave it like
if (cs) ..., because this is confusing it has a meaning of "cs is good or bad?",
while actually, you want to know if it is 0 or 1 (both values are good).


[...]

>>> -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;
>> This one is confusing too...
>> Besides, you don't need the parenthesis.
> Got that. I would fix it.

Good, my previous explanation also applies here.
Thanks


[...]

>>>  static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
>>>  {
>>> -     struct mtd_info *mtd = info->mtd;
>>> +     struct pxa3xx_nand *nand = info->nand_data;
>>> +     struct mtd_info *mtd = get_mtd_by_info(info);
>>>       struct nand_chip *chip = mtd->priv;
>>>
>>>       /* use the common timing to make a try */
>>> -     pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
>>> +     if (pxa3xx_nand_config_flash(info, &builtin_flash_types[0]))
>>> +             return 0;
>>>       chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
>>> -     if (info->is_ready)
>>> +     if (nand->is_ready)
>>>               return 1;
>>>       else
>>>               return 0;
>> I think it is time to change this function return convention to propagate
>> errors and not just 0 or 1, (may be in separate patch) what do you think?
> How about return 0 when sensing the READY signal, or return -ENODEV?

Yes, this should be fine, but also don't forget about
pxa3xx_nand_config_flash() function call - it can return 0 or -EINVAL
and it should also propagate instead of being squashed.

>>> @@ -882,7 +908,8 @@ 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 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;
>>>       struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
>>>       const struct pxa3xx_nand_flash *f = NULL;
>>> @@ -891,27 +918,25 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
>>>       uint64_t chipsize;
>>>       int i, ret, num;
>>>
>>> +     nand->chip_select = info->chip_select;
>>>       if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
>>>               goto KEEP_CONFIG;
>>>
>>>       ret = pxa3xx_nand_sensing(info);
>>>       if (!ret) {
>>> -             kfree(mtd);
>>> -             info->mtd = NULL;
>>> -             printk(KERN_INFO "There is no nand chip on cs 0!\n");
>>> +             free_cs_resource(info, nand->chip_select);
>>> +             printk(KERN_INFO "There is no nand chip on cs %d!\n",
>>> +                             nand->chip_select);
>>>
>>>               return -EINVAL;

after the change of pxa3xx_nand_sensing() function,
you should change the above "return -EINVAL;" into "return ret;"



[...]


-- 
Regards,
Igor.



From dbaryshkov at gmail.com  Thu Jun 23 08:05:29 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 23 Jun 2011 16:05:29 +0400
Subject: [PATCH 3/5] mtd: hide parse_mtd_partitions
In-Reply-To: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
References: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308830731-5698-4-git-send-email-dbaryshkov@gmail.com>

There is no need to export parse_mtd_partitions() now , as it's fully handled
by registration functions. So move the definition to private header and
remove respective EXPORT_SYMBOL_GPL.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.h          |    4 ++++
 drivers/mtd/mtdpart.c          |    1 -
 include/linux/mtd/partitions.h |    3 ---
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/mtdcore.h b/drivers/mtd/mtdcore.h
index 0ed6126..7e7d1a3b 100644
--- a/drivers/mtd/mtdcore.h
+++ b/drivers/mtd/mtdcore.h
@@ -15,8 +15,12 @@ extern int del_mtd_device(struct mtd_info *mtd);
 extern int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *,
 			      int);
 extern int del_mtd_partitions(struct mtd_info *);
+extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
+				struct mtd_partition **pparts,
+				struct mtd_part_parser_data *data);
 
 #define mtd_for_each_device(mtd)			\
 	for ((mtd) = __mtd_next_device(0);		\
 	     (mtd) != NULL;				\
 	     (mtd) = __mtd_next_device(mtd->index + 1))
+
diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 9e8ee05..6997c6c 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -778,7 +778,6 @@ int parse_mtd_partitions(struct mtd_info *master, const char **types,
 	}
 	return ret;
 }
-EXPORT_SYMBOL_GPL(parse_mtd_partitions);
 
 int mtd_is_partition(struct mtd_info *mtd)
 {
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index a8a961a..c98d6b8 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -78,9 +78,6 @@ struct mtd_part_parser {
 
 extern int register_mtd_parser(struct mtd_part_parser *parser);
 extern int deregister_mtd_parser(struct mtd_part_parser *parser);
-extern int parse_mtd_partitions(struct mtd_info *master, const char **types,
-				struct mtd_partition **pparts,
-				struct mtd_part_parser_data *data);
 
 #define put_partition_parser(p) do { module_put((p)->owner); } while(0)
 
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun 23 08:05:27 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 23 Jun 2011 16:05:27 +0400
Subject: [PATCH 1/5] mtd/maps: drop edb7312 support
In-Reply-To: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
References: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308830731-5698-2-git-send-email-dbaryshkov@gmail.com>

EDB7312 isn't supported by mainline kernel, this driver wasn't working
before recent fixes, the same functionality can be achieved via physmap,
so drop it now. If the board support will ever be submitted to mainline,
one either can revert this commit, or use physmap mtd map driver.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/maps/Kconfig   |    7 --
 drivers/mtd/maps/Makefile  |    1 -
 drivers/mtd/maps/edb7312.c |  135 --------------------------------------------
 3 files changed, 0 insertions(+), 143 deletions(-)
 delete mode 100644 drivers/mtd/maps/edb7312.c

diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig
index 46eca3b..891a9e6 100644
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -392,13 +392,6 @@ config MTD_AUTCPU12
 	  This enables access to the NV-RAM on autronix autcpu12 board.
 	  If you have such a board, say 'Y'.
 
-config MTD_EDB7312
-	tristate "CFI Flash device mapped on EDB7312"
-	depends on ARCH_EDB7312 && MTD_CFI
-	help
-	  This enables access to the CFI Flash on the Cogent EDB7312 board.
-	  If you have such a board, say 'Y' here.
-
 config MTD_IMPA7
 	tristate "JEDEC Flash device mapped on impA7"
 	depends on ARM && MTD_JEDECPROBE
diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile
index d6379fe..45dcb8b 100644
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -39,7 +39,6 @@ obj-$(CONFIG_MTD_DBOX2)		+= dbox2-flash.o
 obj-$(CONFIG_MTD_SOLUTIONENGINE)+= solutionengine.o
 obj-$(CONFIG_MTD_PCI)		+= pci.o
 obj-$(CONFIG_MTD_AUTCPU12)	+= autcpu12-nvram.o
-obj-$(CONFIG_MTD_EDB7312)	+= edb7312.o
 obj-$(CONFIG_MTD_IMPA7)		+= impa7.o
 obj-$(CONFIG_MTD_FORTUNET)	+= fortunet.o
 obj-$(CONFIG_MTD_UCLINUX)	+= uclinux.o
diff --git a/drivers/mtd/maps/edb7312.c b/drivers/mtd/maps/edb7312.c
deleted file mode 100644
index b07acd6..0000000
--- a/drivers/mtd/maps/edb7312.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Handle mapping of the NOR flash on Cogent EDB7312 boards
- *
- * Copyright 2002 SYSGO Real-Time Solutions GmbH
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <asm/io.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/map.h>
-#include <linux/mtd/partitions.h>
-
-#define WINDOW_ADDR 0x00000000      /* physical properties of flash */
-#define WINDOW_SIZE 0x01000000
-#define BUSWIDTH    2
-#define FLASH_BLOCKSIZE_MAIN	0x20000
-#define FLASH_NUMBLOCKS_MAIN	128
-/* can be "cfi_probe", "jedec_probe", "map_rom", NULL }; */
-#define PROBETYPES { "cfi_probe", NULL }
-
-#define MSG_PREFIX "EDB7312-NOR:"   /* prefix for our printk()'s */
-#define MTDID      "edb7312-nor"    /* for mtdparts= partitioning */
-
-static struct mtd_info *mymtd;
-
-struct map_info edb7312nor_map = {
-	.name = "NOR flash on EDB7312",
-	.size = WINDOW_SIZE,
-	.bankwidth = BUSWIDTH,
-	.phys = WINDOW_ADDR,
-};
-
-/*
- * MTD partitioning stuff
- */
-static struct mtd_partition static_partitions[3] =
-{
-	{
-		.name = "ARMboot",
-		.size = 0x40000,
-		.offset = 0
-	},
-	{
-		.name = "Kernel",
-		.size = 0x200000,
-		.offset = 0x40000
-	},
-	{
-		.name = "RootFS",
-		.size = 0xDC0000,
-		.offset = 0x240000
-	},
-};
-
-static const char *probes[] = { "RedBoot", "cmdlinepart", NULL };
-
-static int                   mtd_parts_nb = 0;
-static struct mtd_partition *mtd_parts    = 0;
-
-static int __init init_edb7312nor(void)
-{
-	static const char *rom_probe_types[] = PROBETYPES;
-	const char **type;
-	const char *part_type = 0;
-
-       	printk(KERN_NOTICE MSG_PREFIX "0x%08x at 0x%08x\n",
-	       WINDOW_SIZE, WINDOW_ADDR);
-	edb7312nor_map.virt = ioremap(WINDOW_ADDR, WINDOW_SIZE);
-
-	if (!edb7312nor_map.virt) {
-		printk(MSG_PREFIX "failed to ioremap\n");
-		return -EIO;
-	}
-
-	simple_map_init(&edb7312nor_map);
-
-	mymtd = 0;
-	type = rom_probe_types;
-	for(; !mymtd && *type; type++) {
-		mymtd = do_map_probe(*type, &edb7312nor_map);
-	}
-	if (mymtd) {
-		mymtd->owner = THIS_MODULE;
-		mymtd->name = MTDID;
-
-		mtd_parts_nb = parse_mtd_partitions(mymtd, probes, &mtd_parts, 0);
-		if (mtd_parts_nb > 0)
-			part_type = "detected";
-
-		if (mtd_parts_nb == 0) {
-			mtd_parts = static_partitions;
-			mtd_parts_nb = ARRAY_SIZE(static_partitions);
-			part_type = "static";
-		}
-
-		if (mtd_parts_nb == 0)
-			printk(KERN_NOTICE MSG_PREFIX "no partition info available\n");
-		else
-			printk(KERN_NOTICE MSG_PREFIX
-			       "using %s partition definition\n", part_type);
-		/* Register the whole device first. */
-		mtd_device_register(mymtd, NULL, 0);
-		mtd_device_register(mymtd, mtd_parts, mtd_parts_nb);
-		return 0;
-	}
-
-	iounmap((void *)edb7312nor_map.virt);
-	return -ENXIO;
-}
-
-static void __exit cleanup_edb7312nor(void)
-{
-	if (mymtd) {
-		mtd_device_unregister(mymtd);
-		map_destroy(mymtd);
-	}
-	if (edb7312nor_map.virt) {
-		iounmap((void *)edb7312nor_map.virt);
-		edb7312nor_map.virt = 0;
-	}
-}
-
-module_init(init_edb7312nor);
-module_exit(cleanup_edb7312nor);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marius Groeger <mag at sysgo.de>");
-MODULE_DESCRIPTION("Generic configurable MTD map driver");
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun 23 08:05:28 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 23 Jun 2011 16:05:28 +0400
Subject: =?UTF-8?q?=5BPATCH=202/5=5D=20mtd/nand=3A=20drop=20edb7312=20support?=
In-Reply-To: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
References: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308830731-5698-3-git-send-email-dbaryshkov@gmail.com>

EDB7312 isn't supported by mainline kernel, so drop it now.
If the board support will ever be submitted to mainline,
one can revert this commit.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/Kconfig   |    7 --
 drivers/mtd/nand/Makefile  |    1 -
 drivers/mtd/nand/edb7312.c |  188 --------------------------------------------
 3 files changed, 0 insertions(+), 196 deletions(-)
 delete mode 100644 drivers/mtd/nand/edb7312.c

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4c34252..17235d0 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -83,13 +83,6 @@ config MTD_NAND_DENALI_SCRATCH_REG_ADDR
           scratch register here to enable this feature. On Intel Moorestown
           boards, the scratch register is at 0xFF108018.
 
-config MTD_NAND_EDB7312
-	tristate "Support for Cirrus Logic EBD7312 evaluation board"
-	depends on ARCH_EDB7312
-	help
-	  This enables the driver for the Cirrus Logic EBD7312 evaluation
-	  board to access the onboard NAND Flash.
-
 config MTD_NAND_H1900
 	tristate "iPAQ H1900 flash"
 	depends on ARCH_PXA
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 5745d83..c9334e9 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -13,7 +13,6 @@ obj-$(CONFIG_MTD_NAND_SPIA)		+= spia.o
 obj-$(CONFIG_MTD_NAND_AMS_DELTA)	+= ams-delta.o
 obj-$(CONFIG_MTD_NAND_AUTCPU12)		+= autcpu12.o
 obj-$(CONFIG_MTD_NAND_DENALI)		+= denali.o
-obj-$(CONFIG_MTD_NAND_EDB7312)		+= edb7312.o
 obj-$(CONFIG_MTD_NAND_AU1550)		+= au1550nd.o
 obj-$(CONFIG_MTD_NAND_BF5XX)		+= bf5xx_nand.o
 obj-$(CONFIG_MTD_NAND_PPCHAMELEONEVB)	+= ppchameleonevb.o
diff --git a/drivers/mtd/nand/edb7312.c b/drivers/mtd/nand/edb7312.c
deleted file mode 100644
index 0b1bb91..0000000
--- a/drivers/mtd/nand/edb7312.c
+++ /dev/null
@@ -1,188 +0,0 @@
-/*
- *  drivers/mtd/nand/edb7312.c
- *
- *  Copyright (C) 2002 Marius Gr?ger (mag at sysgo.de)
- *
- *  Derived from drivers/mtd/nand/autcpu12.c
- *       Copyright (c) 2001 Thomas Gleixner (gleixner at autronix.de)
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *  Overview:
- *   This is a device driver for the NAND flash device found on the
- *   CLEP7312 board which utilizes the Toshiba TC58V64AFT part. This is
- *   a 64Mibit (8MiB x 8 bits) NAND flash device.
- */
-
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/mtd/mtd.h>
-#include <linux/mtd/nand.h>
-#include <linux/mtd/partitions.h>
-#include <asm/io.h>
-#include <mach/hardware.h>	/* for CLPS7111_VIRT_BASE */
-#include <asm/sizes.h>
-#include <asm/hardware/clps7111.h>
-
-/*
- * MTD structure for EDB7312 board
- */
-static struct mtd_info *ep7312_mtd = NULL;
-
-/*
- * Values specific to the EDB7312 board (used with EP7312 processor)
- */
-#define EP7312_FIO_PBASE 0x10000000	/* Phys address of flash */
-#define EP7312_PXDR	0x0001	/*
-				 * IO offset to Port B data register
-				 * where the CLE, ALE and NCE pins
-				 * are wired to.
-				 */
-#define EP7312_PXDDR	0x0041	/*
-				 * IO offset to Port B data direction
-				 * register so we can control the IO
-				 * lines.
-				 */
-
-/*
- * Module stuff
- */
-
-static unsigned long ep7312_fio_pbase = EP7312_FIO_PBASE;
-static void __iomem *ep7312_pxdr = (void __iomem *)EP7312_PXDR;
-static void __iomem *ep7312_pxddr = (void __iomem *)EP7312_PXDDR;
-
-/*
- * Define static partitions for flash device
- */
-static struct mtd_partition partition_info[] = {
-	{.name = "EP7312 Nand Flash",
-	 .offset = 0,
-	 .size = 8 * 1024 * 1024}
-};
-
-#define NUM_PARTITIONS 1
-
-/*
- *	hardware specific access to control-lines
- *
- *	NAND_NCE: bit 0 -> bit 6 (bit 7 = 1)
- *	NAND_CLE: bit 1 -> bit 4
- *	NAND_ALE: bit 2 -> bit 5
- */
-static void ep7312_hwcontrol(struct mtd_info *mtd, int cmd, unsigned int ctrl)
-{
-	struct nand_chip *chip = mtd->priv;
-
-	if (ctrl & NAND_CTRL_CHANGE) {
-		unsigned char bits = 0x80;
-
-		bits |= (ctrl & (NAND_CLE | NAND_ALE)) << 3;
-		bits |= (ctrl & NAND_NCE) ? 0x00 : 0x40;
-
-		clps_writeb((clps_readb(ep7312_pxdr)  & 0xF0) | bits,
-			    ep7312_pxdr);
-	}
-	if (cmd != NAND_CMD_NONE)
-		writeb(cmd, chip->IO_ADDR_W);
-}
-
-/*
- *	read device ready pin
- */
-static int ep7312_device_ready(struct mtd_info *mtd)
-{
-	return 1;
-}
-
-/*
- * Main initialization routine
- */
-static int __init ep7312_init(void)
-{
-	struct nand_chip *this;
-	void __iomem *ep7312_fio_base;
-
-	/* Allocate memory for MTD device structure and private data */
-	ep7312_mtd = kmalloc(sizeof(struct mtd_info) + sizeof(struct nand_chip), GFP_KERNEL);
-	if (!ep7312_mtd) {
-		printk("Unable to allocate EDB7312 NAND MTD device structure.\n");
-		return -ENOMEM;
-	}
-
-	/* map physical address */
-	ep7312_fio_base = ioremap(ep7312_fio_pbase, SZ_1K);
-	if (!ep7312_fio_base) {
-		printk("ioremap EDB7312 NAND flash failed\n");
-		kfree(ep7312_mtd);
-		return -EIO;
-	}
-
-	/* Get pointer to private data */
-	this = (struct nand_chip *)(&ep7312_mtd[1]);
-
-	/* Initialize structures */
-	memset(ep7312_mtd, 0, sizeof(struct mtd_info));
-	memset(this, 0, sizeof(struct nand_chip));
-
-	/* Link the private data with the MTD structure */
-	ep7312_mtd->priv = this;
-	ep7312_mtd->owner = THIS_MODULE;
-
-	/*
-	 * Set GPIO Port B control register so that the pins are configured
-	 * to be outputs for controlling the NAND flash.
-	 */
-	clps_writeb(0xf0, ep7312_pxddr);
-
-	/* insert callbacks */
-	this->IO_ADDR_R = ep7312_fio_base;
-	this->IO_ADDR_W = ep7312_fio_base;
-	this->cmd_ctrl = ep7312_hwcontrol;
-	this->dev_ready = ep7312_device_ready;
-	/* 15 us command delay time */
-	this->chip_delay = 15;
-
-	/* Scan to find existence of the device */
-	if (nand_scan(ep7312_mtd, 1)) {
-		iounmap((void *)ep7312_fio_base);
-		kfree(ep7312_mtd);
-		return -ENXIO;
-	}
-	ep7312_mtd->name = "edb7312-nand";
-
-	/* Register the partitions */
-	mtd_device_register(ep7312_mtd, NULL, 0,
-			partition_info, NUM_PARTITIONS);
-
-	/* Return happy */
-	return 0;
-}
-
-module_init(ep7312_init);
-
-/*
- * Clean up routine
- */
-static void __exit ep7312_cleanup(void)
-{
-	struct nand_chip *this = (struct nand_chip *)&ep7312_mtd[1];
-
-	/* Release resources, unregister device */
-	nand_release(ap7312_mtd);
-
-	/* Release io resource */
-	iounmap(this->IO_ADDR_R);
-
-	/* Free the MTD device structure */
-	kfree(ep7312_mtd);
-}
-
-module_exit(ep7312_cleanup);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Marius Groeger <mag at sysgo.de>");
-MODULE_DESCRIPTION("MTD map driver for Cogent EDB7312 board");
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun 23 08:05:30 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 23 Jun 2011 16:05:30 +0400
Subject: [PATCH 4/5] mtd: remove put_partition_parser() from public header
In-Reply-To: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
References: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308830731-5698-5-git-send-email-dbaryshkov@gmail.com>

There is no need to pollute public header with a definition private
to mtdpart.c. Move it from mtd/partitions.h to mtdpart.c

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdpart.c          |    2 ++
 include/linux/mtd/partitions.h |    2 --
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
index 6997c6c..c90b7ba 100644
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -706,6 +706,8 @@ static struct mtd_part_parser *get_partition_parser(const char *name)
 	return ret;
 }
 
+#define put_partition_parser(p) do { module_put((p)->owner); } while (0)
+
 int register_mtd_parser(struct mtd_part_parser *p)
 {
 	spin_lock(&part_parser_lock);
diff --git a/include/linux/mtd/partitions.h b/include/linux/mtd/partitions.h
index c98d6b8..2475228 100644
--- a/include/linux/mtd/partitions.h
+++ b/include/linux/mtd/partitions.h
@@ -79,8 +79,6 @@ struct mtd_part_parser {
 extern int register_mtd_parser(struct mtd_part_parser *parser);
 extern int deregister_mtd_parser(struct mtd_part_parser *parser);
 
-#define put_partition_parser(p) do { module_put((p)->owner); } while(0)
-
 int mtd_is_partition(struct mtd_info *mtd);
 int mtd_add_partition(struct mtd_info *master, char *name,
 		      long long offset, long long length);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun 23 08:05:31 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 23 Jun 2011 16:05:31 +0400
Subject: [PATCH 5/5] mtd: drop mtd_device_register
In-Reply-To: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
References: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308830731-5698-6-git-send-email-dbaryshkov@gmail.com>

mtd_device_register() is a limited version of mtd_device_parse_register.
Replace it with macro calling mtd_device_parse_register().

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/mtdcore.c   |   23 -----------------------
 include/linux/mtd/mtd.h |    5 ++---
 2 files changed, 2 insertions(+), 26 deletions(-)

diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index e186399..f9cc2d2 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -429,29 +429,6 @@ out_error:
 }
 
 /**
- * mtd_device_register - register an MTD device.
- *
- * @master: the MTD device to register
- * @parts: the partitions to register - only valid if nr_parts > 0
- * @nr_parts: the number of partitions in parts.  If zero then the full MTD
- *            device is registered
- *
- * Register an MTD device with the system and optionally, a number of
- * partitions.  If nr_parts is 0 then the whole device is registered, otherwise
- * only the partitions are registered.  To register both the full device *and*
- * the partitions, call mtd_device_register() twice, once with nr_parts == 0
- * and once equal to the number of partitions.
- */
-int mtd_device_register(struct mtd_info *master,
-			const struct mtd_partition *parts,
-			int nr_parts)
-{
-	return parts ? add_mtd_partitions(master, parts, nr_parts) :
-		add_mtd_device(master);
-}
-EXPORT_SYMBOL_GPL(mtd_device_register);
-
-/**
  * mtd_device_parse_register - parse partitions and register an MTD device.
  *
  * @mtd: the MTD device to register
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index b2b454b..67774f9 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -325,14 +325,13 @@ static inline uint32_t mtd_mod_by_ws(uint64_t sz, struct mtd_info *mtd)
 struct mtd_partition;
 struct mtd_part_parser_data;
 
-extern int mtd_device_register(struct mtd_info *master,
-			       const struct mtd_partition *parts,
-			       int nr_parts);
 extern int mtd_device_parse_register(struct mtd_info *mtd,
 			      const char **part_probe_types,
 			      struct mtd_part_parser_data *parser_data,
 			      const struct mtd_partition *defparts,
 			      int defnr_parts);
+#define mtd_device_register(master, parts, nr_parts)	\
+	mtd_device_parse_register(master, NULL, NULL, parts, nr_parts)
 extern int mtd_device_unregister(struct mtd_info *master);
 extern struct mtd_info *get_mtd_device(struct mtd_info *mtd, int num);
 extern int __get_mtd_device(struct mtd_info *mtd);
-- 
1.7.5.3



From dbaryshkov at gmail.com  Thu Jun 23 08:05:26 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 23 Jun 2011 16:05:26 +0400
Subject: [PATCH 0/5] Few additional cleanup patches
Message-ID: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>

The following changes since commit 8c2ce1c78ba6cce94d0dfe6c674ea6c0cba56899:

  mtd: socrates_nand.c: use mtd_device_parse_register (2011-06-23 10:43:39 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup

Dmitry Eremin-Solenikov (5):
      mtd/maps: drop edb7312 support
      mtd/nand: drop edb7312 support
      mtd: hide parse_mtd_partitions
      mtd: remove put_partition_parser() from public header
      mtd: drop mtd_device_register

 drivers/mtd/maps/Kconfig       |    7 --
 drivers/mtd/maps/Makefile      |    1 -
 drivers/mtd/maps/edb7312.c     |  135 ----------------------------
 drivers/mtd/mtdcore.c          |   23 -----
 drivers/mtd/mtdcore.h          |    4 +
 drivers/mtd/mtdpart.c          |    3 +-
 drivers/mtd/nand/Kconfig       |    7 --
 drivers/mtd/nand/Makefile      |    1 -
 drivers/mtd/nand/edb7312.c     |  188 ----------------------------------------
 include/linux/mtd/mtd.h        |    5 +-
 include/linux/mtd/partitions.h |    5 -
 11 files changed, 8 insertions(+), 371 deletions(-)
 delete mode 100644 drivers/mtd/maps/edb7312.c
 delete mode 100644 drivers/mtd/nand/edb7312.c



From mrharrbrown at one.co.il  Thu Jun 23 07:45:19 2011
From: mrharrbrown at one.co.il (MR. HARRY BROWN)
Date: Thu, 23 Jun 2011 11:45:19 GMT
Subject: 23rd June 2011 : Investment interest
Message-ID: <201106231145.p5NBjJ1P048770@mail.greitas.lt>

Attn:

Can you secure for me a lucrative investment opportunities in your country?

My interest of investment is in MINING, exotic properties for commercial, residential and development properties and Hotels, and any other viable investment opportunities in your country you deem lucrative based on your recommendation, will be highly welcomed.

You see, I can only invest in your country with assistance of a very competent person like you to guide and direct me appropriately.

Waiting to hear from you.

Regards,

Mr. Brown.
Tel: +2348054454333.





From dedekind1 at gmail.com  Thu Jun 23 10:30:57 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 17:30:57 +0300
Subject: "warning!: only 995 of 1984 eraseblocks have valid erase counter"
In-Reply-To: <2016071dvg4slfufk95id9ov68n2kvbp4j@4ax.com>
References: <o4krv69m77vomji84cs3flljf6obpgfgcs@4ax.com>
	<1308820444.19443.0.camel@sauron>
	<2016071dvg4slfufk95id9ov68n2kvbp4j@4ax.com>
Message-ID: <1308839462.23597.5.camel@sauron>

On Thu, 2011-06-23 at 11:19 +0200, Gilles wrote:
> On Thu, 23 Jun 2011 12:14:01 +0300, Artem Bityutskiy
> <dedekind1 at gmail.com> wrote:
> >I think it is self-explanatory. Please, ask specific question. WRT to
> >consequences - it should not be critical.
> 
> I went ahead, answered yes, and it seems to work OK, but I was curious
> to understand what the message really means.

What exactly is unclear in the messages? :-)

> Before reflashing memory with an image, does ubiformat always warn the
> user that the empty blocks after the image will have their erase
> counter set to the average computed from the used blocks, regardless
> of their actual usage so far?

Yes. If you properly use tools - you should never see the warnings. Most
probably you flash images using UBI-unaware tools, or you erase the
flash using UBI-unaware tools like flash_erase or do it in u-boot.

But I agree that ubiformat could probably be smarter and avoid printing
this warning if half of the flash is UBI-formatted and the other half is
empty.

Current logic is - if not everything is UBI-formatted - warn. But it
could be - if not everything is UBI-formatted and the eraseblocks are
not empty - warn. Feel free to send a patch :-)

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 10:51:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 17:51:36 +0300
Subject: [PATCHv2] UBI: clarify the volume notification types' doc
In-Reply-To: <4DFF687B.6070806@free-electrons.com>
References: <4DFF129E.6070808@free-electrons.com>
	<4DFF687B.6070806@free-electrons.com>
Message-ID: <1308840701.23597.8.camel@sauron>

On Mon, 2011-06-20 at 17:34 +0200, David Wagner wrote:
> I realized the new descriptions of ADDED and REMOVED could also be
> misleading: they can also be triggered after using a userland util
> (ubi{mk,rm}vol).
> 
> (the indentation looks odd but is fine once the patch has been applied)
> 
> Signed-off-by David Wagner <david.wagner at free-electrons.com>
> ---
>  include/linux/mtd/ubi.h |   12 +++++++-----
>  1 files changed, 7 insertions(+), 5 deletions(-)
> 
> diff --git a/include/linux/mtd/ubi.h b/include/linux/mtd/ubi.h
> index b31bd9e..b79e741 100644
> --- a/include/linux/mtd/ubi.h
> +++ b/include/linux/mtd/ubi.h
> @@ -134,11 +134,13 @@ struct ubi_device_info {
> 
>  /*
>   * enum - volume notification types.
> - * @UBI_VOLUME_ADDED: volume has been added
> - * @UBI_VOLUME_REMOVED: start volume volume
> - * @UBI_VOLUME_RESIZED: volume size has been re-sized
> - * @UBI_VOLUME_RENAMED: volume name has been re-named
> - * @UBI_VOLUME_UPDATED: volume name has been updated
> + * @UBI_VOLUME_ADDED: a volume has been added (containing device attached
> + *		      or volume created from a userland util)
> + * @UBI_VOLUME_REMOVED: a volume has been removed (containing device
> detached

The patch is corrupted because of line-wrapping, but I fixed it and
amended the comments a bit (did not like the "userland util" phrase),
and pushed to ubi-2.6.git tree, thanks.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 11:02:51 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 18:02:51 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308841377.23597.10.camel@sauron>

On Wed, 2011-06-22 at 09:49 -0700, Brian Norris wrote:
> Hello,
> 
> I think this should be the last version necessary for this particular patch
> series...
> 
> This series adds, changes, and deprecates several nanddump options, helping make
> nanddump a closer inverse to nandwrite. This is mostly a preparation for the
> next release, when several defaults might change. A short list of the planned
> changes:
> 
>  * unify bad block methods under `--bb=METHOD', deprecating old ones
>  * kill --omitbad in favor of --bb=skipbad
>  * skip bad blocks by default (i.e., --bb=skipbad)
>  * do not dump OOB by default (--omitoob)
>  * add `--oob' to force dumping OOB
> 
> Please let me know when these are accepted and the 1.4.5 release is made, so I
> can send a proper patchset to clean this all up as planned for the 1.4.6
> release.

Pushed, thank you!

> BTW, is each utility supposed to have its own version? (e.g., nanddump has
> version 1.30?) Should these versions be kept in any kind of sync with the
> mtd-utils revision tags? And does Artem take care of this stuff?

Actually no, I do not take care of this and this is messy. Probably it
would be easier if all utils had the same version as the release...

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 23 11:04:57 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 23 Jun 2011 18:04:57 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <1308841377.23597.10.camel@sauron>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron>
Message-ID: <1308841503.23597.12.camel@sauron>

On Thu, 2011-06-23 at 18:02 +0300, Artem Bityutskiy wrote:
> On Wed, 2011-06-22 at 09:49 -0700, Brian Norris wrote:
> > Hello,
> > 
> > I think this should be the last version necessary for this particular patch
> > series...
> > 
> > This series adds, changes, and deprecates several nanddump options, helping make
> > nanddump a closer inverse to nandwrite. This is mostly a preparation for the
> > next release, when several defaults might change. A short list of the planned
> > changes:
> > 
> >  * unify bad block methods under `--bb=METHOD', deprecating old ones
> >  * kill --omitbad in favor of --bb=skipbad
> >  * skip bad blocks by default (i.e., --bb=skipbad)
> >  * do not dump OOB by default (--omitoob)
> >  * add `--oob' to force dumping OOB
> > 
> > Please let me know when these are accepted and the 1.4.5 release is made, so I
> > can send a proper patchset to clean this all up as planned for the 1.4.6
> > release.
> 
> Pushed, thank you!
> 
> > BTW, is each utility supposed to have its own version? (e.g., nanddump has
> > version 1.30?) Should these versions be kept in any kind of sync with the
> > mtd-utils revision tags? And does Artem take care of this stuff?
> 
> Actually no, I do not take care of this and this is messy. Probably it
> would be easier if all utils had the same version as the release...

And speaking about released, should we do a new one? If you see that
some utils should have a version increased - feel free to do so. But
even better we could make the version numbers to be the same as release
number, then this process would be more automated and version would make
some sense...

-- 
Best Regards,
Artem Bityutskiy



From vapier.adi at gmail.com  Thu Jun 23 11:52:07 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 23 Jun 2011 11:52:07 -0400
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <1308841503.23597.12.camel@sauron>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
Message-ID: <BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>

On Thu, Jun 23, 2011 at 11:04, Artem Bityutskiy wrote:
> And speaking about released, should we do a new one? If you see that
> some utils should have a version increased - feel free to do so. But
> even better we could make the version numbers to be the same as release
> number, then this process would be more automated and version would make
> some sense...

the version isnt encoded anywhere.  so if you started using something
like the kernel where the VERSION was in the Makefile, we could use
that to create a header file which all the utils would include.
-mike


From computersforpeace at gmail.com  Thu Jun 23 12:36:32 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 09:36:32 -0700
Subject: bbt and bitflip
In-Reply-To: <1303460103.2757.48.camel@localhost>
References: <4DB033E4.6030105@parrot.com> <4DB06693.5000100@parrot.com>
	<1303460103.2757.48.camel@localhost>
Message-ID: <BANLkTimwOp4uPfQ0udLDycor2MjotUxiHw@mail.gmail.com>

Hello,

On Fri, Apr 22, 2011 at 1:15 AM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2011-04-21 at 19:17 +0200, Matthieu CASTET wrote:
>> Here a quick and dirty patch to make them more robust.
>> Any comment are welcomed.
>
> Would be great if you could test it and submit a nice patch with proper
> commit message and Signed-off-by.

I am interested in Artem's comments on the robustness of flash-based
BBT (here, and more recently on
http://lists.infradead.org/pipermail/linux-mtd/2011-June/036557.html).
I recently have moved to using flash-based BBT (in-band, actually),
and it seemed like several NAND drivers use flash-based BBT as well.
Is it really that un-trustworthy?

So I guess I'm looking for areas of improvement. I see a few suggestions here:

"Also the pattern and version in oob isn't protected by ecc. They can
be corrupted."

I noticed this one recently. My hardware ECC actually *can* do ECC for
what little OOB is actually free, but I realized that the nand_base
code doesn't even try to check the ECC stats (in nand_do_read_oob())
whereas some similar code for nand_do_read_ops *does* check the ECC
stats. Is it fair to adapt the code from nand_do_read_ops to
nand_do_read_oob so that both check for ECC errors, just in case the
hardware supports it? Would this cause any API problems, if users
didn't expect OOB reads to return ECC error statuses? For now, this
would only have any effect if a driver replaces the chip->ecc.read_oob
function with something that performs ECC operations independently and
increments the ECC counters.

And speaking of BBT in OOB:
Anyone know why the flash-based ident pattern and version is
"traditionally" stored in OOB? It was quite recently that Sebastian
Andrzej Siewior added the NAND_USE_FLASH_BBT_NO_OOB flag (which is
slated to be renamed/replaced, FYI). It seems like ...NO_OOB is a
generally good (or at least better) idea. Then we wouldn't even have
to worry much about ECC in OOB.

"read_bbt which ignore ecc bit flip/error"

If I understand right, read_bbt just prints warning message on ECC
flips/errors and otherwise ignores them? Would Matthieu's "quick and
dirty" patch be an OK start for fixing this? (where in the absence of
a valid backup tableb, an ECC error causes a flash rescan and an ECC
bitflip causes an erase/rewrite "scrub"?)

"The bbt should be protected with CRC and if it gets corrupted we
should re-scan the flash and re-create it."

Wouldn't CRC just be a lesser replacement for proper ECC protection?
Or am I missing something?

Brian


From zohar at linux.vnet.ibm.com  Thu Jun 23 17:04:11 2011
From: zohar at linux.vnet.ibm.com (Mimi Zohar)
Date: Thu, 23 Jun 2011 17:04:11 -0400
Subject: [PATCH] security: new security_inode_init_security API adds function
	callback
Message-ID: <1308863051-9521-1-git-send-email-zohar@linux.vnet.ibm.com>

The recently posted EVM/IMA-appraisal patches added a new hook
evm_inode_post_init_security() to calculate the security.evm extended
attribute(xattr) and an additional call to set_xattr().

        security_inode_init_security(&lsm_xattr)
        set_xattr(&lsm_xattr)

        evm_inode_post_init_security(&lsm_xattr, &evm_xattr)
        set_xattr(&evm_xattr)

The ensuing mailing list discussion centered around:
- Steve Whitehouse's questioning the need for two set_xattr() calls.
- Casey Schaufler's multiple LSM xattr support reminder.
- Dave Chinner's questioning the need for the new
  evm_inode_post_init_security() hook.

This patch changes the security_inode_init_security API by adding a
filesystem specific callback to write security extended attributes.
The change is in preparation for supporting the initialization of
multiple LSM xattrs and the EVM xattr.  Initially the callback function
walks an array of xattrs, writing each xattr separately, but could be
optimized to write multiple xattrs at once.

For existing security_inode_init_security() calls, which have yet to
be converted to use the new callback function, such as those in reiserfs
and ocfs2, this patch defines security_old_inode_init_security().

Signed-off-by: Mimi Zohar <zohar at us.ibm.com>
---
 security/security.c          |   39 ++++++++++++++++++++++++++--
 fs/ext2/xattr_security.c     |   34 +++++++++++++-----------
 fs/ext3/xattr_security.c     |   36 ++++++++++++++-----------
 fs/ext4/xattr_security.c     |   36 ++++++++++++++-----------
 fs/btrfs/xattr.c             |   52 +++++++++++++++++++-------------------
 fs/gfs2/inode.c              |   38 +++++++++++++--------------
 fs/jffs2/security.c          |   37 ++++++++++++++------------
 fs/jfs/xattr.c               |   57 ++++++++++++++++++++---------------------
 fs/ocfs2/xattr.c             |   38 +++++++++++++++++----------
 fs/reiserfs/xattr_security.c |    4 +-
 fs/xfs/linux-2.6/xfs_iops.c  |   39 ++++++++++++++--------------
 mm/shmem.c                   |    4 +-
 include/linux/security.h     |   17 +++++++++---
 include/linux/xattr.h        |    6 ++++
 14 files changed, 252 insertions(+), 185 deletions(-)

diff --git a/security/security.c b/security/security.c
index 4ba6d4c..3464d58 100644
--- a/security/security.c
+++ b/security/security.c
@@ -18,6 +18,8 @@
 #include <linux/security.h>
 #include <linux/ima.h>
 
+#define MAX_LSM_XATTR	1
+
 /* Boot-time LSM user choice */
 static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
 	CONFIG_DEFAULT_SECURITY;
@@ -339,15 +341,46 @@ void security_inode_free(struct inode *inode)
 }
 
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-				 const struct qstr *qstr, char **name,
-				 void **value, size_t *len)
+				 const struct qstr *qstr,
+				 const initxattrs initxattrs, void *fs_data)
+{
+	struct xattr new_xattrs[MAX_LSM_XATTR + 1];
+	struct xattr *lsm_xattr;
+	int ret;
+
+	if (unlikely(IS_PRIVATE(inode)))
+		return -EOPNOTSUPP;
+
+	memset(new_xattrs, 0, sizeof new_xattrs);
+	if (!initxattrs)
+		return security_ops->inode_init_security(inode, dir, qstr,
+							 NULL, NULL, NULL);
+	lsm_xattr = new_xattrs;
+	ret = security_ops->inode_init_security(inode, dir, qstr,
+						&lsm_xattr->name,
+						&lsm_xattr->value,
+						&lsm_xattr->value_len);
+	if (ret)
+		goto out;
+	ret = initxattrs(inode, new_xattrs, fs_data);
+out:
+	kfree(lsm_xattr->name);
+	kfree(lsm_xattr->value);
+
+	return (ret == -EOPNOTSUPP) ? 0 : ret;
+}
+EXPORT_SYMBOL(security_inode_init_security);
+
+int security_old_inode_init_security(struct inode *inode, struct inode *dir,
+				     const struct qstr *qstr, char **name,
+				     void **value, size_t *len)
 {
 	if (unlikely(IS_PRIVATE(inode)))
 		return -EOPNOTSUPP;
 	return security_ops->inode_init_security(inode, dir, qstr, name, value,
 						 len);
 }
-EXPORT_SYMBOL(security_inode_init_security);
+EXPORT_SYMBOL(security_old_inode_init_security);
 
 #ifdef CONFIG_SECURITY_PATH
 int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 5d979b4..fc80cf4 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -46,26 +46,28 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
 			      value, size, flags);
 }
 
+int ext2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		    void *fs_info)
+{
+	const struct xattr *xattr;
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
+				     xattr->name, xattr->value,
+				     xattr->value_len, 0);
+		if (err < 0)
+			break;
+	}
+	return err;
+}
+
 int
 ext2_init_security(struct inode *inode, struct inode *dir,
 		   const struct qstr *qstr)
 {
-	int err;
-	size_t len;
-	void *value;
-	char *name;
-
-	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			return 0;
-		return err;
-	}
-	err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
-			     name, value, len, 0);
-	kfree(name);
-	kfree(value);
-	return err;
+	return security_inode_init_security(inode, dir, qstr,
+					    &ext2_initxattrs, NULL);
 }
 
 const struct xattr_handler ext2_xattr_security_handler = {
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index b8d9f83..4202683 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -48,26 +48,30 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
 			      name, value, size, flags);
 }
 
+int ext3_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		    void *fs_info)
+{
+	const struct xattr *xattr;
+	handle_t *handle = fs_info;
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = ext3_xattr_set_handle(handle, inode,
+					    EXT3_XATTR_INDEX_SECURITY,
+					    xattr->name, xattr->value,
+					    xattr->value_len, 0);
+		if (err < 0)
+			break;
+	}
+	return err;
+}
+
 int
 ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
 		   const struct qstr *qstr)
 {
-	int err;
-	size_t len;
-	void *value;
-	char *name;
-
-	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			return 0;
-		return err;
-	}
-	err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
-				    name, value, len, 0);
-	kfree(name);
-	kfree(value);
-	return err;
+	return security_inode_init_security(inode, dir, qstr,
+					    &ext3_initxattrs, handle);
 }
 
 const struct xattr_handler ext3_xattr_security_handler = {
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 007c3bf..e8ccf3a 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -48,26 +48,30 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
 			      name, value, size, flags);
 }
 
+int ext4_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		    void *fs_info)
+{
+	const struct xattr *xattr;
+	handle_t *handle = fs_info;
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = ext4_xattr_set_handle(handle, inode,
+					    EXT4_XATTR_INDEX_SECURITY,
+					    xattr->name, xattr->value,
+					    xattr->value_len, 0);
+		if (err < 0)
+			break;
+	}
+	return err;
+}
+
 int
 ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
 		   const struct qstr *qstr)
 {
-	int err;
-	size_t len;
-	void *value;
-	char *name;
-
-	err = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			return 0;
-		return err;
-	}
-	err = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_SECURITY,
-				    name, value, len, 0);
-	kfree(name);
-	kfree(value);
-	return err;
+	return security_inode_init_security(inode, dir, qstr,
+					    &ext4_initxattrs, handle);
 }
 
 const struct xattr_handler ext4_xattr_security_handler = {
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 5366fe4..53c2317 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -360,36 +360,36 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
 				XATTR_REPLACE);
 }
 
-int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
-			      struct inode *inode, struct inode *dir,
-			      const struct qstr *qstr)
+int btrfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		     void *fs_info)
 {
-	int err;
-	size_t len;
-	void *value;
-	char *suffix;
+	const struct xattr *xattr;
+	struct btrfs_trans_handle *trans = fs_info;
 	char *name;
-
-	err = security_inode_init_security(inode, dir, qstr, &suffix, &value,
-					   &len);
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			return 0;
-		return err;
-	}
-
-	name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
-		       GFP_NOFS);
-	if (!name) {
-		err = -ENOMEM;
-	} else {
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 
+			       strlen(xattr->name) + 1, GFP_NOFS);
+		if (!name) {
+			err = -ENOMEM;
+			break;
+		}
 		strcpy(name, XATTR_SECURITY_PREFIX);
-		strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-		err = __btrfs_setxattr(trans, inode, name, value, len, 0);
+		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
+		err = __btrfs_setxattr(trans, inode, name,
+				       xattr->value, xattr->value_len, 0);
 		kfree(name);
+		if (err < 0)
+			break;
 	}
-
-	kfree(suffix);
-	kfree(value);
 	return err;
 }
+
+int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
+			      struct inode *inode, struct inode *dir,
+			      const struct qstr *qstr)
+{
+	return security_inode_init_security(inode, dir, qstr,
+					    &btrfs_initxattrs, trans);
+}
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 03e0c52..b6dabfe 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -624,31 +624,29 @@ fail:
 	return error;
 }
 
-static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
-			      const struct qstr *qstr)
+int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		    void *fs_info)
 {
-	int err;
-	size_t len;
-	void *value;
-	char *name;
-
-	err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
-					   &name, &value, &len);
-
-	if (err) {
-		if (err == -EOPNOTSUPP)
-			return 0;
-		return err;
+	const struct xattr *xattr;
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = __gfs2_xattr_set(inode, xattr->name, xattr->value,
+				       xattr->value_len, 0,
+				       GFS2_EATYPE_SECURITY);
+		if (err < 0)
+			break;
 	}
-
-	err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0,
-			       GFS2_EATYPE_SECURITY);
-	kfree(value);
-	kfree(name);
-
 	return err;
 }
 
+static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
+			      const struct qstr *qstr)
+{
+	return security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
+					    &gfs2_initxattrs, NULL);
+}
+
 /**
  * gfs2_create_inode - Create a new inode
  * @dir: The parent directory
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index cfeb716..2f27244 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -22,26 +22,29 @@
 #include <linux/security.h>
 #include "nodelist.h"
 
-/* ---- Initial Security Label Attachment -------------- */
-int jffs2_init_security(struct inode *inode, struct inode *dir,
-			const struct qstr *qstr)
+/* ---- Initial Security Label(s) Attachment callback --- */
+int jffs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		     void *fs_info)
 {
-	int rc;
-	size_t len;
-	void *value;
-	char *name;
-
-	rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len);
-	if (rc) {
-		if (rc == -EOPNOTSUPP)
-			return 0;
-		return rc;
+	const struct xattr *xattr;
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
+					xattr->name, xattr->value,
+					xattr->value_len, 0);
+		if (err < 0)
+			break;
 	}
-	rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0);
+	return err;
+}
 
-	kfree(name);
-	kfree(value);
-	return rc;
+/* ---- Initial Security Label(s) Attachment ----------- */
+int jffs2_init_security(struct inode *inode, struct inode *dir,
+			const struct qstr *qstr)
+{
+	return security_inode_init_security(inode, dir, qstr,
+					    &jffs2_initxattrs, NULL);
 }
 
 /* ---- XATTR Handler for "security.*" ----------------- */
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 24838f1..516afd5 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -1091,38 +1091,37 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
 }
 
 #ifdef CONFIG_JFS_SECURITY
-int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
-		      const struct qstr *qstr)
+int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		   void *fs_info)
 {
-	int rc;
-	size_t len;
-	void *value;
-	char *suffix;
+	const struct xattr *xattr;
+	tid_t *tid = fs_info;
 	char *name;
-
-	rc = security_inode_init_security(inode, dir, qstr, &suffix, &value,
-					  &len);
-	if (rc) {
-		if (rc == -EOPNOTSUPP)
-			return 0;
-		return rc;
-	}
-	name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix),
-		       GFP_NOFS);
-	if (!name) {
-		rc = -ENOMEM;
-		goto kmalloc_failed;
+	int err = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
+			       strlen(xattr->name) + 1, GFP_NOFS);
+		if (!name) {
+			err = -ENOMEM;
+			break;
+		}
+		strcpy(name, XATTR_SECURITY_PREFIX);
+		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
+		
+		err = __jfs_setxattr(*tid, inode, name, 
+				     xattr->value, xattr->value_len, 0);
+		kfree(name);
+		if (err < 0)
+			break;
 	}
-	strcpy(name, XATTR_SECURITY_PREFIX);
-	strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix);
-
-	rc = __jfs_setxattr(tid, inode, name, value, len, 0);
-
-	kfree(name);
-kmalloc_failed:
-	kfree(suffix);
-	kfree(value);
+	return err;
+}
 
-	return rc;
+int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
+		      const struct qstr *qstr)
+{
+	return security_inode_init_security(inode, dir, qstr,
+					    &jfs_initxattrs, &tid);
 }
 #endif
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 81ecf9c..40d9956 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7185,20 +7185,9 @@ int ocfs2_init_security_and_acl(struct inode *dir,
 {
 	int ret = 0;
 	struct buffer_head *dir_bh = NULL;
-	struct ocfs2_security_xattr_info si = {
-		.enable = 1,
-	};
 
-	ret = ocfs2_init_security_get(inode, dir, qstr, &si);
+	ret = ocfs2_init_security_get(inode, dir, qstr, NULL);
 	if (!ret) {
-		ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
-				      si.name, si.value, si.value_len,
-				      XATTR_CREATE);
-		if (ret) {
-			mlog_errno(ret);
-			goto leave;
-		}
-	} else if (ret != -EOPNOTSUPP) {
 		mlog_errno(ret);
 		goto leave;
 	}
@@ -7255,6 +7244,22 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
 			       name, value, size, flags);
 }
 
+int ocfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		     void *fs_info)
+{
+	const struct xattr *xattr;
+	int err = 0;
+
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		err = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
+				      xattr->name, xattr->value, 
+				      xattr->value_len, XATTR_CREATE);
+		if (err)
+			break;
+	}
+	return err;
+}
+
 int ocfs2_init_security_get(struct inode *inode,
 			    struct inode *dir,
 			    const struct qstr *qstr,
@@ -7263,8 +7268,13 @@ int ocfs2_init_security_get(struct inode *inode,
 	/* check whether ocfs2 support feature xattr */
 	if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))
 		return -EOPNOTSUPP;
-	return security_inode_init_security(inode, dir, qstr, &si->name,
-					    &si->value, &si->value_len);
+	if (si)
+		return security_old_inode_init_security(inode, dir, qstr,
+							&si->name, &si->value,
+							&si->value_len);
+	
+	return security_inode_init_security(inode, dir, qstr,
+					    &ocfs2_initxattrs, NULL);
 }
 
 int ocfs2_init_security_set(handle_t *handle,
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index ef66c18..534668f 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -66,8 +66,8 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
 	if (IS_PRIVATE(dir))
 		return 0;
 
-	error = security_inode_init_security(inode, dir, qstr, &sec->name,
-					     &sec->value, &sec->length);
+	error = security_old_inode_init_security(inode, dir, qstr, &sec->name,
+						 &sec->value, &sec->length);
 	if (error) {
 		if (error == -EOPNOTSUPP)
 			error = 0;
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index dd21784..1f8eeb8 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -93,37 +93,38 @@ xfs_mark_inode_dirty(
 		mark_inode_dirty(inode);
 }
 
+
+int xfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
+		   void *fs_info)
+{
+	const struct xattr *xattr;
+	struct xfs_inode *ip = XFS_I(inode);
+	int error = 0;
+	
+	for (xattr = xattr_array; xattr->name != NULL; xattr++) {
+		error = xfs_attr_set(ip, xattr->name, xattr->value,
+				     xattr->value_len, ATTR_SECURE);
+		if (error < 0)
+			break;
+	}
+	return error;
+}
+
 /*
  * Hook in SELinux.  This is not quite correct yet, what we really need
  * here (as we do for default ACLs) is a mechanism by which creation of
  * these attrs can be journalled at inode creation time (along with the
  * inode, of course, such that log replay can't cause these to be lost).
  */
+
 STATIC int
 xfs_init_security(
 	struct inode	*inode,
 	struct inode	*dir,
 	const struct qstr *qstr)
 {
-	struct xfs_inode *ip = XFS_I(inode);
-	size_t		length;
-	void		*value;
-	unsigned char	*name;
-	int		error;
-
-	error = security_inode_init_security(inode, dir, qstr, (char **)&name,
-					     &value, &length);
-	if (error) {
-		if (error == -EOPNOTSUPP)
-			return 0;
-		return -error;
-	}
-
-	error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
-
-	kfree(name);
-	kfree(value);
-	return error;
+	return security_inode_init_security(inode, dir, qstr,
+					    &xfs_initxattrs, NULL);
 }
 
 static void
diff --git a/mm/shmem.c b/mm/shmem.c
index d221a1c..518f27c 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1877,7 +1877,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
 	inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
 	if (inode) {
 		error = security_inode_init_security(inode, dir,
-						     &dentry->d_name, NULL,
+						     &dentry->d_name,
 						     NULL, NULL);
 		if (error) {
 			if (error != -EOPNOTSUPP) {
@@ -2017,7 +2017,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
 	if (!inode)
 		return -ENOSPC;
 
-	error = security_inode_init_security(inode, dir, &dentry->d_name, NULL,
+	error = security_inode_init_security(inode, dir, &dentry->d_name,
 					     NULL, NULL);
 	if (error) {
 		if (error != -EOPNOTSUPP) {
diff --git a/include/linux/security.h b/include/linux/security.h
index 8ce59ef..ebad5fb 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -36,6 +36,7 @@
 #include <linux/key.h>
 #include <linux/xfrm.h>
 #include <linux/slab.h>
+#include <linux/xattr.h>
 #include <net/flow.h>
 
 /* Maximum number of letters for an LSM name string */
@@ -147,6 +148,10 @@ extern int mmap_min_addr_handler(struct ctl_table *table, int write,
 				 void __user *buffer, size_t *lenp, loff_t *ppos);
 #endif
 
+/* security_inode_init_security callback function to write xattrs */
+typedef int (*initxattrs) (struct inode *inode,
+			   const struct xattr *xattr_array, void *fs_data);
+
 #ifdef CONFIG_SECURITY
 
 struct security_mnt_opts {
@@ -1704,8 +1709,11 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
 int security_inode_alloc(struct inode *inode);
 void security_inode_free(struct inode *inode);
 int security_inode_init_security(struct inode *inode, struct inode *dir,
-				 const struct qstr *qstr, char **name,
-				 void **value, size_t *len);
+				 const struct qstr *qstr,
+				 initxattrs initxattrs, void *fs_data);
+int security_old_inode_init_security(struct inode *inode, struct inode *dir,
+				     const struct qstr *qstr, char **name,
+				     void **value, size_t *len);
 int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
 int security_inode_link(struct dentry *old_dentry, struct inode *dir,
 			 struct dentry *new_dentry);
@@ -2035,9 +2043,8 @@ static inline void security_inode_free(struct inode *inode)
 static inline int security_inode_init_security(struct inode *inode,
 						struct inode *dir,
 						const struct qstr *qstr,
-						char **name,
-						void **value,
-						size_t *len)
+						initxattrs initxattrs,
+				 		void *fs_data)
 {
 	return -EOPNOTSUPP;
 }
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index aed54c5..7a37866 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -67,6 +67,12 @@ struct xattr_handler {
 		   size_t size, int flags, int handler_flags);
 };
 
+struct xattr {
+	char *name;
+	void *value;
+	size_t value_len;
+};
+
 ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
 ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
 ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
-- 
1.7.3.4



From computersforpeace at gmail.com  Thu Jun 23 17:12:08 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 14:12:08 -0700
Subject: [PATCH] mtd: spelling, capitalization, uniformity
Message-ID: <1308863528-32194-1-git-send-email-computersforpeace@gmail.com>

Therefor -> Therefore
[Intern], [Internal] -> [INTERN]
[REPLACABLE] -> [REPLACEABLE]
syndrom, syndom -> syndrome
ecc -> ECC
buswith -> buswidth
endianess -> endianness
dont -> don't
occures -> occurs
independend -> independent
wihin -> within
erease -> erase
blockes -> blocks
...

(This is based on Artem's l2-mtd-2.6 git tree)

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/chips/jedec_probe.c    |    2 +-
 drivers/mtd/devices/doc2000.c      |    2 +-
 drivers/mtd/devices/doc2001.c      |    2 +-
 drivers/mtd/devices/doc2001plus.c  |    2 +-
 drivers/mtd/devices/docecc.c       |    2 +-
 drivers/mtd/mtdchar.c              |    6 +-
 drivers/mtd/nand/au1550nd.c        |   29 +++++------
 drivers/mtd/nand/cafe_nand.c       |    2 +-
 drivers/mtd/nand/diskonchip.c      |    4 +-
 drivers/mtd/nand/nand_base.c       |  105 ++++++++++++++++++------------------
 drivers/mtd/nand/nand_bbt.c        |    8 ++--
 drivers/mtd/nand/nand_ecc.c        |   10 ++--
 drivers/mtd/nand/rtc_from4.c       |    2 +-
 drivers/mtd/onenand/onenand_base.c |   12 ++--
 drivers/mtd/sm_ftl.c               |    2 +-
 include/linux/mtd/mtd.h            |    2 +-
 include/linux/mtd/nand.h           |   50 +++++++++---------
 17 files changed, 119 insertions(+), 123 deletions(-)

diff --git a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c
index ea832ea..d40c410 100644
--- a/drivers/mtd/chips/jedec_probe.c
+++ b/drivers/mtd/chips/jedec_probe.c
@@ -1914,7 +1914,7 @@ static void jedec_reset(u32 base, struct map_info *map, struct cfi_private *cfi)
 	 * (oh and incidentaly the jedec spec - 3.5.3.3) the reset
 	 * sequence is *supposed* to be 0xaa at 0x5555, 0x55 at
 	 * 0x2aaa, 0xF0 at 0x5555 this will not affect the AMD chips
-	 * as they will ignore the writes and dont care what address
+	 * as they will ignore the writes and don't care what address
 	 * the F0 is written to */
 	if (cfi->addr_unlock1) {
 		DEBUG( MTD_DEBUG_LEVEL3,
diff --git a/drivers/mtd/devices/doc2000.c b/drivers/mtd/devices/doc2000.c
index f7fbf60..ed15447 100644
--- a/drivers/mtd/devices/doc2000.c
+++ b/drivers/mtd/devices/doc2000.c
@@ -699,7 +699,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
 			printk(KERN_ERR "DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-			/* Read the ECC syndrom through the DiskOnChip ECC
+			/* Read the ECC syndrome through the DiskOnChip ECC
 			   logic.  These syndrome will be all ZERO when there
 			   is no error */
 			for (i = 0; i < 6; i++) {
diff --git a/drivers/mtd/devices/doc2001.c b/drivers/mtd/devices/doc2001.c
index 241192f..c6ea860 100644
--- a/drivers/mtd/devices/doc2001.c
+++ b/drivers/mtd/devices/doc2001.c
@@ -464,7 +464,7 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-		/* Read the ECC syndrom through the DiskOnChip ECC logic.
+		/* Read the ECC syndrome through the DiskOnChip ECC logic.
 		   These syndrome will be all ZERO when there is no error */
 		for (i = 0; i < 6; i++) {
 			syndrome[i] = ReadDOC(docptr, ECCSyndrome0 + i);
diff --git a/drivers/mtd/devices/doc2001plus.c b/drivers/mtd/devices/doc2001plus.c
index 09ae0ad..fe82fbf 100644
--- a/drivers/mtd/devices/doc2001plus.c
+++ b/drivers/mtd/devices/doc2001plus.c
@@ -655,7 +655,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
 #ifdef ECC_DEBUG
 		printk("DiskOnChip ECC Error: Read at %lx\n", (long)from);
 #endif
-		/* Read the ECC syndrom through the DiskOnChip ECC logic.
+		/* Read the ECC syndrome through the DiskOnChip ECC logic.
 		   These syndrome will be all ZERO when there is no error */
 		for (i = 0; i < 6; i++)
 			syndrome[i] = ReadDOC(docptr, Mplus_ECCSyndrome0 + i);
diff --git a/drivers/mtd/devices/docecc.c b/drivers/mtd/devices/docecc.c
index 37ef29a..4a1c39b 100644
--- a/drivers/mtd/devices/docecc.c
+++ b/drivers/mtd/devices/docecc.c
@@ -2,7 +2,7 @@
  * ECC algorithm for M-systems disk on chip. We use the excellent Reed
  * Solmon code of Phil Karn (karn at ka9q.ampr.org) available under the
  * GNU GPL License. The rest is simply to convert the disk on chip
- * syndrom into a standard syndom.
+ * syndrome into a standard syndome.
  *
  * Author: Fabrice Bellard (fabrice.bellard at netgem.com)
  * Copyright (C) 2000 Netgem S.A.
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 9f8658e..92fa82d 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -233,9 +233,9 @@ static ssize_t mtd_read(struct file *file, char __user *buf, size_t count,loff_t
 		default:
 			ret = mtd->read(mtd, *ppos, len, &retlen, kbuf);
 		}
-		/* Nand returns -EBADMSG on ecc errors, but it returns
+		/* Nand returns -EBADMSG on ECC errors, but it returns
 		 * the data. For our userspace tools it is important
-		 * to dump areas with ecc errors !
+		 * to dump areas with ECC errors!
 		 * For kernel internal usage it also might return -EUCLEAN
 		 * to signal the caller that a bitflip has occurred and has
 		 * been corrected by the ECC algorithm.
@@ -883,7 +883,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg)
 	}
 #endif
 
-	/* This ioctl is being deprecated - it truncates the ecc layout */
+	/* This ioctl is being deprecated - it truncates the ECC layout */
 	case ECCGETLAYOUT:
 	{
 		struct nand_ecclayout_user *usrlay;
diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c
index e7767ee..60d58d3 100644
--- a/drivers/mtd/nand/au1550nd.c
+++ b/drivers/mtd/nand/au1550nd.c
@@ -48,7 +48,7 @@ static const struct mtd_partition partition_info[] = {
  * au_read_byte -  read one byte from the chip
  * @mtd:	MTD device structure
  *
- *  read function for 8bit buswith
+ * read function for 8bit buswidth
  */
 static u_char au_read_byte(struct mtd_info *mtd)
 {
@@ -63,7 +63,7 @@ static u_char au_read_byte(struct mtd_info *mtd)
  * @mtd:	MTD device structure
  * @byte:	pointer to data byte to write
  *
- *  write function for 8it buswith
+ * write function for 8it buswidth
  */
 static void au_write_byte(struct mtd_info *mtd, u_char byte)
 {
@@ -73,11 +73,10 @@ static void au_write_byte(struct mtd_info *mtd, u_char byte)
 }
 
 /**
- * au_read_byte16 -  read one byte endianess aware from the chip
+ * au_read_byte16 -  read one byte endianness aware from the chip
  * @mtd:	MTD device structure
  *
- *  read function for 16bit buswith with
- * endianess conversion
+ * read function for 16bit buswidth with endianness conversion
  */
 static u_char au_read_byte16(struct mtd_info *mtd)
 {
@@ -88,12 +87,11 @@ static u_char au_read_byte16(struct mtd_info *mtd)
 }
 
 /**
- * au_write_byte16 -  write one byte endianess aware to the chip
+ * au_write_byte16 -  write one byte endianness aware to the chip
  * @mtd:	MTD device structure
  * @byte:	pointer to data byte to write
  *
- *  write function for 16bit buswith with
- * endianess conversion
+ * write function for 16bit buswidth with endianness conversion
  */
 static void au_write_byte16(struct mtd_info *mtd, u_char byte)
 {
@@ -106,8 +104,7 @@ static void au_write_byte16(struct mtd_info *mtd, u_char byte)
  * au_read_word -  read one word from the chip
  * @mtd:	MTD device structure
  *
- *  read function for 16bit buswith without
- * endianess conversion
+ * read function for 16bit buswidth without endianness conversion
  */
 static u16 au_read_word(struct mtd_info *mtd)
 {
@@ -123,7 +120,7 @@ static u16 au_read_word(struct mtd_info *mtd)
  * @buf:	data buffer
  * @len:	number of bytes to write
  *
- *  write function for 8bit buswith
+ * write function for 8bit buswidth
  */
 static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -142,7 +139,7 @@ static void au_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
  * @buf:	buffer to store date
  * @len:	number of bytes to read
  *
- *  read function for 8bit buswith
+ * read function for 8bit buswidth
  */
 static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
 {
@@ -161,7 +158,7 @@ static void au_read_buf(struct mtd_info *mtd, u_char *buf, int len)
  * @buf:	buffer containing the data to compare
  * @len:	number of bytes to compare
  *
- *  verify function for 8bit buswith
+ * verify function for 8bit buswidth
  */
 static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -183,7 +180,7 @@ static int au_verify_buf(struct mtd_info *mtd, const u_char *buf, int len)
  * @buf:	data buffer
  * @len:	number of bytes to write
  *
- *  write function for 16bit buswith
+ * write function for 16bit buswidth
  */
 static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
@@ -205,7 +202,7 @@ static void au_write_buf16(struct mtd_info *mtd, const u_char *buf, int len)
  * @buf:	buffer to store date
  * @len:	number of bytes to read
  *
- *  read function for 16bit buswith
+ * read function for 16bit buswidth
  */
 static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
 {
@@ -226,7 +223,7 @@ static void au_read_buf16(struct mtd_info *mtd, u_char *buf, int len)
  * @buf:	buffer containing the data to compare
  * @len:	number of bytes to compare
  *
- *  verify function for 16bit buswith
+ * verify function for 16bit buswidth
  */
 static int au_verify_buf16(struct mtd_info *mtd, const u_char *buf, int len)
 {
diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index db3bfac..661e5dc 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -370,7 +370,7 @@ static int cafe_nand_read_oob(struct mtd_info *mtd, struct nand_chip *chip,
 	return 1;
 }
 /**
- * cafe_nand_read_page_syndrome - {REPLACABLE] hardware ecc syndrom based page read
+ * cafe_nand_read_page_syndrome - [REPLACEABLE] hardware ecc syndrome based page read
  * @mtd:	mtd info structure
  * @chip:	nand chip info structure
  * @buf:	buffer to store read data
diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c
index b657d7f..de93a98 100644
--- a/drivers/mtd/nand/diskonchip.c
+++ b/drivers/mtd/nand/diskonchip.c
@@ -132,7 +132,7 @@ static struct rs_control *rs_decoder;
 
 /*
  * The HW decoder in the DoC ASIC's provides us a error syndrome,
- * which we must convert to a standard syndrom usable by the generic
+ * which we must convert to a standard syndrome usable by the generic
  * Reed-Solomon library code.
  *
  * Fabrice Bellard figured this out in the old docecc code. I added
@@ -153,7 +153,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 	ds[3] = ((ecc[3] & 0xc0) >> 6) | ((ecc[0] & 0xff) << 2);
 	parity = ecc[1];
 
-	/* Initialize the syndrom buffer */
+	/* Initialize the syndrome buffer */
 	for (i = 0; i < NROOTS; i++)
 		s[i] = ds[0];
 	/*
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 0a3cc39..f41d1af 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -21,7 +21,7 @@
  *  TODO:
  *	Enable cached programming for 2k page size chips
  *	Check, if mtd->ecctype should be set to MTD_ECC_HW
- *	if we have HW ecc support.
+ *	if we have HW ECC support.
  *	The AG-AND chips have nice features for speed improvement,
  *	which are not supported yet. Read / program 4 pages in one go.
  *	BBT table is not serialized, has to be fixed
@@ -159,7 +159,7 @@ static void nand_release_device(struct mtd_info *mtd)
  * nand_read_byte - [DEFAULT] read one byte from the chip
  * @mtd: MTD device structure
  *
- * Default read function for 8bit buswith.
+ * Default read function for 8bit buswidth
  */
 static uint8_t nand_read_byte(struct mtd_info *mtd)
 {
@@ -169,9 +169,11 @@ static uint8_t nand_read_byte(struct mtd_info *mtd)
 
 /**
  * nand_read_byte16 - [DEFAULT] read one byte endianess aware from the chip
+ * nand_read_byte16 - [DEFAULT] read one byte endianness aware from the chip
  * @mtd: MTD device structure
  *
- * Default read function for 16bit buswith with endianess conversion.
+ * Default read function for 16bit buswidth with endianness conversion.
+ *
  */
 static uint8_t nand_read_byte16(struct mtd_info *mtd)
 {
@@ -183,7 +185,7 @@ static uint8_t nand_read_byte16(struct mtd_info *mtd)
  * nand_read_word - [DEFAULT] read one word from the chip
  * @mtd: MTD device structure
  *
- * Default read function for 16bit buswith without endianess conversion.
+ * Default read function for 16bit buswidth without endianness conversion.
  */
 static u16 nand_read_word(struct mtd_info *mtd)
 {
@@ -220,7 +222,7 @@ static void nand_select_chip(struct mtd_info *mtd, int chipnr)
  * @buf: data buffer
  * @len: number of bytes to write
  *
- * Default write function for 8bit buswith.
+ * Default write function for 8bit buswidth.
  */
 static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -237,7 +239,7 @@ static void nand_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  * @buf: buffer to store date
  * @len: number of bytes to read
  *
- * Default read function for 8bit buswith.
+ * Default read function for 8bit buswidth.
  */
 static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
@@ -254,7 +256,7 @@ static void nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
  * @buf: buffer containing the data to compare
  * @len: number of bytes to compare
  *
- * Default verify function for 8bit buswith.
+ * Default verify function for 8bit buswidth.
  */
 static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -273,7 +275,7 @@ static int nand_verify_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
  * @buf: data buffer
  * @len: number of bytes to write
  *
- * Default write function for 16bit buswith.
+ * Default write function for 16bit buswidth.
  */
 static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -293,7 +295,7 @@ static void nand_write_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
  * @buf: buffer to store date
  * @len: number of bytes to read
  *
- * Default read function for 16bit buswith.
+ * Default read function for 16bit buswidth.
  */
 static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
 {
@@ -312,7 +314,7 @@ static void nand_read_buf16(struct mtd_info *mtd, uint8_t *buf, int len)
  * @buf: buffer containing the data to compare
  * @len: number of bytes to compare
  *
- * Default verify function for 16bit buswith.
+ * Default verify function for 16bit buswidth.
  */
 static int nand_verify_buf16(struct mtd_info *mtd, const uint8_t *buf, int len)
 {
@@ -499,7 +501,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
 	}
 }
 
-/* Wait for the ready pin, after a command. The timeout is catched later */
+/* Wait for the ready pin, after a command. The timeout is caught later. */
 void nand_wait_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
@@ -510,7 +512,7 @@ void nand_wait_ready(struct mtd_info *mtd)
 		return panic_nand_wait_ready(mtd, 400);
 
 	led_trigger_event(nand_led_trigger, LED_FULL);
-	/* Wait until command is processed or timeout occures */
+	/* Wait until command is processed or timeout occurs */
 	do {
 		if (chip->dev_ready(mtd))
 			break;
@@ -629,8 +631,8 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
  * @page_addr: the page address for this command, -1 if none
  *
  * Send command to NAND device. This is the version for the new large page
- * devices We dont have the separate regions as we have in the small page
- * devices.  We must emulate NAND_CMD_READOOB to keep the code compatible.
+ * devices. We don't have the separate regions as we have in the small page
+ * devices. We must emulate NAND_CMD_READOOB to keep the code compatible.
  */
 static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 			    int column, int page_addr)
@@ -754,7 +756,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 static void panic_nand_get_device(struct nand_chip *chip,
 		      struct mtd_info *mtd, int new_state)
 {
-	/* Hardware controller shared among independend devices */
+	/* Hardware controller shared among independent devices */
 	chip->controller->active = chip;
 	chip->state = new_state;
 }
@@ -1032,14 +1034,13 @@ out:
 EXPORT_SYMBOL(nand_lock);
 
 /**
- * nand_read_page_raw - [Intern] read raw page data without ecc
+ * nand_read_page_raw - [INTERN] read raw page data without ecc
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: buffer to store read data
  * @page: page number to read
  *
- * Not for syndrome calculating ecc controllers, which use a special oob
- * layout.
+ * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 			      uint8_t *buf, int page)
@@ -1050,7 +1051,7 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_page_raw_syndrome - [Intern] read raw page data without ecc
+ * nand_read_page_raw_syndrome - [INTERN] read raw page data without ecc
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: buffer to store read data
@@ -1093,7 +1094,7 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd,
 }
 
 /**
- * nand_read_page_swecc - [REPLACABLE] software ecc based page read function
+ * nand_read_page_swecc - [REPLACEABLE] software ECC based page read function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: buffer to store read data
@@ -1134,7 +1135,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
+ * nand_read_subpage - [REPLACEABLE] software ECC based sub-page read function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @data_offs: offset of requested data within the page
@@ -1152,7 +1153,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 	int busw = (chip->options & NAND_BUSWIDTH_16) ? 2 : 1;
 	int index = 0;
 
-	/* Column address wihin the page aligned to ECC size (256bytes) */
+	/* Column address within the page aligned to ECC size (256bytes) */
 	start_step = data_offs / chip->ecc.size;
 	end_step = (data_offs + readlen - 1) / chip->ecc.size;
 	num_steps = end_step - start_step + 1;
@@ -1175,7 +1176,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 
 	/*
 	 * The performance is faster if we position offsets according to
-	 * ecc.pos. Let's make sure that there are no gaps in ecc positions.
+	 * ecc.pos. Let's make sure that there are no gaps in ECC positions.
 	 */
 	for (i = 0; i < eccfrag_len - 1; i++) {
 		if (eccpos[i + start_step * chip->ecc.bytes] + 1 !=
@@ -1189,7 +1190,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
 	} else {
 		/*
-		 * Send the command to read the particular ecc bytes take care
+		 * Send the command to read the particular ECC bytes take care
 		 * about buswidth alignment in read_buf.
 		 */
 		index = start_step * chip->ecc.bytes;
@@ -1224,14 +1225,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_page_hwecc - [REPLACABLE] hardware ecc based page read function
+ * nand_read_page_hwecc - [REPLACEABLE] hardware ECC based page read function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: buffer to store read data
  * @page: page number to read
  *
- * Not for syndrome calculating ecc controllers which need a special oob
- * layout.
+ * Not for syndrome calculating ECC controllers which need a special oob layout.
  */
 static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 				uint8_t *buf, int page)
@@ -1270,7 +1270,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_page_hwecc_oob_first - [REPLACABLE] hw ecc, read oob first
+ * nand_read_page_hwecc_oob_first - [REPLACEABLE] hw ecc, read oob first
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: buffer to store read data
@@ -1318,7 +1318,7 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
 }
 
 /**
- * nand_read_page_syndrome - [REPLACABLE] hardware ecc syndrom based page read
+ * nand_read_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page read
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: buffer to store read data
@@ -1373,7 +1373,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_transfer_oob - [Internal] Transfer oob to client buffer
+ * nand_transfer_oob - [INTERN] Transfer oob to client buffer
  * @chip: nand chip structure
  * @oob: oob destination address
  * @ops: oob ops structure
@@ -1421,7 +1421,7 @@ static uint8_t *nand_transfer_oob(struct nand_chip *chip, uint8_t *oob,
 }
 
 /**
- * nand_do_read_ops - [Internal] Read data with ECC
+ * nand_do_read_ops - [INTERN] Read data with ECC
  * @mtd: MTD device structure
  * @from: offset to read from
  * @ops: oob ops structure
@@ -1599,7 +1599,7 @@ static int nand_read(struct mtd_info *mtd, loff_t from, size_t len,
 }
 
 /**
- * nand_read_oob_std - [REPLACABLE] the most common OOB data read function
+ * nand_read_oob_std - [REPLACEABLE] the most common OOB data read function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @page: page number to read
@@ -1617,7 +1617,7 @@ static int nand_read_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_read_oob_syndrome - [REPLACABLE] OOB data read function for HW ECC
+ * nand_read_oob_syndrome - [REPLACEABLE] OOB data read function for HW ECC
  *			    with syndromes
  * @mtd: mtd info structure
  * @chip: nand chip info structure
@@ -1656,7 +1656,7 @@ static int nand_read_oob_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_oob_std - [REPLACABLE] the most common OOB data write function
+ * nand_write_oob_std - [REPLACEABLE] the most common OOB data write function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @page: page number to write
@@ -1679,7 +1679,7 @@ static int nand_write_oob_std(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_oob_syndrome - [REPLACABLE] OOB data write function for HW ECC
+ * nand_write_oob_syndrome - [REPLACEABLE] OOB data write function for HW ECC
  *			     with syndrome - only for large page flash
  * @mtd: mtd info structure
  * @chip: nand chip info structure
@@ -1738,7 +1738,7 @@ static int nand_write_oob_syndrome(struct mtd_info *mtd,
 }
 
 /**
- * nand_do_read_oob - [Intern] NAND read out-of-band
+ * nand_do_read_oob - [INTERN] NAND read out-of-band
  * @mtd: MTD device structure
  * @from: offset to read from
  * @ops: oob operations description structure
@@ -1878,13 +1878,12 @@ out:
 
 
 /**
- * nand_write_page_raw - [Intern] raw page write function
+ * nand_write_page_raw - [INTERN] raw page write function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: data buffer
  *
- * Not for syndrome calculating ecc controllers, which use a special oob
- * layout.
+ * Not for syndrome calculating ECC controllers, which use a special oob layout.
  */
 static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 				const uint8_t *buf)
@@ -1894,7 +1893,7 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_page_raw_syndrome - [Intern] raw page write function
+ * nand_write_page_raw_syndrome - [INTERN] raw page write function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: data buffer
@@ -1933,7 +1932,7 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd,
 		chip->write_buf(mtd, oob, size);
 }
 /**
- * nand_write_page_swecc - [REPLACABLE] software ecc based page write function
+ * nand_write_page_swecc - [REPLACEABLE] software ECC based page write function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: data buffer
@@ -1948,7 +1947,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 	const uint8_t *p = buf;
 	uint32_t *eccpos = chip->ecc.layout->eccpos;
 
-	/* Software ecc calculation */
+	/* Software ECC calculation */
 	for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
 		chip->ecc.calculate(mtd, p, &ecc_calc[i]);
 
@@ -1959,7 +1958,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_page_hwecc - [REPLACABLE] hardware ecc based page write function
+ * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: data buffer
@@ -1987,7 +1986,7 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_write_page_syndrome - [REPLACABLE] hardware ecc syndrom based page write
+ * nand_write_page_syndrome - [REPLACEABLE] hardware ECC syndrome based page write
  * @mtd: mtd info structure
  * @chip: nand chip info structure
  * @buf: data buffer
@@ -2052,7 +2051,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 		chip->ecc.write_page(mtd, chip, buf);
 
 	/*
-	 * Cached progamming disabled for now, Not sure if its worth the
+	 * Cached progamming disabled for now. Not sure if it's worth the
 	 * trouble. The speed gain is not very impressive. (2.3->2.6Mib/s).
 	 */
 	cached = 0;
@@ -2087,7 +2086,7 @@ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_fill_oob - [Internal] Transfer client buffer to oob
+ * nand_fill_oob - [INTERN] Transfer client buffer to oob
  * @mtd: MTD device structure
  * @oob: oob data buffer
  * @len: oob data write length
@@ -2145,7 +2144,7 @@ static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
 #define NOTALIGNED(x)	((x & (chip->subpagesize - 1)) != 0)
 
 /**
- * nand_do_write_ops - [Internal] NAND write with ECC
+ * nand_do_write_ops - [INTERN] NAND write with ECC
  * @mtd: MTD device structure
  * @to: offset to write to
  * @ops: oob operations description structure
@@ -2451,7 +2450,7 @@ out:
 }
 
 /**
- * single_erease_cmd - [GENERIC] NAND standard block erase command function
+ * single_erase_cmd - [GENERIC] NAND standard block erase command function
  * @mtd: MTD device structure
  * @page: the page address of the block which will be erased
  *
@@ -2466,7 +2465,7 @@ static void single_erase_cmd(struct mtd_info *mtd, int page)
 }
 
 /**
- * multi_erease_cmd - [GENERIC] AND specific block erase command function
+ * multi_erase_cmd - [GENERIC] AND specific block erase command function
  * @mtd: MTD device structure
  * @page: the page address of the block which will be erased
  *
@@ -2497,7 +2496,7 @@ static int nand_erase(struct mtd_info *mtd, struct erase_info *instr)
 
 #define BBT_PAGE_MASK	0xffffff3f
 /**
- * nand_erase_nand - [Internal] erase block(s)
+ * nand_erase_nand - [INTERN] erase block(s)
  * @mtd: MTD device structure
  * @instr: erase instruction
  * @allowbbt: allow erasing the bbt area
@@ -2547,7 +2546,7 @@ int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
 	 * If BBT requires refresh, set the BBT page mask to see if the BBT
 	 * should be rewritten. Otherwise the mask is set to 0xffffffff which
 	 * can not be matched. This is also done when the bbt is actually
-	 * erased to avoid recusrsive updates.
+	 * erased to avoid recursive updates.
 	 */
 	if (chip->options & BBT_AUTO_REFRESH && !allowbbt)
 		bbt_masked_page = chip->bbt_td->pages[chipnr] & BBT_PAGE_MASK;
@@ -2821,7 +2820,7 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 	int i;
 	int val;
 
-	/* Try ONFI for unknow chip or LP */
+	/* Try ONFI for unknown chip or LP */
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1);
 	if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' ||
 		chip->read_byte(mtd) != 'F' || chip->read_byte(mtd) != 'I')
@@ -3392,7 +3391,7 @@ int nand_scan_tail(struct mtd_info *mtd)
 	 */
 	chip->ecc.steps = mtd->writesize / chip->ecc.size;
 	if (chip->ecc.steps * chip->ecc.size != mtd->writesize) {
-		printk(KERN_WARNING "Invalid ecc parameters\n");
+		printk(KERN_WARNING "Invalid ECC parameters\n");
 		BUG();
 	}
 	chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index 8875d6d..f30807c 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -149,7 +149,7 @@ static int check_short_pattern(uint8_t *buf, struct nand_bbt_descr *td)
  * add_marker_len - compute the length of the marker in data area
  * @td: BBT descriptor used for computation
  *
- * The length will be 0 if the markeris located in OOB area.
+ * The length will be 0 if the marker is located in OOB area.
  */
 static u32 add_marker_len(struct nand_bbt_descr *td)
 {
@@ -170,7 +170,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
  * @buf: temporary buffer
  * @page: the starting page
  * @num: the number of bbt descriptors to read
- * @td:	 the bbt describtion table
+ * @td: the bbt describtion table
  * @offs: offset in the memory table
  *
  * Read the bad block table starting from page.
@@ -1241,7 +1241,7 @@ static struct nand_bbt_descr agand_flashbased = {
 	.pattern = scan_agand_pattern
 };
 
-/* Generic flash bbt decriptors */
+/* Generic flash bbt descriptors */
 static uint8_t bbt_pattern[] = {'B', 'b', 't', '0' };
 static uint8_t mirror_pattern[] = {'1', 't', 'b', 'B' };
 
@@ -1286,7 +1286,7 @@ static struct nand_bbt_descr bbt_mirror_no_bbt_descr = {
 };
 
 /**
- * nand_create_default_bbt_descr - [Internal] Creates a BBT descriptor structure
+ * nand_create_default_bbt_descr - [INTERN] Creates a BBT descriptor structure
  * @this: NAND chip to create descriptor for
  *
  * This function allocates and initializes a nand_bbt_descr for BBM detection
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 271b8e7..b7cfe0d 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -110,7 +110,7 @@ static const char bitsperbyte[256] = {
 
 /*
  * addressbits is a lookup table to filter out the bits from the xor-ed
- * ecc data that identify the faulty location.
+ * ECC data that identify the faulty location.
  * this is only used for repairing parity
  * see the comments in nand_correct_data for more details
  */
@@ -153,7 +153,7 @@ static const char addressbits[256] = {
  * __nand_calculate_ecc - [NAND Interface] Calculate 3-byte ECC for 256/512-byte
  *			 block
  * @buf:	input buffer with raw data
- * @eccsize:	data bytes per ecc step (256 or 512)
+ * @eccsize:	data bytes per ECC step (256 or 512)
  * @code:	output buffer with ECC
  */
 void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
@@ -348,7 +348,7 @@ void __nand_calculate_ecc(const unsigned char *buf, unsigned int eccsize,
 		rp17 = (par ^ rp16) & 0xff;
 
 	/*
-	 * Finally calculate the ecc bits.
+	 * Finally calculate the ECC bits.
 	 * Again here it might seem that there are performance optimisations
 	 * possible, but benchmarks showed that on the system this is developed
 	 * the code below is the fastest
@@ -436,7 +436,7 @@ EXPORT_SYMBOL(nand_calculate_ecc);
  * @buf:	raw data read from the chip
  * @read_ecc:	ECC from the chip
  * @calc_ecc:	the ECC calculated from raw data
- * @eccsize:	data bytes per ecc step (256 or 512)
+ * @eccsize:	data bytes per ECC step (256 or 512)
  *
  * Detect and correct a 1 bit error for eccsize byte block
  */
@@ -505,7 +505,7 @@ int __nand_correct_data(unsigned char *buf,
 	}
 	/* count nr of bits; use table lookup, faster than calculating it */
 	if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
-		return 1;	/* error in ecc data; no action needed */
+		return 1;	/* error in ECC data; no action needed */
 
 	printk(KERN_ERR "uncorrectable error : ");
 	return -1;
diff --git a/drivers/mtd/nand/rtc_from4.c b/drivers/mtd/nand/rtc_from4.c
index a07da2a..33fe922 100644
--- a/drivers/mtd/nand/rtc_from4.c
+++ b/drivers/mtd/nand/rtc_from4.c
@@ -351,7 +351,7 @@ static int rtc_from4_correct_data(struct mtd_info *mtd, const u_char *buf, u_cha
 		return 0;
 	}
 
-	/* Read the syndrom pattern from the FPGA and correct the bitorder */
+	/* Read the syndrome pattern from the FPGA and correct the bitorder */
 	rs_ecc = (volatile unsigned short *)(rtc_from4_fio_base + RTC_FROM4_RS_ECC);
 	for (i = 0; i < 8; i++) {
 		ecc[i] = bitrev8(*rs_ecc);
diff --git a/drivers/mtd/onenand/onenand_base.c b/drivers/mtd/onenand/onenand_base.c
index ac9e959..5ac37d6 100644
--- a/drivers/mtd/onenand/onenand_base.c
+++ b/drivers/mtd/onenand/onenand_base.c
@@ -1015,7 +1015,7 @@ static void onenand_release_device(struct mtd_info *mtd)
 }
 
 /**
- * onenand_transfer_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_transfer_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd		MTD device structure
  * @param buf		destination address
  * @param column	oob offset to read from
@@ -1821,7 +1821,7 @@ static int onenand_panic_write(struct mtd_info *mtd, loff_t to, size_t len,
 }
 
 /**
- * onenand_fill_auto_oob - [Internal] oob auto-placement transfer
+ * onenand_fill_auto_oob - [INTERN] oob auto-placement transfer
  * @param mtd		MTD device structure
  * @param oob_buf	oob buffer
  * @param buf		source address
@@ -2055,7 +2055,7 @@ static int onenand_write_ops_nolock(struct mtd_info *mtd, loff_t to,
 
 
 /**
- * onenand_write_oob_nolock - [Internal] OneNAND write out-of-band
+ * onenand_write_oob_nolock - [INTERN] OneNAND write out-of-band
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
@@ -2281,7 +2281,7 @@ static int onenand_multiblock_erase_verify(struct mtd_info *mtd,
 }
 
 /**
- * onenand_multiblock_erase - [Internal] erase block(s) using multiblock erase
+ * onenand_multiblock_erase - [INTERN] erase block(s) using multiblock erase
  * @param mtd		MTD device structure
  * @param instr		erase instruction
  * @param region	erase region
@@ -2397,7 +2397,7 @@ static int onenand_multiblock_erase(struct mtd_info *mtd,
 
 
 /**
- * onenand_block_by_block_erase - [Internal] erase block(s) using regular erase
+ * onenand_block_by_block_erase - [INTERN] erase block(s) using regular erase
  * @param mtd		MTD device structure
  * @param instr		erase instruction
  * @param region	erase region
@@ -2922,7 +2922,7 @@ static int onenand_otp_command(struct mtd_info *mtd, int cmd, loff_t addr,
 }
 
 /**
- * onenand_otp_write_oob_nolock - [Internal] OneNAND write out-of-band, specific to OTP
+ * onenand_otp_write_oob_nolock - [INTERN] OneNAND write out-of-band, specific to OTP
  * @param mtd		MTD device structure
  * @param to		offset to write to
  * @param len		number of bytes to write
diff --git a/drivers/mtd/sm_ftl.c b/drivers/mtd/sm_ftl.c
index ed3d6cd..a8befde 100644
--- a/drivers/mtd/sm_ftl.c
+++ b/drivers/mtd/sm_ftl.c
@@ -138,7 +138,7 @@ static int sm_get_lba(uint8_t *lba)
 	if ((lba[0] & 0xF8) != 0x10)
 		return -2;
 
-	/* check parity - endianess doesn't matter */
+	/* check parity - endianness doesn't matter */
 	if (hweight16(*(uint16_t *)lba) & 1)
 		return -2;
 
diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
index b2b454b..db8a2b0 100644
--- a/include/linux/mtd/mtd.h
+++ b/include/linux/mtd/mtd.h
@@ -172,7 +172,7 @@ struct mtd_info {
 	const char *name;
 	int index;
 
-	/* ecc layout structure pointer - read only ! */
+	/* ECC layout structure pointer - read only! */
 	struct nand_ecclayout *ecclayout;
 
 	/* Data for variable erase regions. If numeraseregions is zero,
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index da6e252..38a2fb6 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -42,10 +42,10 @@ extern void nand_release(struct mtd_info *mtd);
 /* Internal helper for board drivers which need to override command function */
 extern void nand_wait_ready(struct mtd_info *mtd);
 
-/* locks all blockes present in the device */
+/* locks all blocks present in the device */
 extern int nand_lock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
-/* unlocks specified locked blockes */
+/* unlocks specified locked blocks */
 extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, uint64_t len);
 
 /* The maximum number of NAND chips in an array */
@@ -150,7 +150,7 @@ typedef enum {
 #define NAND_ECC_READ		0
 /* Reset Hardware ECC for write */
 #define NAND_ECC_WRITE		1
-/* Enable Hardware ECC before syndrom is read back from flash */
+/* Enable Hardware ECC before syndrome is read back from flash */
 #define NAND_ECC_READSYN	2
 
 /* Bit mask for flags passed to do_nand_read_ecc */
@@ -163,7 +163,7 @@ typedef enum {
  */
 /* Chip can not auto increment pages */
 #define NAND_NO_AUTOINCR	0x00000001
-/* Buswitdh is 16 bit */
+/* Buswidth is 16 bit */
 #define NAND_BUSWIDTH_16	0x00000002
 /* Device supports partial programming without padding */
 #define NAND_NO_PADDING		0x00000004
@@ -319,26 +319,26 @@ struct nand_hw_control {
 };
 
 /**
- * struct nand_ecc_ctrl - Control structure for ecc
- * @mode:	ecc mode
- * @steps:	number of ecc steps per page
- * @size:	data bytes per ecc step
- * @bytes:	ecc bytes per step
- * @total:	total number of ecc bytes per page
- * @prepad:	padding information for syndrome based ecc generators
- * @postpad:	padding information for syndrome based ecc generators
+ * struct nand_ecc_ctrl - Control structure for ECC
+ * @mode:	ECC mode
+ * @steps:	number of ECC steps per page
+ * @size:	data bytes per ECC step
+ * @bytes:	ECC bytes per step
+ * @total:	total number of ECC bytes per page
+ * @prepad:	padding information for syndrome based ECC generators
+ * @postpad:	padding information for syndrome based ECC generators
  * @layout:	ECC layout control struct pointer
- * @priv:	pointer to private ecc control data
- * @hwctl:	function to control hardware ecc generator. Must only
+ * @priv:	pointer to private ECC control data
+ * @hwctl:	function to control hardware ECC generator. Must only
  *		be provided if an hardware ECC is available
- * @calculate:	function for ecc calculation or readback from ecc hardware
- * @correct:	function for ecc correction, matching to ecc generator (sw/hw)
+ * @calculate:	function for ECC calculation or readback from ECC hardware
+ * @correct:	function for ECC correction, matching to ECC generator (sw/hw)
  * @read_page_raw:	function to read a raw page without ECC
  * @write_page_raw:	function to write a raw page without ECC
- * @read_page:	function to read a page according to the ecc generator
+ * @read_page:	function to read a page according to the ECC generator
  *		requirements.
  * @read_subpage:	function to read parts of the page covered by ECC.
- * @write_page:	function to write a page according to the ecc generator
+ * @write_page:	function to write a page according to the ECC generator
  *		requirements.
  * @read_oob:	function to read chip OOB data
  * @write_oob:	function to write chip OOB data
@@ -376,8 +376,8 @@ struct nand_ecc_ctrl {
 
 /**
  * struct nand_buffers - buffer structure for read/write
- * @ecccalc:	buffer for calculated ecc
- * @ecccode:	buffer for ecc read from flash
+ * @ecccalc:	buffer for calculated ECC
+ * @ecccode:	buffer for ECC read from flash
  * @databuf:	buffer for data - dynamically sized
  *
  * Do not change the order of buffers. databuf and oobrbuf must be in
@@ -410,7 +410,7 @@ struct nand_buffers {
  *			mtd->oobsize, mtd->writesize and so on.
  *			@id_data contains the 8 bytes values of NAND_CMD_READID.
  *			Return with the bus width.
- * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accesing
+ * @dev_ready:		[BOARDSPECIFIC] hardwarespecific function for accessing
  *			device ready/busy line. If set to NULL no access to
  *			ready/busy is available and the ready/busy information
  *			is read from the chip status register.
@@ -418,7 +418,7 @@ struct nand_buffers {
  *			commands to the chip.
  * @waitfunc:		[REPLACEABLE] hardwarespecific function for wait on
  *			ready.
- * @ecc:		[BOARDSPECIFIC] ecc control ctructure
+ * @ecc:		[BOARDSPECIFIC] ECC control structure
  * @buffers:		buffer structure for read/write
  * @hwcontrol:		platform-specific hardware control structure
  * @ops:		oob operation operands
@@ -455,7 +455,7 @@ struct nand_buffers {
  *			non 0 if ONFI supported.
  * @onfi_params:	[INTERN] holds the ONFI page parameter when ONFI is
  *			supported, 0 otherwise.
- * @ecclayout:		[REPLACEABLE] the default ecc placement scheme
+ * @ecclayout:		[REPLACEABLE] the default ECC placement scheme
  * @bbt:		[INTERN] bad block table pointer
  * @bbt_td:		[REPLACEABLE] bad block table descriptor for flash
  *			lookup.
@@ -463,7 +463,7 @@ struct nand_buffers {
  * @badblock_pattern:	[REPLACEABLE] bad block scan pattern used for initial
  *			bad block scan.
  * @controller:		[REPLACEABLE] a pointer to a hardware controller
- *			structure which is shared among multiple independend
+ *			structure which is shared among multiple independent
  *			devices.
  * @priv:		[OPTIONAL] pointer to private chip date
  * @errstat:		[OPTIONAL] hardware specific function to perform
@@ -603,7 +603,7 @@ extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
  * @partitions:		mtd partition list
  * @chip_delay:		R/B delay value in us
  * @options:		Option flags, e.g. 16bit buswidth
- * @ecclayout:		ecc layout info structure
+ * @ecclayout:		ECC layout info structure
  * @part_probe_types:	NULL-terminated array of probe types
  * @set_parts:		platform specific function to set partitions
  * @priv:		hardware controller specific settings
-- 
1.7.0.4




From computersforpeace at gmail.com  Thu Jun 23 19:00:37 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 16:00:37 -0700
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron>
	<1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
Message-ID: <BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>

On Thu, Jun 23, 2011 at 8:52 AM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> On Thu, Jun 23, 2011 at 11:04, Artem Bityutskiy wrote:
>> And speaking about released, should we do a new one?

Yes, I think so. Then I can eliminate all those warnings and finish my changes!

>> If you see that
>> some utils should have a version increased - feel free to do so.

I think the nanddump, mtdinfo, and flash_{lock, unlock} tools have had
plenty of updates to warrant a bump...but flash_{lock, unlock} doesn't
have a version number (neither do many of the utils). I'll send a
patch for bumping soon...then should the release tag come afterward?

>> But
>> even better we could make the version numbers to be the same as release
>> number, then this process would be more automated and version would make
>> some sense...
>
> the version isnt encoded anywhere. ?so if you started using something
> like the kernel where the VERSION was in the Makefile, we could use
> that to create a header file which all the utils would include.
> -mike
>

I like Mike's idea on the VERSION thing. Unfortunately, few utils
display any version number at all, and of the ones that do, we have a
random "2.1.0" from flash_erase. We wouldn't want to have a decreased
version number...so do we jump to mtd-utils v2.1 and make everything
the same version? Or even v3.0, just for fun?

If we're going for 2.1 (or some other similarly large jump), maybe we
should do the following:
1) increment some individual version numbers (nanddump and mtdinfo only?)
2) make a mtd-utils release 1.4.6
3) take care of all the "feature-removal-schedule" stuff...
4) put the VERSION in the Makefile (still version 1.4.6), have it
generate a header
5) include that header in common.h
6) add a stub version function in common.h that would utilize this
basic info to supply a "--version" option to all utilities that don't
have one (at least, as far as reasonable...)
7) release another mtd-utils, jumping to v2.x (only needing to edit
Makefile for version increments!)

How does this sound?

Brian


From computersforpeace at gmail.com  Thu Jun 23 19:09:47 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 16:09:47 -0700
Subject: [PATCH] mtd-utils: bump nanddump, mtdinfo version numbers
Message-ID: <1308870587-5300-1-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c              |    2 +-
 ubi-utils/src/mtdinfo.c |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 54cb1af..0367d83 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -14,7 +14,7 @@
  */
 
 #define PROGRAM_NAME "nanddump"
-#define VERSION "1.30"
+#define VERSION "1.31"
 
 #define _GNU_SOURCE
 #include <ctype.h>
diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
index b6077e4..bfd7e6d 100644
--- a/ubi-utils/src/mtdinfo.c
+++ b/ubi-utils/src/mtdinfo.c
@@ -21,7 +21,7 @@
  * Author: Artem Bityutskiy
  */
 
-#define PROGRAM_VERSION "1.0"
+#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "mtdinfo"
 
 #include <stdint.h>
-- 
1.7.0.4




From vapier.adi at gmail.com  Thu Jun 23 19:14:03 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 23 Jun 2011 19:14:03 -0400
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
Message-ID: <BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>

On Thu, Jun 23, 2011 at 19:00, Brian Norris wrote:
> Unfortunately, few utils display any version number at all

i've been pondering unifying common options so all tools have the same
behavior.  for example, all utils should work the same with the basic
flags:
-h --help
-V --version
-v --verbose

it's bad enough when these deviate across projects, but even within a
project is even more obnoxious.

> and of the ones that do, we have a
> random "2.1.0" from flash_erase. We wouldn't want to have a decreased
> version number...so do we jump to mtd-utils v2.1 and make everything
> the same version? Or even v3.0, just for fun?

i dont think anyone has scripts parsing these things.  i say let's
just lock them all to the mtd release and forget about it.
-mike


From computersforpeace at gmail.com  Thu Jun 23 19:27:17 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 16:27:17 -0700
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron>
	<1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
Message-ID: <BANLkTinXV-5GWzxn5EoGAfSe2fTWEGjQZw@mail.gmail.com>

On Thu, Jun 23, 2011 at 4:14 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> i've been pondering unifying common options so all tools have the same
> behavior. ?for example, all utils should work the same with the basic
> flags:
> -h --help
> -V --version
> -v --verbose
>
> it's bad enough when these deviate across projects, but even within a
> project is even more obnoxious.

Sounds fine. You wanna take care of that? ;)

>> and of the ones that do, we have a
>> random "2.1.0" from flash_erase. We wouldn't want to have a decreased
>> version number...so do we jump to mtd-utils v2.1 and make everything
>> the same version? Or even v3.0, just for fun?
>
> i dont think anyone has scripts parsing these things. ?i say let's
> just lock them all to the mtd release and forget about it.

OK. So my list's step 7 would just have us jump to 1.4.7 and stick all
utils to that version.

I got the ball rolling with a patch incrementing nanddump and mtdinfo
versions. Then a maintainer can take step 2 on my list (i.e., tag the
release), and Mike and I can hack away at feature-removal...

Brian


From vapier.adi at gmail.com  Thu Jun 23 19:36:41 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 23 Jun 2011 19:36:41 -0400
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTinXV-5GWzxn5EoGAfSe2fTWEGjQZw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
	<BANLkTinXV-5GWzxn5EoGAfSe2fTWEGjQZw@mail.gmail.com>
Message-ID: <BANLkTi=ZW99673rk-03VDHWb7aoUf1LFtQ@mail.gmail.com>

On Thu, Jun 23, 2011 at 19:27, Brian Norris wrote:
> On Thu, Jun 23, 2011 at 4:14 PM, Mike Frysinger wrote:
>> i've been pondering unifying common options so all tools have the same
>> behavior. ?for example, all utils should work the same with the basic
>> flags:
>> -h --help
>> -V --version
>> -v --verbose
>>
>> it's bad enough when these deviate across projects, but even within a
>> project is even more obnoxious.
>
> Sounds fine. You wanna take care of that? ;)

i'll take a peek as i've done this before with other projects

> OK. So my list's step 7 would just have us jump to 1.4.7 and stick all
> utils to that version.

did someone forget to tag/push v1.4.[56] ?  i dont see it in the git repo.
-mike


From computersforpeace at gmail.com  Thu Jun 23 19:40:36 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 16:40:36 -0700
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=ZW99673rk-03VDHWb7aoUf1LFtQ@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron>
	<1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
	<BANLkTinXV-5GWzxn5EoGAfSe2fTWEGjQZw@mail.gmail.com>
	<BANLkTi=ZW99673rk-03VDHWb7aoUf1LFtQ@mail.gmail.com>
Message-ID: <BANLkTin5jFjjB=o1nhDD=_pB9MQ-cLxm5Q@mail.gmail.com>

On Thu, Jun 23, 2011 at 4:36 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> did someone forget to tag/push v1.4.[56] ? ?i dont see it in the git repo.

No, that was my step 2 :) Let me know if the steps are unreasonable.

Brian


From vapier.adi at gmail.com  Thu Jun 23 19:45:53 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Thu, 23 Jun 2011 19:45:53 -0400
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTin5jFjjB=o1nhDD=_pB9MQ-cLxm5Q@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
	<BANLkTinXV-5GWzxn5EoGAfSe2fTWEGjQZw@mail.gmail.com>
	<BANLkTi=ZW99673rk-03VDHWb7aoUf1LFtQ@mail.gmail.com>
	<BANLkTin5jFjjB=o1nhDD=_pB9MQ-cLxm5Q@mail.gmail.com>
Message-ID: <BANLkTimM1YgPru1ksPNNxYNpVYHRbrCEDQ@mail.gmail.com>

On Thu, Jun 23, 2011 at 19:40, Brian Norris wrote:
> On Thu, Jun 23, 2011 at 4:36 PM, Mike Frysinger wrote:
>> did someone forget to tag/push v1.4.[56] ? ?i dont see it in the git repo.
>
> No, that was my step 2 :) Let me know if the steps are unreasonable.

i misread that.  but where's 1.4.5 ? :)
-mike


From computersforpeace at gmail.com  Thu Jun 23 19:45:24 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 16:45:24 -0700
Subject: [PATCH] mtd: nand: handle ECC errors in OOB
Message-ID: <1308872724-6196-1-git-send-email-computersforpeace@gmail.com>

While the standard NAND OOB functions do not do ECC on the spare area,
it is possible for a driver to supply its own OOB ECC functions (e.g., HW
ECC). nand_do_read_oob should act like nand_do_read_ops in checking the
ECC stats and returning -EBADMSG or -EUCLEAN on uncorrectable errors or
correctable bitflips, respectively. These error codes could be used in
flash-based BBT code or in YAFFS, for example.

Doing this, however, messes with the behavior of mtd_do_readoob. Now,
mtd_do_readoob should check whether we had -EUCLEAN or -EBADMSG errors
and discard those as "non-fatal" so that the ioctls can still succeed
with (possibly uncorrected) data.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/mtdchar.c        |   15 +++++++++++++++
 drivers/mtd/nand/nand_base.c |    9 ++++++++-
 2 files changed, 23 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 3f92731..8a45525 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -472,6 +472,21 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
 		ret = -EFAULT;
 
 	kfree(ops.oobbuf);
+
+	/*
+	 * NAND returns -EBADMSG on ECC errors, but it returns the OOB
+	 * data. For our userspace tools it is important to dump areas
+	 * with ECC errors!
+	 * For kernel internal usage it also might return -EUCLEAN
+	 * to signal the caller that a bitflip has occured and has
+	 * been corrected by the ECC algorithm.
+	 *
+	 * Note: most NAND ECC algorithms do not calculate ECC
+	 * for the OOB area.
+	 */
+	if (ret == -EUCLEAN || ret == -EBADMSG)
+		return 0;
+
 	return ret;
 }
 
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a46e9bb..f0ba2da 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1761,6 +1761,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 {
 	int page, realpage, chipnr, sndcmd = 1;
 	struct nand_chip *chip = mtd->priv;
+	struct mtd_ecc_stats stats;
 	int blkcheck = (1 << (chip->phys_erase_shift - chip->page_shift)) - 1;
 	int readlen = ops->ooblen;
 	int len;
@@ -1769,6 +1770,8 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 	DEBUG(MTD_DEBUG_LEVEL3, "%s: from = 0x%08Lx, len = %i\n",
 			__func__, (unsigned long long)from, readlen);
 
+	stats = mtd->ecc_stats;
+
 	if (ops->mode == MTD_OOB_AUTO)
 		len = chip->ecc.layout->oobavail;
 	else
@@ -1838,7 +1841,11 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 	}
 
 	ops->oobretlen = ops->ooblen;
-	return 0;
+
+	if (mtd->ecc_stats.failed - stats.failed)
+		return -EBADMSG;
+
+	return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
 }
 
 /**
-- 
1.7.0.4




From computersforpeace at gmail.com  Thu Jun 23 19:48:04 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Thu, 23 Jun 2011 16:48:04 -0700
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTimM1YgPru1ksPNNxYNpVYHRbrCEDQ@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron>
	<1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
	<BANLkTinXV-5GWzxn5EoGAfSe2fTWEGjQZw@mail.gmail.com>
	<BANLkTi=ZW99673rk-03VDHWb7aoUf1LFtQ@mail.gmail.com>
	<BANLkTin5jFjjB=o1nhDD=_pB9MQ-cLxm5Q@mail.gmail.com>
	<BANLkTimM1YgPru1ksPNNxYNpVYHRbrCEDQ@mail.gmail.com>
Message-ID: <BANLkTikYsCtgb80mPzZZ95QuOPzd7H0cgQ@mail.gmail.com>

On Thu, Jun 23, 2011 at 4:45 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> On Thu, Jun 23, 2011 at 19:40, Brian Norris wrote:
>> On Thu, Jun 23, 2011 at 4:36 PM, Mike Frysinger wrote:
>>> did someone forget to tag/push v1.4.[56] ? ?i dont see it in the git repo.
>>
>> No, that was my step 2 :) Let me know if the steps are unreasonable.
>
> i misread that. ?but where's 1.4.5 ? :)

I guess I miswrote that. Step 2 should be 1.4.5 and Step 7 should be
1.4.6. Silly me.


From jacmet at sunsite.dk  Fri Jun 24 07:46:29 2011
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Fri, 24 Jun 2011 13:46:29 +0200
Subject: [Ubi] Wrong major:minor
In-Reply-To: <BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com> (Mike
	Frysinger's message of "Wed, 1 Jun 2011 06:11:49 -0400")
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
	<1306917455.4405.77.camel@localhost>
	<BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com>
Message-ID: <87mxh78nai.fsf@macbook.be.48ers.dk>

>>>>> "Mike" == Mike Frysinger <vapier.adi at gmail.com> writes:

Hi,

 >> Although I'm not sure - dynamic numbers were introduced because
 >> fixed numbers are PITA, so adding such a parameter would be a step
 >> backward.  Not sure...

 Mike> yeah, i dont think there should be.  at least nothing specific to
 Mike> ubi.  perhaps a general kernel thing where you could match the
 Mike> registered name to a static #, but then that wouldnt be ubi's
 Mike> problem.  that'd be in the core logic and work for all devices.

That already exists - CONFIG_DEVTMPFS.

-- 
Bye, Peter Korsgaard


From gilles.ganault at free.fr  Fri Jun 24 08:05:13 2011
From: gilles.ganault at free.fr (Gilles)
Date: Fri, 24 Jun 2011 14:05:13 +0200
Subject: [Ubi] Wrong major:minor
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
	<1306917455.4405.77.camel@localhost>
	<BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com>
	<87mxh78nai.fsf@macbook.be.48ers.dk>
Message-ID: <8av807po08nju08nd167d549hios21adn1@4ax.com>

On Fri, 24 Jun 2011 13:46:29 +0200, Peter Korsgaard
<jacmet at sunsite.dk> wrote:
>>>>> "Mike" == Mike Frysinger <vapier.adi at gmail.com> writes:
> Mike> yeah, i dont think there should be.  at least nothing specific to
> Mike> ubi.  perhaps a general kernel thing where you could match the
> Mike> registered name to a static #, but then that wouldnt be ubi's
> Mike> problem.  that'd be in the core logic and work for all devices.
>
>That already exists - CONFIG_DEVTMPFS.

Thanks for the tip. Turns out mdev is fast enough to create the dev
nodes at run-time, but it's good to know there's an alternative.



From dedekind1 at gmail.com  Fri Jun 24 08:07:02 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 15:07:02 +0300
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
In-Reply-To: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
References: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
Message-ID: <1308917226.7715.6.camel@koala>

On Wed, 2011-06-22 at 01:02 -0400, Mike Frysinger wrote:
> the current mkfs.jffs2 util has in its --eraseblock handling:
> /* If it's less than 8KiB, they're not allowed */
> if (erase_block_size < 0x2000) {
>     fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
>         erase_block_size);
>     erase_block_size = 0x2000;
> }
> 
> but i cant seem to find documentation on where this comes from.  it's
> not uncommon to have SPI flashes with 4KiB erase sectors, and removing
> this sanity check and allowing 4 KiB seems to produce an image that
> works OK.
> 
> am i missing something ?  or should i send a patch to drop this check ?

I do not believe JFFS2 is able to work with such small erase blocks. In
JFFS2 (and in UBIFS as well) an eraseblock is the basic garbage
collection unit, and nodes cannot cross eraseblock boundaries. And the
maximum node size is 4KiB of data plus few bytes of node header. So 4KiB
won't even fit the largest data node, e.g., containing uncompressible
data.

Even 8KiB is bad, because the amount of wasted space will be large -
JFFS2 will waste the rest of the eraseblock if it does not fit the node.
So the smaller EB is, the more wasted space you have.

For SPI flashes the way out is to emulate larger eraseblock sizes on MTD
level. I'd recommend at least 32 KiB.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 08:16:30 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 15:16:30 +0300
Subject: [PATCH v2] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <20110622051649.GA19948@july>
References: <20110622051649.GA19948@july>
Message-ID: <1308917793.7715.8.camel@koala>

On Wed, 2011-06-22 at 14:16 +0900, Kyungmin Park wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> There are two different 4KiB pagesize chips
> KFM4G16Q4M series have NOP 4 with version ID 0x0131
> But KFM4G16Q5M has NOP 1 with versoin ID 0x013e
> 
> Note that Q5M means that it has NOP 1.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From kmpark at infradead.org  Fri Jun 24 08:20:38 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Fri, 24 Jun 2011 21:20:38 +0900
Subject: [PATCH v2] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <1308917793.7715.8.camel@koala>
References: <20110622051649.GA19948@july>
	<1308917793.7715.8.camel@koala>
Message-ID: <BANLkTinbS1fk=eM6=ANssed7jKih3w=vzw@mail.gmail.com>

On Fri, Jun 24, 2011 at 9:16 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Wed, 2011-06-22 at 14:16 +0900, Kyungmin Park wrote:
>> From: Kyungmin Park <kyungmin.park at samsung.com>
>>
>> There are two different 4KiB pagesize chips
>> KFM4G16Q4M series have NOP 4 with version ID 0x0131
>> But KFM4G16Q5M has NOP 1 with versoin ID 0x013e
>>
>> Note that Q5M means that it has NOP 1.
>>
>> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
>
> Pushed to l2-mtd-2.6.git, thanks.

Hi Artem,

It's required for s5pc110 series and supported at previous kernel, I
mean it's bug fixed.
So please merge it 3.0-rc periods

Thank you,
Kyungmin Park
>
> --
> Best Regards,
> Artem Bityutskiy (???????? ?????)
>
>


From david.wagner at free-electrons.com  Fri Jun 24 09:34:41 2011
From: david.wagner at free-electrons.com (david.wagner at free-electrons.com)
Date: Fri, 24 Jun 2011 15:34:41 +0200
Subject: [RFC] ubiblk: read-only block layer on top of UBI
Message-ID: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>

From: David Wagner <david.wagner at free-electrons.com>

It creates one device for each UBI volume and dynamically add/remove one when a
UBI volume is created or deleted : it registers to UBI notifications.  The
devices are names "ubiblkX_Y" where X is the UBI device number and Y is the
volume ID.

I'm submitting it for review, comments (on the concept as well as on the
implementation) and advice.  It is my first kernel module - a lot of code was
taken from mtd_blkdevs and some from gluebi.

It is only known to work well with SquashFS.  Tests reported that with other
filesystems (ext2/3 and vfat), some bytes in some files (I couldn't find any
pattern), when read through ubiblk, don't match the original content (the
content of a file becomes random on several "lines" and goes back to normal).
The reason for that is still unknown.

Some other known issues are listed in the commit message.

 drivers/mtd/ubi/Kconfig  |    9 +
 drivers/mtd/ubi/Makefile |    1 +
 drivers/mtd/ubi/ubiblk.c |  462 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 472 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/ubi/ubiblk.c

--
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From david.wagner at free-electrons.com  Fri Jun 24 09:34:42 2011
From: david.wagner at free-electrons.com (david.wagner at free-electrons.com)
Date: Fri, 24 Jun 2011 15:34:42 +0200
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
Message-ID: <1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>

From: David Wagner <david.wagner at free-electrons.com>

ubiblk is a read-only block layer on top of UBI.  It presents UBI volumes as
read-only block devices.

It is used by putting a block filesystem image on a UBI volume and then mounting
the corresponding device.

It uses the UBI API to register to UBI notifications (to dynamically create and
delete devices as volumes are added or removed) and to read from the volumes.

Known issues:
 * UBI_VOLUME_RESIZED notification hook isn't implemented yet ;

 * only squashfs is known to work. With ext2/3 and vfat, errors appear randomly
   in the middle of some files.  The reason for that is still unknown ;

 * the modules keeps a table of the devices which length is the maximum number
   of UBI volumes.  It should make use of a linked list.

A lot of code is taken from mtd_blkdevs and gluebi

Signed-off-by: David Wagner <david.wagner at free-electrons.com>
---
 drivers/mtd/ubi/Kconfig  |    9 +
 drivers/mtd/ubi/Makefile |    1 +
 drivers/mtd/ubi/ubiblk.c |  462 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 472 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/ubi/ubiblk.c

diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 4dcc752..389a996 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -60,4 +60,13 @@ config MTD_UBI_DEBUG
 	help
 	  This option enables UBI debugging.
 
+config MTD_UBI_UBIBLK
+	tristate "Read-only block transition layer on top of UBI"
+	help
+	   Read-only block interface on top of UBI.
+
+	   Creates block devices that can be used to mount read-only block
+	   filesystems. Caches reads on a raw UBI volume. Filesystems images
+	   can be flashed using ubiupdatevol or put in a UBI image with
+	   ubinize
 endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index c9302a5..354b2df 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -5,3 +5,4 @@ ubi-y += misc.o
 
 ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
 obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+obj-$(CONFIG_MTD_UBI_UBIBLK) += ubiblk.o
diff --git a/drivers/mtd/ubi/ubiblk.c b/drivers/mtd/ubi/ubiblk.c
new file mode 100644
index 0000000..aab940a
--- /dev/null
+++ b/drivers/mtd/ubi/ubiblk.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (c) Free Electrons, 2011
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: David Wagner
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/mtd/ubi.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include "ubi.h"
+
+#define BLK_SIZE 512
+
+#define UBIBLK_MAX_DEVS (UBI_MAX_DEVICES * UBI_MAX_VOLUMES)
+
+/*
+ * Structure representing a ubiblk device, proxying a UBI volume
+ */
+struct ubiblk_dev {
+	struct ubi_volume_desc *vol_desc;
+	struct ubi_volume_info *vol_info;
+	int ubi_num;
+	int vol_id;
+
+	/* Block stuff */
+	struct gendisk *gd;
+	struct request_queue *rq;
+	struct task_struct *thread;
+
+	/* Protects the access to the UBI volume */
+	struct mutex lock;
+
+	/* Avoids concurrent accesses to the request queue */
+	spinlock_t queue_lock;
+};
+
+/*
+ * Contains the pointers to all ubiblk_dev instances
+ * TODO: use a linked list
+ */
+static struct ubiblk_dev *ubiblk_devs[UBIBLK_MAX_DEVS];
+static struct mutex devtable_lock;
+
+int major;
+static const struct block_device_operations ubiblk_ops;
+
+/*
+ * Read a LEB and fill the request buffer with the requested sector
+ */
+static int do_ubiblk_request(struct request *req, struct ubiblk_dev *dev)
+{
+	unsigned long start, len;
+	int offset;
+	int leb;
+	int ret;
+
+	start = blk_rq_pos(req) << 9;
+	len = blk_rq_cur_bytes(req);
+
+	/* We are always reading. No need to handle writing for now */
+
+	leb = start / dev->vol_info->usable_leb_size;
+	offset = start % dev->vol_info->usable_leb_size;
+
+	if (offset + len > dev->vol_info->usable_leb_size)
+		len = dev->vol_info->usable_leb_size - offset;
+
+	pr_debug("%s(%s) of sector %llu (LEB %d). start=%lu, len=%lu\n",
+		 __func__, rq_data_dir(req) ? "Write" : "Read",
+		 blk_rq_pos(req), leb, start, len);
+
+	ret = ubi_read(dev->vol_desc, leb, req->buffer, offset, len);
+
+	if (ret) {
+		pr_err("ubi_read error\n");
+		return ret;
+	}
+
+	pr_debug("ubi_read done.\n");
+
+	return 0;
+}
+
+static void ubi_ubiblk_request(struct request_queue *rq)
+{
+	struct ubiblk_dev *dev;
+	struct request *req = NULL;
+
+	dev = rq->queuedata;
+
+	if (!dev)
+		while ((req = blk_fetch_request(rq)) != NULL)
+			__blk_end_request_all(req, -ENODEV);
+	else
+		wake_up_process(dev->thread);
+}
+
+/*
+ * Open a UBI volume (get the volume descriptor)
+ */
+static int ubiblk_open(struct block_device *bdev, fmode_t mode)
+{
+	struct ubiblk_dev *dev = bdev->bd_disk->private_data;
+	pr_debug("%s() disk_name=%s, mode=%d\n", __func__,
+		 bdev->bd_disk->disk_name, mode);
+
+	dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+					UBI_READONLY);
+	if (!dev->vol_desc) {
+		pr_err("open_volume failed");
+		return -EINVAL;
+	}
+
+	dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+	if (!dev->vol_info) {
+		ubi_close_volume(dev->vol_desc);
+		dev->vol_desc = NULL;
+		return -ENOMEM;
+	}
+	ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+	return 0;
+}
+
+/*
+ * Close a UBI volume (close the volume descriptor)
+ */
+static int ubiblk_release(struct gendisk *gd, fmode_t mode)
+{
+	struct ubiblk_dev *dev = gd->private_data;
+	pr_debug("%s() disk_name=%s, mode=%d\n", __func__, gd->disk_name,
+		 mode);
+
+	kfree(dev->vol_info);
+	dev->vol_info = NULL;
+	if (dev->vol_desc) {
+		ubi_close_volume(dev->vol_desc);
+		dev->vol_desc = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * Loop on the block request queue and wait for new requests ; run them with
+ * do_ubiblk_request()
+ *
+ * Mostly stolen from mtd_blkdevs.c
+ */
+static int ubi_ubiblk_thread(void *arg)
+{
+	struct ubiblk_dev *dev = arg;
+	struct request_queue *rq = dev->rq;
+	struct request *req = NULL;
+
+	spin_lock_irq(rq->queue_lock);
+
+	while (!kthread_should_stop()) {
+		int res;
+
+		if (!req && !(req = blk_fetch_request(rq))) {
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
+
+			spin_unlock_irq(rq->queue_lock);
+			schedule();
+			spin_lock_irq(rq->queue_lock);
+			continue;
+		}
+
+		spin_unlock_irq(rq->queue_lock);
+
+		mutex_lock(&dev->lock);
+		res = do_ubiblk_request(req, dev);
+		pr_debug("return from request: %d\n", res);
+		mutex_unlock(&dev->lock);
+
+		spin_lock_irq(rq->queue_lock);
+
+		if (!__blk_end_request_cur(req, res))
+			req = NULL;
+	}
+
+	if (req)
+		__blk_end_request_all(req, -EIO);
+
+	spin_unlock_irq(rq->queue_lock);
+
+	return 0;
+}
+
+static int ubiblk_create(struct ubi_device_info *dev_info,
+			 struct ubi_volume_info *vol_info)
+{
+	struct ubiblk_dev *dev;
+	struct gendisk *gd;
+	int i;
+	int ret = 0;
+
+	mutex_lock(&devtable_lock);
+	for (i = 0; i < UBIBLK_MAX_DEVS; i++)
+		if (!ubiblk_devs[i])
+			break;
+
+	if (i == UBIBLK_MAX_DEVS) {
+		/* Shouldn't happen: UBI can't make more volumes than that */
+		pr_err("no slot left for a new ubiblk device.\n");
+		mutex_unlock(&devtable_lock);
+		return -ENOMEM;
+	}
+
+	dev = kzalloc(sizeof(struct ubiblk_dev), GFP_KERNEL);
+	if (!dev) {
+		pr_err("UBIBLK: ENOMEM when trying to create a new"
+		       "ubiblk dev\n");
+		mutex_unlock(&devtable_lock);
+		return -ENOMEM;
+	}
+	ubiblk_devs[i] = dev;
+	mutex_unlock(&devtable_lock);
+
+	mutex_init(&dev->lock);
+	mutex_lock(&dev->lock);
+
+	dev->ubi_num = vol_info->ubi_num;
+	dev->vol_id = vol_info->vol_id;
+
+	dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+					UBI_READONLY);
+	if (IS_ERR(dev->vol_desc)) {
+		pr_err("open_volume failed\n");
+		ret = PTR_ERR(dev->vol_desc);
+		goto out_vol;
+	}
+
+	dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+	if (!dev->vol_info) {
+		ret = -ENOMEM;
+		goto out_info;
+	}
+	ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+	pr_info("Got volume %s: device %d/volume %d of size %d\n",
+		dev->vol_info->name, dev->ubi_num, dev->vol_id,
+		dev->vol_info->size);
+
+	/* Initialize the gendisk of this ubiblk device */
+	gd = alloc_disk(1);
+	if (!gd) {
+		pr_err("alloc_disk failed\n");
+		ret = -ENODEV;
+		goto out_disk;
+	}
+
+	gd->fops = &ubiblk_ops;
+	gd->major = major;
+	gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+	gd->private_data = dev;
+	sprintf(gd->disk_name, "ubiblk%d_%d", dev->ubi_num, dev->vol_id);
+	pr_debug("creating a gd '%s'\n", gd->disk_name);
+	set_capacity(gd,
+		     (dev->vol_info->size *
+		      dev->vol_info->usable_leb_size) >> 9);
+	set_disk_ro(gd, 1);
+	dev->gd = gd;
+
+	spin_lock_init(&dev->queue_lock);
+	dev->rq = blk_init_queue(ubi_ubiblk_request, &dev->queue_lock);
+	if (!dev->rq) {
+		pr_err("init_queue failed\n");
+		ret = -ENODEV;
+		goto out_queue;
+	}
+	dev->rq->queuedata = dev;
+	blk_queue_logical_block_size(dev->rq, BLK_SIZE);
+	dev->gd->queue = dev->rq;
+
+	/* Stolen from mtd_blkdevs.c */
+	/* Create processing thread */
+	dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
+				  "kubiblkd", dev->ubi_num, dev->vol_id);
+	if (IS_ERR(dev->thread)) {
+		ret = PTR_ERR(dev->thread);
+		goto out_thread;
+	}
+
+	add_disk(dev->gd);
+	kfree(dev->vol_info);
+	dev->vol_info = NULL;
+	ubi_close_volume(dev->vol_desc);
+	dev->vol_desc = NULL;
+	mutex_unlock(&dev->lock);
+
+	return 0;
+
+out_thread:
+	blk_cleanup_queue(dev->rq);
+out_queue:
+	put_disk(dev->gd);
+out_disk:
+	kfree(dev->vol_info);
+	dev->vol_info = NULL;
+out_info:
+	ubi_close_volume(dev->vol_desc);
+	dev->vol_desc = NULL;
+out_vol:
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+static int ubiblk_remove(struct ubi_volume_info *vol_info)
+{
+	int i;
+	struct ubiblk_dev *dev;
+
+	for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+		dev = ubiblk_devs[i];
+		if (dev && dev->ubi_num == vol_info->ubi_num &&
+		    dev->vol_id == vol_info->vol_id)
+			break;
+	}
+	if (i == UBIBLK_MAX_DEVS) {
+		pr_warn("Trying to remove %s, which is unknown from ubiblk\n",
+			vol_info->name);
+		return -ENODEV;
+	}
+
+	pr_info("Removing %s\n", vol_info->name);
+
+	if (dev->vol_desc)
+		ubi_close_volume(dev->vol_desc);
+
+	del_gendisk(dev->gd);
+	blk_cleanup_queue(dev->rq);
+	kthread_stop(dev->thread);
+	put_disk(dev->gd);
+
+	kfree(dev->vol_info);
+
+	kfree(ubiblk_devs[i]);
+	ubiblk_devs[i] = NULL;
+
+	return 0;
+}
+
+static int ubiblk_notify(struct notifier_block *nb,
+			 unsigned long notification_type, void *ns_ptr)
+{
+	struct ubi_notification *nt = ns_ptr;
+
+	switch (notification_type) {
+	case UBI_VOLUME_ADDED:
+		ubiblk_create(&nt->di, &nt->vi);
+		break;
+	case UBI_VOLUME_REMOVED:
+		/* TODO */
+		ubiblk_remove(&nt->vi);
+		break;
+	case UBI_VOLUME_RESIZED:
+		/* TODO. needed ? */
+		/* gluebi_resized(&nt->vi); */
+		break;
+	case UBI_VOLUME_UPDATED:
+		break;
+	case UBI_VOLUME_RENAMED:
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static const struct block_device_operations ubiblk_ops = {
+	.owner = THIS_MODULE,
+	.open = ubiblk_open,
+	.release = ubiblk_release,
+};
+
+static struct notifier_block ubiblk_notifier = {
+	.notifier_call = ubiblk_notify,
+};
+
+/*
+ * Initialize the module
+ */
+static int __init ubi_ubiblk_init(void)
+{
+	int ret;
+
+	pr_info("UBIBLK starting\n");
+
+	ret = register_blkdev(0, "ubiblk");
+	if (ret <= 0) {
+		pr_err("UBIBLK: could not register_blkdev\n");
+		return -ENODEV;
+	}
+	major = ret;
+	pr_info("UBIBLK: device's major: %d\n", major);
+
+	mutex_init(&devtable_lock);
+	ret = ubi_register_volume_notifier(&ubiblk_notifier, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void __exit ubi_ubiblk_exit(void)
+{
+	int i;
+
+	pr_info("UBIBLK: going to exit\n");
+
+	ubi_unregister_volume_notifier(&ubiblk_notifier);
+
+	for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+		struct ubiblk_dev *dev = ubiblk_devs[i];
+		if (!dev)
+			continue;
+
+		if (dev->vol_desc)
+			ubi_close_volume(dev->vol_desc);
+
+		del_gendisk(dev->gd);
+		blk_cleanup_queue(dev->rq);
+		kthread_stop(dev->thread);
+		put_disk(dev->gd);
+
+		kfree(dev->vol_info);
+		kfree(dev);
+	}
+
+	unregister_blkdev(major, "ubiblk");
+	pr_info("UBIBLK: The End\n");
+}
+
+module_init(ubi_ubiblk_init);
+module_exit(ubi_ubiblk_exit);
+MODULE_DESCRIPTION("Read-only block transition layer on top of UBI");
+MODULE_AUTHOR("David Wagner");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4



From vapier.adi at gmail.com  Fri Jun 24 10:33:55 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 24 Jun 2011 10:33:55 -0400
Subject: [Ubi] Wrong major:minor
In-Reply-To: <87mxh78nai.fsf@macbook.be.48ers.dk>
References: <5d84u6d24de3ikt776vdrqpnhhecs3aoio@4ax.com>
	<1306917381.4405.76.camel@localhost>
	<1306917455.4405.77.camel@localhost>
	<BANLkTikha6F8GbWDNpwB4Q-v1V36ARcVVA@mail.gmail.com>
	<87mxh78nai.fsf@macbook.be.48ers.dk>
Message-ID: <BANLkTimLY-EG7+3arz-w07UYYEaxLjPwSA@mail.gmail.com>

On Fri, Jun 24, 2011 at 07:46, Peter Korsgaard wrote:
>>>>>> "Mike" == Mike Frysinger writes:
> ?>> Although I'm not sure - dynamic numbers were introduced because
> ?>> fixed numbers are PITA, so adding such a parameter would be a step
> ?>> backward. ?Not sure...
> >
> > yeah, i dont think there should be. ?at least nothing specific to
> > ubi. ?perhaps a general kernel thing where you could match the
> > registered name to a static #, but then that wouldnt be ubi's
> > problem. ?that'd be in the core logic and work for all devices.
>
> That already exists - CONFIG_DEVTMPFS.

while useful, that isnt what we were talking about.  that lets the
kernel populate /dev, that doesnt hardcode major/minor #s.
-mike


From peter.barada at gmail.com  Fri Jun 24 11:09:56 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Fri, 24 Jun 2011 11:09:56 -0400
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <20110622200621.GA26973@parrot.com>
References: <4DF789FC.1030305@gmail.com>
	<1308722655.18119.40.camel@sauron>	<4E020A36.6070708@gmail.com>
	<20110622170747.GC25928@parrot.com>	<4E023FCD.9010800@gmail.com>
	<20110622200621.GA26973@parrot.com>
Message-ID: <4E04A8C4.8000206@gmail.com>

On 06/22/2011 04:06 PM, Ivan Djelic wrote:
> On Wed, Jun 22, 2011 at 08:17:33PM +0100, Peter Barada wrote:
>> On 06/22/2011 01:07 PM, Ivan Djelic wrote:
>>> On one hand it sure would be nice (and a bit complicated) to accurately
>>> describe OOB write constraints, for easier JFFS2/YAFFS2 integration.
>>> On the other hand, I am not sure such a complication is really worth the
>>> trouble, given that on next nand generation:
>>> - OOB areas will not be usable anymore for metadata storage (8-bit ecc leaves
>>>     only 6 spare bytes out of 64)
>>> - partial writes will probably be limited to 1 (like in MLC), meaning that
>>>     JFFS2 clean marking step will be forbidden anyway
>>> Furthermore, userspace will probably need to handle case 3) anyway (no
>>> protected oob bytes) to stay portable...
>>>
>> SLC parts (including this one) look to be around for a while, as well as
>> the products they are already in.  So I think the issue of JFFS2's
>> cleanmarker in the context of this Micron NAND needs to be solved,
>> preferably in a general way so the next oddball NAND chip that comes
>> along doesn't cause MTD, mtd-utils, JFFS2 (and other NAND FS) fits.
>>
>> Does UBIFS do any of the "partial writes" (i.e. write OOB/data area
>> multiple times) as JFFS2 does?
>
> No it doesn't. UBIFS relies on UBI, which itself does not rely on oob for
> storing metadata. BTW, have you considered using UBIFS instead of JFFS2/YAFFS2?
Yes.  However customers are already using JFFS2/YAFFS2 and are reluctant 
to change.
> --
> Ivan
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/


-- 
Peter Barada
peter.barada at gmail.com



From randy.dunlap at oracle.com  Fri Jun 24 12:04:56 2011
From: randy.dunlap at oracle.com (Randy Dunlap)
Date: Fri, 24 Jun 2011 09:04:56 -0700
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
Message-ID: <20110624090456.191f1fda.randy.dunlap@oracle.com>

On Fri, 24 Jun 2011 15:58:22 +1000 Stephen Rothwell wrote:

> Hi all,
> 
> Changes since 20110623:
> 
> My fixes tree includes:
> 	(as an experiment) the early part of mmotm-2011-06-22-13-05
> 	STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE


When CONFIG_MTD=m, CONFIG_MTD_OF_PARTS=y:

drivers/mtd/ofpart.o: In function `init_module':
ofpart.c:(.init.text+0x0): multiple definition of `init_module'
drivers/mtd/mtdcore.o:(.init.text+0x43): first defined here


Full kernel .config file is attached.

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***
-------------- next part --------------
A non-text attachment was scrubbed...
Name: config-r8479
Type: application/octet-stream
Size: 39252 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110624/de893289/attachment-0001.obj>

From vapier.adi at gmail.com  Fri Jun 24 13:10:18 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 24 Jun 2011 13:10:18 -0400
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
In-Reply-To: <1308917226.7715.6.camel@koala>
References: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
	<1308917226.7715.6.camel@koala>
Message-ID: <BANLkTikeC+kfbuowKHbx_yC4ZmcX4nT6Pw@mail.gmail.com>

On Fri, Jun 24, 2011 at 08:07, Artem Bityutskiy wrote:
> On Wed, 2011-06-22 at 01:02 -0400, Mike Frysinger wrote:
>> the current mkfs.jffs2 util has in its --eraseblock handling:
>> /* If it's less than 8KiB, they're not allowed */
>> if (erase_block_size < 0x2000) {
>> ? ? fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
>> ? ? ? ? erase_block_size);
>> ? ? erase_block_size = 0x2000;
>> }
>>
>> but i cant seem to find documentation on where this comes from. ?it's
>> not uncommon to have SPI flashes with 4KiB erase sectors, and removing
>> this sanity check and allowing 4 KiB seems to produce an image that
>> works OK.
>>
>> am i missing something ? ?or should i send a patch to drop this check ?
>
> I do not believe JFFS2 is able to work with such small erase blocks. In
> JFFS2 (and in UBIFS as well) an eraseblock is the basic garbage
> collection unit, and nodes cannot cross eraseblock boundaries. And the
> maximum node size is 4KiB of data plus few bytes of node header. So 4KiB
> won't even fit the largest data node, e.g., containing uncompressible
> data.
>
> Even 8KiB is bad, because the amount of wasted space will be large -
> JFFS2 will waste the rest of the eraseblock if it does not fit the node.
> So the smaller EB is, the more wasted space you have.

i'll send a patch then to mkfs.jffs2 with a little bit of info.  i
couldnt find a FAQ on the mtd webpage that covered this.

> For SPI flashes the way out is to emulate larger eraseblock sizes on MTD
> level. I'd recommend at least 32 KiB.

sorry, but emulate how ?  just tell jffs2 to use an eraseblock size of
32KiB when creating the fs ?
-mike


From computersforpeace at gmail.com  Fri Jun 24 13:37:29 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 10:37:29 -0700
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron>
	<1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
Message-ID: <BANLkTi=b9tnk5tS9FZZ5WP4Nz9PUhMb02A@mail.gmail.com>

Hello,

On Thu, Jun 23, 2011 at 4:00 PM, Brian Norris
<computersforpeace at gmail.com> wrote:
> On Thu, Jun 23, 2011 at 8:52 AM, Mike Frysinger <vapier.adi at gmail.com> wrote:
>> On Thu, Jun 23, 2011 at 11:04, Artem Bityutskiy wrote:
>>> But
>>> even better we could make the version numbers to be the same as release
>>> number, then this process would be more automated and version would make
>>> some sense...
>>
>> the version isnt encoded anywhere. ?so if you started using something
>> like the kernel where the VERSION was in the Makefile, we could use
>> that to create a header file which all the utils would include.
>> -mike
>
> I like Mike's idea on the VERSION thing.

I took a little look at doing this "kernel style," but I'm running
into problems. It seems like this would be a little more difficult
because of the less centralized nature of mtd-utils (in comparison
with the kernel). Plus, I'm not very good with the GNU make system and
don't wanna mess too deep into something that could easily break
various people's build systems...

Also, is it just me or is the mtd-utils build setup pretty ugly? Maybe
I'm just used to how simplistic, unified, and informative the kernel
build system is, whereas mtd-utils prints out all sorts of detailed
info at the expense of *clearly* showing what it's doing.

OK, end of complaint (for now) ; I have some tangential noobish
questions, if anyone would be kind enough to answer:

Are the "ubi-utils" and "tests" meant to have the option of compiling
separately from the other mtd-utils?
Are these tools ever distributed separately? If not, do they need to
be independently buildable? It looks to me like ubi-utils is dependent
on first compiling "lib", but otherwise, they can all be built
separately... Anyway, I think this kinda screws with the centralized
VERSION thing above.
Why is mtdinfo under ubi-utils? Perhaps it should be moved when it
replaces flash_info? I think this is a fair interpretation of Item 3
in the feature-removal plan...

Thanks for putting up with me.

Cheers,
Brian


From computersforpeace at gmail.com  Fri Jun 24 14:03:08 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:08 -0700
Subject: [PATCH 0/6] complete nanddump feature-removals
Message-ID: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>

Here's my patchset to complete the feature removals and change of
defaults for nanddump (+ 1 bug fix for integck...). These should
be pushed after the 1.4.5 release.

Thanks,
Brian

Brian Norris (6):
  nanddump: kill --omitbad, --noskipbad
  nanddump: change default to --bb=skipbad
  nanddump: change -o to mean --oob, not --omitoob
  nanddump: default to NOT dumping OOB data
  feature-removal: remove completed tasks
  integck: fix build error (MS_DIRSYNC, MS_RELATIME)

 feature-removal-schedule.txt       |   37 ----------------
 nanddump.c                         |   85 +++++-------------------------------
 tests/fs-tests/integrity/integck.c |    1 +
 3 files changed, 13 insertions(+), 110 deletions(-)




From computersforpeace at gmail.com  Fri Jun 24 14:03:09 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:09 -0700
Subject: [PATCH 1/6] nanddump: kill --omitbad, --noskipbad
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308938594-20486-2-git-send-email-computersforpeace@gmail.com>

As mentioned previously, we are killing --omitbad in favor of the new
--bb=skipbad option, which functions fairly similarly. Also, --noskipbad
has become --bb=noskipbad, so remove the old `-N' and `--noskipbad' flags.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   46 +---------------------------------------------
 1 files changed, 1 insertions(+), 45 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 0367d83..55c5586 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -64,21 +64,6 @@ static void display_help(void)
 "    dumpbad: dump flash data, including any bad blocks\n"
 "    skipbad: dump good data, completely skipping any bad blocks\n"
 "\n"
-"Deprecated options:\n"
-"The following options are being replaced by --bb=METHOD flags or being\n"
-"removed entirely. Do not continue to use these options.\n"
-"-b         --omitbad            Omit bad blocks from the dump (DEPRECATED)\n"
-"-N         --noskipbad          Read without bad block skipping\n"
-"\n"
-"Notes on --omitbad and --bb=skipbad:\n"
-"* `omitbad' and `skipbad' are very similar; we are deprecating `--omitbad'\n"
-"  in favor of `--bb=skipbad'.\n"
-"* With either option, we stop dumping data when we encounter a bad block\n"
-"  and resume dumping at the next good block. However, with `omitbad', we\n"
-"  count the bad block as part of the total dump length, whereas with\n"
-"  `skipbad', the bad block is skipped, that is, not counted toward the\n"
-"  total dump length.\n"
-"\n"
 "Note on --oob, --omitoob:\n"
 "  To make nanddump act more like an inverse to nandwrite, we are changing\n"
 "  the default OOB behavior. In the next release, nanddump will not dump\n"
@@ -120,7 +105,6 @@ static enum {
 	padbad,   // dump flash data, substituting 0xFF for any bad blocks
 	dumpbad,  // dump flash data, including any bad blocks
 	skipbad,  // dump good data, completely skipping any bad blocks
-	omitbad   // dump flash data, substituting nothing for any bad blocks (DEPRECATED)
 } bb_method = padbad;
 
 static void process_options(int argc, char * const argv[])
@@ -130,7 +114,7 @@ static void process_options(int argc, char * const argv[])
 
 	for (;;) {
 		int option_index = 0;
-		static const char *short_options = "bs:f:l:opqnNca";
+		static const char *short_options = "s:f:l:opqnca";
 		static const struct option long_options[] = {
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
@@ -141,11 +125,9 @@ static void process_options(int argc, char * const argv[])
 			{"file", required_argument, 0, 'f'},
 			{"prettyprint", no_argument, 0, 'p'},
 			{"omitoob", no_argument, 0, 'o'},
-			{"omitbad", no_argument, 0, 'b'}, //DEPRECATED
 			{"startaddress", required_argument, 0, 's'},
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
-			{"noskipbad", no_argument, 0, 'N'},
 			{"quiet", no_argument, 0, 'q'},
 			{0, 0, 0, 0},
 		};
@@ -187,18 +169,6 @@ static void process_options(int argc, char * const argv[])
 						break;
 				}
 				break;
-			case 'b':
-				/* Check if bb_method was already set explicitly */
-				if (bb_default) {
-					bb_default = false;
-					bb_method = omitbad;
-					warnmsg("--omitbad is being deprecated in favor of --bb=skipbad.\n"
-						"  --omitbad will not be available in future releases.\n"
-						"  Please update your usage accordingly.");
-				} else {
-					error++;
-				}
-				break;
 			case 's':
 				start_addr = simple_strtoll(optarg, &error);
 				break;
@@ -233,18 +203,6 @@ static void process_options(int argc, char * const argv[])
 			case 'n':
 				noecc = true;
 				break;
-			case 'N':
-				/* Check if bb_method was already set explicitly */
-				if (bb_default) {
-					bb_default = false;
-					bb_method = dumpbad;
-					warnmsg("--noskipbad is being deprecated in favor of --bb=dumpbad.\n"
-						"  --noskipbad will not be available in future releases.\n"
-						"  Please update your usage accordingly.");
-				} else {
-					error++;
-				}
-				break;
 			case '?':
 				error++;
 				break;
@@ -499,8 +457,6 @@ int main(int argc, char * const argv[])
 					end_addr = mtd.size;
 				continue;
 			}
-			if (bb_method == omitbad)
-				continue;
 			memset(readbuf, 0xff, bs);
 		} else {
 			/* Read page data and exit on failure */
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun 24 14:03:10 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:10 -0700
Subject: [PATCH 2/6] nanddump: change default to --bb=skipbad
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308938594-20486-3-git-send-email-computersforpeace@gmail.com>

As promised, we change the default bad block handling method to
--bb=skipbad. This works as a better inverse to nandwrite, since
nandwrite skips bad blocks when writing data.

And of course, we remove the warning messages.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   11 +++--------
 1 files changed, 3 insertions(+), 8 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 55c5586..9edfbfd 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -60,9 +60,9 @@ static void display_help(void)
 "-s addr    --startaddress=addr  Start address\n"
 "\n"
 "--bb=METHOD, where METHOD can be `padbad', `dumpbad', or `skipbad':\n"
-"    padbad:  dump flash data, substituting 0xFF for any bad blocks (default)\n"
+"    padbad:  dump flash data, substituting 0xFF for any bad blocks\n"
 "    dumpbad: dump flash data, including any bad blocks\n"
-"    skipbad: dump good data, completely skipping any bad blocks\n"
+"    skipbad: dump good data, completely skipping any bad blocks (default)\n"
 "\n"
 "Note on --oob, --omitoob:\n"
 "  To make nanddump act more like an inverse to nandwrite, we are changing\n"
@@ -105,7 +105,7 @@ static enum {
 	padbad,   // dump flash data, substituting 0xFF for any bad blocks
 	dumpbad,  // dump flash data, including any bad blocks
 	skipbad,  // dump good data, completely skipping any bad blocks
-} bb_method = padbad;
+} bb_method = skipbad;
 
 static void process_options(int argc, char * const argv[])
 {
@@ -229,11 +229,6 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (bb_default)
-		warnmsg("you did not specify a default bad-block handling\n"
-			"  method. In future versions, the default will change to\n"
-			"  --bb=skipbad. Use \"nanddump --help\" for more information.");
-
 	if (oob_default)
 		warnmsg("in next release, nanddump will not dump OOB\n"
 			"  by default. Use `nanddump --oob' explicitly to ensure\n"
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun 24 14:03:11 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:11 -0700
Subject: [PATCH 3/6] nanddump: change -o to mean --oob, not --omitoob
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308938594-20486-4-git-send-email-computersforpeace@gmail.com>

As warned earlier, we are changing the meaning of `nanddump -o' to
mirror the usage in nandwrite, where -o means to include OOB (i.e.,
`nandwrite -o' writes data to both in-band and out-of-band areas, so
`nanddump -o' should dump data from both in-band and out-of-band areas).

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   14 +++++++-------
 1 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 9edfbfd..adf268b 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -53,8 +53,8 @@ static void display_help(void)
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"-o         --omitoob            Omit OOB data (default in next release)\n"
-"           --oob                Dump OOB data (current default)\n"
+"           --omitoob            Omit OOB data (default in next release)\n"
+"-o         --oob                Dump OOB data (current default)\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
@@ -119,12 +119,12 @@ static void process_options(int argc, char * const argv[])
 			{"help", no_argument, 0, 0},
 			{"version", no_argument, 0, 0},
 			{"bb", required_argument, 0, 0},
-			{"oob", no_argument, 0, 0},
+			{"omitoob", no_argument, 0, 0},
 			{"forcebinary", no_argument, 0, 'a'},
 			{"canonicalprint", no_argument, 0, 'c'},
 			{"file", required_argument, 0, 'f'},
+			{"oob", no_argument, 0, 'o'},
 			{"prettyprint", no_argument, 0, 'p'},
-			{"omitoob", no_argument, 0, 'o'},
 			{"startaddress", required_argument, 0, 's'},
 			{"length", required_argument, 0, 'l'},
 			{"noecc", no_argument, 0, 'n'},
@@ -159,10 +159,10 @@ static void process_options(int argc, char * const argv[])
 							error++;
 						bb_default = false;
 						break;
-					case 3: /* --oob */
+					case 3: /* --omitoob */
 						if (oob_default) {
 							oob_default = false;
-							omitoob = false;
+							omitoob = true;
 						} else {
 							errmsg_die("--oob and --oomitoob are mutually exclusive");
 						}
@@ -184,7 +184,7 @@ static void process_options(int argc, char * const argv[])
 			case 'o':
 				if (oob_default) {
 					oob_default = false;
-					omitoob = true;
+					omitoob = false;
 				} else {
 					errmsg_die("--oob and --oomitoob are mutually exclusive");
 				}
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun 24 14:03:12 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:12 -0700
Subject: [PATCH 4/6] nanddump: default to NOT dumping OOB data
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308938594-20486-5-git-send-email-computersforpeace@gmail.com>

Since nandwrite doesn't write OOB data by default, we don't dump OOB data
by default, in order to be a more proper inverse function.

Remove the warnings and change the default.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |   20 ++++----------------
 1 files changed, 4 insertions(+), 16 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index adf268b..54198ae 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -53,8 +53,8 @@ static void display_help(void)
 "-f file    --file=file          Dump to file\n"
 "-l length  --length=length      Length\n"
 "-n         --noecc              Read without error correction\n"
-"           --omitoob            Omit OOB data (default in next release)\n"
-"-o         --oob                Dump OOB data (current default)\n"
+"           --omitoob            Omit OOB data (default)\n"
+"-o         --oob                Dump OOB data\n"
 "-p         --prettyprint        Print nice (hexdump)\n"
 "-q         --quiet              Don't display progress and status messages\n"
 "-s addr    --startaddress=addr  Start address\n"
@@ -62,14 +62,7 @@ static void display_help(void)
 "--bb=METHOD, where METHOD can be `padbad', `dumpbad', or `skipbad':\n"
 "    padbad:  dump flash data, substituting 0xFF for any bad blocks\n"
 "    dumpbad: dump flash data, including any bad blocks\n"
-"    skipbad: dump good data, completely skipping any bad blocks (default)\n"
-"\n"
-"Note on --oob, --omitoob:\n"
-"  To make nanddump act more like an inverse to nandwrite, we are changing\n"
-"  the default OOB behavior. In the next release, nanddump will not dump\n"
-"  OOB data by default. We will leave both the `--omitoob' and `--oob'\n"
-"  options, but to mirror nandwrite, the short option `-o' will then stand\n"
-"  for `--oob', not `--omitoob'. Please adjust your usage accordingly.\n",
+"    skipbad: dump good data, completely skipping any bad blocks (default)\n",
 	PROGRAM_NAME);
 	exit(EXIT_SUCCESS);
 }
@@ -92,7 +85,7 @@ static void display_version(void)
 
 static bool			pretty_print = false;	// print nice
 static bool			noecc = false;		// don't error correct
-static bool			omitoob = false;	// omit oob data
+static bool			omitoob = true;		// omit oob data
 static long long		start_addr;		// start address
 static long long		length;			// dump length
 static const char		*mtddev;		// mtd device name
@@ -229,11 +222,6 @@ static void process_options(int argc, char * const argv[])
 		exit(EXIT_FAILURE);
 	}
 
-	if (oob_default)
-		warnmsg("in next release, nanddump will not dump OOB\n"
-			"  by default. Use `nanddump --oob' explicitly to ensure\n"
-			"  it is dumped.");
-
 	if ((argc - optind) != 1 || error)
 		display_help();
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun 24 14:03:13 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:13 -0700
Subject: [PATCH 5/6] feature-removal: remove completed tasks
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308938594-20486-6-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |   37 -------------------------------------
 1 files changed, 0 insertions(+), 37 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index 338bc08..a5980f7 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -40,40 +40,3 @@ This is duplicating behavior with the mtdinfo utility.  Now the util
 warns when people use it, but it'll be removed in release 1.4.6.
 
 ---------------------------
-
-4. Rename --noskipbad option, kill --omitbad, change default BB method for nanddump
-
-Our bad block handling methods are getting disorganized. They will be replaced
-by a series of --bb=METHOD options (see `nanddump --help').
-
-In addition, the previous default bad block behavior was to dump 0xFF in place
-of bad blocks. This was not a good "inverse operation" of nandwrite. Thus, the
-current default behavior has become the (new) option --bb=padbad, and in 1.4.6,
-the default will be --bb=skipbad.
-
-The new `--bb=METHOD' options are included in this release, but all feature
-removals and changed defaults will occur in 1.4.6. For now, there are
-appropriate deprecation warning messages and an alert telling about the
-soon-to-be-default settings.
-
-Transition summary table:
------------------------------------------------------------------------------------------------------------
- Old option     New option                 Comment
------------------------------------------------------------------------------------------------------------
- <default>      --bb=padbad                dump flash data, substituting 0xFF for any bad blocks
- --noskipbad    --bb=dumpbad               dump flash data, including any bad blocks
- --skipbad      --bb=skipbad, <default>    dump good data, completely skipping any bad blocks (new default)
- --omitbad      N/A                        very similar to `skipbad', will be removed soon
-
----------------------------
-
-5. nanddump will not dump OOB by default
-
-In 1.4.6, nanddump will not dump OOB by default. To dump OOB, you will have to
-explicitly use the option `--oob'. For now, there is simply a warning every
-time you use nanddump without explicitly choosing `--oob' or `--omitoob'.
-
-Note that `-o' will no longer stand for `--omitoob'. To unify with nandwrite,
-it will stand for `--oob' (Dump OOB data).
-
----------------------------
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun 24 14:03:14 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:03:14 -0700
Subject: [PATCH 6/6] integck: fix build error (MS_DIRSYNC, MS_RELATIME)
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308938594-20486-7-git-send-email-computersforpeace@gmail.com>

Need to include <linux/fs.h>, at least for my build system. Otherwise,
you can't build the 'tests'.

integck.c: In function ?parse_mount_options?:
integck.c:2862: error: ?MS_DIRSYNC? undeclared (first use in this
function)
integck.c:2862: error: (Each undeclared identifier is reported only once
integck.c:2862: error: for each function it appears in.)
integck.c:2872: error: ?MS_RELATIME? undeclared (first use in this
function)

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 tests/fs-tests/integrity/integck.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/tests/fs-tests/integrity/integck.c b/tests/fs-tests/integrity/integck.c
index 54e5ddc..30322cd 100644
--- a/tests/fs-tests/integrity/integck.c
+++ b/tests/fs-tests/integrity/integck.c
@@ -36,6 +36,7 @@
 #include <sys/vfs.h>
 #include <sys/mount.h>
 #include <sys/statvfs.h>
+#include <linux/fs.h>
 
 #define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME "integck"
-- 
1.7.0.4




From computersforpeace at gmail.com  Fri Jun 24 14:08:54 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 11:08:54 -0700
Subject: [PATCH 1/6] nanddump: kill --omitbad, --noskipbad
In-Reply-To: <1308938594-20486-2-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
	<1308938594-20486-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTi=aOniZ2FYom=_Nte0dmKu7MxUYXg@mail.gmail.com>

On Fri, Jun 24, 2011 at 11:03 AM, Brian Norris
<computersforpeace at gmail.com> wrote:
> As mentioned previously, we are killing --omitbad in favor of the new
> --bb=skipbad option, which functions fairly similarly. Also, --noskipbad
> has become --bb=noskipbad, so remove the old `-N' and `--noskipbad' flags.

Oops, I meant `--bb=dumpbad', not `--bb=noskipbad'. I'll resend if you
need me to change the commit msg...


From vapier.adi at gmail.com  Fri Jun 24 14:28:21 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 24 Jun 2011 14:28:21 -0400
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=b9tnk5tS9FZZ5WP4Nz9PUhMb02A@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTi=b9tnk5tS9FZZ5WP4Nz9PUhMb02A@mail.gmail.com>
Message-ID: <BANLkTi=baMZA4_xPw-aeDPm_NBV7uAQ+Dw@mail.gmail.com>

On Fri, Jun 24, 2011 at 13:37, Brian Norris wrote:
> I took a little look at doing this "kernel style," but I'm running
> into problems. It seems like this would be a little more difficult
> because of the less centralized nature of mtd-utils (in comparison
> with the kernel). Plus, I'm not very good with the GNU make system and
> don't wanna mess too deep into something that could easily break
> various people's build systems...

yes, it'd take a little bit of loving to make it happen

> Also, is it just me or is the mtd-utils build setup pretty ugly? Maybe
> I'm just used to how simplistic, unified, and informative the kernel
> build system is, whereas mtd-utils prints out all sorts of detailed
> info at the expense of *clearly* showing what it's doing.

you're used to the extra work that the kernel does to make the output
pretty.  if you look at the amount of make code required to accomplish
that, the mtd-utils code is actually a loooot simpler.

> Are the "ubi-utils" and "tests" meant to have the option of compiling
> separately from the other mtd-utils?
> Are these tools ever distributed separately? If not, do they need to
> be independently buildable? It looks to me like ubi-utils is dependent
> on first compiling "lib", but otherwise, they can all be built
> separately... Anyway, I think this kinda screws with the centralized
> VERSION thing above.

i wouldnt mind redoing some of the build system logic to be like the
kernel in that there is no recursion ... everything is included in the
top level make file and built there.  it'd probably simplify the pain
we've seen in the past where mtd-utils attempts to auto-build
out-of-tree when cross-compiling.

> Why is mtdinfo under ubi-utils? Perhaps it should be moved when it
> replaces flash_info? I think this is a fair interpretation of Item 3
> in the feature-removal plan...

i blame Artem
-mike


From dedekind1 at gmail.com  Fri Jun 24 14:46:49 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 21:46:49 +0300
Subject: [PATCH v2] mtd: OneNAND: Detect the correct NOP when 4KiB pagesize
In-Reply-To: <BANLkTinbS1fk=eM6=ANssed7jKih3w=vzw@mail.gmail.com>
References: <20110622051649.GA19948@july> <1308917793.7715.8.camel@koala>
	<BANLkTinbS1fk=eM6=ANssed7jKih3w=vzw@mail.gmail.com>
Message-ID: <1308941216.13493.0.camel@koala>

On Fri, 2011-06-24 at 21:20 +0900, Kyungmin Park wrote:
> On Fri, Jun 24, 2011 at 9:16 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Wed, 2011-06-22 at 14:16 +0900, Kyungmin Park wrote:
> >> From: Kyungmin Park <kyungmin.park at samsung.com>
> >>
> >> There are two different 4KiB pagesize chips
> >> KFM4G16Q4M series have NOP 4 with version ID 0x0131
> >> But KFM4G16Q5M has NOP 1 with versoin ID 0x013e
> >>
> >> Note that Q5M means that it has NOP 1.
> >>
> >> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> >
> > Pushed to l2-mtd-2.6.git, thanks.
> 
> Hi Artem,
> 
> It's required for s5pc110 series and supported at previous kernel, I
> mean it's bug fixed.
> So please merge it 3.0-rc periods

Only dwmw2 does this, so please, ask him.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 15:20:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:20:08 +0300
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
In-Reply-To: <BANLkTikeC+kfbuowKHbx_yC4ZmcX4nT6Pw@mail.gmail.com>
References: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
	<1308917226.7715.6.camel@koala>
	<BANLkTikeC+kfbuowKHbx_yC4ZmcX4nT6Pw@mail.gmail.com>
Message-ID: <1308943210.13493.10.camel@koala>

On Fri, 2011-06-24 at 13:10 -0400, Mike Frysinger wrote:
> On Fri, Jun 24, 2011 at 08:07, Artem Bityutskiy wrote:
> > On Wed, 2011-06-22 at 01:02 -0400, Mike Frysinger wrote:
> >> the current mkfs.jffs2 util has in its --eraseblock handling:
> >> /* If it's less than 8KiB, they're not allowed */
> >> if (erase_block_size < 0x2000) {
> >>     fprintf(stderr, "Erase size 0x%x too small. Increasing to 8KiB minimum\n",
> >>         erase_block_size);
> >>     erase_block_size = 0x2000;
> >> }
> >>
> >> but i cant seem to find documentation on where this comes from.  it's
> >> not uncommon to have SPI flashes with 4KiB erase sectors, and removing
> >> this sanity check and allowing 4 KiB seems to produce an image that
> >> works OK.
> >>
> >> am i missing something ?  or should i send a patch to drop this check ?
> >
> > I do not believe JFFS2 is able to work with such small erase blocks. In
> > JFFS2 (and in UBIFS as well) an eraseblock is the basic garbage
> > collection unit, and nodes cannot cross eraseblock boundaries. And the
> > maximum node size is 4KiB of data plus few bytes of node header. So 4KiB
> > won't even fit the largest data node, e.g., containing uncompressible
> > data.
> >
> > Even 8KiB is bad, because the amount of wasted space will be large -
> > JFFS2 will waste the rest of the eraseblock if it does not fit the node.
> > So the smaller EB is, the more wasted space you have.
> 
> i'll send a patch then to mkfs.jffs2 with a little bit of info.  i
> couldnt find a FAQ on the mtd webpage that covered this.

You could even send a patch against the mtd-www.git repo and add a piece
of doc to the web site :-)

> > For SPI flashes the way out is to emulate larger eraseblock sizes on MTD
> > level. I'd recommend at least 32 KiB.
> 
> sorry, but emulate how ?

Well, I was thinking about teaching MTD to merge real PEBs and report
larger EB size up to JFFS2. Probably this could be done via an MTD
module parameter and/or an ioctl.

>   just tell jffs2 to use an eraseblock size of
> 32KiB when creating the fs ?

Yes, the other way is to teach JFFS2 to merge PEBs and work with
multiple of PEBs. In fact in the past it could do this, but that was
removed because of some issues, do not remember what.

The only complication I see is bad blocks. When you merge PEBs and one
of them is bad, then the good PEBs which are in this merge should be
treated as bad as well. But this should not be very difficult to do.

On the one hand, teaching JFFS2 deal with small PEBs seems to make more
sense, on the other hand, doing this on driver level has an advantage -
you do not have to modify the file-system and you automatically make UBI
benefit from this - UBI scan time goes down when eraseblocks become
larger.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 15:21:33 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:21:33 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=baMZA4_xPw-aeDPm_NBV7uAQ+Dw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTi=b9tnk5tS9FZZ5WP4Nz9PUhMb02A@mail.gmail.com>
	<BANLkTi=baMZA4_xPw-aeDPm_NBV7uAQ+Dw@mail.gmail.com>
Message-ID: <1308943297.13493.11.camel@koala>

On Fri, 2011-06-24 at 14:28 -0400, Mike Frysinger wrote:
> > Why is mtdinfo under ubi-utils? Perhaps it should be moved when it
> > replaces flash_info? I think this is a fair interpretation of Item 3
> > in the feature-removal plan...
> 
> i blame Artem

Yes, fair blame, I was too lazy to make things properly and did not want
to deal with piles of ancient code, sorry.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier.adi at gmail.com  Fri Jun 24 15:23:38 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Fri, 24 Jun 2011 15:23:38 -0400
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
In-Reply-To: <1308943210.13493.10.camel@koala>
References: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
	<1308917226.7715.6.camel@koala>
	<BANLkTikeC+kfbuowKHbx_yC4ZmcX4nT6Pw@mail.gmail.com>
	<1308943210.13493.10.camel@koala>
Message-ID: <BANLkTimkgCz_yBnDOXyafhSV5S+R1un_YQ@mail.gmail.com>

On Fri, Jun 24, 2011 at 15:20, Artem Bityutskiy wrote:
> On Fri, 2011-06-24 at 13:10 -0400, Mike Frysinger wrote:
>> On Fri, Jun 24, 2011 at 08:07, Artem Bityutskiy wrote:
>> > For SPI flashes the way out is to emulate larger eraseblock sizes on MTD
>> > level. I'd recommend at least 32 KiB.
>>
>> sorry, but emulate how ?
>
> Well, I was thinking about teaching MTD to merge real PEBs and report
> larger EB size up to JFFS2. Probably this could be done via an MTD
> module parameter and/or an ioctl.
>
>> ? just tell jffs2 to use an eraseblock size of
>> 32KiB when creating the fs ?
>
> Yes, the other way is to teach JFFS2 to merge PEBs and work with
> multiple of PEBs. In fact in the past it could do this, but that was
> removed because of some issues, do not remember what.
>
> The only complication I see is bad blocks. When you merge PEBs and one
> of them is bad, then the good PEBs which are in this merge should be
> treated as bad as well. But this should not be very difficult to do.
>
> On the one hand, teaching JFFS2 deal with small PEBs seems to make more
> sense, on the other hand, doing this on driver level has an advantage -
> you do not have to modify the file-system and you automatically make UBI
> benefit from this - UBI scan time goes down when eraseblocks become
> larger.

this is way above my familiarity with the code base.  i'll just post
patches to update the docs.
-mike


From dedekind1 at gmail.com  Fri Jun 24 15:26:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:26:17 +0300
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <4E020A36.6070708@gmail.com>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
	<4E020A36.6070708@gmail.com>
Message-ID: <1308943581.13493.15.camel@koala>

On Wed, 2011-06-22 at 11:28 -0400, Peter Barada wrote:
> Thoughts?

Sorry, could you please define the problem you are trying to solve?
Sorry if you did define it in your long post, but I could not easily
find it.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 15:29:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:29:34 +0300
Subject: mkfs.jffs2 min erase block size: 4 vs 8 KiB
In-Reply-To: <BANLkTimkgCz_yBnDOXyafhSV5S+R1un_YQ@mail.gmail.com>
References: <BANLkTi=G+HxWtLgj6wUSQAY1FfjTFC8JjQ@mail.gmail.com>
	<1308917226.7715.6.camel@koala>
	<BANLkTikeC+kfbuowKHbx_yC4ZmcX4nT6Pw@mail.gmail.com>
	<1308943210.13493.10.camel@koala>
	<BANLkTimkgCz_yBnDOXyafhSV5S+R1un_YQ@mail.gmail.com>
Message-ID: <1308943791.13493.16.camel@koala>

On Fri, 2011-06-24 at 15:23 -0400, Mike Frysinger wrote:
> > Yes, the other way is to teach JFFS2 to merge PEBs and work with
> > multiple of PEBs. In fact in the past it could do this, but that was
> > removed because of some issues, do not remember what.
> >
> > The only complication I see is bad blocks. When you merge PEBs and one
> > of them is bad, then the good PEBs which are in this merge should be
> > treated as bad as well. But this should not be very difficult to do.
> >
> > On the one hand, teaching JFFS2 deal with small PEBs seems to make more
> > sense, on the other hand, doing this on driver level has an advantage -
> > you do not have to modify the file-system and you automatically make UBI
> > benefit from this - UBI scan time goes down when eraseblocks become
> > larger.
> 
> this is way above my familiarity with the code base.  i'll just post
> patches to update the docs.

Fair enough - ones who really need to solve this issue can work on it -
no need to do that if you do not really need this now.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 15:36:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:36:17 +0300
Subject: [PATCH 0/5] Few additional cleanup patches
In-Reply-To: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
References: <1308830731-5698-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1308944185.13493.17.camel@koala>

On Thu, 2011-06-23 at 16:05 +0400, Dmitry Eremin-Solenikov wrote:
> The following changes since commit 8c2ce1c78ba6cce94d0dfe6c674ea6c0cba56899:
> 
>   mtd: socrates_nand.c: use mtd_device_parse_register (2011-06-23 10:43:39 +0300)
> 
> are available in the git repository at:
>   git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup
> 
> Dmitry Eremin-Solenikov (5):
>       mtd/maps: drop edb7312 support
>       mtd/nand: drop edb7312 support
>       mtd: hide parse_mtd_partitions
>       mtd: remove put_partition_parser() from public header
>       mtd: drop mtd_device_register

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 15:38:52 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:38:52 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
Message-ID: <1308944335.13493.19.camel@koala>

On Thu, 2011-06-23 at 11:52 -0400, Mike Frysinger wrote:
> On Thu, Jun 23, 2011 at 11:04, Artem Bityutskiy wrote:
> > And speaking about released, should we do a new one? If you see that
> > some utils should have a version increased - feel free to do so. But
> > even better we could make the version numbers to be the same as release
> > number, then this process would be more automated and version would make
> > some sense...
> 
> the version isnt encoded anywhere.  so if you started using something
> like the kernel where the VERSION was in the Makefile, we could use
> that to create a header file which all the utils would include.

Absolutely agree, but I've changed my employer recently and now very
busy and barely have time to follow the mailing list, so I'd be happy if
someone sent a patch :-)

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 15:55:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 22:55:36 +0300
Subject: bbt and bitflip
In-Reply-To: <BANLkTimwOp4uPfQ0udLDycor2MjotUxiHw@mail.gmail.com>
References: <4DB033E4.6030105@parrot.com> <4DB06693.5000100@parrot.com>
	<1303460103.2757.48.camel@localhost>
	<BANLkTimwOp4uPfQ0udLDycor2MjotUxiHw@mail.gmail.com>
Message-ID: <1308945343.13493.25.camel@koala>

On Thu, 2011-06-23 at 09:36 -0700, Brian Norris wrote:
> I am interested in Artem's comments on the robustness of flash-based
> BBT (here, and more recently on
> http://lists.infradead.org/pipermail/linux-mtd/2011-June/036557.html).
> I recently have moved to using flash-based BBT (in-band, actually),
> and it seemed like several NAND drivers use flash-based BBT as well.
> Is it really that un-trustworthy?

If you confirm that everything is great and robust when the on-flash BBT
gets corrupted - the NAND core for sure notices any corruptions and
falls-back to the traditional scanning method and restores the on-flash
BBT - then I apologize for saying that I do not trust it. Also, I do not
really know the details of this, so I may be completely wrong.

> "The bbt should be protected with CRC and if it gets corrupted we
> should re-scan the flash and re-create it."
> 
> Wouldn't CRC just be a lesser replacement for proper ECC protection?
> Or am I missing something?

I'd say ECC and CRC play different roles. ECC is about handling NAND
PITAs like read/write/erase disturb, and CRC is about noticing any
corruption and recover, instead of reporting inaccurate information up -
e.g., reporting a good block as bad.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 16:00:15 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 23:00:15 +0300
Subject: [PATCH] mtd: spelling, capitalization, uniformity
In-Reply-To: <1308863528-32194-1-git-send-email-computersforpeace@gmail.com>
References: <1308863528-32194-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308945621.13493.26.camel@koala>

On Thu, 2011-06-23 at 14:12 -0700, Brian Norris wrote:
> Therefor -> Therefore
> [Intern], [Internal] -> [INTERN]
> [REPLACABLE] -> [REPLACEABLE]
> syndrom, syndom -> syndrome
> ecc -> ECC
> buswith -> buswidth
> endianess -> endianness
> dont -> don't
> occures -> occurs
> independend -> independent
> wihin -> within
> erease -> erase
> blockes -> blocks
> ...
> 
> (This is based on Artem's l2-mtd-2.6 git tree)
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 16:11:12 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 23:11:12 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=b9tnk5tS9FZZ5WP4Nz9PUhMb02A@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTi=b9tnk5tS9FZZ5WP4Nz9PUhMb02A@mail.gmail.com>
Message-ID: <1308946279.13493.29.camel@koala>

On Fri, 2011-06-24 at 10:37 -0700, Brian Norris wrote:
> Are the "ubi-utils" and "tests" meant to have the option of compiling
> separately from the other mtd-utils?

Probably not.

> Are these tools ever distributed separately? If not, do they need to
> be independently buildable?

I do not think that we need ubi-utils to be buildable separately.

>  It looks to me like ubi-utils is dependent
> on first compiling "lib", but otherwise, they can all be built
> separately... Anyway, I think this kinda screws with the centralized
> VERSION thing above.
> Why is mtdinfo under ubi-utils? Perhaps it should be moved when it
> replaces flash_info? I think this is a fair interpretation of Item 3
> in the feature-removal plan...

Yeah, it can be moved.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 16:16:53 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 23:16:53 +0300
Subject: [PATCH] mtd-utils: bump nanddump, mtdinfo version numbers
In-Reply-To: <1308870587-5300-1-git-send-email-computersforpeace@gmail.com>
References: <1308870587-5300-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308946617.13493.33.camel@koala>

On Thu, 2011-06-23 at 16:09 -0700, Brian Norris wrote:
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  nanddump.c              |    2 +-
>  ubi-utils/src/mtdinfo.c |    2 +-
>  2 files changed, 2 insertions(+), 2 deletions(-)

Pushed, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 16:15:12 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 23:15:12 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
Message-ID: <1308946515.13493.32.camel@koala>

On Thu, 2011-06-23 at 16:00 -0700, Brian Norris wrote:
> If we're going for 2.1 (or some other similarly large jump), maybe we
> should do the following:
> 1) increment some individual version numbers (nanddump and mtdinfo only?)
> 2) make a mtd-utils release 1.4.6
> 3) take care of all the "feature-removal-schedule" stuff...
> 4) put the VERSION in the Makefile (still version 1.4.6), have it
> generate a header
> 5) include that header in common.h
> 6) add a stub version function in common.h that would utilize this
> basic info to supply a "--version" option to all utilities that don't
> have one (at least, as far as reasonable...)
> 7) release another mtd-utils, jumping to v2.x (only needing to edit
> Makefile for version increments!)

Sounds good, and I personally do not mind to call it 2.0 or 3.0 or
1.4.6, you choose.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 16:20:17 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 23:20:17 +0300
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
Message-ID: <1308946822.13493.36.camel@koala>

On Thu, 2011-06-23 at 19:14 -0400, Mike Frysinger wrote:
> > and of the ones that do, we have a
> > random "2.1.0" from flash_erase. We wouldn't want to have a
> decreased
> > version number...so do we jump to mtd-utils v2.1 and make everything
> > the same version? Or even v3.0, just for fun?
> 
> i dont think anyone has scripts parsing these things.  i say let's
> just lock them all to the mtd release and forget about it.

Let's ask CC Peter who is packaging mtd-utils just in case. Peter, will
you suffer if mtd-utils' version all suddenly become 1.4.6? Also, will
you suffer if we switch to 2.0 or 3.0 - 2 numbers instead of 3?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Fri Jun 24 16:26:06 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Fri, 24 Jun 2011 23:26:06 +0300
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <20110624090456.191f1fda.randy.dunlap@oracle.com>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
Message-ID: <1308947172.13493.37.camel@koala>

On Fri, 2011-06-24 at 09:04 -0700, Randy Dunlap wrote:
> On Fri, 24 Jun 2011 15:58:22 +1000 Stephen Rothwell wrote:
> 
> > Hi all,
> > 
> > Changes since 20110623:
> > 
> > My fixes tree includes:
> > 	(as an experiment) the early part of mmotm-2011-06-22-13-05
> > 	STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
> 
> 
> When CONFIG_MTD=m, CONFIG_MTD_OF_PARTS=y:
> 
> drivers/mtd/ofpart.o: In function `init_module':
> ofpart.c:(.init.text+0x0): multiple definition of `init_module'
> drivers/mtd/mtdcore.o:(.init.text+0x43): first defined here

I guess this is some old issue? I do not think ofpart can be compiled-in
if the mtd core is a module...

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From mlcreech at gmail.com  Fri Jun 24 16:36:52 2011
From: mlcreech at gmail.com (Matthew L. Creech)
Date: Fri, 24 Jun 2011 16:36:52 -0400
Subject: bbt and bitflip
In-Reply-To: <1308945343.13493.25.camel@koala>
References: <4DB033E4.6030105@parrot.com> <4DB06693.5000100@parrot.com>
	<1303460103.2757.48.camel@localhost>
	<BANLkTimwOp4uPfQ0udLDycor2MjotUxiHw@mail.gmail.com>
	<1308945343.13493.25.camel@koala>
Message-ID: <BANLkTim-1VxX9bypbTbO=jm9dGykZ8Dviw@mail.gmail.com>

On Fri, Jun 24, 2011 at 3:55 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>
> If you confirm that everything is great and robust when the on-flash BBT
> gets corrupted - the NAND core for sure notices any corruptions and
> falls-back to the traditional scanning method and restores the on-flash
> BBT - then I apologize for saying that I do not trust it. Also, I do not
> really know the details of this, so I may be completely wrong.
>

I'm still trying to pinpoint the cause of the BBT corruptions that I
encountered, but _if_ they were caused by bit-flips, then it
definitely appears that your initial statement was accurate: the
devices were in many cases unbootable because the corrupted BBT was
treated as legit.

This also seems to be the case when looking at the code in nand_bbt.c:
if an ECC error is encountered in read_bbt(), it prints a warning but
then continues to process the BBT data.  Maybe there's an additional
assumption that I'm overlooking, but at a glance it seems like that
would allow bit errors to accumulate and wrongly flag good blocks as
bad.

-- 
Matthew L. Creech


From randy.dunlap at oracle.com  Fri Jun 24 16:38:40 2011
From: randy.dunlap at oracle.com (Randy Dunlap)
Date: Fri, 24 Jun 2011 13:38:40 -0700
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <1308947172.13493.37.camel@koala>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>	
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
	<1308947172.13493.37.camel@koala>
Message-ID: <4E04F5D0.9090900@oracle.com>

On 06/24/11 13:26, Artem Bityutskiy wrote:
> On Fri, 2011-06-24 at 09:04 -0700, Randy Dunlap wrote:
>> On Fri, 24 Jun 2011 15:58:22 +1000 Stephen Rothwell wrote:
>>
>>> Hi all,
>>>
>>> Changes since 20110623:
>>>
>>> My fixes tree includes:
>>> 	(as an experiment) the early part of mmotm-2011-06-22-13-05
>>> 	STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
>>
>>
>> When CONFIG_MTD=m, CONFIG_MTD_OF_PARTS=y:
>>
>> drivers/mtd/ofpart.o: In function `init_module':
>> ofpart.c:(.init.text+0x0): multiple definition of `init_module'
>> drivers/mtd/mtdcore.o:(.init.text+0x43): first defined here
> 
> I guess this is some old issue? I do not think ofpart can be compiled-in
> if the mtd core is a module...

[adding driver author, Vitaly]

No, it's a current issue.

config MTD_OF_PARTS
	def_bool y
	depends on OF

and (implicitly) depends on MTD.  MTD=m, so boolean => y.


-- 
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***


From computersforpeace at gmail.com  Fri Jun 24 18:38:14 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Fri, 24 Jun 2011 15:38:14 -0700
Subject: [PATCH] mtd-utils: bump nanddump, mtdinfo version numbers
In-Reply-To: <1308946617.13493.33.camel@koala>
References: <1308870587-5300-1-git-send-email-computersforpeace@gmail.com>
	<1308946617.13493.33.camel@koala>
Message-ID: <BANLkTine75yQYoJ2F6Xy=LOZ26SxXK=ZaA@mail.gmail.com>

On Fri, Jun 24, 2011 at 1:16 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2011-06-23 at 16:09 -0700, Brian Norris wrote:
>> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
>> ---
>> ?nanddump.c ? ? ? ? ? ? ?| ? ?2 +-
>> ?ubi-utils/src/mtdinfo.c | ? ?2 +-
>> ?2 files changed, 2 insertions(+), 2 deletions(-)
>
> Pushed, thanks!

You sure? It looks like you missed :)


From vapier at gentoo.org  Sat Jun 25 00:57:37 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 00:57:37 -0400
Subject: [PATCH] punt redundant libcrc32
Message-ID: <1308977857-3220-1-git-send-email-vapier@gentoo.org>

The libcrc32.a is only used in one place: mkfs.ubifs.  But this also
uses libmtd.a, and the only file in libcrc32.a is also in libmtd.a.
So libcrc32.a itself is completely redundant.  Punt!

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 lib/Makefile        |    5 ++---
 mkfs.ubifs/Makefile |    2 +-
 2 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/lib/Makefile b/lib/Makefile
index 9de6a7d..9b01d32 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -6,12 +6,11 @@ SUBDIRS =
 
 # CFLAGS += -Werror
 CPPFLAGS += -I../include
-LIBS = libmtd libcrc32
-TARGETS = libmtd.a libcrc32.a
+LIBS = libmtd
+TARGETS = libmtd.a
 
 include ../common.mk
 
-$(BUILDDIR)/libcrc32.a: $(addprefix $(BUILDDIR)/, libcrc32.o)
 $(BUILDDIR)/libmtd.a: $(addprefix $(BUILDDIR)/,\
        libmtd.o libmtd_legacy.o libcrc32.o libfec.o)
 
diff --git a/mkfs.ubifs/Makefile b/mkfs.ubifs/Makefile
index 499f9e5..ba21a8c 100644
--- a/mkfs.ubifs/Makefile
+++ b/mkfs.ubifs/Makefile
@@ -7,7 +7,7 @@ ALL_SOURCES=*.[ch] hashtable/*.[ch]
 TARGETS = mkfs.ubifs
 
 LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
-LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd -lcrc32
+LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd
 LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
 
 include ../common.mk
-- 
1.7.5.3



From dedekind1 at gmail.com  Sat Jun 25 02:09:05 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 09:09:05 +0300
Subject: [PATCH] mtd-utils: bump nanddump, mtdinfo version numbers
In-Reply-To: <BANLkTine75yQYoJ2F6Xy=LOZ26SxXK=ZaA@mail.gmail.com>
References: <1308870587-5300-1-git-send-email-computersforpeace@gmail.com>
	<1308946617.13493.33.camel@koala>
	<BANLkTine75yQYoJ2F6Xy=LOZ26SxXK=ZaA@mail.gmail.com>
Message-ID: <1308982153.23868.0.camel@koala>

On Fri, 2011-06-24 at 15:38 -0700, Brian Norris wrote:
> On Fri, Jun 24, 2011 at 1:16 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Thu, 2011-06-23 at 16:09 -0700, Brian Norris wrote:
> >> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> >> ---
> >>  nanddump.c              |    2 +-
> >>  ubi-utils/src/mtdinfo.c |    2 +-
> >>  2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > Pushed, thanks!
> 
> You sure? It looks like you missed :)

Oops, fixed!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Jun 25 02:12:03 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 09:12:03 +0300
Subject: [PATCH] punt redundant libcrc32
In-Reply-To: <1308977857-3220-1-git-send-email-vapier@gentoo.org>
References: <1308977857-3220-1-git-send-email-vapier@gentoo.org>
Message-ID: <1308982328.23868.1.camel@koala>

On Sat, 2011-06-25 at 00:57 -0400, Mike Frysinger wrote:
> The libcrc32.a is only used in one place: mkfs.ubifs.  But this also
> uses libmtd.a, and the only file in libcrc32.a is also in libmtd.a.
> So libcrc32.a itself is completely redundant.  Punt!
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed, thank you!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier at gentoo.org  Sat Jun 25 02:30:01 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 02:30:01 -0400
Subject: [PATCH] build: remove old SYMLINKS variable
Message-ID: <1308983401-27015-1-git-send-email-vapier@gentoo.org>

This is only used to create symlinks to out of tree files.  I doubt it
has any relevance anymore now that jffs2 has been merged into mainline.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 Makefile |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/Makefile b/Makefile
index 8bdba8e..d69206a 100644
--- a/Makefile
+++ b/Makefile
@@ -25,8 +25,6 @@ TARGETS = ftl_format flash_erase nanddump doc_loadbios \
 	sumtool #jffs2reader
 SCRIPTS = flash_eraseall
 
-SYMLINKS =
-
 LDLIBS = -L$(BUILDDIR)/lib -lmtd
 LDDEPS = $(BUILDDIR)/lib/libmtd.a
 
@@ -36,7 +34,6 @@ include common.mk
 subdirs_mkfs.ubifs_all: subdirs_ubi-utils_all
 
 clean::
-	-rm -f $(SYMLINKS)
 ifneq ($(BUILDDIR)/.git,)
 ifneq ($(BUILDDIR),.)
 ifneq ($(BUILDDIR),$(CURDIR))
@@ -46,9 +43,6 @@ endif
 endif
 	$(MAKE) -C $(TESTS) clean
 
-$(SYMLINKS):
-	ln -sf ../fs/jffs2/$@ $@
-
 $(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\
 	compr_rtime.o mkfs.jffs2.o compr_zlib.o compr_lzo.o \
 	compr.o rbtree.o)
-- 
1.7.5.3



From vapier at gentoo.org  Sat Jun 25 02:30:04 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 02:30:04 -0400
Subject: [PATCH] rewrite build system to avoid recursion
Message-ID: <1308983405-27064-1-git-send-email-vapier@gentoo.org>

The ubi-utils/src/ subdir is tossed as it just complicates things for no
real gain.

The top level clean is replaced with a `find -delete` on objects, so it
might prune more than necessary, but many projects now do this sort of
thing and no one complained there.

A "mkdep" helper generates the actual rule, and the variables are used
with "foreach" to expand these automatically.

While we're gutting things, also through in kbuild style output while
building to make things more legible.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 Makefile                        |   81 ++-
 common.mk                       |   46 +-
 lib/Makefile                    |   22 -
 mkfs.ubifs/Makefile             |   29 -
 ubi-utils/Makefile              |   60 --
 ubi-utils/dictionary.c          |  405 ++++++++++++
 ubi-utils/dictionary.h          |  174 +++++
 ubi-utils/libiniparser.c        |  646 ++++++++++++++++++
 ubi-utils/libscan.c             |  225 +++++++
 ubi-utils/libubi.c              | 1372 +++++++++++++++++++++++++++++++++++++++
 ubi-utils/libubi_int.h          |  131 ++++
 ubi-utils/libubigen.c           |  315 +++++++++
 ubi-utils/mtdinfo.c             |  446 +++++++++++++
 ubi-utils/src/dictionary.c      |  405 ------------
 ubi-utils/src/dictionary.h      |  174 -----
 ubi-utils/src/libiniparser.c    |  646 ------------------
 ubi-utils/src/libscan.c         |  225 -------
 ubi-utils/src/libubi.c          | 1372 ---------------------------------------
 ubi-utils/src/libubi_int.h      |  131 ----
 ubi-utils/src/libubigen.c       |  315 ---------
 ubi-utils/src/mtdinfo.c         |  446 -------------
 ubi-utils/src/ubiattach.c       |  225 -------
 ubi-utils/src/ubicrc32.c        |  124 ----
 ubi-utils/src/ubidetach.c       |  208 ------
 ubi-utils/src/ubiformat.c       |  950 ---------------------------
 ubi-utils/src/ubimkvol.c        |  295 ---------
 ubi-utils/src/ubinfo.c          |  434 -------------
 ubi-utils/src/ubinize.c         |  628 ------------------
 ubi-utils/src/ubirename.c       |  147 -----
 ubi-utils/src/ubirmvol.c        |  211 ------
 ubi-utils/src/ubirsvol.c        |  245 -------
 ubi-utils/src/ubiupdatevol.c    |  324 ---------
 ubi-utils/src/ubiutils-common.c |  211 ------
 ubi-utils/ubiattach.c           |  225 +++++++
 ubi-utils/ubicrc32.c            |  124 ++++
 ubi-utils/ubidetach.c           |  208 ++++++
 ubi-utils/ubiformat.c           |  950 +++++++++++++++++++++++++++
 ubi-utils/ubimkvol.c            |  295 +++++++++
 ubi-utils/ubinfo.c              |  434 +++++++++++++
 ubi-utils/ubinize.c             |  628 ++++++++++++++++++
 ubi-utils/ubirename.c           |  147 +++++
 ubi-utils/ubirmvol.c            |  211 ++++++
 ubi-utils/ubirsvol.c            |  245 +++++++
 ubi-utils/ubiupdatevol.c        |  324 +++++++++
 ubi-utils/ubiutils-common.c     |  211 ++++++
 45 files changed, 7804 insertions(+), 7866 deletions(-)
 delete mode 100644 lib/Makefile
 delete mode 100644 mkfs.ubifs/Makefile
 delete mode 100644 ubi-utils/Makefile
 create mode 100644 ubi-utils/dictionary.c
 create mode 100644 ubi-utils/dictionary.h
 create mode 100644 ubi-utils/libiniparser.c
 create mode 100644 ubi-utils/libscan.c
 create mode 100644 ubi-utils/libubi.c
 create mode 100644 ubi-utils/libubi_int.h
 create mode 100644 ubi-utils/libubigen.c
 create mode 100644 ubi-utils/mtdinfo.c
 delete mode 100644 ubi-utils/src/dictionary.c
 delete mode 100644 ubi-utils/src/dictionary.h
 delete mode 100644 ubi-utils/src/libiniparser.c
 delete mode 100644 ubi-utils/src/libscan.c
 delete mode 100644 ubi-utils/src/libubi.c
 delete mode 100644 ubi-utils/src/libubi_int.h
 delete mode 100644 ubi-utils/src/libubigen.c
 delete mode 100644 ubi-utils/src/mtdinfo.c
 delete mode 100644 ubi-utils/src/ubiattach.c
 delete mode 100644 ubi-utils/src/ubicrc32.c
 delete mode 100644 ubi-utils/src/ubidetach.c
 delete mode 100644 ubi-utils/src/ubiformat.c
 delete mode 100644 ubi-utils/src/ubimkvol.c
 delete mode 100644 ubi-utils/src/ubinfo.c
 delete mode 100644 ubi-utils/src/ubinize.c
 delete mode 100644 ubi-utils/src/ubirename.c
 delete mode 100644 ubi-utils/src/ubirmvol.c
 delete mode 100644 ubi-utils/src/ubirsvol.c
 delete mode 100644 ubi-utils/src/ubiupdatevol.c
 delete mode 100644 ubi-utils/src/ubiutils-common.c
 create mode 100644 ubi-utils/ubiattach.c
 create mode 100644 ubi-utils/ubicrc32.c
 create mode 100644 ubi-utils/ubidetach.c
 create mode 100644 ubi-utils/ubiformat.c
 create mode 100644 ubi-utils/ubimkvol.c
 create mode 100644 ubi-utils/ubinfo.c
 create mode 100644 ubi-utils/ubinize.c
 create mode 100644 ubi-utils/ubirename.c
 create mode 100644 ubi-utils/ubirmvol.c
 create mode 100644 ubi-utils/ubirsvol.c
 create mode 100644 ubi-utils/ubiupdatevol.c
 create mode 100644 ubi-utils/ubiutils-common.c

diff --git a/Makefile b/Makefile
index d69206a..bd5ada3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 
 # -*- sh -*-
 
-CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
+CPPFLAGS += -I./include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
 
 ifeq ($(WITHOUT_XATTR), 1)
   CPPFLAGS += -DWITHOUT_XATTR
@@ -12,10 +12,10 @@ else
   LZOLDLIBS = -llzo2
 endif
 
-SUBDIRS = lib ubi-utils mkfs.ubifs
 TESTS = tests
 
-TARGETS = ftl_format flash_erase nanddump doc_loadbios \
+MTD_BINS = \
+	ftl_format flash_erase nanddump doc_loadbios \
 	ftl_check mkfs.jffs2 flash_lock flash_unlock flash_info \
 	flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \
 	jffs2dump \
@@ -23,16 +23,21 @@ TARGETS = ftl_format flash_erase nanddump doc_loadbios \
 	rfddump rfdformat \
 	serve_image recv_image \
 	sumtool #jffs2reader
+UBI_BINS = \
+	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
+
+BINS = $(MTD_BINS)
+BINS += mkfs.ubifs/mkfs.ubifs
+BINS += $(addprefix ubi-utils/,$(UBI_BINS))
 SCRIPTS = flash_eraseall
 
-LDLIBS = -L$(BUILDDIR)/lib -lmtd
-LDDEPS = $(BUILDDIR)/lib/libmtd.a
+TARGETS = $(BINS)
+TARGETS += lib/libmtd.a
+TARGETS += ubi-utils/libubi.a
 
 include common.mk
 
-# mkfs.ubifs needs -lubi which is in ubi-utils/
-subdirs_mkfs.ubifs_all: subdirs_ubi-utils_all
-
 clean::
 ifneq ($(BUILDDIR)/.git,)
 ifneq ($(BUILDDIR),.)
@@ -41,23 +46,14 @@ ifneq ($(BUILDDIR),$(CURDIR))
 endif
 endif
 endif
+	find $(BUILDDIR)/ -xdev \
+		'(' -name '*.[ao]' -o -name '.*.c.dep' ')' \
+		-exec rm -f {} +
 	$(MAKE) -C $(TESTS) clean
 
-$(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\
-	compr_rtime.o mkfs.jffs2.o compr_zlib.o compr_lzo.o \
-	compr.o rbtree.o)
-LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
-
-$(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o
-LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
-
-$(BUILDDIR)/lib/libmtd.a: subdirs_lib_all ;
-
-install:: ${TARGETS} ${SCRIPTS}
+install:: ${BINS} ${SCRIPTS}
 	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
+	install -m 0755 ${BINS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
 	mkdir -p ${DESTDIR}/${MANDIR}/man1
 	gzip -9c mkfs.jffs2.1 > ${DESTDIR}/${MANDIR}/man1/mkfs.jffs2.1.gz
 
@@ -66,3 +62,44 @@ tests::
 
 cscope:
 	cscope -bR
+
+#
+# Utils in top level
+#
+obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o compr_lzo.o compr.o rbtree.o
+LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
+
+LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
+
+$(foreach v,$(MTD_BINS),$(eval $(call mkdep,,$(v))))
+
+#
+# Common libmtd
+#
+obj-libmtd.a = libmtd.o libmtd_legacy.o libcrc32.o libfec.o
+$(call _mkdep,lib/,libmtd.a)
+
+#
+# Utils in mkfs.ubifs subdir
+#
+obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o \
+	hashtable/hashtable.o hashtable/hashtable_itr.o
+LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid
+$(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
+
+#
+# Utils in ubi-utils/ subdir
+#
+obj-libiniparser.a = libiniparser.o dictionary.o
+obj-libscan.a      = libscan.o
+obj-libubi.a       = libubi.o
+obj-libubigen.a    = libubigen.o
+
+obj-mtdinfo   = libubigen.a
+obj-ubinize   = libubigen.a libiniparser.a
+obj-ubiformat = libubigen.a libscan.a
+
+$(foreach v,libubi.a libubigen.a libiniparser.a libscan.a,$(eval $(call _mkdep,ubi-utils/,$(v))))
+$(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-common.o)))
diff --git a/common.mk b/common.mk
index 0f3d447..51231e9 100644
--- a/common.mk
+++ b/common.mk
@@ -39,34 +39,46 @@ override BUILDDIR := $(patsubst %/,%,$(BUILDDIR))
 
 override TARGETS := $(addprefix $(BUILDDIR)/,$(TARGETS))
 
-SUBDIRS_ALL = $(patsubst %,subdirs_%_all,$(SUBDIRS))
-SUBDIRS_CLEAN = $(patsubst %,subdirs_%_clean,$(SUBDIRS))
-SUBDIRS_INSTALL = $(patsubst %,subdirs_%_install,$(SUBDIRS))
+ifeq ($(V),1)
+XECHO = @:
+Q =
+else
+XECHO = @echo
+Q = @
+endif
+define BECHO
+$(XECHO) "  $1      $(subst $(BUILDDIR)/,,$@)"
+endef
 
-all:: $(TARGETS) $(SUBDIRS_ALL)
+all:: $(TARGETS)
 
-clean:: $(SUBDIRS_CLEAN)
+clean::
 	rm -f $(BUILDDIR)/*.o $(TARGETS) $(BUILDDIR)/.*.c.dep
 
-install:: $(TARGETS) $(SUBDIRS_INSTALL)
+install:: $(TARGETS)
 
-%: %.o $(LDDEPS) $(LDDEPS_$(notdir $@))
-	$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))
+define _mkdep
+$(BUILDDIR)/$1$2: $(addprefix $(BUILDDIR)/$1,$(obj-$2) $3) $(addprefix $(BUILDDIR)/,$4)
+endef
+define mkdep
+$(call _mkdep,$1,$2,$3 $2.o,$4 lib/libmtd.a)
+endef
+
+%: %.o $(LDDEPS)
+	$(call BECHO,LD)
+	$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))
 
 $(BUILDDIR)/%.a:
-	$(AR) crv $@ $^
-	$(RANLIB) $@
+	$(call BECHO,AR)
+	$(Q)$(AR) cr $@ $^
+	$(Q)$(RANLIB) $@
 
 $(BUILDDIR)/%.o: %.c
 ifneq ($(BUILDDIR),$(CURDIR))
-	mkdir -p $(dir $@)
+	$(Q)mkdir -p $(dir $@)
 endif
-	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep
-
-subdirs_%:
-	d=$(patsubst subdirs_%,%,$@); \
-	t=`echo $$d | sed s:.*_::` d=`echo $$d | sed s:_.*::`; \
-	$(MAKE) BUILDDIR=$(BUILDDIR)/$$d -C $$d $$t
+	$(call BECHO,CC)
+	$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep
 
 .SUFFIXES:
 
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index 9b01d32..0000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Makefile for libmtd
-#
-
-SUBDIRS =
-
-# CFLAGS += -Werror
-CPPFLAGS += -I../include
-LIBS = libmtd
-TARGETS = libmtd.a
-
-include ../common.mk
-
-$(BUILDDIR)/libmtd.a: $(addprefix $(BUILDDIR)/,\
-       libmtd.o libmtd_legacy.o libcrc32.o libfec.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-
-uninstall:
diff --git a/mkfs.ubifs/Makefile b/mkfs.ubifs/Makefile
deleted file mode 100644
index ba21a8c..0000000
--- a/mkfs.ubifs/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-
-CPPFLAGS += -I../include -I../ubi-utils/include
-CPPFLAGS += $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
-
-ALL_SOURCES=*.[ch] hashtable/*.[ch]
-
-TARGETS = mkfs.ubifs
-
-LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
-LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd
-LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-
-include ../common.mk
-
-$(BUILDDIR)/mkfs.ubifs: $(addprefix $(BUILDDIR)/,\
-	crc16.o lpt.o compr.o devtable.o \
-	hashtable/hashtable.o hashtable/hashtable_itr.o)
-
-clean::
-	rm -f $(BUILDDIR)/hashtable/*.o cscope.*
-
-cscope:
-	@echo $(ALL_SOURCES) > cscope.files
-	@cscope -bR
-	@rm cscope.files
-
-install:: ${TARGETS}
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
deleted file mode 100644
index df81cd9..0000000
--- a/ubi-utils/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Makefile for ubi-utils
-#
-
-KERNELHDR := ../include
-
-# CFLAGS += -Werror
-CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
-
-LIBS = libubi libubigen libiniparser libscan
-TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
-          ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
-
-VPATH = src
-LDLIBS = -L$(BUILDDIR)/../lib -lmtd
-
-include ../common.mk
-
-# And the below is the rule to get final executable from its .o and ubiutils-common.o
-$(TARGETS): $(addprefix $(BUILDDIR)/,\
-	libubi.a ubiutils-common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
-
-$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
-	ubicrc32.o)
-#	$(CC) $(CFLAGS) -o $@ $^
-
-$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
-	ubinize.o ubiutils-common.o libiniparser.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
-
-$(BUILDDIR)/mtdinfo: $(addprefix $(BUILDDIR)/,\
-	libubigen.a ubiutils-common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lubigen -o $@
-
-$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
-	ubiformat.o ubiutils-common.o libscan.a libubi.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
-
-$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
-
-$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
-
-$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
-	libiniparser.o dictionary.o)
-
-$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
-	libscan.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-
-uninstall:
-	for file in ${TARGETS}; do \
-		$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
-	done
diff --git a/ubi-utils/dictionary.c b/ubi-utils/dictionary.c
new file mode 100644
index 0000000..b7c9ebf
--- /dev/null
+++ b/ubi-utils/dictionary.c
@@ -0,0 +1,405 @@
+/*-------------------------------------------------------------------------*/
+/**
+   @file	dictionary.c
+   @author	N. Devillard
+   @date	Sep 2007
+   @version	$Revision: 1.27 $
+   @brief	Implements a dictionary for string variables.
+
+   This module implements a simple dictionary object, i.e. a list
+   of string/string associations. This object is useful to store e.g.
+   informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+	$Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
+	$Revision: 1.27 $
+*/
+/*---------------------------------------------------------------------------
+   								Includes
+ ---------------------------------------------------------------------------*/
+#include "dictionary.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/** Maximum value size for integers and doubles. */
+#define MAXVALSZ	1024
+
+/** Minimal allocated number of entries in a dictionary */
+#define DICTMINSZ	128
+
+/** Invalid key token */
+#define DICT_INVALID_KEY    ((char*)-1)
+
+/*---------------------------------------------------------------------------
+  							Private functions
+ ---------------------------------------------------------------------------*/
+
+/* Doubles the allocated size associated to a pointer */
+/* 'size' is the current allocated size. */
+static void * mem_double(void * ptr, int size)
+{
+    void * newptr ;
+ 
+    newptr = calloc(2*size, 1);
+    if (newptr==NULL) {
+        return NULL ;
+    }
+    memcpy(newptr, ptr, size);
+    free(ptr);
+    return newptr ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Duplicate a string
+  @param    s String to duplicate
+  @return   Pointer to a newly allocated string, to be freed with free()
+
+  This is a replacement for strdup(). This implementation is provided
+  for systems that do not have it.
+ */
+/*--------------------------------------------------------------------------*/
+static char * xstrdup(char * s)
+{
+    char * t ;
+    if (!s)
+        return NULL ;
+    t = malloc(strlen(s)+1) ;
+    if (t) {
+        strcpy(t,s);
+    }
+    return t ;
+}
+
+/*---------------------------------------------------------------------------
+  							Function codes
+ ---------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Compute the hash key for a string.
+  @param	key		Character string to use for key.
+  @return	1 unsigned int on at least 32 bits.
+
+  This hash function has been taken from an Article in Dr Dobbs Journal.
+  This is normally a collision-free function, distributing keys evenly.
+  The key is stored anyway in the struct so that collision can be avoided
+  by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(char * key)
+{
+	int			len ;
+	unsigned	hash ;
+	int			i ;
+
+	len = strlen(key);
+	for (hash=0, i=0 ; i<len ; i++) {
+		hash += (unsigned)key[i] ;
+		hash += (hash<<10);
+		hash ^= (hash>>6) ;
+	}
+	hash += (hash <<3);
+	hash ^= (hash >>11);
+	hash += (hash <<15);
+	return hash ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Create a new dictionary object.
+  @param	size	Optional initial size of the dictionary.
+  @return	1 newly allocated dictionary objet.
+
+  This function allocates a new dictionary object of given size and returns
+  it. If you do not know in advance (roughly) the number of entries in the
+  dictionary, give size=0.
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * dictionary_new(int size)
+{
+	dictionary	*	d ;
+
+	/* If no size was specified, allocate space for DICTMINSZ */
+	if (size<DICTMINSZ) size=DICTMINSZ ;
+
+	if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
+		return NULL;
+	}
+	d->size = size ;
+	d->val  = (char **)calloc(size, sizeof(char*));
+	d->key  = (char **)calloc(size, sizeof(char*));
+	d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
+	return d ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Delete a dictionary object
+  @param	d	dictionary object to deallocate.
+  @return	void
+
+  Deallocate a dictionary object and all memory associated to it.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_del(dictionary * d)
+{
+	int		i ;
+
+	if (d==NULL) return ;
+	for (i=0 ; i<d->size ; i++) {
+		if (d->key[i]!=NULL)
+			free(d->key[i]);
+		if (d->val[i]!=NULL)
+			free(d->val[i]);
+	}
+	free(d->val);
+	free(d->key);
+	free(d->hash);
+	free(d);
+	return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Get a value from a dictionary.
+  @param	d		dictionary object to search.
+  @param	key		Key to look for in the dictionary.
+  @param    def     Default value to return if key not found.
+  @return	1 pointer to internally allocated character string.
+
+  This function locates a key in a dictionary and returns a pointer to its
+  value, or the passed 'def' pointer if no such key can be found in
+  dictionary. The returned character pointer points to data internal to the
+  dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * dictionary_get(dictionary * d, char * key, char * def)
+{
+	unsigned	hash ;
+	int			i ;
+
+	hash = dictionary_hash(key);
+	for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        /* Compare hash */
+		if (hash==d->hash[i]) {
+            /* Compare string, to avoid hash collisions */
+            if (!strcmp(key, d->key[i])) {
+				return d->val[i] ;
+			}
+		}
+	}
+	return def ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set a value in a dictionary.
+  @param    d       dictionary object to modify.
+  @param    key     Key to modify or add.
+  @param    val     Value to add.
+  @return   int     0 if Ok, anything else otherwise
+
+  If the given key is found in the dictionary, the associated value is
+  replaced by the provided one. If the key cannot be found in the
+  dictionary, it is added to it.
+
+  It is Ok to provide a NULL value for val, but NULL values for the dictionary
+  or the key are considered as errors: the function will return immediately
+  in such a case.
+
+  Notice that if you dictionary_set a variable to NULL, a call to
+  dictionary_get will return a NULL value: the variable will be found, and
+  its value (NULL) is returned. In other words, setting the variable
+  content to NULL is equivalent to deleting the variable from the
+  dictionary. It is not possible (in this implementation) to have a key in
+  the dictionary without value.
+
+  This function returns non-zero in case of failure.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_set(dictionary * d, char * key, char * val)
+{
+	int			i ;
+	unsigned	hash ;
+
+	if (d==NULL || key==NULL) return -1 ;
+	
+	/* Compute hash for this key */
+	hash = dictionary_hash(key) ;
+	/* Find if value is already in dictionary */
+	if (d->n>0) {
+		for (i=0 ; i<d->size ; i++) {
+            if (d->key[i]==NULL)
+                continue ;
+			if (hash==d->hash[i]) { /* Same hash value */
+				if (!strcmp(key, d->key[i])) {	 /* Same key */
+					/* Found a value: modify and return */
+					if (d->val[i]!=NULL)
+						free(d->val[i]);
+                    d->val[i] = val ? xstrdup(val) : NULL ;
+                    /* Value has been modified: return */
+					return 0 ;
+				}
+			}
+		}
+	}
+	/* Add a new value */
+	/* See if dictionary needs to grow */
+	if (d->n==d->size) {
+
+		/* Reached maximum size: reallocate dictionary */
+		d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
+		d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
+		d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
+        if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
+            /* Cannot grow dictionary */
+            return -1 ;
+        }
+		/* Double size */
+		d->size *= 2 ;
+	}
+
+    /* Insert key in the first empty slot */
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL) {
+            /* Add key here */
+            break ;
+        }
+    }
+	/* Copy key */
+	d->key[i]  = xstrdup(key);
+    d->val[i]  = val ? xstrdup(val) : NULL ;
+	d->hash[i] = hash;
+	d->n ++ ;
+	return 0 ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Delete a key in a dictionary
+  @param	d		dictionary object to modify.
+  @param	key		Key to remove.
+  @return   void
+
+  This function deletes a key in a dictionary. Nothing is done if the
+  key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, char * key)
+{
+	unsigned	hash ;
+	int			i ;
+
+	if (key == NULL) {
+		return;
+	}
+
+	hash = dictionary_hash(key);
+	for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        /* Compare hash */
+		if (hash==d->hash[i]) {
+            /* Compare string, to avoid hash collisions */
+            if (!strcmp(key, d->key[i])) {
+                /* Found key */
+                break ;
+			}
+		}
+	}
+    if (i>=d->size)
+        /* Key not found */
+        return ;
+
+    free(d->key[i]);
+    d->key[i] = NULL ;
+    if (d->val[i]!=NULL) {
+        free(d->val[i]);
+        d->val[i] = NULL ;
+    }
+    d->hash[i] = 0 ;
+    d->n -- ;
+    return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Dump a dictionary to an opened file pointer.
+  @param	d	Dictionary to dump
+  @param	f	Opened file pointer.
+  @return	void
+
+  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+  output file pointers.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_dump(dictionary * d, FILE * out)
+{
+	int		i ;
+
+	if (d==NULL || out==NULL) return ;
+	if (d->n<1) {
+		fprintf(out, "empty dictionary\n");
+		return ;
+	}
+	for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]) {
+            fprintf(out, "%20s\t[%s]\n",
+                    d->key[i],
+                    d->val[i] ? d->val[i] : "UNDEF");
+        }
+	}
+	return ;
+}
+
+
+/* Test code */
+#ifdef TESTDIC
+#define NVALS 20000
+int main(int argc, char *argv[])
+{
+	dictionary	*	d ;
+	char	*	val ;
+	int			i ;
+	char		cval[90] ;
+
+	/* Allocate dictionary */
+	printf("allocating...\n");
+	d = dictionary_new(0);
+	
+	/* Set values in dictionary */
+	printf("setting %d values...\n", NVALS);
+	for (i=0 ; i<NVALS ; i++) {
+		sprintf(cval, "%04d", i);
+		dictionary_set(d, cval, "salut");
+	}
+	printf("getting %d values...\n", NVALS);
+	for (i=0 ; i<NVALS ; i++) {
+		sprintf(cval, "%04d", i);
+		val = dictionary_get(d, cval, DICT_INVALID_KEY);
+		if (val==DICT_INVALID_KEY) {
+			printf("cannot get value for key [%s]\n", cval);
+		}
+	}
+    printf("unsetting %d values...\n", NVALS);
+	for (i=0 ; i<NVALS ; i++) {
+		sprintf(cval, "%04d", i);
+		dictionary_unset(d, cval);
+	}
+    if (d->n != 0) {
+        printf("error deleting values\n");
+    }
+	printf("deallocating...\n");
+	dictionary_del(d);
+	return 0 ;
+}
+#endif
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/dictionary.h b/ubi-utils/dictionary.h
new file mode 100644
index 0000000..c7d1790
--- /dev/null
+++ b/ubi-utils/dictionary.h
@@ -0,0 +1,174 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+   @file    dictionary.h
+   @author  N. Devillard
+   @date    Sep 2007
+   @version $Revision: 1.12 $
+   @brief   Implements a dictionary for string variables.
+
+   This module implements a simple dictionary object, i.e. a list
+   of string/string associations. This object is useful to store e.g.
+   informations retrieved from a configuration file (ini files).
+*/
+/*--------------------------------------------------------------------------*/
+
+/*
+	$Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
+	$Author: ndevilla $
+	$Date: 2007-11-23 21:37:00 $
+	$Revision: 1.12 $
+*/
+
+#ifndef _DICTIONARY_H_
+#define _DICTIONARY_H_
+
+/*---------------------------------------------------------------------------
+   								Includes
+ ---------------------------------------------------------------------------*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+/*---------------------------------------------------------------------------
+   								New types
+ ---------------------------------------------------------------------------*/
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Dictionary object
+
+  This object contains a list of string/string associations. Each
+  association is identified by a unique string key. Looking up values
+  in the dictionary is speeded up by the use of a (hopefully collision-free)
+  hash function.
+ */
+/*-------------------------------------------------------------------------*/
+typedef struct _dictionary_ {
+	int				n ;		/** Number of entries in dictionary */
+	int				size ;	/** Storage size */
+	char 		**	val ;	/** List of string values */
+	char 		**  key ;	/** List of string keys */
+	unsigned	 *	hash ;	/** List of hash values for keys */
+} dictionary ;
+
+
+/*---------------------------------------------------------------------------
+  							Function prototypes
+ ---------------------------------------------------------------------------*/
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Compute the hash key for a string.
+  @param    key     Character string to use for key.
+  @return   1 unsigned int on at least 32 bits.
+
+  This hash function has been taken from an Article in Dr Dobbs Journal.
+  This is normally a collision-free function, distributing keys evenly.
+  The key is stored anyway in the struct so that collision can be avoided
+  by comparing the key itself in last resort.
+ */
+/*--------------------------------------------------------------------------*/
+unsigned dictionary_hash(char * key);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Create a new dictionary object.
+  @param    size    Optional initial size of the dictionary.
+  @return   1 newly allocated dictionary objet.
+
+  This function allocates a new dictionary object of given size and returns
+  it. If you do not know in advance (roughly) the number of entries in the
+  dictionary, give size=0.
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * dictionary_new(int size);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete a dictionary object
+  @param    d   dictionary object to deallocate.
+  @return   void
+
+  Deallocate a dictionary object and all memory associated to it.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_del(dictionary * vd);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get a value from a dictionary.
+  @param    d       dictionary object to search.
+  @param    key     Key to look for in the dictionary.
+  @param    def     Default value to return if key not found.
+  @return   1 pointer to internally allocated character string.
+
+  This function locates a key in a dictionary and returns a pointer to its
+  value, or the passed 'def' pointer if no such key can be found in
+  dictionary. The returned character pointer points to data internal to the
+  dictionary object, you should not try to free it or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * dictionary_get(dictionary * d, char * key, char * def);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set a value in a dictionary.
+  @param    d       dictionary object to modify.
+  @param    key     Key to modify or add.
+  @param    val     Value to add.
+  @return   int     0 if Ok, anything else otherwise
+
+  If the given key is found in the dictionary, the associated value is
+  replaced by the provided one. If the key cannot be found in the
+  dictionary, it is added to it.
+
+  It is Ok to provide a NULL value for val, but NULL values for the dictionary
+  or the key are considered as errors: the function will return immediately
+  in such a case.
+
+  Notice that if you dictionary_set a variable to NULL, a call to
+  dictionary_get will return a NULL value: the variable will be found, and
+  its value (NULL) is returned. In other words, setting the variable
+  content to NULL is equivalent to deleting the variable from the
+  dictionary. It is not possible (in this implementation) to have a key in
+  the dictionary without value.
+
+  This function returns non-zero in case of failure.
+ */
+/*--------------------------------------------------------------------------*/
+int dictionary_set(dictionary * vd, char * key, char * val);
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete a key in a dictionary
+  @param    d       dictionary object to modify.
+  @param    key     Key to remove.
+  @return   void
+
+  This function deletes a key in a dictionary. Nothing is done if the
+  key cannot be found.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_unset(dictionary * d, char * key);
+
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Dump a dictionary to an opened file pointer.
+  @param    d   Dictionary to dump
+  @param    f   Opened file pointer.
+  @return   void
+
+  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
+  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
+  output file pointers.
+ */
+/*--------------------------------------------------------------------------*/
+void dictionary_dump(dictionary * d, FILE * out);
+
+#endif
diff --git a/ubi-utils/libiniparser.c b/ubi-utils/libiniparser.c
new file mode 100644
index 0000000..3bea51e
--- /dev/null
+++ b/ubi-utils/libiniparser.c
@@ -0,0 +1,646 @@
+
+/*-------------------------------------------------------------------------*/
+/**
+   @file    iniparser.c
+   @author  N. Devillard
+   @date    Sep 2007
+   @version 3.0
+   @brief   Parser for ini files.
+*/
+/*--------------------------------------------------------------------------*/
+/*
+    $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $
+    $Revision: 2.18 $
+    $Date: 2008-01-03 18:35:39 $
+*/
+/*---------------------------- Includes ------------------------------------*/
+#include <ctype.h>
+#include <libiniparser.h>
+
+/*---------------------------- Defines -------------------------------------*/
+#define ASCIILINESZ         (1024)
+#define INI_INVALID_KEY     ((char*)-1)
+
+/*---------------------------------------------------------------------------
+                        Private to this module
+ ---------------------------------------------------------------------------*/
+/**
+ * This enum stores the status for each parsed line (internal use only).
+ */
+typedef enum _line_status_ {
+    LINE_UNPROCESSED,
+    LINE_ERROR,
+    LINE_EMPTY,
+    LINE_COMMENT,
+    LINE_SECTION,
+    LINE_VALUE
+} line_status ;
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Convert a string to lowercase.
+  @param	s	String to convert.
+  @return	ptr to statically allocated string.
+
+  This function returns a pointer to a statically allocated string
+  containing a lowercased version of the input string. Do not free
+  or modify the returned string! Since the returned string is statically
+  allocated, it will be modified at each function call (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+static char * strlwc(const char * s)
+{
+    static char l[ASCIILINESZ+1];
+    int i ;
+
+    if (s==NULL) return NULL ;
+    memset(l, 0, ASCIILINESZ+1);
+    i=0 ;
+    while (s[i] && i<ASCIILINESZ) {
+        l[i] = (char)tolower((int)s[i]);
+        i++ ;
+    }
+    l[ASCIILINESZ]=(char)0;
+    return l ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Remove blanks at the beginning and the end of a string.
+  @param	s	String to parse.
+  @return	ptr to statically allocated string.
+
+  This function returns a pointer to a statically allocated string,
+  which is identical to the input string, except that all blank
+  characters at the end and the beg. of the string have been removed.
+  Do not free or modify the returned string! Since the returned string
+  is statically allocated, it will be modified at each function call
+  (not re-entrant).
+ */
+/*--------------------------------------------------------------------------*/
+static char * strstrip(char * s)
+{
+    static char l[ASCIILINESZ+1];
+	char * last ;
+	
+    if (s==NULL) return NULL ;
+    
+	while (isspace((int)*s) && *s) s++;
+	memset(l, 0, ASCIILINESZ+1);
+	strcpy(l, s);
+	last = l + strlen(l);
+	while (last > l) {
+		if (!isspace((int)*(last-1)))
+			break ;
+		last -- ;
+	}
+	*last = (char)0;
+	return (char*)l ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get number of sections in a dictionary
+  @param    d   Dictionary to examine
+  @return   int Number of sections found in dictionary
+
+  This function returns the number of sections found in a dictionary.
+  The test to recognize sections is done on the string stored in the
+  dictionary: a section name is given as "section" whereas a key is
+  stored as "section:key", thus the test looks for entries that do not
+  contain a colon.
+
+  This clearly fails in the case a section name contains a colon, but
+  this should simply be avoided.
+
+  This function returns -1 in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getnsec(dictionary * d)
+{
+    int i ;
+    int nsec ;
+
+    if (d==NULL) return -1 ;
+    nsec=0 ;
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        if (strchr(d->key[i], ':')==NULL) {
+            nsec ++ ;
+        }
+    }
+    return nsec ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get name for section n in a dictionary.
+  @param    d   Dictionary to examine
+  @param    n   Section number (from 0 to nsec-1).
+  @return   Pointer to char string
+
+  This function locates the n-th section in a dictionary and returns
+  its name as a pointer to a string statically allocated inside the
+  dictionary. Do not free or modify the returned string!
+
+  This function returns NULL in case of error.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getsecname(dictionary * d, int n)
+{
+    int i ;
+    int foundsec ;
+
+    if (d==NULL || n<0) return NULL ;
+    foundsec=0 ;
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        if (strchr(d->key[i], ':')==NULL) {
+            foundsec++ ;
+            if (foundsec>n)
+                break ;
+        }
+    }
+    if (foundsec<=n) {
+        return NULL ;
+    }
+    return d->key[i] ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Dump a dictionary to an opened file pointer.
+  @param    d   Dictionary to dump.
+  @param    f   Opened file pointer to dump to.
+  @return   void
+
+  This function prints out the contents of a dictionary, one element by
+  line, onto the provided file pointer. It is OK to specify @c stderr
+  or @c stdout as output files. This function is meant for debugging
+  purposes mostly.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump(dictionary * d, FILE * f)
+{
+    int     i ;
+
+    if (d==NULL || f==NULL) return ;
+    for (i=0 ; i<d->size ; i++) {
+        if (d->key[i]==NULL)
+            continue ;
+        if (d->val[i]!=NULL) {
+            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
+        } else {
+            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
+        }
+    }
+    return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Save a dictionary to a loadable ini file
+  @param    d   Dictionary to dump
+  @param    f   Opened file pointer to dump to
+  @return   void
+
+  This function dumps a given dictionary into a loadable ini file.
+  It is Ok to specify @c stderr or @c stdout as output files.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_dump_ini(dictionary * d, FILE * f)
+{
+    int     i, j ;
+    char    keym[ASCIILINESZ+1];
+    int     nsec ;
+    char *  secname ;
+    int     seclen ;
+
+    if (d==NULL || f==NULL) return ;
+
+    nsec = iniparser_getnsec(d);
+    if (nsec<1) {
+        /* No section in file: dump all keys as they are */
+        for (i=0 ; i<d->size ; i++) {
+            if (d->key[i]==NULL)
+                continue ;
+            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
+        }
+        return ;
+    }
+    for (i=0 ; i<nsec ; i++) {
+        secname = iniparser_getsecname(d, i) ;
+        seclen  = (int)strlen(secname);
+        fprintf(f, "\n[%s]\n", secname);
+        sprintf(keym, "%s:", secname);
+        for (j=0 ; j<d->size ; j++) {
+            if (d->key[j]==NULL)
+                continue ;
+            if (!strncmp(d->key[j], keym, seclen+1)) {
+                fprintf(f,
+                        "%-30s = %s\n",
+                        d->key[j]+seclen+1,
+                        d->val[j] ? d->val[j] : "");
+            }
+        }
+    }
+    fprintf(f, "\n");
+    return ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key
+  @param    d       Dictionary to search
+  @param    key     Key string to look for
+  @param    def     Default value to return if key not found.
+  @return   pointer to statically allocated character string
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the pointer passed as 'def' is returned.
+  The returned char pointer is pointing to a string allocated in
+  the dictionary, do not free or modify it.
+ */
+/*--------------------------------------------------------------------------*/
+char * iniparser_getstring(dictionary * d, const char * key, char * def)
+{
+    char * lc_key ;
+    char * sval ;
+
+    if (d==NULL || key==NULL)
+        return def ;
+
+    lc_key = strlwc(key);
+    sval = dictionary_get(d, lc_key, def);
+    return sval ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to an int
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   integer
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+
+  Supported values for integers include the usual C notation
+  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
+  are supported. Examples:
+
+  "42"      ->  42
+  "042"     ->  34 (octal -> decimal)
+  "0x42"    ->  66 (hexa  -> decimal)
+
+  Warning: the conversion may overflow in various ways. Conversion is
+  totally outsourced to strtol(), see the associated man page for overflow
+  handling.
+
+  Credits: Thanks to A. Becker for suggesting strtol()
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getint(dictionary * d, const char * key, int notfound)
+{
+    char    *   str ;
+
+    str = iniparser_getstring(d, key, INI_INVALID_KEY);
+    if (str==INI_INVALID_KEY) return notfound ;
+    return (int)strtol(str, NULL, 0);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to a double
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   double
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+ */
+/*--------------------------------------------------------------------------*/
+double iniparser_getdouble(dictionary * d, char * key, double notfound)
+{
+    char    *   str ;
+
+    str = iniparser_getstring(d, key, INI_INVALID_KEY);
+    if (str==INI_INVALID_KEY) return notfound ;
+    return atof(str);
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Get the string associated to a key, convert to a boolean
+  @param    d Dictionary to search
+  @param    key Key string to look for
+  @param    notfound Value to return in case of error
+  @return   integer
+
+  This function queries a dictionary for a key. A key as read from an
+  ini file is given as "section:key". If the key cannot be found,
+  the notfound value is returned.
+
+  A true boolean is found if one of the following is matched:
+
+  - A string starting with 'y'
+  - A string starting with 'Y'
+  - A string starting with 't'
+  - A string starting with 'T'
+  - A string starting with '1'
+
+  A false boolean is found if one of the following is matched:
+
+  - A string starting with 'n'
+  - A string starting with 'N'
+  - A string starting with 'f'
+  - A string starting with 'F'
+  - A string starting with '0'
+
+  The notfound value returned if no boolean is identified, does not
+  necessarily have to be 0 or 1.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_getboolean(dictionary * d, const char * key, int notfound)
+{
+    char    *   c ;
+    int         ret ;
+
+    c = iniparser_getstring(d, key, INI_INVALID_KEY);
+    if (c==INI_INVALID_KEY) return notfound ;
+    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
+        ret = 1 ;
+    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
+        ret = 0 ;
+    } else {
+        ret = notfound ;
+    }
+    return ret;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Finds out if a given entry exists in a dictionary
+  @param    ini     Dictionary to search
+  @param    entry   Name of the entry to look for
+  @return   integer 1 if entry exists, 0 otherwise
+
+  Finds out if a given entry exists in the dictionary. Since sections
+  are stored as keys with NULL associated values, this is the only way
+  of querying for the presence of sections in a dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_find_entry(
+    dictionary  *   ini,
+    char        *   entry
+)
+{
+    int found=0 ;
+    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
+        found = 1 ;
+    }
+    return found ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Set an entry in a dictionary.
+  @param    ini     Dictionary to modify.
+  @param    entry   Entry to modify (entry name)
+  @param    val     New value to associate to the entry.
+  @return   int 0 if Ok, -1 otherwise.
+
+  If the given entry can be found in the dictionary, it is modified to
+  contain the provided value. If it cannot be found, -1 is returned.
+  It is Ok to set val to NULL.
+ */
+/*--------------------------------------------------------------------------*/
+int iniparser_set(dictionary * ini, char * entry, char * val)
+{
+    return dictionary_set(ini, strlwc(entry), val) ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Delete an entry in a dictionary
+  @param    ini     Dictionary to modify
+  @param    entry   Entry to delete (entry name)
+  @return   void
+
+  If the given entry can be found, it is deleted from the dictionary.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_unset(dictionary * ini, char * entry)
+{
+    dictionary_unset(ini, strlwc(entry));
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief	Load a single line from an INI file
+  @param    input_line  Input line, may be concatenated multi-line input
+  @param    section     Output space to store section
+  @param    key         Output space to store key
+  @param    value       Output space to store value
+  @return   line_status value
+ */
+/*--------------------------------------------------------------------------*/
+static line_status iniparser_line(
+    char * input_line,
+    char * section,
+    char * key,
+    char * value)
+{   
+    line_status sta ;
+    char        line[ASCIILINESZ+1];
+    int         len ;
+
+    strcpy(line, strstrip(input_line));
+    len = (int)strlen(line);
+
+    sta = LINE_UNPROCESSED ;
+    if (len<1) {
+        /* Empty line */
+        sta = LINE_EMPTY ;
+    } else if (line[0]=='#') {
+        /* Comment line */
+        sta = LINE_COMMENT ; 
+    } else if (line[0]=='[' && line[len-1]==']') {
+        /* Section name */
+        sscanf(line, "[%[^]]", section);
+        strcpy(section, strstrip(section));
+        strcpy(section, strlwc(section));
+        sta = LINE_SECTION ;
+    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
+           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
+           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
+        /* Usual key=value, with or without comments */
+        strcpy(key, strstrip(key));
+        strcpy(key, strlwc(key));
+        strcpy(value, strstrip(value));
+        /*
+         * sscanf cannot handle '' or "" as empty values
+         * this is done here
+         */
+        if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
+            value[0]=0 ;
+        }
+        sta = LINE_VALUE ;
+    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
+           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
+        /*
+         * Special cases:
+         * key=
+         * key=;
+         * key=#
+         */
+        strcpy(key, strstrip(key));
+        strcpy(key, strlwc(key));
+        value[0]=0 ;
+        sta = LINE_VALUE ;
+    } else {
+        /* Generate syntax error */
+        sta = LINE_ERROR ;
+    }
+    return sta ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Parse an ini file and return an allocated dictionary object
+  @param    ininame Name of the ini file to read.
+  @return   Pointer to newly allocated dictionary
+
+  This is the parser for ini files. This function is called, providing
+  the name of the file to be read. It returns a dictionary object that
+  should not be accessed directly, but through accessor functions
+  instead.
+
+  The returned dictionary must be freed using iniparser_freedict().
+ */
+/*--------------------------------------------------------------------------*/
+dictionary * iniparser_load(const char * ininame)
+{
+    FILE * in ;
+
+    char line    [ASCIILINESZ+1] ;
+    char section [ASCIILINESZ+1] ;
+    char key     [ASCIILINESZ+1] ;
+    char tmp     [ASCIILINESZ+1] ;
+    char val     [ASCIILINESZ+1] ;
+
+    int  last=0 ;
+    int  len ;
+    int  lineno=0 ;
+    int  errs=0;
+
+    dictionary * dict ;
+
+    if ((in=fopen(ininame, "r"))==NULL) {
+        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
+        return NULL ;
+    }
+
+    dict = dictionary_new(0) ;
+    if (!dict) {
+        fclose(in);
+        return NULL ;
+    }
+
+    memset(line,    0, ASCIILINESZ);
+    memset(section, 0, ASCIILINESZ);
+    memset(key,     0, ASCIILINESZ);
+    memset(val,     0, ASCIILINESZ);
+    last=0 ;
+
+    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
+        lineno++ ;
+        len = (int)strlen(line)-1;
+        /* Safety check against buffer overflows */
+        if (line[len]!='\n') {
+            fprintf(stderr,
+                    "iniparser: input line too long in %s (%d)\n",
+                    ininame,
+                    lineno);
+            dictionary_del(dict);
+            fclose(in);
+            return NULL ;
+        }
+        /* Get rid of \n and spaces at end of line */
+        while ((len>=0) &&
+                ((line[len]=='\n') || (isspace(line[len])))) {
+            line[len]=0 ;
+            len-- ;
+        }
+        /* Detect multi-line */
+        if (line[len]=='\\') {
+            /* Multi-line value */
+            last=len ;
+            continue ;
+        } else {
+            last=0 ;
+        }
+        switch (iniparser_line(line, section, key, val)) {
+            case LINE_EMPTY:
+            case LINE_COMMENT:
+            break ;
+
+            case LINE_SECTION:
+            errs = dictionary_set(dict, section, NULL);
+            break ;
+
+            case LINE_VALUE:
+            sprintf(tmp, "%s:%s", section, key);
+            errs = dictionary_set(dict, tmp, val) ;
+            break ;
+
+            case LINE_ERROR:
+            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
+                    ininame,
+                    lineno);
+            fprintf(stderr, "-> %s\n", line);
+            errs++ ;
+            break;
+
+            default:
+            break ;
+        }
+        memset(line, 0, ASCIILINESZ);
+        last=0;
+        if (errs<0) {
+            fprintf(stderr, "iniparser: memory allocation failure\n");
+            break ;
+        }
+    }
+    if (errs) {
+        dictionary_del(dict);
+        dict = NULL ;
+    }
+    fclose(in);
+    return dict ;
+}
+
+/*-------------------------------------------------------------------------*/
+/**
+  @brief    Free all memory associated to an ini dictionary
+  @param    d Dictionary to free
+  @return   void
+
+  Free all memory associated to an ini dictionary.
+  It is mandatory to call this function before the dictionary object
+  gets out of the current context.
+ */
+/*--------------------------------------------------------------------------*/
+void iniparser_freedict(dictionary * d)
+{
+    dictionary_del(d);
+}
+
+/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/libscan.c b/ubi-utils/libscan.c
new file mode 100644
index 0000000..dc47a89
--- /dev/null
+++ b/ubi-utils/libscan.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI scanning library.
+ */
+
+#define PROGRAM_NAME "libscan"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <mtd_swab.h>
+#include <mtd/ubi-media.h>
+#include <mtd/mtd-user.h>
+#include <libmtd.h>
+#include <libscan.h>
+#include <crc32.h>
+#include "common.h"
+
+static int all_ff(const void *buf, int len)
+{
+	int i;
+	const uint8_t *p = buf;
+
+	for (i = 0; i < len; i++)
+		if (p[i] != 0xFF)
+			return 0;
+	return 1;
+}
+
+int ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info,
+	     int verbose)
+{
+	int eb, v = (verbose == 2), pr = (verbose == 1);
+	struct ubi_scan_info *si;
+	unsigned long long sum = 0;
+
+	si = calloc(1, sizeof(struct ubi_scan_info));
+	if (!si)
+		return sys_errmsg("cannot allocate %zd bytes of memory",
+				  sizeof(struct ubi_scan_info));
+
+	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
+	if (!si->ec) {
+		sys_errmsg("cannot allocate %zd bytes of memory",
+			   sizeof(struct ubi_scan_info));
+		goto out_si;
+	}
+
+	si->vid_hdr_offs = si->data_offs = -1;
+
+	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		int ret;
+		uint32_t crc;
+		struct ubi_ec_hdr ech;
+		unsigned long long ec;
+
+		if (v) {
+			normsg_cont("scanning eraseblock %d", eb);
+			fflush(stdout);
+		}
+		if (pr) {
+			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete  ",
+			       eb, (long long)(eb + 1) * 100 / mtd->eb_cnt);
+			fflush(stdout);
+		}
+
+		ret = mtd_is_bad(mtd, fd, eb);
+		if (ret == -1)
+			goto out_ec;
+		if (ret) {
+			si->bad_cnt += 1;
+			si->ec[eb] = EB_BAD;
+			if (v)
+				printf(": bad\n");
+			continue;
+		}
+
+		ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr));
+		if (ret < 0)
+			goto out_ec;
+
+		if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) {
+			if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) {
+				si->empty_cnt += 1;
+				si->ec[eb] = EB_EMPTY;
+				if (v)
+					printf(": empty\n");
+			} else {
+				si->alien_cnt += 1;
+				si->ec[eb] = EB_ALIEN;
+				if (v)
+					printf(": alien\n");
+			}
+			continue;
+		}
+
+		crc = mtd_crc32(UBI_CRC32_INIT, &ech, UBI_EC_HDR_SIZE_CRC);
+		if (be32_to_cpu(ech.hdr_crc) != crc) {
+			si->corrupted_cnt += 1;
+			si->ec[eb] = EB_CORRUPTED;
+			if (v)
+				printf(": bad CRC %#08x, should be %#08x\n",
+				       crc, be32_to_cpu(ech.hdr_crc));
+			continue;
+		}
+
+		ec = be64_to_cpu(ech.ec);
+		if (ec > EC_MAX) {
+			if (pr)
+				printf("\n");
+			errmsg("erase counter in EB %d is %llu, while this "
+			       "program expects them to be less than %u",
+			       eb, ec, EC_MAX);
+			goto out_ec;
+		}
+
+		if (si->vid_hdr_offs == -1) {
+			si->vid_hdr_offs = be32_to_cpu(ech.vid_hdr_offset);
+			si->data_offs = be32_to_cpu(ech.data_offset);
+			if (si->data_offs % mtd->min_io_size) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("bad data offset %d at eraseblock %d (n"
+					"of multiple of min. I/O unit size %d)",
+					si->data_offs, eb, mtd->min_io_size);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+
+			}
+		} else {
+			if ((int)be32_to_cpu(ech.vid_hdr_offset) != si->vid_hdr_offs) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("inconsistent VID header offset: was "
+					"%d, but is %d in eraseblock %d",
+					si->vid_hdr_offs,
+					be32_to_cpu(ech.vid_hdr_offset), eb);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+			}
+			if ((int)be32_to_cpu(ech.data_offset) != si->data_offs) {
+				if (pr)
+					printf("\n");
+				if (v)
+					printf(": corrupted because of the below\n");
+				warnmsg("inconsistent data offset: was %d, but"
+					" is %d in eraseblock %d",
+					si->data_offs,
+					be32_to_cpu(ech.data_offset), eb);
+				warnmsg("treat eraseblock %d as corrupted", eb);
+				si->corrupted_cnt += 1;
+				si->ec[eb] = EB_CORRUPTED;
+				continue;
+			}
+		}
+
+		si->ok_cnt += 1;
+		si->ec[eb] = ec;
+		if (v)
+			printf(": OK, erase counter %u\n", si->ec[eb]);
+	}
+
+	if (si->ok_cnt != 0) {
+		/* Calculate mean erase counter */
+		for (eb = 0; eb < mtd->eb_cnt; eb++) {
+			if (si->ec[eb] > EC_MAX)
+				continue;
+			sum += si->ec[eb];
+		}
+		si->mean_ec = sum / si->ok_cnt;
+	}
+
+	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
+	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
+		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
+		si->empty_cnt, si->alien_cnt, si->bad_cnt);
+
+	*info = si;
+	if (pr)
+		printf("\n");
+	return 0;
+
+out_ec:
+	free(si->ec);
+out_si:
+	free(si);
+	*info = NULL;
+	return -1;
+}
+
+void ubi_scan_free(struct ubi_scan_info *si)
+{
+	free(si->ec);
+	free(si);
+}
diff --git a/ubi-utils/libubi.c b/ubi-utils/libubi.c
new file mode 100644
index 0000000..4d5f316
--- /dev/null
+++ b/ubi-utils/libubi.c
@@ -0,0 +1,1372 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI (Unsorted Block Images) library.
+ */
+
+#define PROGRAM_NAME "libubi"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <limits.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <libubi.h>
+#include "libubi_int.h"
+#include "common.h"
+
+/**
+ * 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) {
+		sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
+		return NULL;
+	}
+
+	memcpy(n, path, len1);
+	if (n[len1 - 1] != '/')
+		n[len1++] = '/';
+
+	memcpy(n + len1, name, len2 + 1);
+	return n;
+}
+
+/**
+ * read_positive_ll - read a positive 'long long' value from a file.
+ * @file: the file to read from
+ * @value: the result is stored here
+ *
+ * This function reads file @file and interprets its contents as a positive
+ * 'long long' integer. If this is not true, it fails with %EINVAL error code.
+ * Returns %0 in case of success and %-1 in case of failure.
+ */
+static int read_positive_ll(const char *file, long long *value)
+{
+	int fd, rd;
+	char buf[50];
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, buf, sizeof(buf));
+	if (rd == -1) {
+		sys_errmsg("cannot read \"%s\"", file);
+		goto out_error;
+	}
+	if (rd == sizeof(buf)) {
+		errmsg("contents of \"%s\" is too long", file);
+		errno = EINVAL;
+		goto out_error;
+	}
+	buf[rd] = '\0';
+
+	if (sscanf(buf, "%lld\n", value) != 1) {
+		errmsg("cannot read integer from \"%s\"\n", file);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (*value < 0) {
+		errmsg("negative value %lld in \"%s\"", *value, file);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (close(fd))
+		return sys_errmsg("close failed on \"%s\"", file);
+
+	return 0;
+
+out_error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * read_positive_int - read a positive 'int' value from a file.
+ * @file: the file to read from
+ * @value: the result is stored here
+ *
+ * This function is the same as 'read_positive_ll()', but it reads an 'int'
+ * value, not 'long long'.
+ */
+static int read_positive_int(const char *file, int *value)
+{
+	long long res;
+
+	if (read_positive_ll(file, &res))
+		return -1;
+
+	/* Make sure the value is not too big */
+	if (res > INT_MAX) {
+		errmsg("value %lld read from file \"%s\" is out of range",
+		       res, file);
+		errno = EINVAL;
+		return -1;
+	}
+
+	*value = res;
+	return 0;
+}
+
+/**
+ * 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 read_data(const char *file, void *buf, int buf_len)
+{
+	int fd, rd, tmp, tmp1;
+
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	rd = read(fd, buf, buf_len);
+	if (rd == -1) {
+		sys_errmsg("cannot read \"%s\"", file);
+		goto out_error;
+	}
+
+	if (rd == buf_len) {
+		errmsg("contents of \"%s\" is too long", file);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	((char *)buf)[rd] = '\0';
+
+	/* Make sure all data is read */
+	tmp1 = read(fd, &tmp, 1);
+	if (tmp1 == 1) {
+		sys_errmsg("cannot read \"%s\"", file);
+		goto out_error;
+	}
+	if (tmp1) {
+		errmsg("file \"%s\" contains too much data (> %d bytes)",
+		       file, buf_len);
+		errno = EINVAL;
+		goto out_error;
+	}
+
+	if (close(fd)) {
+		sys_errmsg("close failed on \"%s\"", file);
+		return -1;
+	}
+
+	return rd;
+
+out_error:
+	close(fd);
+	return -1;
+}
+
+/**
+ * read_major - read major and minor numbers from a file.
+ * @file: name of the file to read from
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns % in case of succes, and %-1 in case of failure.
+ */
+static int read_major(const char *file, int *major, int *minor)
+{
+	int ret;
+	char buf[50];
+
+	ret = read_data(file, buf, 50);
+	if (ret < 0)
+		return ret;
+
+	ret = sscanf(buf, "%d:%d\n", major, minor);
+	if (ret != 2) {
+		errno = EINVAL;
+		return errmsg("\"%s\" does not have major:minor format", file);
+	}
+
+	if (*major < 0 || *minor < 0) {
+		errno = EINVAL;
+		return errmsg("bad major:minor %d:%d in \"%s\"",
+			      *major, *minor, file);
+	}
+
+	return 0;
+}
+
+/**
+ * dev_read_int - read a positive 'int' value from an UBI device sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_int(const char *patt, int dev_num, int *value)
+{
+	char file[strlen(patt) + 50];
+
+	sprintf(file, patt, dev_num);
+	return read_positive_int(file, value);
+}
+
+/**
+ * vol_read_int - read a positive 'int' value from an UBI volume sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
+{
+	char file[strlen(patt) + 100];
+
+	sprintf(file, patt, dev_num, vol_id);
+	return read_positive_int(file, value);
+}
+
+/**
+ * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_read_ll(const char *patt, int dev_num, long long *value)
+{
+	char file[strlen(patt) + 50];
+
+	sprintf(file, patt, dev_num);
+	return read_positive_ll(file, value);
+}
+
+/**
+ * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @value: the result is stored here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int vol_read_ll(const char *patt, int dev_num, int vol_id,
+		       long long *value)
+{
+	char file[strlen(patt) + 100];
+
+	sprintf(file, patt, dev_num, vol_id);
+	return read_positive_ll(file, value);
+}
+
+/**
+ * vol_read_data - read data from an UBI volume's sysfs file.
+ * @patt: file pattern to read from
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @buf: 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.
+ */
+static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
+			 int buf_len)
+{
+	char file[strlen(patt) + 100];
+
+	sprintf(file, patt, dev_num, vol_id);
+	return read_data(file, buf, buf_len);
+}
+
+/**
+ * dev_get_major - get major and minor numbers of an UBI device.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor)
+{
+	char file[strlen(lib->dev_dev) + 50];
+
+	sprintf(file, lib->dev_dev, dev_num);
+	return read_major(file, major, minor);
+}
+
+/**
+ * vol_get_major - get major and minor numbers of an UBI volume.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number
+ * @vol_id: volume ID
+ * @major: major number is returned here
+ * @minor: minor number is returned here
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,
+			 int *major, int *minor)
+{
+	char file[strlen(lib->vol_dev) + 100];
+
+	sprintf(file, lib->vol_dev, dev_num, vol_id);
+	return read_major(file, major, minor);
+}
+
+/**
+ * vol_node2nums - find UBI device number and volume ID by volume device node
+ *                 file.
+ * @lib: UBI library descriptor
+ * @node: UBI character device node name
+ * @dev_num: UBI device number is returned here
+ * @vol_id: volume ID is returned hers
+ *
+ * This function returns zero in case of succes and %-1 in case of failure.
+ */
+static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
+			 int *vol_id)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, fd, major, minor;
+	char file[strlen(lib->ubi_vol) + 100];
+
+	if (stat(node, &st))
+		return sys_errmsg("cannot get information about \"%s\"",
+				  node);
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a character device", node);
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (minor == 0) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a volume character device", node);
+	}
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+
+		ret = dev_get_major(lib, i, &major1, &minor1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (major1 == major)
+			break;
+	}
+
+	if (i > info.highest_dev_num) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	/* Make sure this UBI volume exists */
+	sprintf(file, lib->ubi_vol, i, minor - 1);
+	fd = open(file, O_RDONLY);
+	if (fd == -1) {
+		errno = ENODEV;
+		return -1;
+	}
+
+	*dev_num = i;
+	*vol_id = minor - 1;
+	errno = 0;
+	return 0;
+}
+
+/**
+ * dev_node2num - find UBI device number by its character device node.
+ * @lib: UBI library descriptor
+ * @node: UBI character device node name
+ * @dev_num: UBI device number is returned here
+ *
+ * This function returns %0 in case of success and %-1 in case of failure.
+ */
+static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, major, minor;
+
+	if (stat(node, &st))
+		return sys_errmsg("cannot get information about \"%s\"", node);
+
+	if (!S_ISCHR(st.st_mode)) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not a character device", node);
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (minor != 0) {
+		errno = EINVAL;
+		return errmsg("\"%s\" is not an UBI character device", node);
+	}
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+
+		ret = dev_get_major(lib, i, &major1, &minor1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (major1 == major) {
+			if (minor1 != 0) {
+				errmsg("UBI character device minor number is "
+				       "%d, but must be 0", minor1);
+				errno = EINVAL;
+				return -1;
+			}
+			errno = 0;
+			*dev_num = i;
+			return 0;
+		}
+	}
+
+	errno = ENODEV;
+	return -1;
+}
+
+int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num)
+{
+	struct ubi_info info;
+	int i, ret, mtd_num1;
+	struct libubi *lib = desc;
+
+	if (ubi_get_info(desc, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (mtd_num1 == mtd_num) {
+			errno = 0;
+			*dev_num = i;
+			return 0;
+		}
+	}
+
+	errno = 0;
+	return -1;
+}
+
+libubi_t libubi_open(void)
+{
+	int fd, version;
+	struct libubi *lib;
+
+	lib = calloc(1, sizeof(struct libubi));
+	if (!lib)
+		return NULL;
+
+	lib->sysfs_ctrl = mkpath("/sys", SYSFS_CTRL);
+	if (!lib->sysfs_ctrl)
+		goto out_error;
+
+	lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);
+	if (!lib->ctrl_dev)
+		goto out_error;
+
+	lib->sysfs_ubi = mkpath("/sys", SYSFS_UBI);
+	if (!lib->sysfs_ubi)
+		goto out_error;
+
+	/* Make sure UBI is present */
+	fd = open(lib->sysfs_ubi, O_RDONLY);
+	if (fd == -1) {
+		errno = 0;
+		goto out_error;
+	}
+
+	if (close(fd)) {
+		sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
+		goto out_error;
+	}
+
+	lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
+	if (!lib->ubi_dev)
+		goto out_error;
+
+	lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
+	if (!lib->ubi_version)
+		goto out_error;
+
+	lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
+	if (!lib->dev_dev)
+		goto out_error;
+
+	lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
+	if (!lib->dev_avail_ebs)
+		goto out_error;
+
+	lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
+	if (!lib->dev_total_ebs)
+		goto out_error;
+
+	lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
+	if (!lib->dev_bad_count)
+		goto out_error;
+
+	lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
+	if (!lib->dev_eb_size)
+		goto out_error;
+
+	lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
+	if (!lib->dev_max_ec)
+		goto out_error;
+
+	lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
+	if (!lib->dev_bad_rsvd)
+		goto out_error;
+
+	lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
+	if (!lib->dev_max_vols)
+		goto out_error;
+
+	lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
+	if (!lib->dev_min_io_size)
+		goto out_error;
+
+	lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM);
+	if (!lib->dev_mtd_num)
+		goto out_error;
+
+	lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
+	if (!lib->ubi_vol)
+		goto out_error;
+
+	lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
+	if (!lib->vol_type)
+		goto out_error;
+
+	lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
+	if (!lib->vol_dev)
+		goto out_error;
+
+	lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
+	if (!lib->vol_alignment)
+		goto out_error;
+
+	lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
+	if (!lib->vol_data_bytes)
+		goto out_error;
+
+	lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
+	if (!lib->vol_rsvd_ebs)
+		goto out_error;
+
+	lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
+	if (!lib->vol_eb_size)
+		goto out_error;
+
+	lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
+	if (!lib->vol_corrupted)
+		goto out_error;
+
+	lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
+	if (!lib->vol_name)
+		goto out_error;
+
+	if (read_positive_int(lib->ubi_version, &version))
+		goto out_error;
+	if (version != LIBUBI_UBI_VERSION) {
+		errmsg("this library was made for UBI version %d, but UBI "
+		       "version %d is detected\n", LIBUBI_UBI_VERSION, version);
+		goto out_error;
+	}
+
+	return lib;
+
+out_error:
+	libubi_close((libubi_t)lib);
+	return NULL;
+}
+
+void libubi_close(libubi_t desc)
+{
+	struct libubi *lib = (struct libubi *)desc;
+
+	free(lib->vol_name);
+	free(lib->vol_corrupted);
+	free(lib->vol_eb_size);
+	free(lib->vol_rsvd_ebs);
+	free(lib->vol_data_bytes);
+	free(lib->vol_alignment);
+	free(lib->vol_dev);
+	free(lib->vol_type);
+	free(lib->ubi_vol);
+	free(lib->dev_mtd_num);
+	free(lib->dev_min_io_size);
+	free(lib->dev_max_vols);
+	free(lib->dev_bad_rsvd);
+	free(lib->dev_max_ec);
+	free(lib->dev_eb_size);
+	free(lib->dev_bad_count);
+	free(lib->dev_total_ebs);
+	free(lib->dev_avail_ebs);
+	free(lib->dev_dev);
+	free(lib->ubi_version);
+	free(lib->ubi_dev);
+	free(lib->sysfs_ubi);
+	free(lib->ctrl_dev);
+	free(lib->sysfs_ctrl);
+	free(lib);
+}
+
+/**
+ * do_attach - perform the actual attach operation.
+ * @node: name of the UBI control character device node
+ * @r: attach request
+ *
+ * This function performs the actual UBI attach operation. Returns %0 in case of
+ * success and %-1 in case of failure. @r->ubi_num contains newly created UBI
+ * device number.
+ */
+static int do_attach(const char *node, const struct ubi_attach_req *r)
+{
+	int fd, ret;
+
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	ret = ioctl(fd, UBI_IOCATT, r);
+	close(fd);
+	if (ret == -1)
+		return -1;
+
+#ifdef UDEV_SETTLE_HACK
+//	if (system("udevsettle") == -1)
+//		return -1;
+	usleep(100000);
+#endif
+	return ret;
+}
+
+int ubi_attach_mtd(libubi_t desc, const char *node,
+		   struct ubi_attach_request *req)
+{
+	struct ubi_attach_req r;
+	int ret;
+
+	(void)desc;
+
+	memset(&r, 0, sizeof(struct ubi_attach_req));
+	r.ubi_num = req->dev_num;
+	r.mtd_num = req->mtd_num;
+	r.vid_hdr_offset = req->vid_hdr_offset;
+
+	ret = do_attach(node, &r);
+	if (ret == 0)
+		req->dev_num = r.ubi_num;
+
+	return ret;
+}
+
+#ifndef MTD_CHAR_MAJOR
+/*
+ * This is taken from kernel <linux/mtd/mtd.h> and is unlikely to change anytime
+ * soon.
+ */
+#define MTD_CHAR_MAJOR 90
+#endif
+
+/**
+ * mtd_node_to_num - converts device node to MTD number.
+ * @mtd_dev_node: path to device node to convert
+ *
+ * This function converts given @mtd_dev_node to MTD device number.
+ * @mtd_dev_node should contain path to the MTD device node. Returns MTD device
+ * number in case of success and %-1 in case of failure (errno is set).
+ */
+static int mtd_node_to_num(const char *mtd_dev_node)
+{
+	int major, minor;
+	struct stat sb;
+
+	if (stat(mtd_dev_node, &sb) < 0)
+		return sys_errmsg("cannot stat \"%s\"", mtd_dev_node);
+
+	if (!S_ISCHR(sb.st_mode)) {
+		errno = EINVAL;
+		return sys_errmsg("\"%s\" is not a character device",
+				  mtd_dev_node);
+	}
+
+	major = major(sb.st_rdev);
+	minor = minor(sb.st_rdev);
+
+	if (major != MTD_CHAR_MAJOR) {
+		errno = EINVAL;
+		return sys_errmsg("\"%s\" is not an MTD device", mtd_dev_node);
+	}
+
+	return minor / 2;
+}
+
+int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req)
+{
+	struct ubi_attach_req r;
+	int ret;
+
+	if (!req->mtd_dev_node)
+		/* Fallback to opening by mtd_num */
+		return ubi_attach_mtd(desc, node, req);
+
+	memset(&r, 0, sizeof(struct ubi_attach_req));
+	r.ubi_num = req->dev_num;
+	r.vid_hdr_offset = req->vid_hdr_offset;
+
+	/*
+	 * User has passed path to device node. Lets find out MTD device number
+	 * of the device and pass it to the kernel.
+	 */
+	r.mtd_num = mtd_node_to_num(req->mtd_dev_node);
+	if (r.mtd_num == -1)
+		return -1;
+
+	ret = do_attach(node, &r);
+	if (ret == 0)
+		req->dev_num = r.ubi_num;
+
+	return ret;
+}
+
+int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
+{
+	int ret, ubi_dev;
+
+	ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
+	if (ret == -1) {
+		errno = ENODEV;
+		return ret;
+	}
+
+	return ubi_remove_dev(desc, node, ubi_dev);
+}
+
+int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node)
+{
+	int mtd_num;
+
+	if (!mtd_dev_node) {
+		errno = EINVAL;
+		return -1;
+	}
+
+	mtd_num = mtd_node_to_num(mtd_dev_node);
+	if (mtd_num == -1)
+		return -1;
+
+	return ubi_detach_mtd(desc, node, mtd_num);
+}
+
+int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
+{
+	int fd, ret;
+
+	desc = desc;
+
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+	ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
+	if (ret == -1)
+		goto out_close;
+
+#ifdef UDEV_SETTLE_HACK
+//	if (system("udevsettle") == -1)
+//		return -1;
+	usleep(100000);
+#endif
+
+out_close:
+	close(fd);
+	return ret;
+}
+
+int ubi_probe_node(libubi_t desc, const char *node)
+{
+	struct stat st;
+	struct ubi_info info;
+	int i, fd, major, minor;
+	struct libubi *lib = (struct libubi *)desc;
+	char file[strlen(lib->ubi_vol) + 100];
+
+	if (stat(node, &st))
+		return sys_errmsg("cannot get information about \"%s\"", node);
+
+	if (!S_ISCHR(st.st_mode)) {
+		errmsg("\"%s\" is not a character device", node);
+		errno = EINVAL;
+		return -1;
+	}
+
+	major = major(st.st_rdev);
+	minor = minor(st.st_rdev);
+
+	if (ubi_get_info((libubi_t *)lib, &info))
+		return -1;
+
+	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
+		int major1, minor1, ret;
+
+		ret = dev_get_major(lib, i, &major1, &minor1);
+		if (ret) {
+			if (errno == ENOENT)
+				continue;
+			if (!errno)
+				goto out_not_ubi;
+			return -1;
+		}
+
+		if (major1 == major)
+			break;
+	}
+
+	if (i > info.highest_dev_num)
+		goto out_not_ubi;
+
+	if (minor == 0)
+		return 1;
+
+	/* This is supposdely an UBI volume device node */
+	sprintf(file, lib->ubi_vol, i, minor - 1);
+	fd = open(file, O_RDONLY);
+	if (fd == -1)
+		goto out_not_ubi;
+
+	return 2;
+
+out_not_ubi:
+	errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to "
+	       "any existing UBI device or volume", node, major, minor);
+	errno = ENODEV;
+	return -1;
+}
+
+int ubi_get_info(libubi_t desc, struct ubi_info *info)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	struct libubi *lib = (struct libubi *)desc;
+
+	memset(info, 0, sizeof(struct ubi_info));
+
+	if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) {
+		/*
+		 * Older UBI versions did not have control device, so we do not
+		 * panic here for compatibility reasons. May be few years later
+		 * we could return -1 here, but for now just set major:minor to
+		 * -1.
+		 */
+		info->ctrl_major = info->ctrl_minor = -1;
+	}
+
+	/*
+	 * We have to scan the UBI sysfs directory to identify how many UBI
+	 * devices are present.
+	 */
+	sysfs_ubi = opendir(lib->sysfs_ubi);
+	if (!sysfs_ubi)
+		return -1;
+
+	info->lowest_dev_num = INT_MAX;
+	while (1) {
+		int dev_num, ret;
+		char tmp_buf[256];
+
+		errno = 0;
+		dirent = readdir(sysfs_ubi);
+		if (!dirent)
+			break;
+
+		if (strlen(dirent->d_name) >= 255) {
+			errmsg("invalid entry in %s: \"%s\"",
+			       lib->sysfs_ubi, dirent->d_name);
+			errno = EINVAL;
+			goto out_close;
+		}
+
+		ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s",
+			     &dev_num, tmp_buf);
+		if (ret == 1) {
+			info->dev_count += 1;
+			if (dev_num > info->highest_dev_num)
+				info->highest_dev_num = dev_num;
+			if (dev_num < info->lowest_dev_num)
+				info->lowest_dev_num = dev_num;
+		}
+	}
+
+	if (!dirent && errno) {
+		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
+		goto out_close;
+	}
+
+	if (closedir(sysfs_ubi))
+		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
+
+	if (info->lowest_dev_num == INT_MAX)
+		info->lowest_dev_num = 0;
+
+	if (read_positive_int(lib->ubi_version, &info->version))
+		return -1;
+
+	return 0;
+
+out_close:
+	closedir(sysfs_ubi);
+	return -1;
+}
+
+int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
+{
+	int fd, ret;
+	struct ubi_mkvol_req r;
+	size_t n;
+
+	memset(&r, 0, sizeof(struct ubi_mkvol_req));
+
+	desc = desc;
+	r.vol_id = req->vol_id;
+	r.alignment = req->alignment;
+	r.bytes = req->bytes;
+	r.vol_type = req->vol_type;
+
+	n = strlen(req->name);
+	if (n > UBI_MAX_VOLUME_NAME)
+		return -1;
+
+	strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
+	r.name_len = n;
+
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	ret = ioctl(fd, UBI_IOCMKVOL, &r);
+	if (ret == -1) {
+		close(fd);
+		return ret;
+	}
+
+	close(fd);
+	req->vol_id = r.vol_id;
+
+#ifdef UDEV_SETTLE_HACK
+//	if (system("udevsettle") == -1)
+//		return -1;
+	usleep(100000);
+#endif
+
+	return 0;
+}
+
+int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
+{
+	int fd, ret;
+
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
+	if (ret == -1) {
+		close(fd);
+		return ret;
+	}
+
+	close(fd);
+
+#ifdef UDEV_SETTLE_HACK
+//	if (system("udevsettle") == -1)
+//		return -1;
+	usleep(100000);
+#endif
+
+	return 0;
+}
+
+int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol)
+{
+	int fd, ret;
+
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return -1;
+
+	ret = ioctl(fd, UBI_IOCRNVOL, rnvol);
+	if (ret == -1) {
+		close(fd);
+		return ret;
+	}
+
+	close(fd);
+
+#ifdef UDEV_SETTLE_HACK
+//	if (system("udevsettle") == -1)
+//		return -1;
+	usleep(100000);
+#endif
+
+	return 0;
+}
+
+int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
+{
+	int fd, ret;
+	struct ubi_rsvol_req req;
+
+	desc = desc;
+	fd = open(node, O_RDONLY);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", node);
+
+	req.bytes = bytes;
+	req.vol_id = vol_id;
+
+	ret = ioctl(fd, UBI_IOCRSVOL, &req);
+	close(fd);
+	return ret;
+}
+
+int ubi_update_start(libubi_t desc, int fd, long long bytes)
+{
+	desc = desc;
+	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
+		return -1;
+	return 0;
+}
+
+int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
+{
+	struct ubi_leb_change_req req;
+
+	desc = desc;
+	memset(&req, 0, sizeof(struct ubi_leb_change_req));
+	req.lnum = lnum;
+	req.bytes = bytes;
+	req.dtype = dtype;
+
+	if (ioctl(fd, UBI_IOCEBCH, &req))
+		return -1;
+	return 0;
+}
+
+/**
+ * dev_present - check whether an UBI device is present.
+ * @lib: libubi descriptor
+ * @dev_num: UBI device number to check
+ *
+ * This function returns %1 if UBI device is present and %0 if not.
+ */
+static int dev_present(struct libubi *lib, int dev_num)
+{
+	struct stat st;
+	char file[strlen(lib->ubi_dev) + 50];
+
+	sprintf(file, lib->ubi_dev, dev_num);
+	return !stat(file, &st);
+}
+
+int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
+{
+	DIR *sysfs_ubi;
+	struct dirent *dirent;
+	struct libubi *lib = (struct libubi *)desc;
+
+	memset(info, 0, sizeof(struct ubi_dev_info));
+	info->dev_num = dev_num;
+
+	if (!dev_present(lib, dev_num))
+		return -1;
+
+	sysfs_ubi = opendir(lib->sysfs_ubi);
+	if (!sysfs_ubi)
+		return -1;
+
+	info->lowest_vol_id = INT_MAX;
+
+	while (1) {
+		int vol_id, ret, devno;
+		char tmp_buf[256];
+
+		errno = 0;
+		dirent = readdir(sysfs_ubi);
+		if (!dirent)
+			break;
+
+		if (strlen(dirent->d_name) >= 255) {
+			errmsg("invalid entry in %s: \"%s\"",
+			       lib->sysfs_ubi, dirent->d_name);
+			goto out_close;
+		}
+
+		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf);
+		if (ret == 2 && devno == dev_num) {
+			info->vol_count += 1;
+			if (vol_id > info->highest_vol_id)
+				info->highest_vol_id = vol_id;
+			if (vol_id < info->lowest_vol_id)
+				info->lowest_vol_id = vol_id;
+		}
+	}
+
+	if (!dirent && errno) {
+		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
+		goto out_close;
+	}
+
+	if (closedir(sysfs_ubi))
+		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
+
+	if (info->lowest_vol_id == INT_MAX)
+		info->lowest_vol_id = 0;
+
+	if (dev_get_major(lib, dev_num, &info->major, &info->minor))
+		return -1;
+
+	if (dev_read_int(lib->dev_mtd_num, dev_num, &info->mtd_num))
+		return -1;
+	if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs))
+		return -1;
+	if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs))
+		return -1;
+	if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
+		return -1;
+	if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size))
+		return -1;
+	if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
+		return -1;
+	if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
+		return -1;
+	if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
+		return -1;
+	if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
+		return -1;
+
+	info->avail_bytes = (long long)info->avail_lebs * info->leb_size;
+	info->total_bytes = (long long)info->total_lebs * info->leb_size;
+
+	return 0;
+
+out_close:
+	closedir(sysfs_ubi);
+	return -1;
+}
+
+int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
+{
+	int err, dev_num;
+	struct libubi *lib = (struct libubi *)desc;
+
+	err = ubi_probe_node(desc, node);
+	if (err != 1) {
+		if (err == 2)
+			errno = ENODEV;
+		return -1;
+	}
+
+	if (dev_node2num(lib, node, &dev_num))
+		return -1;
+
+	return ubi_get_dev_info1(desc, dev_num, info);
+}
+
+int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
+		      struct ubi_vol_info *info)
+{
+	int ret;
+	struct libubi *lib = (struct libubi *)desc;
+	char buf[50];
+
+	memset(info, 0, sizeof(struct ubi_vol_info));
+	info->dev_num = dev_num;
+	info->vol_id = vol_id;
+
+	if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor))
+		return -1;
+
+	ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50);
+	if (ret < 0)
+		return -1;
+
+	if (strncmp(buf, "static\n", ret) == 0)
+		info->type = UBI_STATIC_VOLUME;
+	else if (strncmp(buf, "dynamic\n", ret) == 0)
+		info->type = UBI_DYNAMIC_VOLUME;
+	else {
+		errmsg("bad value at \"%s\"", buf);
+		errno = EINVAL;
+		return -1;
+	}
+
+	ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
+			   &info->alignment);
+	if (ret)
+		return -1;
+	ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
+			  &info->data_bytes);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size);
+	if (ret)
+		return -1;
+	ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
+			   &info->corrupted);
+	if (ret)
+		return -1;
+	info->rsvd_bytes = (long long)info->leb_size * info->rsvd_lebs;
+
+	ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
+			    UBI_VOL_NAME_MAX + 2);
+	if (ret < 0)
+		return -1;
+
+	info->name[ret - 1] = '\0';
+	return 0;
+}
+
+int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
+{
+	int err, vol_id, dev_num;
+	struct libubi *lib = (struct libubi *)desc;
+
+	err = ubi_probe_node(desc, node);
+	if (err != 2) {
+		if (err == 1)
+			errno = ENODEV;
+		return -1;
+	}
+
+	if (vol_node2nums(lib, node, &dev_num, &vol_id))
+		return -1;
+
+	return ubi_get_vol_info1(desc, dev_num, vol_id, info);
+}
+
+int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
+			 struct ubi_vol_info *info)
+{
+	int i, err;
+	unsigned int nlen = strlen(name);
+	struct ubi_dev_info dev_info;
+
+	if (nlen == 0) {
+		errmsg("bad \"name\" input parameter");
+		errno = EINVAL;
+		return -1;
+	}
+
+	err = ubi_get_dev_info1(desc, dev_num, &dev_info);
+	if (err)
+		return err;
+
+	for (i = dev_info.lowest_vol_id;
+	     i <= dev_info.highest_vol_id; i++) {
+		err = ubi_get_vol_info1(desc, dev_num, i, info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (nlen == strlen(info->name) && !strcmp(name, info->name))
+			return 0;
+	}
+
+	errno = ENOENT;
+	return -1;
+}
+
+int ubi_set_property(int fd, uint8_t property, uint64_t value)
+{
+	struct ubi_set_prop_req r;
+
+	memset(&r, 0, sizeof(struct ubi_set_prop_req));
+	r.property = property;
+	r.value = value;
+
+	return ioctl(fd, UBI_IOCSETPROP, &r);
+}
+
+int ubi_leb_unmap(int fd, int lnum)
+{
+	return ioctl(fd, UBI_IOCEBUNMAP, &lnum);
+}
+
+int ubi_is_mapped(int fd, int lnum)
+{
+	return ioctl(fd, UBI_IOCEBISMAP, &lnum);
+}
diff --git a/ubi-utils/libubi_int.h b/ubi-utils/libubi_int.h
new file mode 100644
index 0000000..c3aa37a
--- /dev/null
+++ b/ubi-utils/libubi_int.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Author: Artem Bityutskiy
+ *
+ * UBI (Unsorted Block Images) library.
+ */
+
+#ifndef __LIBUBI_INT_H__
+#define __LIBUBI_INT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The below are pre-define UBI file and directory names.
+ *
+ * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'.
+ * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is
+ * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y'
+ * directories to '/sys/class/ubi/'. For now libubi assumes old layout.
+ */
+
+#define SYSFS_UBI         "class/ubi"
+#define SYSFS_CTRL        "class/misc/ubi_ctrl/"
+
+#define CTRL_DEV          "dev"
+
+#define UBI_VER           "version"
+#define UBI_DEV_NAME_PATT "ubi%d"
+
+#define DEV_DEV           "dev"
+#define DEV_AVAIL_EBS     "avail_eraseblocks"
+#define DEV_TOTAL_EBS     "total_eraseblocks"
+#define DEV_BAD_COUNT     "bad_peb_count"
+#define DEV_EB_SIZE       "eraseblock_size"
+#define DEV_MAX_EC        "max_ec"
+#define DEV_MAX_RSVD      "reserved_for_bad"
+#define DEV_MAX_VOLS      "max_vol_count"
+#define DEV_MIN_IO_SIZE   "min_io_size"
+#define DEV_MTD_NUM       "mtd_num"
+
+#define UBI_VOL_NAME_PATT "ubi%d_%d"
+#define VOL_TYPE          "type"
+#define VOL_DEV           "dev"
+#define VOL_ALIGNMENT     "alignment"
+#define VOL_DATA_BYTES    "data_bytes"
+#define VOL_RSVD_EBS      "reserved_ebs"
+#define VOL_EB_SIZE       "usable_eb_size"
+#define VOL_CORRUPTED     "corrupted"
+#define VOL_NAME          "name"
+
+/**
+ * libubi - UBI library description data structure.
+ * @sysfs: sysfs file system path
+ * @sysfs_ctrl: UBI control device directory in sysfs
+ * @ctrl_dev: UBI control device major/minor numbers sysfs file
+ * @sysfs_ubi: UBI directory in sysfs
+ * @ubi_dev: UBI device sysfs directory pattern
+ * @ubi_version: UBI version file sysfs path
+ * @dev_dev: UBI device major/minor numbers file pattern
+ * @dev_avail_ebs: count of available eraseblocks sysfs path pattern
+ * @dev_total_ebs: total eraseblocks count sysfs path pattern
+ * @dev_bad_count: count of bad eraseblocks sysfs path pattern
+ * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern
+ * @dev_max_ec: maximum erase counter sysfs path pattern
+ * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks
+ *                handling
+ * @dev_max_vols: maximum volumes number count sysfs path pattern
+ * @dev_min_io_size: minimum I/O unit size sysfs path pattern
+ * @dev_mtd_num: MTD device number
+ * @ubi_vol: UBI volume sysfs directory pattern
+ * @vol_type: volume type sysfs path pattern
+ * @vol_dev: volume major/minor numbers file pattern
+ * @vol_alignment: volume alignment sysfs path pattern
+ * @vol_data_bytes: volume data size sysfs path pattern
+ * @vol_rsvd_ebs: volume reserved size sysfs path pattern
+ * @vol_eb_size: volume eraseblock size sysfs path pattern
+ * @vol_corrupted: volume corruption flag sysfs path pattern
+ * @vol_name: volume name sysfs path pattern
+ */
+struct libubi
+{
+	char *sysfs;
+	char *sysfs_ctrl;
+	char *ctrl_dev;
+	char *sysfs_ubi;
+	char *ubi_dev;
+	char *ubi_version;
+	char *dev_dev;
+	char *dev_avail_ebs;
+	char *dev_total_ebs;
+	char *dev_bad_count;
+	char *dev_eb_size;
+	char *dev_max_ec;
+	char *dev_bad_rsvd;
+	char *dev_max_vols;
+	char *dev_min_io_size;
+	char *dev_mtd_num;
+	char *ubi_vol;
+	char *vol_type;
+	char *vol_dev;
+	char *vol_alignment;
+	char *vol_data_bytes;
+	char *vol_rsvd_ebs;
+	char *vol_eb_size;
+	char *vol_corrupted;
+	char *vol_name;
+	char *vol_max_count;
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !__LIBUBI_INT_H__ */
diff --git a/ubi-utils/libubigen.c b/ubi-utils/libubigen.c
new file mode 100644
index 0000000..9eaa7f5
--- /dev/null
+++ b/ubi-utils/libubigen.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Generating UBI images.
+ *
+ * Authors: Oliver Lohmann
+ *          Artem Bityutskiy
+ */
+
+#define PROGRAM_NAME "libubigen"
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <mtd/ubi-media.h>
+#include <mtd_swab.h>
+#include <libubigen.h>
+#include <crc32.h>
+#include "common.h"
+
+void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
+		      int subpage_size, int vid_hdr_offs, int ubi_ver,
+		      uint32_t image_seq)
+{
+	if (!vid_hdr_offs) {
+		vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
+		vid_hdr_offs /= subpage_size;
+		vid_hdr_offs *= subpage_size;
+	}
+
+	ui->peb_size = peb_size;
+	ui->min_io_size = min_io_size;
+	ui->vid_hdr_offs = vid_hdr_offs;
+	ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
+	ui->data_offs /= min_io_size;
+	ui->data_offs *= min_io_size;
+	ui->leb_size = peb_size - ui->data_offs;
+	ui->ubi_ver = ubi_ver;
+	ui->image_seq = image_seq;
+
+	ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
+	if (ui->max_volumes > UBI_MAX_VOLUMES)
+		ui->max_volumes = UBI_MAX_VOLUMES;
+	ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
+}
+
+struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
+{
+	struct ubi_vtbl_record *vtbl;
+	int i;
+
+	vtbl = calloc(1, ui->vtbl_size);
+	if (!vtbl) {
+		sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
+		return NULL;
+	}
+
+	for (i = 0; i < ui->max_volumes; i++) {
+		uint32_t crc = mtd_crc32(UBI_CRC32_INIT, &vtbl[i],
+				     UBI_VTBL_RECORD_SIZE_CRC);
+		vtbl[i].crc = cpu_to_be32(crc);
+	}
+
+	return vtbl;
+}
+
+int ubigen_add_volume(const struct ubigen_info *ui,
+		      const struct ubigen_vol_info *vi,
+		      struct ubi_vtbl_record *vtbl)
+{
+	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
+	uint32_t tmp;
+
+	if (vi->id >= ui->max_volumes) {
+		errmsg("too high volume id %d, max. volumes is %d",
+		       vi->id, ui->max_volumes);
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (vi->alignment >= ui->leb_size) {
+		errmsg("too large alignment %d, max is %d (LEB size)",
+		       vi->alignment, ui->leb_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	memset(vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
+	tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
+	vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
+	vtbl_rec->alignment = cpu_to_be32(vi->alignment);
+	vtbl_rec->vol_type = vi->type;
+	tmp = ui->leb_size % vi->alignment;
+	vtbl_rec->data_pad = cpu_to_be32(tmp);
+	vtbl_rec->flags = vi->flags;
+
+	memcpy(vtbl_rec->name, vi->name, vi->name_len);
+	vtbl_rec->name[vi->name_len] = '\0';
+	vtbl_rec->name_len = cpu_to_be16(vi->name_len);
+
+	tmp = mtd_crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
+	vtbl_rec->crc =	 cpu_to_be32(tmp);
+	return 0;
+}
+
+void ubigen_init_ec_hdr(const struct ubigen_info *ui,
+		        struct ubi_ec_hdr *hdr, long long ec)
+{
+	uint32_t crc;
+
+	memset(hdr, 0, sizeof(struct ubi_ec_hdr));
+
+	hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->ec = cpu_to_be64(ec);
+	hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
+	hdr->data_offset = cpu_to_be32(ui->data_offs);
+	hdr->image_seq = cpu_to_be32(ui->image_seq);
+
+	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+}
+
+void ubigen_init_vid_hdr(const struct ubigen_info *ui,
+			 const struct ubigen_vol_info *vi,
+			 struct ubi_vid_hdr *hdr, int lnum,
+			 const void *data, int data_size)
+{
+	uint32_t crc;
+
+	memset(hdr, 0, sizeof(struct ubi_vid_hdr));
+
+	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
+	hdr->version = ui->ubi_ver;
+	hdr->vol_type = vi->type;
+	hdr->vol_id = cpu_to_be32(vi->id);
+	hdr->lnum = cpu_to_be32(lnum);
+	hdr->data_pad = cpu_to_be32(vi->data_pad);
+	hdr->compat = vi->compat;
+
+	if (vi->type == UBI_VID_STATIC) {
+		hdr->data_size = cpu_to_be32(data_size);
+		hdr->used_ebs = cpu_to_be32(vi->used_ebs);
+		crc = mtd_crc32(UBI_CRC32_INIT, data, data_size);
+		hdr->data_crc = cpu_to_be32(crc);
+	}
+
+	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+}
+
+int ubigen_write_volume(const struct ubigen_info *ui,
+			const struct ubigen_vol_info *vi, long long ec,
+			long long bytes, int in, int out)
+{
+	int len = vi->usable_leb_size, rd, lnum = 0;
+	char *inbuf, *outbuf;
+
+	if (vi->id >= ui->max_volumes) {
+		errmsg("too high volume id %d, max. volumes is %d",
+		       vi->id, ui->max_volumes);
+		errno = EINVAL;
+		return -1;
+	}
+
+	if (vi->alignment >= ui->leb_size) {
+		errmsg("too large alignment %d, max is %d (LEB size)",
+		       vi->alignment, ui->leb_size);
+		errno = EINVAL;
+		return -1;
+	}
+
+	inbuf = malloc(ui->leb_size);
+	if (!inbuf)
+		return sys_errmsg("cannot allocate %d bytes of memory",
+				  ui->leb_size);
+	outbuf = malloc(ui->peb_size);
+	if (!outbuf) {
+		sys_errmsg("cannot allocate %d bytes of memory", ui->peb_size);
+		goto out_free;
+	}
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
+
+	while (bytes) {
+		int l;
+		struct ubi_vid_hdr *vid_hdr;
+
+		if (bytes < len)
+			len = bytes;
+		bytes -= len;
+
+		l = len;
+		do {
+			rd = read(in, inbuf + len - l, l);
+			if (rd != l) {
+				sys_errmsg("cannot read %d bytes from the input file", l);
+				goto out_free1;
+			}
+
+			l -= rd;
+		} while (l);
+
+		vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+		ubigen_init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
+
+		memcpy(outbuf + ui->data_offs, inbuf, len);
+		memset(outbuf + ui->data_offs + len, 0xFF,
+		       ui->peb_size - ui->data_offs - len);
+
+		if (write(out, outbuf, ui->peb_size) != ui->peb_size) {
+			sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
+			goto out_free1;
+		}
+
+		lnum += 1;
+	}
+
+	free(outbuf);
+	free(inbuf);
+	return 0;
+
+out_free1:
+	free(outbuf);
+out_free:
+	free(inbuf);
+	return -1;
+}
+
+int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
+			    long long ec1, long long ec2,
+			    struct ubi_vtbl_record *vtbl, int fd)
+{
+	int ret;
+	struct ubigen_vol_info vi;
+	char *outbuf;
+	struct ubi_vid_hdr *vid_hdr;
+	off_t seek;
+
+	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
+	vi.id = UBI_LAYOUT_VOLUME_ID;
+	vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
+	vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
+	vi.usable_leb_size = ui->leb_size - vi.data_pad;
+	vi.data_pad = ui->leb_size - vi.usable_leb_size;
+	vi.type = UBI_LAYOUT_VOLUME_TYPE;
+	vi.name = UBI_LAYOUT_VOLUME_NAME;
+	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
+	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
+
+	outbuf = malloc(ui->peb_size);
+	if (!outbuf)
+		return sys_errmsg("failed to allocate %d bytes",
+				  ui->peb_size);
+
+	memset(outbuf, 0xFF, ui->data_offs);
+	vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
+	memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
+	memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
+	       ui->peb_size - ui->data_offs - ui->vtbl_size);
+
+	seek = peb1 * ui->peb_size;
+	if (lseek(fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek output file");
+		goto out_free;
+	}
+
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
+	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
+	ret = write(fd, outbuf, ui->peb_size);
+	if (ret != ui->peb_size) {
+		sys_errmsg("cannot write %d bytes", ui->peb_size);
+		goto out_free;
+	}
+
+	seek = peb2 * ui->peb_size;
+	if (lseek(fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek output file");
+		goto out_free;
+	}
+	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
+	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
+	ret = write(fd, outbuf, ui->peb_size);
+	if (ret != ui->peb_size) {
+		sys_errmsg("cannot write %d bytes", ui->peb_size);
+		goto out_free;
+	}
+
+	free(outbuf);
+	return 0;
+
+out_free:
+	free(outbuf);
+	return -1;
+}
diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
new file mode 100644
index 0000000..bfd7e6d
--- /dev/null
+++ b/ubi-utils/mtdinfo.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (C) 2009 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to get MTD information.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "mtdinfo"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <mtd/mtd-user.h>
+
+#include <libubigen.h>
+#include <libmtd.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int mtdn;
+	unsigned int all:1;
+	unsigned int ubinfo:1;
+	unsigned int map:1;
+	const char *node;
+};
+
+static struct args args = {
+	.mtdn = -1,
+	.ubinfo = 0,
+	.all = 0,
+	.node = NULL,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to print MTD information.";
+
+static const char optionsstr[] =
+"-m, --mtdn=<MTD device number>  MTD device number to get information about\n"
+"                                (deprecated option, will be removed, do not use)\n"
+"-u, --ubi-info                  print what would UBI layout be if it was put\n"
+"                                on this MTD device\n"
+"-M, --map                       print eraseblock map\n"
+"-a, --all                       print information about all MTD devices\n"
+"-h, --help                      print help message\n"
+"-V, --version                   print program version";
+
+static const char usage[] =
+"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n"
+"\t\t[--ubi-info] [--help] [--version]\n"
+"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
+"\t\t[--version]\n"
+"Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
+"Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
+"Example 3: " PROGRAM_NAME " /dev/mtd0 - print information MTD device /dev/mtd0\n"
+"Example 4: " PROGRAM_NAME " /dev/mtd0 -u - print information MTD device /dev/mtd0\n"
+"\t\t\t\tand include UBI layout information\n"
+"Example 5: " PROGRAM_NAME " -a - print information about all MTD devices\n"
+"\t\t\tand include UBI layout information\n";
+
+static const struct option long_options[] = {
+	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
+	{ .name = "map",       .has_arg = 0, .flag = NULL, .val = 'M' },
+	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
+	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "am:uMhV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'a':
+			args.all = 1;
+			break;
+
+		case 'u':
+			args.ubinfo = 1;
+			break;
+
+		case 'm':
+			args.mtdn = simple_strtoul(optarg, &error);
+			if (error || args.mtdn < 0)
+				return errmsg("bad MTD device number: \"%s\"", optarg);
+			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
+			break;
+
+		case 'M':
+			args.map = 1;
+			break;
+
+		case 'h':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			printf("%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc - 1)
+		args.node = argv[optind];
+	else if (optind < argc)
+		return errmsg("more then one MTD device specified (use -h for help)");
+
+	if (args.all && (args.node || args.mtdn != -1)) {
+		args.mtdn = -1;
+		args.node = NULL;
+	}
+
+	if (args.map && !args.node)
+		return errmsg("-M requires MTD device node name");
+
+	return 0;
+}
+
+static int translate_dev(libmtd_t libmtd, const char *node)
+{
+	int err;
+	struct mtd_dev_info mtd;
+
+	err = mtd_get_dev_info(libmtd, node, &mtd);
+	if (err) {
+		if (errno == ENODEV)
+			return errmsg("\"%s\" does not correspond to any "
+				      "existing MTD device", node);
+		return sys_errmsg("cannot get information about MTD "
+				  "device \"%s\"", node);
+	}
+
+	args.mtdn = mtd.mtd_num;
+	return 0;
+}
+
+static void print_ubi_info(const struct mtd_info *mtd_info,
+			   const struct mtd_dev_info *mtd)
+{
+	struct ubigen_info ui;
+
+	if (!mtd_info->sysfs_supported) {
+		errmsg("cannot provide UBI info, becasue sub-page size is "
+		       "not known");
+		return;
+	}
+
+	ubigen_info_init(&ui, mtd->eb_size, mtd->min_io_size, mtd->subpage_size,
+			 0, 1, 0);
+	printf("Default UBI VID header offset:  %d\n", ui.vid_hdr_offs);
+	printf("Default UBI data offset:        %d\n", ui.data_offs);
+	printf("Default UBI LEB size:           ");
+	ubiutils_print_bytes(ui.leb_size, 0);
+	printf("\n");
+	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
+}
+
+static void print_region_map(const struct mtd_dev_info *mtd, int fd,
+			     const region_info_t *reginfo)
+{
+	unsigned long start;
+	int i, width;
+	int ret_locked, errno_locked, ret_bad, errno_bad;
+
+	printf("Eraseblock map:\n");
+
+	/* Figure out the number of spaces to pad w/out libm */
+	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
+		continue;
+
+	/* If we don't have a fd to query, just show the bare map */
+	if (fd == -1) {
+		ret_locked = ret_bad = -1;
+		errno_locked = errno_bad = ENODEV;
+	} else
+		ret_locked = ret_bad = errno_locked = errno_bad = 0;
+
+	for (i = 0; i < reginfo->numblocks; ++i) {
+		start = reginfo->offset + i * reginfo->erasesize;
+		printf(" %*i: %08lx ", width, i, start);
+
+		if (ret_locked != -1) {
+			ret_locked = mtd_is_locked(mtd, fd, i);
+			if (ret_locked == 1)
+				printf("RO ");
+			else
+				errno_locked = errno;
+		}
+		if (ret_locked != 1)
+			printf("   ");
+
+		if (ret_bad != -1) {
+			ret_bad = mtd_is_bad(mtd, fd, i);
+			if (ret_bad == 1)
+				printf("BAD ");
+			else
+				errno_bad = errno;
+		}
+		if (ret_bad != 1)
+			printf("    ");
+
+		if (((i + 1) % 4) == 0)
+			printf("\n");
+	}
+	if (i % 4)
+		printf("\n");
+
+	if (ret_locked == -1 && errno_locked != EOPNOTSUPP) {
+		errno = errno_locked;
+		sys_errmsg("could not read locked block info");
+	}
+
+	if (mtd->bb_allowed && ret_bad == -1 && errno_bad != EOPNOTSUPP) {
+		errno = errno_bad;
+		sys_errmsg("could not read bad block info");
+	}
+}
+
+static void print_region_info(const struct mtd_dev_info *mtd)
+{
+	region_info_t reginfo;
+	int r, fd;
+
+	/* If we don't have any region info, just return */
+	if (!args.map && mtd->region_cnt == 0)
+		return;
+
+	/* First open the device so we can query it */
+	fd = open(args.node, O_RDONLY | O_CLOEXEC);
+	if (fd == -1) {
+		sys_errmsg("couldn't open MTD dev: %s", args.node);
+		if (mtd->region_cnt)
+			return;
+	}
+
+	/* Walk all the regions and show the map for them */
+	if (mtd->region_cnt) {
+		for (r = 0; r < mtd->region_cnt; ++r) {
+			printf("Eraseblock region %i: ", r);
+			if (mtd_regioninfo(fd, r, &reginfo) == 0) {
+				printf(" offset: %#x size: %#x numblocks: %#x\n",
+					reginfo.offset, reginfo.erasesize,
+					reginfo.numblocks);
+				if (args.map)
+					print_region_map(mtd, fd, &reginfo);
+			} else
+				printf(" info is unavailable\n");
+		}
+	} else {
+		reginfo.offset = 0;
+		reginfo.erasesize = mtd->eb_size;
+		reginfo.numblocks = mtd->eb_cnt;
+		reginfo.regionindex = 0;
+		print_region_map(mtd, fd, &reginfo);
+	}
+
+	if (fd != -1)
+		close(fd);
+}
+
+static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
+{
+	int err;
+	struct mtd_dev_info mtd;
+
+	err = mtd_get_dev_info1(libmtd, mtdn, &mtd);
+	if (err) {
+		if (errno == ENODEV)
+			return errmsg("mtd%d does not correspond to any "
+				      "existing MTD device", mtdn);
+		return sys_errmsg("cannot get information about MTD device %d",
+				  mtdn);
+	}
+
+	printf("mtd%d\n", mtd.mtd_num);
+	printf("Name:                           %s\n", mtd.name);
+	printf("Type:                           %s\n", mtd.type_str);
+	printf("Eraseblock size:                ");
+	ubiutils_print_bytes(mtd.eb_size, 0);
+	printf("\n");
+	printf("Amount of eraseblocks:          %d (", mtd.eb_cnt);
+	ubiutils_print_bytes(mtd.size, 0);
+	printf(")\n");
+	printf("Minimum input/output unit size: %d %s\n",
+	       mtd.min_io_size, mtd.min_io_size > 1 ? "bytes" : "byte");
+	if (mtd_info->sysfs_supported)
+		printf("Sub-page size:                  %d %s\n",
+		       mtd.subpage_size,
+		       mtd.subpage_size > 1 ? "bytes" : "byte");
+	else if (mtd.type == MTD_NANDFLASH)
+		printf("Sub-page size:                  unknown\n");
+
+	if (mtd.oob_size > 0)
+		printf("OOB size:                       %d bytes\n",
+		       mtd.oob_size);
+	if (mtd.region_cnt > 0)
+		printf("Additional erase regions:       %d\n", mtd.oob_size);
+	if (mtd_info->sysfs_supported)
+		printf("Character device major/minor:   %d:%d\n",
+		       mtd.major, mtd.minor);
+	printf("Bad blocks are allowed:         %s\n",
+	       mtd.bb_allowed ? "true" : "false");
+	printf("Device is writable:             %s\n",
+	      mtd.writable ? "true" : "false");
+
+	if (args.ubinfo)
+		print_ubi_info(mtd_info, &mtd);
+
+	print_region_info(&mtd);
+
+	printf("\n");
+	return 0;
+}
+
+static int print_general_info(libmtd_t libmtd, const struct mtd_info *mtd_info,
+			      int all)
+{
+	int i, err, first = 1;
+	struct mtd_dev_info mtd;
+
+	printf("Count of MTD devices:           %d\n", mtd_info->mtd_dev_cnt);
+	if (mtd_info->mtd_dev_cnt == 0)
+		return 0;
+
+	for (i = mtd_info->lowest_mtd_num;
+	     i <= mtd_info->highest_mtd_num; i++) {
+		err = mtd_get_dev_info1(libmtd, i, &mtd);
+		if (err == -1) {
+			if (errno == ENODEV)
+				continue;
+			return sys_errmsg("libmtd failed get MTD device %d "
+					  "information", i);
+		}
+
+		if (!first)
+			printf(", mtd%d", i);
+		else {
+			printf("Present MTD devices:            mtd%d", i);
+			first = 0;
+		}
+	}
+	printf("\n");
+	printf("Sysfs interface supported:      %s\n",
+	       mtd_info->sysfs_supported ? "yes" : "no");
+
+	if (!all)
+		return 0;
+
+	first = 1;
+	printf("\n");
+
+	for (i = mtd_info->lowest_mtd_num;
+	     i <= mtd_info->highest_mtd_num; i++) {
+		err = print_dev_info(libmtd, mtd_info, i);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libmtd_t libmtd;
+	struct mtd_info mtd_info;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libmtd = libmtd_open();
+	if (libmtd == NULL) {
+		if (errno == 0)
+			return errmsg("MTD is not present in the system");
+		return sys_errmsg("cannot open libmtd");
+	}
+
+	err = mtd_get_info(libmtd, &mtd_info);
+	if (err) {
+		if (errno == ENODEV)
+			return errmsg("MTD is not present");
+		return sys_errmsg("cannot get MTD information");
+	}
+
+	if (args.node) {
+		/*
+		 * A character device was specified, translate this to MTD
+		 * device number.
+		 */
+		err = translate_dev(libmtd, args.node);
+		if (err)
+			goto out_libmtd;
+	}
+
+	if (args.mtdn == -1)
+		err = print_general_info(libmtd, &mtd_info, args.all);
+	else
+		err = print_dev_info(libmtd, &mtd_info, args.mtdn);
+	if (err)
+		goto out_libmtd;
+
+	libmtd_close(libmtd);
+	return 0;
+
+out_libmtd:
+	libmtd_close(libmtd);
+	return -1;
+}
diff --git a/ubi-utils/src/dictionary.c b/ubi-utils/src/dictionary.c
deleted file mode 100644
index b7c9ebf..0000000
--- a/ubi-utils/src/dictionary.c
+++ /dev/null
@@ -1,405 +0,0 @@
-/*-------------------------------------------------------------------------*/
-/**
-   @file	dictionary.c
-   @author	N. Devillard
-   @date	Sep 2007
-   @version	$Revision: 1.27 $
-   @brief	Implements a dictionary for string variables.
-
-   This module implements a simple dictionary object, i.e. a list
-   of string/string associations. This object is useful to store e.g.
-   informations retrieved from a configuration file (ini files).
-*/
-/*--------------------------------------------------------------------------*/
-
-/*
-	$Id: dictionary.c,v 1.27 2007-11-23 21:39:18 ndevilla Exp $
-	$Revision: 1.27 $
-*/
-/*---------------------------------------------------------------------------
-   								Includes
- ---------------------------------------------------------------------------*/
-#include "dictionary.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/** Maximum value size for integers and doubles. */
-#define MAXVALSZ	1024
-
-/** Minimal allocated number of entries in a dictionary */
-#define DICTMINSZ	128
-
-/** Invalid key token */
-#define DICT_INVALID_KEY    ((char*)-1)
-
-/*---------------------------------------------------------------------------
-  							Private functions
- ---------------------------------------------------------------------------*/
-
-/* Doubles the allocated size associated to a pointer */
-/* 'size' is the current allocated size. */
-static void * mem_double(void * ptr, int size)
-{
-    void * newptr ;
- 
-    newptr = calloc(2*size, 1);
-    if (newptr==NULL) {
-        return NULL ;
-    }
-    memcpy(newptr, ptr, size);
-    free(ptr);
-    return newptr ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Duplicate a string
-  @param    s String to duplicate
-  @return   Pointer to a newly allocated string, to be freed with free()
-
-  This is a replacement for strdup(). This implementation is provided
-  for systems that do not have it.
- */
-/*--------------------------------------------------------------------------*/
-static char * xstrdup(char * s)
-{
-    char * t ;
-    if (!s)
-        return NULL ;
-    t = malloc(strlen(s)+1) ;
-    if (t) {
-        strcpy(t,s);
-    }
-    return t ;
-}
-
-/*---------------------------------------------------------------------------
-  							Function codes
- ---------------------------------------------------------------------------*/
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Compute the hash key for a string.
-  @param	key		Character string to use for key.
-  @return	1 unsigned int on at least 32 bits.
-
-  This hash function has been taken from an Article in Dr Dobbs Journal.
-  This is normally a collision-free function, distributing keys evenly.
-  The key is stored anyway in the struct so that collision can be avoided
-  by comparing the key itself in last resort.
- */
-/*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key)
-{
-	int			len ;
-	unsigned	hash ;
-	int			i ;
-
-	len = strlen(key);
-	for (hash=0, i=0 ; i<len ; i++) {
-		hash += (unsigned)key[i] ;
-		hash += (hash<<10);
-		hash ^= (hash>>6) ;
-	}
-	hash += (hash <<3);
-	hash ^= (hash >>11);
-	hash += (hash <<15);
-	return hash ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Create a new dictionary object.
-  @param	size	Optional initial size of the dictionary.
-  @return	1 newly allocated dictionary objet.
-
-  This function allocates a new dictionary object of given size and returns
-  it. If you do not know in advance (roughly) the number of entries in the
-  dictionary, give size=0.
- */
-/*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size)
-{
-	dictionary	*	d ;
-
-	/* If no size was specified, allocate space for DICTMINSZ */
-	if (size<DICTMINSZ) size=DICTMINSZ ;
-
-	if (!(d = (dictionary *)calloc(1, sizeof(dictionary)))) {
-		return NULL;
-	}
-	d->size = size ;
-	d->val  = (char **)calloc(size, sizeof(char*));
-	d->key  = (char **)calloc(size, sizeof(char*));
-	d->hash = (unsigned int *)calloc(size, sizeof(unsigned));
-	return d ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Delete a dictionary object
-  @param	d	dictionary object to deallocate.
-  @return	void
-
-  Deallocate a dictionary object and all memory associated to it.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * d)
-{
-	int		i ;
-
-	if (d==NULL) return ;
-	for (i=0 ; i<d->size ; i++) {
-		if (d->key[i]!=NULL)
-			free(d->key[i]);
-		if (d->val[i]!=NULL)
-			free(d->val[i]);
-	}
-	free(d->val);
-	free(d->key);
-	free(d->hash);
-	free(d);
-	return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Get a value from a dictionary.
-  @param	d		dictionary object to search.
-  @param	key		Key to look for in the dictionary.
-  @param    def     Default value to return if key not found.
-  @return	1 pointer to internally allocated character string.
-
-  This function locates a key in a dictionary and returns a pointer to its
-  value, or the passed 'def' pointer if no such key can be found in
-  dictionary. The returned character pointer points to data internal to the
-  dictionary object, you should not try to free it or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * dictionary_get(dictionary * d, char * key, char * def)
-{
-	unsigned	hash ;
-	int			i ;
-
-	hash = dictionary_hash(key);
-	for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        /* Compare hash */
-		if (hash==d->hash[i]) {
-            /* Compare string, to avoid hash collisions */
-            if (!strcmp(key, d->key[i])) {
-				return d->val[i] ;
-			}
-		}
-	}
-	return def ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set a value in a dictionary.
-  @param    d       dictionary object to modify.
-  @param    key     Key to modify or add.
-  @param    val     Value to add.
-  @return   int     0 if Ok, anything else otherwise
-
-  If the given key is found in the dictionary, the associated value is
-  replaced by the provided one. If the key cannot be found in the
-  dictionary, it is added to it.
-
-  It is Ok to provide a NULL value for val, but NULL values for the dictionary
-  or the key are considered as errors: the function will return immediately
-  in such a case.
-
-  Notice that if you dictionary_set a variable to NULL, a call to
-  dictionary_get will return a NULL value: the variable will be found, and
-  its value (NULL) is returned. In other words, setting the variable
-  content to NULL is equivalent to deleting the variable from the
-  dictionary. It is not possible (in this implementation) to have a key in
-  the dictionary without value.
-
-  This function returns non-zero in case of failure.
- */
-/*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * d, char * key, char * val)
-{
-	int			i ;
-	unsigned	hash ;
-
-	if (d==NULL || key==NULL) return -1 ;
-	
-	/* Compute hash for this key */
-	hash = dictionary_hash(key) ;
-	/* Find if value is already in dictionary */
-	if (d->n>0) {
-		for (i=0 ; i<d->size ; i++) {
-            if (d->key[i]==NULL)
-                continue ;
-			if (hash==d->hash[i]) { /* Same hash value */
-				if (!strcmp(key, d->key[i])) {	 /* Same key */
-					/* Found a value: modify and return */
-					if (d->val[i]!=NULL)
-						free(d->val[i]);
-                    d->val[i] = val ? xstrdup(val) : NULL ;
-                    /* Value has been modified: return */
-					return 0 ;
-				}
-			}
-		}
-	}
-	/* Add a new value */
-	/* See if dictionary needs to grow */
-	if (d->n==d->size) {
-
-		/* Reached maximum size: reallocate dictionary */
-		d->val  = (char **)mem_double(d->val,  d->size * sizeof(char*)) ;
-		d->key  = (char **)mem_double(d->key,  d->size * sizeof(char*)) ;
-		d->hash = (unsigned int *)mem_double(d->hash, d->size * sizeof(unsigned)) ;
-        if ((d->val==NULL) || (d->key==NULL) || (d->hash==NULL)) {
-            /* Cannot grow dictionary */
-            return -1 ;
-        }
-		/* Double size */
-		d->size *= 2 ;
-	}
-
-    /* Insert key in the first empty slot */
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL) {
-            /* Add key here */
-            break ;
-        }
-    }
-	/* Copy key */
-	d->key[i]  = xstrdup(key);
-    d->val[i]  = val ? xstrdup(val) : NULL ;
-	d->hash[i] = hash;
-	d->n ++ ;
-	return 0 ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Delete a key in a dictionary
-  @param	d		dictionary object to modify.
-  @param	key		Key to remove.
-  @return   void
-
-  This function deletes a key in a dictionary. Nothing is done if the
-  key cannot be found.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char * key)
-{
-	unsigned	hash ;
-	int			i ;
-
-	if (key == NULL) {
-		return;
-	}
-
-	hash = dictionary_hash(key);
-	for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        /* Compare hash */
-		if (hash==d->hash[i]) {
-            /* Compare string, to avoid hash collisions */
-            if (!strcmp(key, d->key[i])) {
-                /* Found key */
-                break ;
-			}
-		}
-	}
-    if (i>=d->size)
-        /* Key not found */
-        return ;
-
-    free(d->key[i]);
-    d->key[i] = NULL ;
-    if (d->val[i]!=NULL) {
-        free(d->val[i]);
-        d->val[i] = NULL ;
-    }
-    d->hash[i] = 0 ;
-    d->n -- ;
-    return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Dump a dictionary to an opened file pointer.
-  @param	d	Dictionary to dump
-  @param	f	Opened file pointer.
-  @return	void
-
-  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
-  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
-  output file pointers.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out)
-{
-	int		i ;
-
-	if (d==NULL || out==NULL) return ;
-	if (d->n<1) {
-		fprintf(out, "empty dictionary\n");
-		return ;
-	}
-	for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]) {
-            fprintf(out, "%20s\t[%s]\n",
-                    d->key[i],
-                    d->val[i] ? d->val[i] : "UNDEF");
-        }
-	}
-	return ;
-}
-
-
-/* Test code */
-#ifdef TESTDIC
-#define NVALS 20000
-int main(int argc, char *argv[])
-{
-	dictionary	*	d ;
-	char	*	val ;
-	int			i ;
-	char		cval[90] ;
-
-	/* Allocate dictionary */
-	printf("allocating...\n");
-	d = dictionary_new(0);
-	
-	/* Set values in dictionary */
-	printf("setting %d values...\n", NVALS);
-	for (i=0 ; i<NVALS ; i++) {
-		sprintf(cval, "%04d", i);
-		dictionary_set(d, cval, "salut");
-	}
-	printf("getting %d values...\n", NVALS);
-	for (i=0 ; i<NVALS ; i++) {
-		sprintf(cval, "%04d", i);
-		val = dictionary_get(d, cval, DICT_INVALID_KEY);
-		if (val==DICT_INVALID_KEY) {
-			printf("cannot get value for key [%s]\n", cval);
-		}
-	}
-    printf("unsetting %d values...\n", NVALS);
-	for (i=0 ; i<NVALS ; i++) {
-		sprintf(cval, "%04d", i);
-		dictionary_unset(d, cval);
-	}
-    if (d->n != 0) {
-        printf("error deleting values\n");
-    }
-	printf("deallocating...\n");
-	dictionary_del(d);
-	return 0 ;
-}
-#endif
-/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/src/dictionary.h
deleted file mode 100644
index c7d1790..0000000
--- a/ubi-utils/src/dictionary.h
+++ /dev/null
@@ -1,174 +0,0 @@
-
-/*-------------------------------------------------------------------------*/
-/**
-   @file    dictionary.h
-   @author  N. Devillard
-   @date    Sep 2007
-   @version $Revision: 1.12 $
-   @brief   Implements a dictionary for string variables.
-
-   This module implements a simple dictionary object, i.e. a list
-   of string/string associations. This object is useful to store e.g.
-   informations retrieved from a configuration file (ini files).
-*/
-/*--------------------------------------------------------------------------*/
-
-/*
-	$Id: dictionary.h,v 1.12 2007-11-23 21:37:00 ndevilla Exp $
-	$Author: ndevilla $
-	$Date: 2007-11-23 21:37:00 $
-	$Revision: 1.12 $
-*/
-
-#ifndef _DICTIONARY_H_
-#define _DICTIONARY_H_
-
-/*---------------------------------------------------------------------------
-   								Includes
- ---------------------------------------------------------------------------*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-/*---------------------------------------------------------------------------
-   								New types
- ---------------------------------------------------------------------------*/
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Dictionary object
-
-  This object contains a list of string/string associations. Each
-  association is identified by a unique string key. Looking up values
-  in the dictionary is speeded up by the use of a (hopefully collision-free)
-  hash function.
- */
-/*-------------------------------------------------------------------------*/
-typedef struct _dictionary_ {
-	int				n ;		/** Number of entries in dictionary */
-	int				size ;	/** Storage size */
-	char 		**	val ;	/** List of string values */
-	char 		**  key ;	/** List of string keys */
-	unsigned	 *	hash ;	/** List of hash values for keys */
-} dictionary ;
-
-
-/*---------------------------------------------------------------------------
-  							Function prototypes
- ---------------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Compute the hash key for a string.
-  @param    key     Character string to use for key.
-  @return   1 unsigned int on at least 32 bits.
-
-  This hash function has been taken from an Article in Dr Dobbs Journal.
-  This is normally a collision-free function, distributing keys evenly.
-  The key is stored anyway in the struct so that collision can be avoided
-  by comparing the key itself in last resort.
- */
-/*--------------------------------------------------------------------------*/
-unsigned dictionary_hash(char * key);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Create a new dictionary object.
-  @param    size    Optional initial size of the dictionary.
-  @return   1 newly allocated dictionary objet.
-
-  This function allocates a new dictionary object of given size and returns
-  it. If you do not know in advance (roughly) the number of entries in the
-  dictionary, give size=0.
- */
-/*--------------------------------------------------------------------------*/
-dictionary * dictionary_new(int size);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete a dictionary object
-  @param    d   dictionary object to deallocate.
-  @return   void
-
-  Deallocate a dictionary object and all memory associated to it.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_del(dictionary * vd);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get a value from a dictionary.
-  @param    d       dictionary object to search.
-  @param    key     Key to look for in the dictionary.
-  @param    def     Default value to return if key not found.
-  @return   1 pointer to internally allocated character string.
-
-  This function locates a key in a dictionary and returns a pointer to its
-  value, or the passed 'def' pointer if no such key can be found in
-  dictionary. The returned character pointer points to data internal to the
-  dictionary object, you should not try to free it or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * dictionary_get(dictionary * d, char * key, char * def);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set a value in a dictionary.
-  @param    d       dictionary object to modify.
-  @param    key     Key to modify or add.
-  @param    val     Value to add.
-  @return   int     0 if Ok, anything else otherwise
-
-  If the given key is found in the dictionary, the associated value is
-  replaced by the provided one. If the key cannot be found in the
-  dictionary, it is added to it.
-
-  It is Ok to provide a NULL value for val, but NULL values for the dictionary
-  or the key are considered as errors: the function will return immediately
-  in such a case.
-
-  Notice that if you dictionary_set a variable to NULL, a call to
-  dictionary_get will return a NULL value: the variable will be found, and
-  its value (NULL) is returned. In other words, setting the variable
-  content to NULL is equivalent to deleting the variable from the
-  dictionary. It is not possible (in this implementation) to have a key in
-  the dictionary without value.
-
-  This function returns non-zero in case of failure.
- */
-/*--------------------------------------------------------------------------*/
-int dictionary_set(dictionary * vd, char * key, char * val);
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete a key in a dictionary
-  @param    d       dictionary object to modify.
-  @param    key     Key to remove.
-  @return   void
-
-  This function deletes a key in a dictionary. Nothing is done if the
-  key cannot be found.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_unset(dictionary * d, char * key);
-
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Dump a dictionary to an opened file pointer.
-  @param    d   Dictionary to dump
-  @param    f   Opened file pointer.
-  @return   void
-
-  Dumps a dictionary onto an opened file pointer. Key pairs are printed out
-  as @c [Key]=[Value], one per line. It is Ok to provide stdout or stderr as
-  output file pointers.
- */
-/*--------------------------------------------------------------------------*/
-void dictionary_dump(dictionary * d, FILE * out);
-
-#endif
diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/src/libiniparser.c
deleted file mode 100644
index 3bea51e..0000000
--- a/ubi-utils/src/libiniparser.c
+++ /dev/null
@@ -1,646 +0,0 @@
-
-/*-------------------------------------------------------------------------*/
-/**
-   @file    iniparser.c
-   @author  N. Devillard
-   @date    Sep 2007
-   @version 3.0
-   @brief   Parser for ini files.
-*/
-/*--------------------------------------------------------------------------*/
-/*
-    $Id: iniparser.c,v 2.18 2008-01-03 18:35:39 ndevilla Exp $
-    $Revision: 2.18 $
-    $Date: 2008-01-03 18:35:39 $
-*/
-/*---------------------------- Includes ------------------------------------*/
-#include <ctype.h>
-#include <libiniparser.h>
-
-/*---------------------------- Defines -------------------------------------*/
-#define ASCIILINESZ         (1024)
-#define INI_INVALID_KEY     ((char*)-1)
-
-/*---------------------------------------------------------------------------
-                        Private to this module
- ---------------------------------------------------------------------------*/
-/**
- * This enum stores the status for each parsed line (internal use only).
- */
-typedef enum _line_status_ {
-    LINE_UNPROCESSED,
-    LINE_ERROR,
-    LINE_EMPTY,
-    LINE_COMMENT,
-    LINE_SECTION,
-    LINE_VALUE
-} line_status ;
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Convert a string to lowercase.
-  @param	s	String to convert.
-  @return	ptr to statically allocated string.
-
-  This function returns a pointer to a statically allocated string
-  containing a lowercased version of the input string. Do not free
-  or modify the returned string! Since the returned string is statically
-  allocated, it will be modified at each function call (not re-entrant).
- */
-/*--------------------------------------------------------------------------*/
-static char * strlwc(const char * s)
-{
-    static char l[ASCIILINESZ+1];
-    int i ;
-
-    if (s==NULL) return NULL ;
-    memset(l, 0, ASCIILINESZ+1);
-    i=0 ;
-    while (s[i] && i<ASCIILINESZ) {
-        l[i] = (char)tolower((int)s[i]);
-        i++ ;
-    }
-    l[ASCIILINESZ]=(char)0;
-    return l ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Remove blanks at the beginning and the end of a string.
-  @param	s	String to parse.
-  @return	ptr to statically allocated string.
-
-  This function returns a pointer to a statically allocated string,
-  which is identical to the input string, except that all blank
-  characters at the end and the beg. of the string have been removed.
-  Do not free or modify the returned string! Since the returned string
-  is statically allocated, it will be modified at each function call
-  (not re-entrant).
- */
-/*--------------------------------------------------------------------------*/
-static char * strstrip(char * s)
-{
-    static char l[ASCIILINESZ+1];
-	char * last ;
-	
-    if (s==NULL) return NULL ;
-    
-	while (isspace((int)*s) && *s) s++;
-	memset(l, 0, ASCIILINESZ+1);
-	strcpy(l, s);
-	last = l + strlen(l);
-	while (last > l) {
-		if (!isspace((int)*(last-1)))
-			break ;
-		last -- ;
-	}
-	*last = (char)0;
-	return (char*)l ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get number of sections in a dictionary
-  @param    d   Dictionary to examine
-  @return   int Number of sections found in dictionary
-
-  This function returns the number of sections found in a dictionary.
-  The test to recognize sections is done on the string stored in the
-  dictionary: a section name is given as "section" whereas a key is
-  stored as "section:key", thus the test looks for entries that do not
-  contain a colon.
-
-  This clearly fails in the case a section name contains a colon, but
-  this should simply be avoided.
-
-  This function returns -1 in case of error.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getnsec(dictionary * d)
-{
-    int i ;
-    int nsec ;
-
-    if (d==NULL) return -1 ;
-    nsec=0 ;
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        if (strchr(d->key[i], ':')==NULL) {
-            nsec ++ ;
-        }
-    }
-    return nsec ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get name for section n in a dictionary.
-  @param    d   Dictionary to examine
-  @param    n   Section number (from 0 to nsec-1).
-  @return   Pointer to char string
-
-  This function locates the n-th section in a dictionary and returns
-  its name as a pointer to a string statically allocated inside the
-  dictionary. Do not free or modify the returned string!
-
-  This function returns NULL in case of error.
- */
-/*--------------------------------------------------------------------------*/
-char * iniparser_getsecname(dictionary * d, int n)
-{
-    int i ;
-    int foundsec ;
-
-    if (d==NULL || n<0) return NULL ;
-    foundsec=0 ;
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        if (strchr(d->key[i], ':')==NULL) {
-            foundsec++ ;
-            if (foundsec>n)
-                break ;
-        }
-    }
-    if (foundsec<=n) {
-        return NULL ;
-    }
-    return d->key[i] ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Dump a dictionary to an opened file pointer.
-  @param    d   Dictionary to dump.
-  @param    f   Opened file pointer to dump to.
-  @return   void
-
-  This function prints out the contents of a dictionary, one element by
-  line, onto the provided file pointer. It is OK to specify @c stderr
-  or @c stdout as output files. This function is meant for debugging
-  purposes mostly.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_dump(dictionary * d, FILE * f)
-{
-    int     i ;
-
-    if (d==NULL || f==NULL) return ;
-    for (i=0 ; i<d->size ; i++) {
-        if (d->key[i]==NULL)
-            continue ;
-        if (d->val[i]!=NULL) {
-            fprintf(f, "[%s]=[%s]\n", d->key[i], d->val[i]);
-        } else {
-            fprintf(f, "[%s]=UNDEF\n", d->key[i]);
-        }
-    }
-    return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Save a dictionary to a loadable ini file
-  @param    d   Dictionary to dump
-  @param    f   Opened file pointer to dump to
-  @return   void
-
-  This function dumps a given dictionary into a loadable ini file.
-  It is Ok to specify @c stderr or @c stdout as output files.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_dump_ini(dictionary * d, FILE * f)
-{
-    int     i, j ;
-    char    keym[ASCIILINESZ+1];
-    int     nsec ;
-    char *  secname ;
-    int     seclen ;
-
-    if (d==NULL || f==NULL) return ;
-
-    nsec = iniparser_getnsec(d);
-    if (nsec<1) {
-        /* No section in file: dump all keys as they are */
-        for (i=0 ; i<d->size ; i++) {
-            if (d->key[i]==NULL)
-                continue ;
-            fprintf(f, "%s = %s\n", d->key[i], d->val[i]);
-        }
-        return ;
-    }
-    for (i=0 ; i<nsec ; i++) {
-        secname = iniparser_getsecname(d, i) ;
-        seclen  = (int)strlen(secname);
-        fprintf(f, "\n[%s]\n", secname);
-        sprintf(keym, "%s:", secname);
-        for (j=0 ; j<d->size ; j++) {
-            if (d->key[j]==NULL)
-                continue ;
-            if (!strncmp(d->key[j], keym, seclen+1)) {
-                fprintf(f,
-                        "%-30s = %s\n",
-                        d->key[j]+seclen+1,
-                        d->val[j] ? d->val[j] : "");
-            }
-        }
-    }
-    fprintf(f, "\n");
-    return ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key
-  @param    d       Dictionary to search
-  @param    key     Key string to look for
-  @param    def     Default value to return if key not found.
-  @return   pointer to statically allocated character string
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the pointer passed as 'def' is returned.
-  The returned char pointer is pointing to a string allocated in
-  the dictionary, do not free or modify it.
- */
-/*--------------------------------------------------------------------------*/
-char * iniparser_getstring(dictionary * d, const char * key, char * def)
-{
-    char * lc_key ;
-    char * sval ;
-
-    if (d==NULL || key==NULL)
-        return def ;
-
-    lc_key = strlwc(key);
-    sval = dictionary_get(d, lc_key, def);
-    return sval ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to an int
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   integer
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
-
-  Supported values for integers include the usual C notation
-  so decimal, octal (starting with 0) and hexadecimal (starting with 0x)
-  are supported. Examples:
-
-  "42"      ->  42
-  "042"     ->  34 (octal -> decimal)
-  "0x42"    ->  66 (hexa  -> decimal)
-
-  Warning: the conversion may overflow in various ways. Conversion is
-  totally outsourced to strtol(), see the associated man page for overflow
-  handling.
-
-  Credits: Thanks to A. Becker for suggesting strtol()
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getint(dictionary * d, const char * key, int notfound)
-{
-    char    *   str ;
-
-    str = iniparser_getstring(d, key, INI_INVALID_KEY);
-    if (str==INI_INVALID_KEY) return notfound ;
-    return (int)strtol(str, NULL, 0);
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to a double
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   double
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
- */
-/*--------------------------------------------------------------------------*/
-double iniparser_getdouble(dictionary * d, char * key, double notfound)
-{
-    char    *   str ;
-
-    str = iniparser_getstring(d, key, INI_INVALID_KEY);
-    if (str==INI_INVALID_KEY) return notfound ;
-    return atof(str);
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Get the string associated to a key, convert to a boolean
-  @param    d Dictionary to search
-  @param    key Key string to look for
-  @param    notfound Value to return in case of error
-  @return   integer
-
-  This function queries a dictionary for a key. A key as read from an
-  ini file is given as "section:key". If the key cannot be found,
-  the notfound value is returned.
-
-  A true boolean is found if one of the following is matched:
-
-  - A string starting with 'y'
-  - A string starting with 'Y'
-  - A string starting with 't'
-  - A string starting with 'T'
-  - A string starting with '1'
-
-  A false boolean is found if one of the following is matched:
-
-  - A string starting with 'n'
-  - A string starting with 'N'
-  - A string starting with 'f'
-  - A string starting with 'F'
-  - A string starting with '0'
-
-  The notfound value returned if no boolean is identified, does not
-  necessarily have to be 0 or 1.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_getboolean(dictionary * d, const char * key, int notfound)
-{
-    char    *   c ;
-    int         ret ;
-
-    c = iniparser_getstring(d, key, INI_INVALID_KEY);
-    if (c==INI_INVALID_KEY) return notfound ;
-    if (c[0]=='y' || c[0]=='Y' || c[0]=='1' || c[0]=='t' || c[0]=='T') {
-        ret = 1 ;
-    } else if (c[0]=='n' || c[0]=='N' || c[0]=='0' || c[0]=='f' || c[0]=='F') {
-        ret = 0 ;
-    } else {
-        ret = notfound ;
-    }
-    return ret;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Finds out if a given entry exists in a dictionary
-  @param    ini     Dictionary to search
-  @param    entry   Name of the entry to look for
-  @return   integer 1 if entry exists, 0 otherwise
-
-  Finds out if a given entry exists in the dictionary. Since sections
-  are stored as keys with NULL associated values, this is the only way
-  of querying for the presence of sections in a dictionary.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_find_entry(
-    dictionary  *   ini,
-    char        *   entry
-)
-{
-    int found=0 ;
-    if (iniparser_getstring(ini, entry, INI_INVALID_KEY)!=INI_INVALID_KEY) {
-        found = 1 ;
-    }
-    return found ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Set an entry in a dictionary.
-  @param    ini     Dictionary to modify.
-  @param    entry   Entry to modify (entry name)
-  @param    val     New value to associate to the entry.
-  @return   int 0 if Ok, -1 otherwise.
-
-  If the given entry can be found in the dictionary, it is modified to
-  contain the provided value. If it cannot be found, -1 is returned.
-  It is Ok to set val to NULL.
- */
-/*--------------------------------------------------------------------------*/
-int iniparser_set(dictionary * ini, char * entry, char * val)
-{
-    return dictionary_set(ini, strlwc(entry), val) ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Delete an entry in a dictionary
-  @param    ini     Dictionary to modify
-  @param    entry   Entry to delete (entry name)
-  @return   void
-
-  If the given entry can be found, it is deleted from the dictionary.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_unset(dictionary * ini, char * entry)
-{
-    dictionary_unset(ini, strlwc(entry));
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief	Load a single line from an INI file
-  @param    input_line  Input line, may be concatenated multi-line input
-  @param    section     Output space to store section
-  @param    key         Output space to store key
-  @param    value       Output space to store value
-  @return   line_status value
- */
-/*--------------------------------------------------------------------------*/
-static line_status iniparser_line(
-    char * input_line,
-    char * section,
-    char * key,
-    char * value)
-{   
-    line_status sta ;
-    char        line[ASCIILINESZ+1];
-    int         len ;
-
-    strcpy(line, strstrip(input_line));
-    len = (int)strlen(line);
-
-    sta = LINE_UNPROCESSED ;
-    if (len<1) {
-        /* Empty line */
-        sta = LINE_EMPTY ;
-    } else if (line[0]=='#') {
-        /* Comment line */
-        sta = LINE_COMMENT ; 
-    } else if (line[0]=='[' && line[len-1]==']') {
-        /* Section name */
-        sscanf(line, "[%[^]]", section);
-        strcpy(section, strstrip(section));
-        strcpy(section, strlwc(section));
-        sta = LINE_SECTION ;
-    } else if (sscanf (line, "%[^=] = \"%[^\"]\"", key, value) == 2
-           ||  sscanf (line, "%[^=] = '%[^\']'",   key, value) == 2
-           ||  sscanf (line, "%[^=] = %[^;#]",     key, value) == 2) {
-        /* Usual key=value, with or without comments */
-        strcpy(key, strstrip(key));
-        strcpy(key, strlwc(key));
-        strcpy(value, strstrip(value));
-        /*
-         * sscanf cannot handle '' or "" as empty values
-         * this is done here
-         */
-        if (!strcmp(value, "\"\"") || (!strcmp(value, "''"))) {
-            value[0]=0 ;
-        }
-        sta = LINE_VALUE ;
-    } else if (sscanf(line, "%[^=] = %[;#]", key, value)==2
-           ||  sscanf(line, "%[^=] %[=]", key, value) == 2) {
-        /*
-         * Special cases:
-         * key=
-         * key=;
-         * key=#
-         */
-        strcpy(key, strstrip(key));
-        strcpy(key, strlwc(key));
-        value[0]=0 ;
-        sta = LINE_VALUE ;
-    } else {
-        /* Generate syntax error */
-        sta = LINE_ERROR ;
-    }
-    return sta ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Parse an ini file and return an allocated dictionary object
-  @param    ininame Name of the ini file to read.
-  @return   Pointer to newly allocated dictionary
-
-  This is the parser for ini files. This function is called, providing
-  the name of the file to be read. It returns a dictionary object that
-  should not be accessed directly, but through accessor functions
-  instead.
-
-  The returned dictionary must be freed using iniparser_freedict().
- */
-/*--------------------------------------------------------------------------*/
-dictionary * iniparser_load(const char * ininame)
-{
-    FILE * in ;
-
-    char line    [ASCIILINESZ+1] ;
-    char section [ASCIILINESZ+1] ;
-    char key     [ASCIILINESZ+1] ;
-    char tmp     [ASCIILINESZ+1] ;
-    char val     [ASCIILINESZ+1] ;
-
-    int  last=0 ;
-    int  len ;
-    int  lineno=0 ;
-    int  errs=0;
-
-    dictionary * dict ;
-
-    if ((in=fopen(ininame, "r"))==NULL) {
-        fprintf(stderr, "iniparser: cannot open %s\n", ininame);
-        return NULL ;
-    }
-
-    dict = dictionary_new(0) ;
-    if (!dict) {
-        fclose(in);
-        return NULL ;
-    }
-
-    memset(line,    0, ASCIILINESZ);
-    memset(section, 0, ASCIILINESZ);
-    memset(key,     0, ASCIILINESZ);
-    memset(val,     0, ASCIILINESZ);
-    last=0 ;
-
-    while (fgets(line+last, ASCIILINESZ-last, in)!=NULL) {
-        lineno++ ;
-        len = (int)strlen(line)-1;
-        /* Safety check against buffer overflows */
-        if (line[len]!='\n') {
-            fprintf(stderr,
-                    "iniparser: input line too long in %s (%d)\n",
-                    ininame,
-                    lineno);
-            dictionary_del(dict);
-            fclose(in);
-            return NULL ;
-        }
-        /* Get rid of \n and spaces at end of line */
-        while ((len>=0) &&
-                ((line[len]=='\n') || (isspace(line[len])))) {
-            line[len]=0 ;
-            len-- ;
-        }
-        /* Detect multi-line */
-        if (line[len]=='\\') {
-            /* Multi-line value */
-            last=len ;
-            continue ;
-        } else {
-            last=0 ;
-        }
-        switch (iniparser_line(line, section, key, val)) {
-            case LINE_EMPTY:
-            case LINE_COMMENT:
-            break ;
-
-            case LINE_SECTION:
-            errs = dictionary_set(dict, section, NULL);
-            break ;
-
-            case LINE_VALUE:
-            sprintf(tmp, "%s:%s", section, key);
-            errs = dictionary_set(dict, tmp, val) ;
-            break ;
-
-            case LINE_ERROR:
-            fprintf(stderr, "iniparser: syntax error in %s (%d):\n",
-                    ininame,
-                    lineno);
-            fprintf(stderr, "-> %s\n", line);
-            errs++ ;
-            break;
-
-            default:
-            break ;
-        }
-        memset(line, 0, ASCIILINESZ);
-        last=0;
-        if (errs<0) {
-            fprintf(stderr, "iniparser: memory allocation failure\n");
-            break ;
-        }
-    }
-    if (errs) {
-        dictionary_del(dict);
-        dict = NULL ;
-    }
-    fclose(in);
-    return dict ;
-}
-
-/*-------------------------------------------------------------------------*/
-/**
-  @brief    Free all memory associated to an ini dictionary
-  @param    d Dictionary to free
-  @return   void
-
-  Free all memory associated to an ini dictionary.
-  It is mandatory to call this function before the dictionary object
-  gets out of the current context.
- */
-/*--------------------------------------------------------------------------*/
-void iniparser_freedict(dictionary * d)
-{
-    dictionary_del(d);
-}
-
-/* vim: set ts=4 et sw=4 tw=75 */
diff --git a/ubi-utils/src/libscan.c b/ubi-utils/src/libscan.c
deleted file mode 100644
index dc47a89..0000000
--- a/ubi-utils/src/libscan.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem Bityutskiy
- *
- * UBI scanning library.
- */
-
-#define PROGRAM_NAME "libscan"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdint.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdlib.h>
-
-#include <mtd_swab.h>
-#include <mtd/ubi-media.h>
-#include <mtd/mtd-user.h>
-#include <libmtd.h>
-#include <libscan.h>
-#include <crc32.h>
-#include "common.h"
-
-static int all_ff(const void *buf, int len)
-{
-	int i;
-	const uint8_t *p = buf;
-
-	for (i = 0; i < len; i++)
-		if (p[i] != 0xFF)
-			return 0;
-	return 1;
-}
-
-int ubi_scan(struct mtd_dev_info *mtd, int fd, struct ubi_scan_info **info,
-	     int verbose)
-{
-	int eb, v = (verbose == 2), pr = (verbose == 1);
-	struct ubi_scan_info *si;
-	unsigned long long sum = 0;
-
-	si = calloc(1, sizeof(struct ubi_scan_info));
-	if (!si)
-		return sys_errmsg("cannot allocate %zd bytes of memory",
-				  sizeof(struct ubi_scan_info));
-
-	si->ec = calloc(mtd->eb_cnt, sizeof(uint32_t));
-	if (!si->ec) {
-		sys_errmsg("cannot allocate %zd bytes of memory",
-			   sizeof(struct ubi_scan_info));
-		goto out_si;
-	}
-
-	si->vid_hdr_offs = si->data_offs = -1;
-
-	verbose(v, "start scanning eraseblocks 0-%d", mtd->eb_cnt);
-	for (eb = 0; eb < mtd->eb_cnt; eb++) {
-		int ret;
-		uint32_t crc;
-		struct ubi_ec_hdr ech;
-		unsigned long long ec;
-
-		if (v) {
-			normsg_cont("scanning eraseblock %d", eb);
-			fflush(stdout);
-		}
-		if (pr) {
-			printf("\r" PROGRAM_NAME ": scanning eraseblock %d -- %2lld %% complete  ",
-			       eb, (long long)(eb + 1) * 100 / mtd->eb_cnt);
-			fflush(stdout);
-		}
-
-		ret = mtd_is_bad(mtd, fd, eb);
-		if (ret == -1)
-			goto out_ec;
-		if (ret) {
-			si->bad_cnt += 1;
-			si->ec[eb] = EB_BAD;
-			if (v)
-				printf(": bad\n");
-			continue;
-		}
-
-		ret = mtd_read(mtd, fd, eb, 0, &ech, sizeof(struct ubi_ec_hdr));
-		if (ret < 0)
-			goto out_ec;
-
-		if (be32_to_cpu(ech.magic) != UBI_EC_HDR_MAGIC) {
-			if (all_ff(&ech, sizeof(struct ubi_ec_hdr))) {
-				si->empty_cnt += 1;
-				si->ec[eb] = EB_EMPTY;
-				if (v)
-					printf(": empty\n");
-			} else {
-				si->alien_cnt += 1;
-				si->ec[eb] = EB_ALIEN;
-				if (v)
-					printf(": alien\n");
-			}
-			continue;
-		}
-
-		crc = mtd_crc32(UBI_CRC32_INIT, &ech, UBI_EC_HDR_SIZE_CRC);
-		if (be32_to_cpu(ech.hdr_crc) != crc) {
-			si->corrupted_cnt += 1;
-			si->ec[eb] = EB_CORRUPTED;
-			if (v)
-				printf(": bad CRC %#08x, should be %#08x\n",
-				       crc, be32_to_cpu(ech.hdr_crc));
-			continue;
-		}
-
-		ec = be64_to_cpu(ech.ec);
-		if (ec > EC_MAX) {
-			if (pr)
-				printf("\n");
-			errmsg("erase counter in EB %d is %llu, while this "
-			       "program expects them to be less than %u",
-			       eb, ec, EC_MAX);
-			goto out_ec;
-		}
-
-		if (si->vid_hdr_offs == -1) {
-			si->vid_hdr_offs = be32_to_cpu(ech.vid_hdr_offset);
-			si->data_offs = be32_to_cpu(ech.data_offset);
-			if (si->data_offs % mtd->min_io_size) {
-				if (pr)
-					printf("\n");
-				if (v)
-					printf(": corrupted because of the below\n");
-				warnmsg("bad data offset %d at eraseblock %d (n"
-					"of multiple of min. I/O unit size %d)",
-					si->data_offs, eb, mtd->min_io_size);
-				warnmsg("treat eraseblock %d as corrupted", eb);
-				si->corrupted_cnt += 1;
-				si->ec[eb] = EB_CORRUPTED;
-				continue;
-
-			}
-		} else {
-			if ((int)be32_to_cpu(ech.vid_hdr_offset) != si->vid_hdr_offs) {
-				if (pr)
-					printf("\n");
-				if (v)
-					printf(": corrupted because of the below\n");
-				warnmsg("inconsistent VID header offset: was "
-					"%d, but is %d in eraseblock %d",
-					si->vid_hdr_offs,
-					be32_to_cpu(ech.vid_hdr_offset), eb);
-				warnmsg("treat eraseblock %d as corrupted", eb);
-				si->corrupted_cnt += 1;
-				si->ec[eb] = EB_CORRUPTED;
-				continue;
-			}
-			if ((int)be32_to_cpu(ech.data_offset) != si->data_offs) {
-				if (pr)
-					printf("\n");
-				if (v)
-					printf(": corrupted because of the below\n");
-				warnmsg("inconsistent data offset: was %d, but"
-					" is %d in eraseblock %d",
-					si->data_offs,
-					be32_to_cpu(ech.data_offset), eb);
-				warnmsg("treat eraseblock %d as corrupted", eb);
-				si->corrupted_cnt += 1;
-				si->ec[eb] = EB_CORRUPTED;
-				continue;
-			}
-		}
-
-		si->ok_cnt += 1;
-		si->ec[eb] = ec;
-		if (v)
-			printf(": OK, erase counter %u\n", si->ec[eb]);
-	}
-
-	if (si->ok_cnt != 0) {
-		/* Calculate mean erase counter */
-		for (eb = 0; eb < mtd->eb_cnt; eb++) {
-			if (si->ec[eb] > EC_MAX)
-				continue;
-			sum += si->ec[eb];
-		}
-		si->mean_ec = sum / si->ok_cnt;
-	}
-
-	si->good_cnt = mtd->eb_cnt - si->bad_cnt;
-	verbose(v, "finished, mean EC %lld, %d OK, %d corrupted, %d empty, %d "
-		"alien, bad %d", si->mean_ec, si->ok_cnt, si->corrupted_cnt,
-		si->empty_cnt, si->alien_cnt, si->bad_cnt);
-
-	*info = si;
-	if (pr)
-		printf("\n");
-	return 0;
-
-out_ec:
-	free(si->ec);
-out_si:
-	free(si);
-	*info = NULL;
-	return -1;
-}
-
-void ubi_scan_free(struct ubi_scan_info *si)
-{
-	free(si->ec);
-	free(si);
-}
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/src/libubi.c
deleted file mode 100644
index 4d5f316..0000000
--- a/ubi-utils/src/libubi.c
+++ /dev/null
@@ -1,1372 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#define PROGRAM_NAME "libubi"
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <limits.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <libubi.h>
-#include "libubi_int.h"
-#include "common.h"
-
-/**
- * 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) {
-		sys_errmsg("cannot allocate %d bytes", len1 + len2 + 2);
-		return NULL;
-	}
-
-	memcpy(n, path, len1);
-	if (n[len1 - 1] != '/')
-		n[len1++] = '/';
-
-	memcpy(n + len1, name, len2 + 1);
-	return n;
-}
-
-/**
- * read_positive_ll - read a positive 'long long' value from a file.
- * @file: the file to read from
- * @value: the result is stored here
- *
- * This function reads file @file and interprets its contents as a positive
- * 'long long' integer. If this is not true, it fails with %EINVAL error code.
- * Returns %0 in case of success and %-1 in case of failure.
- */
-static int read_positive_ll(const char *file, long long *value)
-{
-	int fd, rd;
-	char buf[50];
-
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	rd = read(fd, buf, sizeof(buf));
-	if (rd == -1) {
-		sys_errmsg("cannot read \"%s\"", file);
-		goto out_error;
-	}
-	if (rd == sizeof(buf)) {
-		errmsg("contents of \"%s\" is too long", file);
-		errno = EINVAL;
-		goto out_error;
-	}
-	buf[rd] = '\0';
-
-	if (sscanf(buf, "%lld\n", value) != 1) {
-		errmsg("cannot read integer from \"%s\"\n", file);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (*value < 0) {
-		errmsg("negative value %lld in \"%s\"", *value, file);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (close(fd))
-		return sys_errmsg("close failed on \"%s\"", file);
-
-	return 0;
-
-out_error:
-	close(fd);
-	return -1;
-}
-
-/**
- * read_positive_int - read a positive 'int' value from a file.
- * @file: the file to read from
- * @value: the result is stored here
- *
- * This function is the same as 'read_positive_ll()', but it reads an 'int'
- * value, not 'long long'.
- */
-static int read_positive_int(const char *file, int *value)
-{
-	long long res;
-
-	if (read_positive_ll(file, &res))
-		return -1;
-
-	/* Make sure the value is not too big */
-	if (res > INT_MAX) {
-		errmsg("value %lld read from file \"%s\" is out of range",
-		       res, file);
-		errno = EINVAL;
-		return -1;
-	}
-
-	*value = res;
-	return 0;
-}
-
-/**
- * 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 read_data(const char *file, void *buf, int buf_len)
-{
-	int fd, rd, tmp, tmp1;
-
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	rd = read(fd, buf, buf_len);
-	if (rd == -1) {
-		sys_errmsg("cannot read \"%s\"", file);
-		goto out_error;
-	}
-
-	if (rd == buf_len) {
-		errmsg("contents of \"%s\" is too long", file);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	((char *)buf)[rd] = '\0';
-
-	/* Make sure all data is read */
-	tmp1 = read(fd, &tmp, 1);
-	if (tmp1 == 1) {
-		sys_errmsg("cannot read \"%s\"", file);
-		goto out_error;
-	}
-	if (tmp1) {
-		errmsg("file \"%s\" contains too much data (> %d bytes)",
-		       file, buf_len);
-		errno = EINVAL;
-		goto out_error;
-	}
-
-	if (close(fd)) {
-		sys_errmsg("close failed on \"%s\"", file);
-		return -1;
-	}
-
-	return rd;
-
-out_error:
-	close(fd);
-	return -1;
-}
-
-/**
- * read_major - read major and minor numbers from a file.
- * @file: name of the file to read from
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns % in case of succes, and %-1 in case of failure.
- */
-static int read_major(const char *file, int *major, int *minor)
-{
-	int ret;
-	char buf[50];
-
-	ret = read_data(file, buf, 50);
-	if (ret < 0)
-		return ret;
-
-	ret = sscanf(buf, "%d:%d\n", major, minor);
-	if (ret != 2) {
-		errno = EINVAL;
-		return errmsg("\"%s\" does not have major:minor format", file);
-	}
-
-	if (*major < 0 || *minor < 0) {
-		errno = EINVAL;
-		return errmsg("bad major:minor %d:%d in \"%s\"",
-			      *major, *minor, file);
-	}
-
-	return 0;
-}
-
-/**
- * dev_read_int - read a positive 'int' value from an UBI device sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_int(const char *patt, int dev_num, int *value)
-{
-	char file[strlen(patt) + 50];
-
-	sprintf(file, patt, dev_num);
-	return read_positive_int(file, value);
-}
-
-/**
- * vol_read_int - read a positive 'int' value from an UBI volume sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_int(const char *patt, int dev_num, int vol_id, int *value)
-{
-	char file[strlen(patt) + 100];
-
-	sprintf(file, patt, dev_num, vol_id);
-	return read_positive_int(file, value);
-}
-
-/**
- * dev_read_ll - read a positive 'long long' value from an UBI device sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_read_ll(const char *patt, int dev_num, long long *value)
-{
-	char file[strlen(patt) + 50];
-
-	sprintf(file, patt, dev_num);
-	return read_positive_ll(file, value);
-}
-
-/**
- * vol_read_ll - read a positive 'long long' value from an UBI volume sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @value: the result is stored here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int vol_read_ll(const char *patt, int dev_num, int vol_id,
-		       long long *value)
-{
-	char file[strlen(patt) + 100];
-
-	sprintf(file, patt, dev_num, vol_id);
-	return read_positive_ll(file, value);
-}
-
-/**
- * vol_read_data - read data from an UBI volume's sysfs file.
- * @patt: file pattern to read from
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @buf: 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.
- */
-static int vol_read_data(const char *patt, int dev_num, int vol_id, void *buf,
-			 int buf_len)
-{
-	char file[strlen(patt) + 100];
-
-	sprintf(file, patt, dev_num, vol_id);
-	return read_data(file, buf, buf_len);
-}
-
-/**
- * dev_get_major - get major and minor numbers of an UBI device.
- * @lib: libubi descriptor
- * @dev_num: UBI device number
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int dev_get_major(struct libubi *lib, int dev_num, int *major, int *minor)
-{
-	char file[strlen(lib->dev_dev) + 50];
-
-	sprintf(file, lib->dev_dev, dev_num);
-	return read_major(file, major, minor);
-}
-
-/**
- * vol_get_major - get major and minor numbers of an UBI volume.
- * @lib: libubi descriptor
- * @dev_num: UBI device number
- * @vol_id: volume ID
- * @major: major number is returned here
- * @minor: minor number is returned here
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int vol_get_major(struct libubi *lib, int dev_num, int vol_id,
-			 int *major, int *minor)
-{
-	char file[strlen(lib->vol_dev) + 100];
-
-	sprintf(file, lib->vol_dev, dev_num, vol_id);
-	return read_major(file, major, minor);
-}
-
-/**
- * vol_node2nums - find UBI device number and volume ID by volume device node
- *                 file.
- * @lib: UBI library descriptor
- * @node: UBI character device node name
- * @dev_num: UBI device number is returned here
- * @vol_id: volume ID is returned hers
- *
- * This function returns zero in case of succes and %-1 in case of failure.
- */
-static int vol_node2nums(struct libubi *lib, const char *node, int *dev_num,
-			 int *vol_id)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, fd, major, minor;
-	char file[strlen(lib->ubi_vol) + 100];
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot get information about \"%s\"",
-				  node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a character device", node);
-	}
-
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
-
-	if (minor == 0) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a volume character device", node);
-	}
-
-	if (ubi_get_info((libubi_t *)lib, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-
-		ret = dev_get_major(lib, i, &major1, &minor1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (major1 == major)
-			break;
-	}
-
-	if (i > info.highest_dev_num) {
-		errno = ENODEV;
-		return -1;
-	}
-
-	/* Make sure this UBI volume exists */
-	sprintf(file, lib->ubi_vol, i, minor - 1);
-	fd = open(file, O_RDONLY);
-	if (fd == -1) {
-		errno = ENODEV;
-		return -1;
-	}
-
-	*dev_num = i;
-	*vol_id = minor - 1;
-	errno = 0;
-	return 0;
-}
-
-/**
- * dev_node2num - find UBI device number by its character device node.
- * @lib: UBI library descriptor
- * @node: UBI character device node name
- * @dev_num: UBI device number is returned here
- *
- * This function returns %0 in case of success and %-1 in case of failure.
- */
-static int dev_node2num(struct libubi *lib, const char *node, int *dev_num)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, major, minor;
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot get information about \"%s\"", node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not a character device", node);
-	}
-
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
-
-	if (minor != 0) {
-		errno = EINVAL;
-		return errmsg("\"%s\" is not an UBI character device", node);
-	}
-
-	if (ubi_get_info((libubi_t *)lib, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-
-		ret = dev_get_major(lib, i, &major1, &minor1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (major1 == major) {
-			if (minor1 != 0) {
-				errmsg("UBI character device minor number is "
-				       "%d, but must be 0", minor1);
-				errno = EINVAL;
-				return -1;
-			}
-			errno = 0;
-			*dev_num = i;
-			return 0;
-		}
-	}
-
-	errno = ENODEV;
-	return -1;
-}
-
-int mtd_num2ubi_dev(libubi_t desc, int mtd_num, int *dev_num)
-{
-	struct ubi_info info;
-	int i, ret, mtd_num1;
-	struct libubi *lib = desc;
-
-	if (ubi_get_info(desc, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		ret = dev_read_int(lib->dev_mtd_num, i, &mtd_num1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (mtd_num1 == mtd_num) {
-			errno = 0;
-			*dev_num = i;
-			return 0;
-		}
-	}
-
-	errno = 0;
-	return -1;
-}
-
-libubi_t libubi_open(void)
-{
-	int fd, version;
-	struct libubi *lib;
-
-	lib = calloc(1, sizeof(struct libubi));
-	if (!lib)
-		return NULL;
-
-	lib->sysfs_ctrl = mkpath("/sys", SYSFS_CTRL);
-	if (!lib->sysfs_ctrl)
-		goto out_error;
-
-	lib->ctrl_dev = mkpath(lib->sysfs_ctrl, CTRL_DEV);
-	if (!lib->ctrl_dev)
-		goto out_error;
-
-	lib->sysfs_ubi = mkpath("/sys", SYSFS_UBI);
-	if (!lib->sysfs_ubi)
-		goto out_error;
-
-	/* Make sure UBI is present */
-	fd = open(lib->sysfs_ubi, O_RDONLY);
-	if (fd == -1) {
-		errno = 0;
-		goto out_error;
-	}
-
-	if (close(fd)) {
-		sys_errmsg("close failed on \"%s\"", lib->sysfs_ubi);
-		goto out_error;
-	}
-
-	lib->ubi_dev = mkpath(lib->sysfs_ubi, UBI_DEV_NAME_PATT);
-	if (!lib->ubi_dev)
-		goto out_error;
-
-	lib->ubi_version = mkpath(lib->sysfs_ubi, UBI_VER);
-	if (!lib->ubi_version)
-		goto out_error;
-
-	lib->dev_dev = mkpath(lib->ubi_dev, DEV_DEV);
-	if (!lib->dev_dev)
-		goto out_error;
-
-	lib->dev_avail_ebs = mkpath(lib->ubi_dev, DEV_AVAIL_EBS);
-	if (!lib->dev_avail_ebs)
-		goto out_error;
-
-	lib->dev_total_ebs = mkpath(lib->ubi_dev, DEV_TOTAL_EBS);
-	if (!lib->dev_total_ebs)
-		goto out_error;
-
-	lib->dev_bad_count = mkpath(lib->ubi_dev, DEV_BAD_COUNT);
-	if (!lib->dev_bad_count)
-		goto out_error;
-
-	lib->dev_eb_size = mkpath(lib->ubi_dev, DEV_EB_SIZE);
-	if (!lib->dev_eb_size)
-		goto out_error;
-
-	lib->dev_max_ec = mkpath(lib->ubi_dev, DEV_MAX_EC);
-	if (!lib->dev_max_ec)
-		goto out_error;
-
-	lib->dev_bad_rsvd = mkpath(lib->ubi_dev, DEV_MAX_RSVD);
-	if (!lib->dev_bad_rsvd)
-		goto out_error;
-
-	lib->dev_max_vols = mkpath(lib->ubi_dev, DEV_MAX_VOLS);
-	if (!lib->dev_max_vols)
-		goto out_error;
-
-	lib->dev_min_io_size = mkpath(lib->ubi_dev, DEV_MIN_IO_SIZE);
-	if (!lib->dev_min_io_size)
-		goto out_error;
-
-	lib->dev_mtd_num = mkpath(lib->ubi_dev, DEV_MTD_NUM);
-	if (!lib->dev_mtd_num)
-		goto out_error;
-
-	lib->ubi_vol = mkpath(lib->sysfs_ubi, UBI_VOL_NAME_PATT);
-	if (!lib->ubi_vol)
-		goto out_error;
-
-	lib->vol_type = mkpath(lib->ubi_vol, VOL_TYPE);
-	if (!lib->vol_type)
-		goto out_error;
-
-	lib->vol_dev = mkpath(lib->ubi_vol, VOL_DEV);
-	if (!lib->vol_dev)
-		goto out_error;
-
-	lib->vol_alignment = mkpath(lib->ubi_vol, VOL_ALIGNMENT);
-	if (!lib->vol_alignment)
-		goto out_error;
-
-	lib->vol_data_bytes = mkpath(lib->ubi_vol, VOL_DATA_BYTES);
-	if (!lib->vol_data_bytes)
-		goto out_error;
-
-	lib->vol_rsvd_ebs = mkpath(lib->ubi_vol, VOL_RSVD_EBS);
-	if (!lib->vol_rsvd_ebs)
-		goto out_error;
-
-	lib->vol_eb_size = mkpath(lib->ubi_vol, VOL_EB_SIZE);
-	if (!lib->vol_eb_size)
-		goto out_error;
-
-	lib->vol_corrupted = mkpath(lib->ubi_vol, VOL_CORRUPTED);
-	if (!lib->vol_corrupted)
-		goto out_error;
-
-	lib->vol_name = mkpath(lib->ubi_vol, VOL_NAME);
-	if (!lib->vol_name)
-		goto out_error;
-
-	if (read_positive_int(lib->ubi_version, &version))
-		goto out_error;
-	if (version != LIBUBI_UBI_VERSION) {
-		errmsg("this library was made for UBI version %d, but UBI "
-		       "version %d is detected\n", LIBUBI_UBI_VERSION, version);
-		goto out_error;
-	}
-
-	return lib;
-
-out_error:
-	libubi_close((libubi_t)lib);
-	return NULL;
-}
-
-void libubi_close(libubi_t desc)
-{
-	struct libubi *lib = (struct libubi *)desc;
-
-	free(lib->vol_name);
-	free(lib->vol_corrupted);
-	free(lib->vol_eb_size);
-	free(lib->vol_rsvd_ebs);
-	free(lib->vol_data_bytes);
-	free(lib->vol_alignment);
-	free(lib->vol_dev);
-	free(lib->vol_type);
-	free(lib->ubi_vol);
-	free(lib->dev_mtd_num);
-	free(lib->dev_min_io_size);
-	free(lib->dev_max_vols);
-	free(lib->dev_bad_rsvd);
-	free(lib->dev_max_ec);
-	free(lib->dev_eb_size);
-	free(lib->dev_bad_count);
-	free(lib->dev_total_ebs);
-	free(lib->dev_avail_ebs);
-	free(lib->dev_dev);
-	free(lib->ubi_version);
-	free(lib->ubi_dev);
-	free(lib->sysfs_ubi);
-	free(lib->ctrl_dev);
-	free(lib->sysfs_ctrl);
-	free(lib);
-}
-
-/**
- * do_attach - perform the actual attach operation.
- * @node: name of the UBI control character device node
- * @r: attach request
- *
- * This function performs the actual UBI attach operation. Returns %0 in case of
- * success and %-1 in case of failure. @r->ubi_num contains newly created UBI
- * device number.
- */
-static int do_attach(const char *node, const struct ubi_attach_req *r)
-{
-	int fd, ret;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	ret = ioctl(fd, UBI_IOCATT, r);
-	close(fd);
-	if (ret == -1)
-		return -1;
-
-#ifdef UDEV_SETTLE_HACK
-//	if (system("udevsettle") == -1)
-//		return -1;
-	usleep(100000);
-#endif
-	return ret;
-}
-
-int ubi_attach_mtd(libubi_t desc, const char *node,
-		   struct ubi_attach_request *req)
-{
-	struct ubi_attach_req r;
-	int ret;
-
-	(void)desc;
-
-	memset(&r, 0, sizeof(struct ubi_attach_req));
-	r.ubi_num = req->dev_num;
-	r.mtd_num = req->mtd_num;
-	r.vid_hdr_offset = req->vid_hdr_offset;
-
-	ret = do_attach(node, &r);
-	if (ret == 0)
-		req->dev_num = r.ubi_num;
-
-	return ret;
-}
-
-#ifndef MTD_CHAR_MAJOR
-/*
- * This is taken from kernel <linux/mtd/mtd.h> and is unlikely to change anytime
- * soon.
- */
-#define MTD_CHAR_MAJOR 90
-#endif
-
-/**
- * mtd_node_to_num - converts device node to MTD number.
- * @mtd_dev_node: path to device node to convert
- *
- * This function converts given @mtd_dev_node to MTD device number.
- * @mtd_dev_node should contain path to the MTD device node. Returns MTD device
- * number in case of success and %-1 in case of failure (errno is set).
- */
-static int mtd_node_to_num(const char *mtd_dev_node)
-{
-	int major, minor;
-	struct stat sb;
-
-	if (stat(mtd_dev_node, &sb) < 0)
-		return sys_errmsg("cannot stat \"%s\"", mtd_dev_node);
-
-	if (!S_ISCHR(sb.st_mode)) {
-		errno = EINVAL;
-		return sys_errmsg("\"%s\" is not a character device",
-				  mtd_dev_node);
-	}
-
-	major = major(sb.st_rdev);
-	minor = minor(sb.st_rdev);
-
-	if (major != MTD_CHAR_MAJOR) {
-		errno = EINVAL;
-		return sys_errmsg("\"%s\" is not an MTD device", mtd_dev_node);
-	}
-
-	return minor / 2;
-}
-
-int ubi_attach(libubi_t desc, const char *node, struct ubi_attach_request *req)
-{
-	struct ubi_attach_req r;
-	int ret;
-
-	if (!req->mtd_dev_node)
-		/* Fallback to opening by mtd_num */
-		return ubi_attach_mtd(desc, node, req);
-
-	memset(&r, 0, sizeof(struct ubi_attach_req));
-	r.ubi_num = req->dev_num;
-	r.vid_hdr_offset = req->vid_hdr_offset;
-
-	/*
-	 * User has passed path to device node. Lets find out MTD device number
-	 * of the device and pass it to the kernel.
-	 */
-	r.mtd_num = mtd_node_to_num(req->mtd_dev_node);
-	if (r.mtd_num == -1)
-		return -1;
-
-	ret = do_attach(node, &r);
-	if (ret == 0)
-		req->dev_num = r.ubi_num;
-
-	return ret;
-}
-
-int ubi_detach_mtd(libubi_t desc, const char *node, int mtd_num)
-{
-	int ret, ubi_dev;
-
-	ret = mtd_num2ubi_dev(desc, mtd_num, &ubi_dev);
-	if (ret == -1) {
-		errno = ENODEV;
-		return ret;
-	}
-
-	return ubi_remove_dev(desc, node, ubi_dev);
-}
-
-int ubi_detach(libubi_t desc, const char *node, const char *mtd_dev_node)
-{
-	int mtd_num;
-
-	if (!mtd_dev_node) {
-		errno = EINVAL;
-		return -1;
-	}
-
-	mtd_num = mtd_node_to_num(mtd_dev_node);
-	if (mtd_num == -1)
-		return -1;
-
-	return ubi_detach_mtd(desc, node, mtd_num);
-}
-
-int ubi_remove_dev(libubi_t desc, const char *node, int ubi_dev)
-{
-	int fd, ret;
-
-	desc = desc;
-
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-	ret = ioctl(fd, UBI_IOCDET, &ubi_dev);
-	if (ret == -1)
-		goto out_close;
-
-#ifdef UDEV_SETTLE_HACK
-//	if (system("udevsettle") == -1)
-//		return -1;
-	usleep(100000);
-#endif
-
-out_close:
-	close(fd);
-	return ret;
-}
-
-int ubi_probe_node(libubi_t desc, const char *node)
-{
-	struct stat st;
-	struct ubi_info info;
-	int i, fd, major, minor;
-	struct libubi *lib = (struct libubi *)desc;
-	char file[strlen(lib->ubi_vol) + 100];
-
-	if (stat(node, &st))
-		return sys_errmsg("cannot get information about \"%s\"", node);
-
-	if (!S_ISCHR(st.st_mode)) {
-		errmsg("\"%s\" is not a character device", node);
-		errno = EINVAL;
-		return -1;
-	}
-
-	major = major(st.st_rdev);
-	minor = minor(st.st_rdev);
-
-	if (ubi_get_info((libubi_t *)lib, &info))
-		return -1;
-
-	for (i = info.lowest_dev_num; i <= info.highest_dev_num; i++) {
-		int major1, minor1, ret;
-
-		ret = dev_get_major(lib, i, &major1, &minor1);
-		if (ret) {
-			if (errno == ENOENT)
-				continue;
-			if (!errno)
-				goto out_not_ubi;
-			return -1;
-		}
-
-		if (major1 == major)
-			break;
-	}
-
-	if (i > info.highest_dev_num)
-		goto out_not_ubi;
-
-	if (minor == 0)
-		return 1;
-
-	/* This is supposdely an UBI volume device node */
-	sprintf(file, lib->ubi_vol, i, minor - 1);
-	fd = open(file, O_RDONLY);
-	if (fd == -1)
-		goto out_not_ubi;
-
-	return 2;
-
-out_not_ubi:
-	errmsg("\"%s\" has major:minor %d:%d, but this does not correspond to "
-	       "any existing UBI device or volume", node, major, minor);
-	errno = ENODEV;
-	return -1;
-}
-
-int ubi_get_info(libubi_t desc, struct ubi_info *info)
-{
-	DIR *sysfs_ubi;
-	struct dirent *dirent;
-	struct libubi *lib = (struct libubi *)desc;
-
-	memset(info, 0, sizeof(struct ubi_info));
-
-	if (read_major(lib->ctrl_dev, &info->ctrl_major, &info->ctrl_minor)) {
-		/*
-		 * Older UBI versions did not have control device, so we do not
-		 * panic here for compatibility reasons. May be few years later
-		 * we could return -1 here, but for now just set major:minor to
-		 * -1.
-		 */
-		info->ctrl_major = info->ctrl_minor = -1;
-	}
-
-	/*
-	 * We have to scan the UBI sysfs directory to identify how many UBI
-	 * devices are present.
-	 */
-	sysfs_ubi = opendir(lib->sysfs_ubi);
-	if (!sysfs_ubi)
-		return -1;
-
-	info->lowest_dev_num = INT_MAX;
-	while (1) {
-		int dev_num, ret;
-		char tmp_buf[256];
-
-		errno = 0;
-		dirent = readdir(sysfs_ubi);
-		if (!dirent)
-			break;
-
-		if (strlen(dirent->d_name) >= 255) {
-			errmsg("invalid entry in %s: \"%s\"",
-			       lib->sysfs_ubi, dirent->d_name);
-			errno = EINVAL;
-			goto out_close;
-		}
-
-		ret = sscanf(dirent->d_name, UBI_DEV_NAME_PATT"%s",
-			     &dev_num, tmp_buf);
-		if (ret == 1) {
-			info->dev_count += 1;
-			if (dev_num > info->highest_dev_num)
-				info->highest_dev_num = dev_num;
-			if (dev_num < info->lowest_dev_num)
-				info->lowest_dev_num = dev_num;
-		}
-	}
-
-	if (!dirent && errno) {
-		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
-		goto out_close;
-	}
-
-	if (closedir(sysfs_ubi))
-		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
-
-	if (info->lowest_dev_num == INT_MAX)
-		info->lowest_dev_num = 0;
-
-	if (read_positive_int(lib->ubi_version, &info->version))
-		return -1;
-
-	return 0;
-
-out_close:
-	closedir(sysfs_ubi);
-	return -1;
-}
-
-int ubi_mkvol(libubi_t desc, const char *node, struct ubi_mkvol_request *req)
-{
-	int fd, ret;
-	struct ubi_mkvol_req r;
-	size_t n;
-
-	memset(&r, 0, sizeof(struct ubi_mkvol_req));
-
-	desc = desc;
-	r.vol_id = req->vol_id;
-	r.alignment = req->alignment;
-	r.bytes = req->bytes;
-	r.vol_type = req->vol_type;
-
-	n = strlen(req->name);
-	if (n > UBI_MAX_VOLUME_NAME)
-		return -1;
-
-	strncpy(r.name, req->name, UBI_MAX_VOLUME_NAME + 1);
-	r.name_len = n;
-
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	ret = ioctl(fd, UBI_IOCMKVOL, &r);
-	if (ret == -1) {
-		close(fd);
-		return ret;
-	}
-
-	close(fd);
-	req->vol_id = r.vol_id;
-
-#ifdef UDEV_SETTLE_HACK
-//	if (system("udevsettle") == -1)
-//		return -1;
-	usleep(100000);
-#endif
-
-	return 0;
-}
-
-int ubi_rmvol(libubi_t desc, const char *node, int vol_id)
-{
-	int fd, ret;
-
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	ret = ioctl(fd, UBI_IOCRMVOL, &vol_id);
-	if (ret == -1) {
-		close(fd);
-		return ret;
-	}
-
-	close(fd);
-
-#ifdef UDEV_SETTLE_HACK
-//	if (system("udevsettle") == -1)
-//		return -1;
-	usleep(100000);
-#endif
-
-	return 0;
-}
-
-int ubi_rnvols(libubi_t desc, const char *node, struct ubi_rnvol_req *rnvol)
-{
-	int fd, ret;
-
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return -1;
-
-	ret = ioctl(fd, UBI_IOCRNVOL, rnvol);
-	if (ret == -1) {
-		close(fd);
-		return ret;
-	}
-
-	close(fd);
-
-#ifdef UDEV_SETTLE_HACK
-//	if (system("udevsettle") == -1)
-//		return -1;
-	usleep(100000);
-#endif
-
-	return 0;
-}
-
-int ubi_rsvol(libubi_t desc, const char *node, int vol_id, long long bytes)
-{
-	int fd, ret;
-	struct ubi_rsvol_req req;
-
-	desc = desc;
-	fd = open(node, O_RDONLY);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", node);
-
-	req.bytes = bytes;
-	req.vol_id = vol_id;
-
-	ret = ioctl(fd, UBI_IOCRSVOL, &req);
-	close(fd);
-	return ret;
-}
-
-int ubi_update_start(libubi_t desc, int fd, long long bytes)
-{
-	desc = desc;
-	if (ioctl(fd, UBI_IOCVOLUP, &bytes))
-		return -1;
-	return 0;
-}
-
-int ubi_leb_change_start(libubi_t desc, int fd, int lnum, int bytes, int dtype)
-{
-	struct ubi_leb_change_req req;
-
-	desc = desc;
-	memset(&req, 0, sizeof(struct ubi_leb_change_req));
-	req.lnum = lnum;
-	req.bytes = bytes;
-	req.dtype = dtype;
-
-	if (ioctl(fd, UBI_IOCEBCH, &req))
-		return -1;
-	return 0;
-}
-
-/**
- * dev_present - check whether an UBI device is present.
- * @lib: libubi descriptor
- * @dev_num: UBI device number to check
- *
- * This function returns %1 if UBI device is present and %0 if not.
- */
-static int dev_present(struct libubi *lib, int dev_num)
-{
-	struct stat st;
-	char file[strlen(lib->ubi_dev) + 50];
-
-	sprintf(file, lib->ubi_dev, dev_num);
-	return !stat(file, &st);
-}
-
-int ubi_get_dev_info1(libubi_t desc, int dev_num, struct ubi_dev_info *info)
-{
-	DIR *sysfs_ubi;
-	struct dirent *dirent;
-	struct libubi *lib = (struct libubi *)desc;
-
-	memset(info, 0, sizeof(struct ubi_dev_info));
-	info->dev_num = dev_num;
-
-	if (!dev_present(lib, dev_num))
-		return -1;
-
-	sysfs_ubi = opendir(lib->sysfs_ubi);
-	if (!sysfs_ubi)
-		return -1;
-
-	info->lowest_vol_id = INT_MAX;
-
-	while (1) {
-		int vol_id, ret, devno;
-		char tmp_buf[256];
-
-		errno = 0;
-		dirent = readdir(sysfs_ubi);
-		if (!dirent)
-			break;
-
-		if (strlen(dirent->d_name) >= 255) {
-			errmsg("invalid entry in %s: \"%s\"",
-			       lib->sysfs_ubi, dirent->d_name);
-			goto out_close;
-		}
-
-		ret = sscanf(dirent->d_name, UBI_VOL_NAME_PATT"%s", &devno, &vol_id, tmp_buf);
-		if (ret == 2 && devno == dev_num) {
-			info->vol_count += 1;
-			if (vol_id > info->highest_vol_id)
-				info->highest_vol_id = vol_id;
-			if (vol_id < info->lowest_vol_id)
-				info->lowest_vol_id = vol_id;
-		}
-	}
-
-	if (!dirent && errno) {
-		sys_errmsg("readdir failed on \"%s\"", lib->sysfs_ubi);
-		goto out_close;
-	}
-
-	if (closedir(sysfs_ubi))
-		return sys_errmsg("closedir failed on \"%s\"", lib->sysfs_ubi);
-
-	if (info->lowest_vol_id == INT_MAX)
-		info->lowest_vol_id = 0;
-
-	if (dev_get_major(lib, dev_num, &info->major, &info->minor))
-		return -1;
-
-	if (dev_read_int(lib->dev_mtd_num, dev_num, &info->mtd_num))
-		return -1;
-	if (dev_read_int(lib->dev_avail_ebs, dev_num, &info->avail_lebs))
-		return -1;
-	if (dev_read_int(lib->dev_total_ebs, dev_num, &info->total_lebs))
-		return -1;
-	if (dev_read_int(lib->dev_bad_count, dev_num, &info->bad_count))
-		return -1;
-	if (dev_read_int(lib->dev_eb_size, dev_num, &info->leb_size))
-		return -1;
-	if (dev_read_int(lib->dev_bad_rsvd, dev_num, &info->bad_rsvd))
-		return -1;
-	if (dev_read_ll(lib->dev_max_ec, dev_num, &info->max_ec))
-		return -1;
-	if (dev_read_int(lib->dev_max_vols, dev_num, &info->max_vol_count))
-		return -1;
-	if (dev_read_int(lib->dev_min_io_size, dev_num, &info->min_io_size))
-		return -1;
-
-	info->avail_bytes = (long long)info->avail_lebs * info->leb_size;
-	info->total_bytes = (long long)info->total_lebs * info->leb_size;
-
-	return 0;
-
-out_close:
-	closedir(sysfs_ubi);
-	return -1;
-}
-
-int ubi_get_dev_info(libubi_t desc, const char *node, struct ubi_dev_info *info)
-{
-	int err, dev_num;
-	struct libubi *lib = (struct libubi *)desc;
-
-	err = ubi_probe_node(desc, node);
-	if (err != 1) {
-		if (err == 2)
-			errno = ENODEV;
-		return -1;
-	}
-
-	if (dev_node2num(lib, node, &dev_num))
-		return -1;
-
-	return ubi_get_dev_info1(desc, dev_num, info);
-}
-
-int ubi_get_vol_info1(libubi_t desc, int dev_num, int vol_id,
-		      struct ubi_vol_info *info)
-{
-	int ret;
-	struct libubi *lib = (struct libubi *)desc;
-	char buf[50];
-
-	memset(info, 0, sizeof(struct ubi_vol_info));
-	info->dev_num = dev_num;
-	info->vol_id = vol_id;
-
-	if (vol_get_major(lib, dev_num, vol_id, &info->major, &info->minor))
-		return -1;
-
-	ret = vol_read_data(lib->vol_type, dev_num, vol_id, buf, 50);
-	if (ret < 0)
-		return -1;
-
-	if (strncmp(buf, "static\n", ret) == 0)
-		info->type = UBI_STATIC_VOLUME;
-	else if (strncmp(buf, "dynamic\n", ret) == 0)
-		info->type = UBI_DYNAMIC_VOLUME;
-	else {
-		errmsg("bad value at \"%s\"", buf);
-		errno = EINVAL;
-		return -1;
-	}
-
-	ret = vol_read_int(lib->vol_alignment, dev_num, vol_id,
-			   &info->alignment);
-	if (ret)
-		return -1;
-	ret = vol_read_ll(lib->vol_data_bytes, dev_num, vol_id,
-			  &info->data_bytes);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_rsvd_ebs, dev_num, vol_id, &info->rsvd_lebs);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_eb_size, dev_num, vol_id, &info->leb_size);
-	if (ret)
-		return -1;
-	ret = vol_read_int(lib->vol_corrupted, dev_num, vol_id,
-			   &info->corrupted);
-	if (ret)
-		return -1;
-	info->rsvd_bytes = (long long)info->leb_size * info->rsvd_lebs;
-
-	ret = vol_read_data(lib->vol_name, dev_num, vol_id, &info->name,
-			    UBI_VOL_NAME_MAX + 2);
-	if (ret < 0)
-		return -1;
-
-	info->name[ret - 1] = '\0';
-	return 0;
-}
-
-int ubi_get_vol_info(libubi_t desc, const char *node, struct ubi_vol_info *info)
-{
-	int err, vol_id, dev_num;
-	struct libubi *lib = (struct libubi *)desc;
-
-	err = ubi_probe_node(desc, node);
-	if (err != 2) {
-		if (err == 1)
-			errno = ENODEV;
-		return -1;
-	}
-
-	if (vol_node2nums(lib, node, &dev_num, &vol_id))
-		return -1;
-
-	return ubi_get_vol_info1(desc, dev_num, vol_id, info);
-}
-
-int ubi_get_vol_info1_nm(libubi_t desc, int dev_num, const char *name,
-			 struct ubi_vol_info *info)
-{
-	int i, err;
-	unsigned int nlen = strlen(name);
-	struct ubi_dev_info dev_info;
-
-	if (nlen == 0) {
-		errmsg("bad \"name\" input parameter");
-		errno = EINVAL;
-		return -1;
-	}
-
-	err = ubi_get_dev_info1(desc, dev_num, &dev_info);
-	if (err)
-		return err;
-
-	for (i = dev_info.lowest_vol_id;
-	     i <= dev_info.highest_vol_id; i++) {
-		err = ubi_get_vol_info1(desc, dev_num, i, info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (nlen == strlen(info->name) && !strcmp(name, info->name))
-			return 0;
-	}
-
-	errno = ENOENT;
-	return -1;
-}
-
-int ubi_set_property(int fd, uint8_t property, uint64_t value)
-{
-	struct ubi_set_prop_req r;
-
-	memset(&r, 0, sizeof(struct ubi_set_prop_req));
-	r.property = property;
-	r.value = value;
-
-	return ioctl(fd, UBI_IOCSETPROP, &r);
-}
-
-int ubi_leb_unmap(int fd, int lnum)
-{
-	return ioctl(fd, UBI_IOCEBUNMAP, &lnum);
-}
-
-int ubi_is_mapped(int fd, int lnum)
-{
-	return ioctl(fd, UBI_IOCEBISMAP, &lnum);
-}
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/src/libubi_int.h
deleted file mode 100644
index c3aa37a..0000000
--- a/ubi-utils/src/libubi_int.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * Author: Artem Bityutskiy
- *
- * UBI (Unsorted Block Images) library.
- */
-
-#ifndef __LIBUBI_INT_H__
-#define __LIBUBI_INT_H__
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/*
- * The below are pre-define UBI file and directory names.
- *
- * Note, older kernels put 'ubiX_Y' directories straight to '/sys/class/ubi/'.
- * New kernels puts 'ubiX_Y' directories to '/sys/class/ubi/ubiX/', which is
- * saner. And for compatibility reasons it also puts symlinks to 'ubiX_Y'
- * directories to '/sys/class/ubi/'. For now libubi assumes old layout.
- */
-
-#define SYSFS_UBI         "class/ubi"
-#define SYSFS_CTRL        "class/misc/ubi_ctrl/"
-
-#define CTRL_DEV          "dev"
-
-#define UBI_VER           "version"
-#define UBI_DEV_NAME_PATT "ubi%d"
-
-#define DEV_DEV           "dev"
-#define DEV_AVAIL_EBS     "avail_eraseblocks"
-#define DEV_TOTAL_EBS     "total_eraseblocks"
-#define DEV_BAD_COUNT     "bad_peb_count"
-#define DEV_EB_SIZE       "eraseblock_size"
-#define DEV_MAX_EC        "max_ec"
-#define DEV_MAX_RSVD      "reserved_for_bad"
-#define DEV_MAX_VOLS      "max_vol_count"
-#define DEV_MIN_IO_SIZE   "min_io_size"
-#define DEV_MTD_NUM       "mtd_num"
-
-#define UBI_VOL_NAME_PATT "ubi%d_%d"
-#define VOL_TYPE          "type"
-#define VOL_DEV           "dev"
-#define VOL_ALIGNMENT     "alignment"
-#define VOL_DATA_BYTES    "data_bytes"
-#define VOL_RSVD_EBS      "reserved_ebs"
-#define VOL_EB_SIZE       "usable_eb_size"
-#define VOL_CORRUPTED     "corrupted"
-#define VOL_NAME          "name"
-
-/**
- * libubi - UBI library description data structure.
- * @sysfs: sysfs file system path
- * @sysfs_ctrl: UBI control device directory in sysfs
- * @ctrl_dev: UBI control device major/minor numbers sysfs file
- * @sysfs_ubi: UBI directory in sysfs
- * @ubi_dev: UBI device sysfs directory pattern
- * @ubi_version: UBI version file sysfs path
- * @dev_dev: UBI device major/minor numbers file pattern
- * @dev_avail_ebs: count of available eraseblocks sysfs path pattern
- * @dev_total_ebs: total eraseblocks count sysfs path pattern
- * @dev_bad_count: count of bad eraseblocks sysfs path pattern
- * @dev_eb_size: size of UBI device's eraseblocks sysfs path pattern
- * @dev_max_ec: maximum erase counter sysfs path pattern
- * @dev_bad_rsvd: count of physical eraseblock reserved for bad eraseblocks
- *                handling
- * @dev_max_vols: maximum volumes number count sysfs path pattern
- * @dev_min_io_size: minimum I/O unit size sysfs path pattern
- * @dev_mtd_num: MTD device number
- * @ubi_vol: UBI volume sysfs directory pattern
- * @vol_type: volume type sysfs path pattern
- * @vol_dev: volume major/minor numbers file pattern
- * @vol_alignment: volume alignment sysfs path pattern
- * @vol_data_bytes: volume data size sysfs path pattern
- * @vol_rsvd_ebs: volume reserved size sysfs path pattern
- * @vol_eb_size: volume eraseblock size sysfs path pattern
- * @vol_corrupted: volume corruption flag sysfs path pattern
- * @vol_name: volume name sysfs path pattern
- */
-struct libubi
-{
-	char *sysfs;
-	char *sysfs_ctrl;
-	char *ctrl_dev;
-	char *sysfs_ubi;
-	char *ubi_dev;
-	char *ubi_version;
-	char *dev_dev;
-	char *dev_avail_ebs;
-	char *dev_total_ebs;
-	char *dev_bad_count;
-	char *dev_eb_size;
-	char *dev_max_ec;
-	char *dev_bad_rsvd;
-	char *dev_max_vols;
-	char *dev_min_io_size;
-	char *dev_mtd_num;
-	char *ubi_vol;
-	char *vol_type;
-	char *vol_dev;
-	char *vol_alignment;
-	char *vol_data_bytes;
-	char *vol_rsvd_ebs;
-	char *vol_eb_size;
-	char *vol_corrupted;
-	char *vol_name;
-	char *vol_max_count;
-};
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* !__LIBUBI_INT_H__ */
diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/src/libubigen.c
deleted file mode 100644
index 9eaa7f5..0000000
--- a/ubi-utils/src/libubigen.c
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- * Copyright (C) 2008 Nokia Corporation
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Generating UBI images.
- *
- * Authors: Oliver Lohmann
- *          Artem Bityutskiy
- */
-
-#define PROGRAM_NAME "libubigen"
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <mtd/ubi-media.h>
-#include <mtd_swab.h>
-#include <libubigen.h>
-#include <crc32.h>
-#include "common.h"
-
-void ubigen_info_init(struct ubigen_info *ui, int peb_size, int min_io_size,
-		      int subpage_size, int vid_hdr_offs, int ubi_ver,
-		      uint32_t image_seq)
-{
-	if (!vid_hdr_offs) {
-		vid_hdr_offs = UBI_EC_HDR_SIZE + subpage_size - 1;
-		vid_hdr_offs /= subpage_size;
-		vid_hdr_offs *= subpage_size;
-	}
-
-	ui->peb_size = peb_size;
-	ui->min_io_size = min_io_size;
-	ui->vid_hdr_offs = vid_hdr_offs;
-	ui->data_offs = vid_hdr_offs + UBI_VID_HDR_SIZE + min_io_size - 1;
-	ui->data_offs /= min_io_size;
-	ui->data_offs *= min_io_size;
-	ui->leb_size = peb_size - ui->data_offs;
-	ui->ubi_ver = ubi_ver;
-	ui->image_seq = image_seq;
-
-	ui->max_volumes = ui->leb_size / UBI_VTBL_RECORD_SIZE;
-	if (ui->max_volumes > UBI_MAX_VOLUMES)
-		ui->max_volumes = UBI_MAX_VOLUMES;
-	ui->vtbl_size = ui->max_volumes * UBI_VTBL_RECORD_SIZE;
-}
-
-struct ubi_vtbl_record *ubigen_create_empty_vtbl(const struct ubigen_info *ui)
-{
-	struct ubi_vtbl_record *vtbl;
-	int i;
-
-	vtbl = calloc(1, ui->vtbl_size);
-	if (!vtbl) {
-		sys_errmsg("cannot allocate %d bytes of memory", ui->vtbl_size);
-		return NULL;
-	}
-
-	for (i = 0; i < ui->max_volumes; i++) {
-		uint32_t crc = mtd_crc32(UBI_CRC32_INIT, &vtbl[i],
-				     UBI_VTBL_RECORD_SIZE_CRC);
-		vtbl[i].crc = cpu_to_be32(crc);
-	}
-
-	return vtbl;
-}
-
-int ubigen_add_volume(const struct ubigen_info *ui,
-		      const struct ubigen_vol_info *vi,
-		      struct ubi_vtbl_record *vtbl)
-{
-	struct ubi_vtbl_record *vtbl_rec = &vtbl[vi->id];
-	uint32_t tmp;
-
-	if (vi->id >= ui->max_volumes) {
-		errmsg("too high volume id %d, max. volumes is %d",
-		       vi->id, ui->max_volumes);
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (vi->alignment >= ui->leb_size) {
-		errmsg("too large alignment %d, max is %d (LEB size)",
-		       vi->alignment, ui->leb_size);
-		errno = EINVAL;
-		return -1;
-	}
-
-	memset(vtbl_rec, 0, sizeof(struct ubi_vtbl_record));
-	tmp = (vi->bytes + ui->leb_size - 1) / ui->leb_size;
-	vtbl_rec->reserved_pebs = cpu_to_be32(tmp);
-	vtbl_rec->alignment = cpu_to_be32(vi->alignment);
-	vtbl_rec->vol_type = vi->type;
-	tmp = ui->leb_size % vi->alignment;
-	vtbl_rec->data_pad = cpu_to_be32(tmp);
-	vtbl_rec->flags = vi->flags;
-
-	memcpy(vtbl_rec->name, vi->name, vi->name_len);
-	vtbl_rec->name[vi->name_len] = '\0';
-	vtbl_rec->name_len = cpu_to_be16(vi->name_len);
-
-	tmp = mtd_crc32(UBI_CRC32_INIT, vtbl_rec, UBI_VTBL_RECORD_SIZE_CRC);
-	vtbl_rec->crc =	 cpu_to_be32(tmp);
-	return 0;
-}
-
-void ubigen_init_ec_hdr(const struct ubigen_info *ui,
-		        struct ubi_ec_hdr *hdr, long long ec)
-{
-	uint32_t crc;
-
-	memset(hdr, 0, sizeof(struct ubi_ec_hdr));
-
-	hdr->magic = cpu_to_be32(UBI_EC_HDR_MAGIC);
-	hdr->version = ui->ubi_ver;
-	hdr->ec = cpu_to_be64(ec);
-	hdr->vid_hdr_offset = cpu_to_be32(ui->vid_hdr_offs);
-	hdr->data_offset = cpu_to_be32(ui->data_offs);
-	hdr->image_seq = cpu_to_be32(ui->image_seq);
-
-	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-	hdr->hdr_crc = cpu_to_be32(crc);
-}
-
-void ubigen_init_vid_hdr(const struct ubigen_info *ui,
-			 const struct ubigen_vol_info *vi,
-			 struct ubi_vid_hdr *hdr, int lnum,
-			 const void *data, int data_size)
-{
-	uint32_t crc;
-
-	memset(hdr, 0, sizeof(struct ubi_vid_hdr));
-
-	hdr->magic = cpu_to_be32(UBI_VID_HDR_MAGIC);
-	hdr->version = ui->ubi_ver;
-	hdr->vol_type = vi->type;
-	hdr->vol_id = cpu_to_be32(vi->id);
-	hdr->lnum = cpu_to_be32(lnum);
-	hdr->data_pad = cpu_to_be32(vi->data_pad);
-	hdr->compat = vi->compat;
-
-	if (vi->type == UBI_VID_STATIC) {
-		hdr->data_size = cpu_to_be32(data_size);
-		hdr->used_ebs = cpu_to_be32(vi->used_ebs);
-		crc = mtd_crc32(UBI_CRC32_INIT, data, data_size);
-		hdr->data_crc = cpu_to_be32(crc);
-	}
-
-	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_VID_HDR_SIZE_CRC);
-	hdr->hdr_crc = cpu_to_be32(crc);
-}
-
-int ubigen_write_volume(const struct ubigen_info *ui,
-			const struct ubigen_vol_info *vi, long long ec,
-			long long bytes, int in, int out)
-{
-	int len = vi->usable_leb_size, rd, lnum = 0;
-	char *inbuf, *outbuf;
-
-	if (vi->id >= ui->max_volumes) {
-		errmsg("too high volume id %d, max. volumes is %d",
-		       vi->id, ui->max_volumes);
-		errno = EINVAL;
-		return -1;
-	}
-
-	if (vi->alignment >= ui->leb_size) {
-		errmsg("too large alignment %d, max is %d (LEB size)",
-		       vi->alignment, ui->leb_size);
-		errno = EINVAL;
-		return -1;
-	}
-
-	inbuf = malloc(ui->leb_size);
-	if (!inbuf)
-		return sys_errmsg("cannot allocate %d bytes of memory",
-				  ui->leb_size);
-	outbuf = malloc(ui->peb_size);
-	if (!outbuf) {
-		sys_errmsg("cannot allocate %d bytes of memory", ui->peb_size);
-		goto out_free;
-	}
-
-	memset(outbuf, 0xFF, ui->data_offs);
-	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec);
-
-	while (bytes) {
-		int l;
-		struct ubi_vid_hdr *vid_hdr;
-
-		if (bytes < len)
-			len = bytes;
-		bytes -= len;
-
-		l = len;
-		do {
-			rd = read(in, inbuf + len - l, l);
-			if (rd != l) {
-				sys_errmsg("cannot read %d bytes from the input file", l);
-				goto out_free1;
-			}
-
-			l -= rd;
-		} while (l);
-
-		vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
-		ubigen_init_vid_hdr(ui, vi, vid_hdr, lnum, inbuf, len);
-
-		memcpy(outbuf + ui->data_offs, inbuf, len);
-		memset(outbuf + ui->data_offs + len, 0xFF,
-		       ui->peb_size - ui->data_offs - len);
-
-		if (write(out, outbuf, ui->peb_size) != ui->peb_size) {
-			sys_errmsg("cannot write %d bytes to the output file", ui->peb_size);
-			goto out_free1;
-		}
-
-		lnum += 1;
-	}
-
-	free(outbuf);
-	free(inbuf);
-	return 0;
-
-out_free1:
-	free(outbuf);
-out_free:
-	free(inbuf);
-	return -1;
-}
-
-int ubigen_write_layout_vol(const struct ubigen_info *ui, int peb1, int peb2,
-			    long long ec1, long long ec2,
-			    struct ubi_vtbl_record *vtbl, int fd)
-{
-	int ret;
-	struct ubigen_vol_info vi;
-	char *outbuf;
-	struct ubi_vid_hdr *vid_hdr;
-	off_t seek;
-
-	vi.bytes = ui->leb_size * UBI_LAYOUT_VOLUME_EBS;
-	vi.id = UBI_LAYOUT_VOLUME_ID;
-	vi.alignment = UBI_LAYOUT_VOLUME_ALIGN;
-	vi.data_pad = ui->leb_size % UBI_LAYOUT_VOLUME_ALIGN;
-	vi.usable_leb_size = ui->leb_size - vi.data_pad;
-	vi.data_pad = ui->leb_size - vi.usable_leb_size;
-	vi.type = UBI_LAYOUT_VOLUME_TYPE;
-	vi.name = UBI_LAYOUT_VOLUME_NAME;
-	vi.name_len = strlen(UBI_LAYOUT_VOLUME_NAME);
-	vi.compat = UBI_LAYOUT_VOLUME_COMPAT;
-
-	outbuf = malloc(ui->peb_size);
-	if (!outbuf)
-		return sys_errmsg("failed to allocate %d bytes",
-				  ui->peb_size);
-
-	memset(outbuf, 0xFF, ui->data_offs);
-	vid_hdr = (struct ubi_vid_hdr *)(&outbuf[ui->vid_hdr_offs]);
-	memcpy(outbuf + ui->data_offs, vtbl, ui->vtbl_size);
-	memset(outbuf + ui->data_offs + ui->vtbl_size, 0xFF,
-	       ui->peb_size - ui->data_offs - ui->vtbl_size);
-
-	seek = peb1 * ui->peb_size;
-	if (lseek(fd, seek, SEEK_SET) != seek) {
-		sys_errmsg("cannot seek output file");
-		goto out_free;
-	}
-
-	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec1);
-	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 0, NULL, 0);
-	ret = write(fd, outbuf, ui->peb_size);
-	if (ret != ui->peb_size) {
-		sys_errmsg("cannot write %d bytes", ui->peb_size);
-		goto out_free;
-	}
-
-	seek = peb2 * ui->peb_size;
-	if (lseek(fd, seek, SEEK_SET) != seek) {
-		sys_errmsg("cannot seek output file");
-		goto out_free;
-	}
-	ubigen_init_ec_hdr(ui, (struct ubi_ec_hdr *)outbuf, ec2);
-	ubigen_init_vid_hdr(ui, &vi, vid_hdr, 1, NULL, 0);
-	ret = write(fd, outbuf, ui->peb_size);
-	if (ret != ui->peb_size) {
-		sys_errmsg("cannot write %d bytes", ui->peb_size);
-		goto out_free;
-	}
-
-	free(outbuf);
-	return 0;
-
-out_free:
-	free(outbuf);
-	return -1;
-}
diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/src/mtdinfo.c
deleted file mode 100644
index bfd7e6d..0000000
--- a/ubi-utils/src/mtdinfo.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright (C) 2009 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to get MTD information.
- *
- * Author: Artem Bityutskiy
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "mtdinfo"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <mtd/mtd-user.h>
-
-#include <libubigen.h>
-#include <libmtd.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int mtdn;
-	unsigned int all:1;
-	unsigned int ubinfo:1;
-	unsigned int map:1;
-	const char *node;
-};
-
-static struct args args = {
-	.mtdn = -1,
-	.ubinfo = 0,
-	.all = 0,
-	.node = NULL,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to print MTD information.";
-
-static const char optionsstr[] =
-"-m, --mtdn=<MTD device number>  MTD device number to get information about\n"
-"                                (deprecated option, will be removed, do not use)\n"
-"-u, --ubi-info                  print what would UBI layout be if it was put\n"
-"                                on this MTD device\n"
-"-M, --map                       print eraseblock map\n"
-"-a, --all                       print information about all MTD devices\n"
-"-h, --help                      print help message\n"
-"-V, --version                   print program version";
-
-static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n"
-"\t\t[--ubi-info] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
-"\t\t[--version]\n"
-"Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
-"Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
-"Example 3: " PROGRAM_NAME " /dev/mtd0 - print information MTD device /dev/mtd0\n"
-"Example 4: " PROGRAM_NAME " /dev/mtd0 -u - print information MTD device /dev/mtd0\n"
-"\t\t\t\tand include UBI layout information\n"
-"Example 5: " PROGRAM_NAME " -a - print information about all MTD devices\n"
-"\t\t\tand include UBI layout information\n";
-
-static const struct option long_options[] = {
-	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
-	{ .name = "map",       .has_arg = 0, .flag = NULL, .val = 'M' },
-	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
-	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "am:uMhV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'a':
-			args.all = 1;
-			break;
-
-		case 'u':
-			args.ubinfo = 1;
-			break;
-
-		case 'm':
-			args.mtdn = simple_strtoul(optarg, &error);
-			if (error || args.mtdn < 0)
-				return errmsg("bad MTD device number: \"%s\"", optarg);
-			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
-			break;
-
-		case 'M':
-			args.map = 1;
-			break;
-
-		case 'h':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			printf("%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc - 1)
-		args.node = argv[optind];
-	else if (optind < argc)
-		return errmsg("more then one MTD device specified (use -h for help)");
-
-	if (args.all && (args.node || args.mtdn != -1)) {
-		args.mtdn = -1;
-		args.node = NULL;
-	}
-
-	if (args.map && !args.node)
-		return errmsg("-M requires MTD device node name");
-
-	return 0;
-}
-
-static int translate_dev(libmtd_t libmtd, const char *node)
-{
-	int err;
-	struct mtd_dev_info mtd;
-
-	err = mtd_get_dev_info(libmtd, node, &mtd);
-	if (err) {
-		if (errno == ENODEV)
-			return errmsg("\"%s\" does not correspond to any "
-				      "existing MTD device", node);
-		return sys_errmsg("cannot get information about MTD "
-				  "device \"%s\"", node);
-	}
-
-	args.mtdn = mtd.mtd_num;
-	return 0;
-}
-
-static void print_ubi_info(const struct mtd_info *mtd_info,
-			   const struct mtd_dev_info *mtd)
-{
-	struct ubigen_info ui;
-
-	if (!mtd_info->sysfs_supported) {
-		errmsg("cannot provide UBI info, becasue sub-page size is "
-		       "not known");
-		return;
-	}
-
-	ubigen_info_init(&ui, mtd->eb_size, mtd->min_io_size, mtd->subpage_size,
-			 0, 1, 0);
-	printf("Default UBI VID header offset:  %d\n", ui.vid_hdr_offs);
-	printf("Default UBI data offset:        %d\n", ui.data_offs);
-	printf("Default UBI LEB size:           ");
-	ubiutils_print_bytes(ui.leb_size, 0);
-	printf("\n");
-	printf("Maximum UBI volumes count:      %d\n", ui.max_volumes);
-}
-
-static void print_region_map(const struct mtd_dev_info *mtd, int fd,
-			     const region_info_t *reginfo)
-{
-	unsigned long start;
-	int i, width;
-	int ret_locked, errno_locked, ret_bad, errno_bad;
-
-	printf("Eraseblock map:\n");
-
-	/* Figure out the number of spaces to pad w/out libm */
-	for (i = 1, width = 0; i < reginfo->numblocks; i *= 10, ++width)
-		continue;
-
-	/* If we don't have a fd to query, just show the bare map */
-	if (fd == -1) {
-		ret_locked = ret_bad = -1;
-		errno_locked = errno_bad = ENODEV;
-	} else
-		ret_locked = ret_bad = errno_locked = errno_bad = 0;
-
-	for (i = 0; i < reginfo->numblocks; ++i) {
-		start = reginfo->offset + i * reginfo->erasesize;
-		printf(" %*i: %08lx ", width, i, start);
-
-		if (ret_locked != -1) {
-			ret_locked = mtd_is_locked(mtd, fd, i);
-			if (ret_locked == 1)
-				printf("RO ");
-			else
-				errno_locked = errno;
-		}
-		if (ret_locked != 1)
-			printf("   ");
-
-		if (ret_bad != -1) {
-			ret_bad = mtd_is_bad(mtd, fd, i);
-			if (ret_bad == 1)
-				printf("BAD ");
-			else
-				errno_bad = errno;
-		}
-		if (ret_bad != 1)
-			printf("    ");
-
-		if (((i + 1) % 4) == 0)
-			printf("\n");
-	}
-	if (i % 4)
-		printf("\n");
-
-	if (ret_locked == -1 && errno_locked != EOPNOTSUPP) {
-		errno = errno_locked;
-		sys_errmsg("could not read locked block info");
-	}
-
-	if (mtd->bb_allowed && ret_bad == -1 && errno_bad != EOPNOTSUPP) {
-		errno = errno_bad;
-		sys_errmsg("could not read bad block info");
-	}
-}
-
-static void print_region_info(const struct mtd_dev_info *mtd)
-{
-	region_info_t reginfo;
-	int r, fd;
-
-	/* If we don't have any region info, just return */
-	if (!args.map && mtd->region_cnt == 0)
-		return;
-
-	/* First open the device so we can query it */
-	fd = open(args.node, O_RDONLY | O_CLOEXEC);
-	if (fd == -1) {
-		sys_errmsg("couldn't open MTD dev: %s", args.node);
-		if (mtd->region_cnt)
-			return;
-	}
-
-	/* Walk all the regions and show the map for them */
-	if (mtd->region_cnt) {
-		for (r = 0; r < mtd->region_cnt; ++r) {
-			printf("Eraseblock region %i: ", r);
-			if (mtd_regioninfo(fd, r, &reginfo) == 0) {
-				printf(" offset: %#x size: %#x numblocks: %#x\n",
-					reginfo.offset, reginfo.erasesize,
-					reginfo.numblocks);
-				if (args.map)
-					print_region_map(mtd, fd, &reginfo);
-			} else
-				printf(" info is unavailable\n");
-		}
-	} else {
-		reginfo.offset = 0;
-		reginfo.erasesize = mtd->eb_size;
-		reginfo.numblocks = mtd->eb_cnt;
-		reginfo.regionindex = 0;
-		print_region_map(mtd, fd, &reginfo);
-	}
-
-	if (fd != -1)
-		close(fd);
-}
-
-static int print_dev_info(libmtd_t libmtd, const struct mtd_info *mtd_info, int mtdn)
-{
-	int err;
-	struct mtd_dev_info mtd;
-
-	err = mtd_get_dev_info1(libmtd, mtdn, &mtd);
-	if (err) {
-		if (errno == ENODEV)
-			return errmsg("mtd%d does not correspond to any "
-				      "existing MTD device", mtdn);
-		return sys_errmsg("cannot get information about MTD device %d",
-				  mtdn);
-	}
-
-	printf("mtd%d\n", mtd.mtd_num);
-	printf("Name:                           %s\n", mtd.name);
-	printf("Type:                           %s\n", mtd.type_str);
-	printf("Eraseblock size:                ");
-	ubiutils_print_bytes(mtd.eb_size, 0);
-	printf("\n");
-	printf("Amount of eraseblocks:          %d (", mtd.eb_cnt);
-	ubiutils_print_bytes(mtd.size, 0);
-	printf(")\n");
-	printf("Minimum input/output unit size: %d %s\n",
-	       mtd.min_io_size, mtd.min_io_size > 1 ? "bytes" : "byte");
-	if (mtd_info->sysfs_supported)
-		printf("Sub-page size:                  %d %s\n",
-		       mtd.subpage_size,
-		       mtd.subpage_size > 1 ? "bytes" : "byte");
-	else if (mtd.type == MTD_NANDFLASH)
-		printf("Sub-page size:                  unknown\n");
-
-	if (mtd.oob_size > 0)
-		printf("OOB size:                       %d bytes\n",
-		       mtd.oob_size);
-	if (mtd.region_cnt > 0)
-		printf("Additional erase regions:       %d\n", mtd.oob_size);
-	if (mtd_info->sysfs_supported)
-		printf("Character device major/minor:   %d:%d\n",
-		       mtd.major, mtd.minor);
-	printf("Bad blocks are allowed:         %s\n",
-	       mtd.bb_allowed ? "true" : "false");
-	printf("Device is writable:             %s\n",
-	      mtd.writable ? "true" : "false");
-
-	if (args.ubinfo)
-		print_ubi_info(mtd_info, &mtd);
-
-	print_region_info(&mtd);
-
-	printf("\n");
-	return 0;
-}
-
-static int print_general_info(libmtd_t libmtd, const struct mtd_info *mtd_info,
-			      int all)
-{
-	int i, err, first = 1;
-	struct mtd_dev_info mtd;
-
-	printf("Count of MTD devices:           %d\n", mtd_info->mtd_dev_cnt);
-	if (mtd_info->mtd_dev_cnt == 0)
-		return 0;
-
-	for (i = mtd_info->lowest_mtd_num;
-	     i <= mtd_info->highest_mtd_num; i++) {
-		err = mtd_get_dev_info1(libmtd, i, &mtd);
-		if (err == -1) {
-			if (errno == ENODEV)
-				continue;
-			return sys_errmsg("libmtd failed get MTD device %d "
-					  "information", i);
-		}
-
-		if (!first)
-			printf(", mtd%d", i);
-		else {
-			printf("Present MTD devices:            mtd%d", i);
-			first = 0;
-		}
-	}
-	printf("\n");
-	printf("Sysfs interface supported:      %s\n",
-	       mtd_info->sysfs_supported ? "yes" : "no");
-
-	if (!all)
-		return 0;
-
-	first = 1;
-	printf("\n");
-
-	for (i = mtd_info->lowest_mtd_num;
-	     i <= mtd_info->highest_mtd_num; i++) {
-		err = print_dev_info(libmtd, mtd_info, i);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libmtd_t libmtd;
-	struct mtd_info mtd_info;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libmtd = libmtd_open();
-	if (libmtd == NULL) {
-		if (errno == 0)
-			return errmsg("MTD is not present in the system");
-		return sys_errmsg("cannot open libmtd");
-	}
-
-	err = mtd_get_info(libmtd, &mtd_info);
-	if (err) {
-		if (errno == ENODEV)
-			return errmsg("MTD is not present");
-		return sys_errmsg("cannot get MTD information");
-	}
-
-	if (args.node) {
-		/*
-		 * A character device was specified, translate this to MTD
-		 * device number.
-		 */
-		err = translate_dev(libmtd, args.node);
-		if (err)
-			goto out_libmtd;
-	}
-
-	if (args.mtdn == -1)
-		err = print_general_info(libmtd, &mtd_info, args.all);
-	else
-		err = print_dev_info(libmtd, &mtd_info, args.mtdn);
-	if (err)
-		goto out_libmtd;
-
-	libmtd_close(libmtd);
-	return 0;
-
-out_libmtd:
-	libmtd_close(libmtd);
-	return -1;
-}
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/src/ubiattach.c
deleted file mode 100644
index 4f18e99..0000000
--- a/ubi-utils/src/ubiattach.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to attach MTD devices to UBI.
- *
- * Author: Artem Bityutskiy
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubiattach"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-#define DEFAULT_CTRL_DEV "/dev/ubi_ctrl"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int devn;
-	int mtdn;
-	int vidoffs;
-	const char *node;
-	const char *dev;
-};
-
-static struct args args = {
-	.devn = UBI_DEV_NUM_AUTO,
-	.mtdn = -1,
-	.vidoffs = 0,
-	.node = NULL,
-	.dev = NULL,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to attach MTD device to UBI.";
-
-static const char optionsstr[] =
-"-d, --devn=<number>   the number to assign to the newly created UBI device\n"
-"                      (assigned automatically if this is not specified)\n"
-"-p, --dev-path=<path> path to MTD device node to attach\n"
-"-m, --mtdn=<number>   MTD device number to attach (alternative method, e.g\n"
-"                      if the character device node does not exist)\n"
-"-O, --vid-hdr-offset  VID header offset (do not specify this unless you really\n"
-"                      know what you are doing, the default should be optimal)\n"
-"-h, --help            print help message\n"
-"-V, --version         print program version";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n"
-"\t[-m <MTD device number>] [-d <UBI device number>] [-p <path to device>]\n"
-"\t[--mtdn=<MTD device number>] [--devn=<UBI device number>]\n"
-"\t[--dev-path=<path to device>]\n"
-"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n"
-"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - attach /dev/mtd0 to UBI\n"
-"Example 2: " PROGRAM_NAME " -m 0 - attach MTD device 0 (mtd0) to UBI\n"
-"Example 3: " PROGRAM_NAME " -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI\n"
-"           and create UBI device number 3 (ubi3)";
-
-static const struct option long_options[] = {
-	{ .name = "devn",           .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "dev-path",       .has_arg = 1, .flag = NULL, .val = 'p' },
-	{ .name = "mtdn",           .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "p:m:d:O:hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'p':
-			args.dev = optarg;
-			break;
-		case 'd':
-			args.devn = simple_strtoul(optarg, &error);
-			if (error || args.devn < 0)
-				return errmsg("bad UBI device number: \"%s\"", optarg);
-
-			break;
-
-		case 'm':
-			args.mtdn = simple_strtoul(optarg, &error);
-			if (error || args.mtdn < 0)
-				return errmsg("bad MTD device number: \"%s\"", optarg);
-
-			break;
-
-		case 'O':
-			args.vidoffs = simple_strtoul(optarg, &error);
-			if (error || args.vidoffs <= 0)
-				return errmsg("bad VID header offset: \"%s\"", optarg);
-
-			break;
-
-		case 'h':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		args.node = DEFAULT_CTRL_DEV;
-	else if (optind != argc - 1)
-		return errmsg("more then one UBI control device specified (use -h for help)");
-	else
-		args.node = argv[optind];
-
-	if (args.mtdn == -1 && args.dev == NULL)
-		return errmsg("MTD device to attach was not specified (use -h for help)");
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_info ubi_info;
-	struct ubi_dev_info dev_info;
-	struct ubi_attach_request req;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			return errmsg("UBI is not present in the system");
-		return sys_errmsg("cannot open libubi");
-	}
-
-	/*
-	 * Make sure the kernel is fresh enough and this feature is supported.
-	 */
-	err = ubi_get_info(libubi, &ubi_info);
-	if (err) {
-		sys_errmsg("cannot get UBI information");
-		goto out_libubi;
-	}
-
-	if (ubi_info.ctrl_major == -1) {
-		errmsg("MTD attach/detach feature is not supported by your kernel");
-		goto out_libubi;
-	}
-
-	req.dev_num = args.devn;
-	req.mtd_num = args.mtdn;
-	req.vid_hdr_offset = args.vidoffs;
-	req.mtd_dev_node = args.dev;
-
-	err = ubi_attach(libubi, args.node, &req);
-	if (err) {
-		if (args.dev)
-			sys_errmsg("cannot attach \"%s\"", args.dev);
-		else
-			sys_errmsg("cannot attach mtd%d", args.mtdn);
-		goto out_libubi;
-	}
-
-	/* Print some information about the new UBI device */
-	err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info);
-	if (err) {
-		sys_errmsg("cannot get information about newly created UBI device");
-		goto out_libubi;
-	}
-
-	printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs);
-	ubiutils_print_bytes(dev_info.total_bytes, 0);
-	printf("), available %d LEBs (", dev_info.avail_lebs);
-	ubiutils_print_bytes(dev_info.avail_bytes, 0);
-	printf("), LEB size ");
-	ubiutils_print_bytes(dev_info.leb_size, 1);
-	printf("\n");
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/src/ubicrc32.c
deleted file mode 100644
index 73ec595..0000000
--- a/ubi-utils/src/ubicrc32.c
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Calculate CRC32 with UBI start value (0xFFFFFFFF) for a given binary image.
- *
- * Author: Oliver Lohmann
- */
-
-#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME    "ubicrc32"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <unistd.h>
-#include <mtd/ubi-media.h>
-#include <crc32.h>
-
-#include "common.h"
-
-#define BUFSIZE 4096
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
-
-static const char optionsstr[] =
-"-h, --help                    print help message\n"
-"-V, --version                 print program version";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <file to calculate CRC32 for> [-h] [--help]";
-
-static const struct option long_options[] = {
-	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key;
-
-		key = getopt_long(argc, argv, "hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'h':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err = 0;
-	uint32_t crc = UBI_CRC32_INIT;
-	char buf[BUFSIZE];
-	FILE *fp;
-
-	if (argc > 1) {
-		fp = fopen(argv[1], "r");
-		if (!fp)
-			return sys_errmsg("cannot open \"%s\"", argv[1]);
-	} else
-		fp = stdin;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return err;
-
-	while (!feof(fp)) {
-		size_t read;
-
-		read = fread(buf, 1, BUFSIZE, fp);
-		if (ferror(fp)) {
-			sys_errmsg("cannot read input file");
-			err = -1;
-			goto out_close;
-		}
-		crc = mtd_crc32(crc, buf, read);
-	}
-
-	printf("0x%08x\n", crc);
-
-out_close:
-	if (fp != stdin)
-		fclose(fp);
-	return err;
-}
diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/src/ubidetach.c
deleted file mode 100644
index 668f1bd..0000000
--- a/ubi-utils/src/ubidetach.c
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2007 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to delete UBI devices (detach MTD devices from UBI).
- *
- * Author: Artem Bityutskiy
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubidetach"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-
-#define DEFAULT_CTRL_DEV "/dev/ubi_ctrl"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int devn;
-	int mtdn;
-	const char *node;
-	const char *dev;
-};
-
-static struct args args = {
-	.devn = UBI_DEV_NUM_AUTO,
-	.mtdn = -1,
-	.node = NULL,
-	.dev = NULL,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-" - tool to remove UBI devices (detach MTD devices from UBI)";
-
-static const char optionsstr[] =
-"-d, --devn=<UBI device number>  UBI device number to delete\n"
-"-p, --dev-path=<path to device> or alternatively, MTD device node path to detach\n"
-"-m, --mtdn=<MTD device number>  or alternatively, MTD device number to detach\n"
-"-h, --help                      print help message\n"
-"-V, --version                   print program version";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n"
-"\t[-d <UBI device number>] [-m <MTD device number>] [-p <path to device>]\n"
-"\t[--devn=<UBI device number>] [--mtdn=<MTD device number>]\n"
-"\t[--dev-path=<path to device>]\n"
-"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n"
-"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - detach MTD device /dev/mtd0\n"
-"Example 2: " PROGRAM_NAME " -d 2 - delete UBI device 2 (ubi2)\n"
-"Example 3: " PROGRAM_NAME " -m 0 - detach MTD device 0 (mtd0)";
-
-static const struct option long_options[] = {
-	{ .name = "devn",     .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "dev-path", .has_arg = 1, .flag = NULL, .val = 'p' },
-	{ .name = "mtdn",     .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "help",     .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",  .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "p:m:d:hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'p':
-			args.dev = optarg;
-			break;
-		case 'd':
-			args.devn = simple_strtoul(optarg, &error);
-			if (error || args.devn < 0)
-				return errmsg("bad UBI device number: \"%s\"", optarg);
-
-			break;
-
-		case 'm':
-			args.mtdn = simple_strtoul(optarg, &error);
-			if (error || args.mtdn < 0)
-				return errmsg("bad MTD device number: \"%s\"", optarg);
-
-			break;
-
-		case 'h':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		args.node = DEFAULT_CTRL_DEV;
-	else if (optind != argc - 1)
-		return errmsg("more then one UBI control device specified (use -h for help)");
-	else
-		args.node = argv[optind];
-
-	if (args.mtdn == -1 && args.devn == -1 && args.dev == NULL)
-		return errmsg("neither MTD nor UBI devices were specified (use -h for help)");
-
-	if (args.devn != -1) {
-		if (args.mtdn != -1 || args.dev != NULL)
-			return errmsg("specify either MTD or UBI device (use -h for help)");
-
-	} else if (args.mtdn != -1 && args.dev != NULL)
-		return errmsg("specify either MTD number or device node (use -h for help)");
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_info ubi_info;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			return errmsg("UBI is not present in the system");
-		return sys_errmsg("cannot open libubi");
-	}
-
-	/*
-	 * Make sure the kernel is fresh enough and this feature is supported.
-	 */
-	err = ubi_get_info(libubi, &ubi_info);
-	if (err) {
-		sys_errmsg("cannot get UBI information");
-		goto out_libubi;
-	}
-
-	if (ubi_info.ctrl_major == -1) {
-		errmsg("MTD detach/detach feature is not supported by your kernel");
-		goto out_libubi;
-	}
-
-	if (args.devn != -1) {
-		err = ubi_remove_dev(libubi, args.node, args.devn);
-		if (err) {
-			sys_errmsg("cannot remove ubi%d", args.devn);
-			goto out_libubi;
-		}
-	} else {
-		if (args.dev != NULL) {
-			err = ubi_detach(libubi, args.node, args.dev);
-			if (err) {
-				sys_errmsg("cannot detach \"%s\"", args.dev);
-				goto out_libubi;
-			}
-		} else {
-			err = ubi_detach_mtd(libubi, args.node, args.mtdn);
-			if (err) {
-				sys_errmsg("cannot detach mtd%d", args.mtdn);
-				goto out_libubi;
-			}
-		}
-	}
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
-
diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/src/ubiformat.c
deleted file mode 100644
index c4b944a..0000000
--- a/ubi-utils/src/ubiformat.c
+++ /dev/null
@@ -1,950 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * An utility to format MTD devices into UBI and flash UBI images.
- *
- * Author: Artem Bityutskiy
- */
-
-/*
- * Maximum amount of consequtive eraseblocks which are considered as normal by
- * this utility. Otherwise it is assume that something is wrong with the flash
- * or the driver, and eraseblocks are stopped being marked as bad.
- */
-#define MAX_CONSECUTIVE_BAD_BLOCKS 4
-
-#define PROGRAM_VERSION "1.5"
-#define PROGRAM_NAME    "ubiformat"
-
-#include <sys/stat.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <fcntl.h>
-
-#include <libubi.h>
-#include <libmtd.h>
-#include <libscan.h>
-#include <libubigen.h>
-#include <mtd_swab.h>
-#include <crc32.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-/* The variables below are set by command line arguments */
-struct args {
-	unsigned int yes:1;
-	unsigned int quiet:1;
-	unsigned int verbose:1;
-	unsigned int override_ec:1;
-	unsigned int novtbl:1;
-	unsigned int manual_subpage;
-	int subpage_size;
-	int vid_hdr_offs;
-	int ubi_ver;
-	uint32_t image_seq;
-	off_t image_sz;
-	long long ec;
-	const char *image;
-	const char *node;
-	int node_fd;
-};
-
-static struct args args =
-{
-	.ubi_ver   = 1,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-		" - a tool to format MTD devices and flash UBI images";
-
-static const char optionsstr[] =
-"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
-"                             headers, e.g. sub-page size in case of NAND\n"
-"                             flash (equivalent to the minimum input/output\n"
-"                             unit size by default)\n"
-"-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n"
-"                             physical eraseblock (default is the next\n"
-"                             minimum I/O unit or sub-page after the EC\n"
-"                             header)\n"
-"-n, --no-volume-table        only erase all eraseblock and preserve erase\n"
-"                             counters, do not write empty volume table\n"
-"-f, --flash-image=<file>     flash image file, or '-' for stdin\n"
-"-S, --image-size=<bytes>     bytes in input, if not reading from file\n"
-"-e, --erase-counter=<value>  use <value> as the erase counter value for all\n"
-"                             eraseblocks\n"
-"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
-"                             (default is 1)\n"
-"-Q, --image-seq=<num>        32-bit UBI image sequence number to use\n"
-"                             (by default a random number is picked)\n"
-"-y, --yes                    assume the answer is \"yes\" for all question\n"
-"                             this program would otherwise ask\n"
-"-q, --quiet                  suppress progress percentage information\n"
-"-v, --verbose                be verbose\n"
-"-h, -?, --help               print help message\n"
-"-V, --version                print program version\n";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]\n"
-"\t\t\t[-f <file>] [-S <bytes>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]\n"
-"\t\t\t[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]\n"
-"\t\t\t[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]\n"
-"\t\t\t[--ubi-ver=<num>] [--yes] [--quiet] [--verbose] [--help] [--version]\n\n"
-"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n"
-"           not ask questions.\n"
-"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n"
-"           be quiet and force erase counter value 0.";
-
-static const struct option long_options[] = {
-	{ .name = "sub-page-size",   .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "vid-hdr-offset",  .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' },
-	{ .name = "flash-image",     .has_arg = 1, .flag = NULL, .val = 'f' },
-	{ .name = "image-size",      .has_arg = 1, .flag = NULL, .val = 'S' },
-	{ .name = "yes",             .has_arg = 0, .flag = NULL, .val = 'y' },
-	{ .name = "erase-counter",   .has_arg = 1, .flag = NULL, .val = 'e' },
-	{ .name = "quiet",           .has_arg = 0, .flag = NULL, .val = 'q' },
-	{ .name = "verbose",         .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "ubi-ver",         .has_arg = 1, .flag = NULL, .val = 'x' },
-	{ .name = "help",            .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",         .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	ubiutils_srand();
-	args.image_seq = rand();
-
-	while (1) {
-		int key, error = 0;
-		unsigned long int image_seq;
-
-		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 's':
-			args.subpage_size = ubiutils_get_bytes(optarg);
-			if (args.subpage_size <= 0)
-				return errmsg("bad sub-page size: \"%s\"", optarg);
-			if (!is_power_of_2(args.subpage_size))
-				return errmsg("sub-page size should be power of 2");
-			break;
-
-		case 'O':
-			args.vid_hdr_offs = simple_strtoul(optarg, &error);
-			if (error || args.vid_hdr_offs <= 0)
-				return errmsg("bad VID header offset: \"%s\"", optarg);
-			break;
-
-		case 'e':
-			args.ec = simple_strtoull(optarg, &error);
-			if (error || args.ec < 0)
-				return errmsg("bad erase counter value: \"%s\"", optarg);
-			if (args.ec >= EC_MAX)
-				return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX);
-			args.override_ec = 1;
-			break;
-
-		case 'f':
-			args.image = optarg;
-			break;
-
-		case 'S':
-			args.image_sz = ubiutils_get_bytes(optarg);
-			if (args.image_sz <= 0)
-				return errmsg("bad image-size: \"%s\"", optarg);
-			break;
-
-		case 'n':
-			args.novtbl = 1;
-			break;
-
-		case 'y':
-			args.yes = 1;
-			break;
-
-		case 'q':
-			args.quiet = 1;
-			break;
-
-		case 'x':
-			args.ubi_ver = simple_strtoul(optarg, &error);
-			if (error || args.ubi_ver < 0)
-				return errmsg("bad UBI version: \"%s\"", optarg);
-			break;
-
-		case 'Q':
-			image_seq = simple_strtoul(optarg, &error);
-			if (error || image_seq > 0xFFFFFFFF)
-				return errmsg("bad UBI image sequence number: \"%s\"", optarg);
-			args.image_seq = image_seq;
-			break;
-
-
-		case 'v':
-			args.verbose = 1;
-			break;
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case 'h':
-		case '?':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (args.quiet && args.verbose)
-		return errmsg("using \"-q\" and \"-v\" at the same time does not make sense");
-
-	if (optind == argc)
-		return errmsg("MTD device name was not specified (use -h for help)");
-	else if (optind != argc - 1)
-		return errmsg("more then one MTD device specified (use -h for help)");
-
-	if (args.image && args.novtbl)
-		return errmsg("-n cannot be used together with -f");
-
-
-	args.node = argv[optind];
-	return 0;
-}
-
-static int want_exit(void)
-{
-	char buf[4];
-
-	while (1) {
-		normsg_cont("continue? (yes/no)  ");
-		if (scanf("%3s", buf) == EOF) {
-			sys_errmsg("scanf returned unexpected EOF, assume \"yes\"");
-			return 1;
-		}
-		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
-			return 0;
-		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
-			return 1;
-	}
-}
-
-static int answer_is_yes(void)
-{
-	char buf[4];
-
-	while (1) {
-		if (scanf("%3s", buf) == EOF) {
-			sys_errmsg("scanf returned unexpected EOF, assume \"no\"");
-			return 0;
-		}
-		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
-			return 1;
-		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
-			return 0;
-	}
-}
-
-static void print_bad_eraseblocks(const struct mtd_dev_info *mtd,
-				  const struct ubi_scan_info *si)
-{
-	int first = 1, eb;
-
-	if (si->bad_cnt == 0)
-		return;
-
-	normsg_cont("%d bad eraseblocks found, numbers: ", si->bad_cnt);
-	for (eb = 0; eb < mtd->eb_cnt; eb++) {
-		if (si->ec[eb] != EB_BAD)
-			continue;
-		if (first) {
-			printf("%d", eb);
-			first = 0;
-		} else
-			printf(", %d", eb);
-	}
-	printf("\n");
-}
-
-static int change_ech(struct ubi_ec_hdr *hdr, uint32_t image_seq,
-		      long long ec)
-{
-	uint32_t crc;
-
-	/* Check the EC header */
-	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)
-		return errmsg("bad UBI magic %#08x, should be %#08x",
-			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);
-
-	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-	if (be32_to_cpu(hdr->hdr_crc) != crc)
-		return errmsg("bad CRC %#08x, should be %#08x\n",
-			      crc, be32_to_cpu(hdr->hdr_crc));
-
-	hdr->image_seq = cpu_to_be32(image_seq);
-	hdr->ec = cpu_to_be64(ec);
-	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
-	hdr->hdr_crc = cpu_to_be32(crc);
-
-	return 0;
-}
-
-static int drop_ffs(const struct mtd_dev_info *mtd, const void *buf, int len)
-{
-	int i;
-
-        for (i = len - 1; i >= 0; i--)
-		if (((const uint8_t *)buf)[i] != 0xFF)
-		      break;
-
-        /* The resulting length must be aligned to the minimum flash I/O size */
-        len = i + 1;
-	len = (len + mtd->min_io_size - 1) / mtd->min_io_size;
-	len *=  mtd->min_io_size;
-        return len;
-}
-
-static int open_file(off_t *sz)
-{
-	int fd;
-
-	if (!strcmp(args.image, "-")) {
-		if (args.image_sz == 0)
-			return errmsg("must use '-S' with non-zero value when reading from stdin");
-
-		*sz = args.image_sz;
-		fd  = dup(STDIN_FILENO);
-		if (fd < 0)
-			return sys_errmsg("failed to dup stdin");
-	} else {
-		struct stat st;
-
-		if (stat(args.image, &st))
-			return sys_errmsg("cannot open \"%s\"", args.image);
-
-		*sz = st.st_size;
-		fd  = open(args.image, O_RDONLY);
-		if (fd == -1)
-			return sys_errmsg("cannot open \"%s\"", args.image);
-	}
-
-	return fd;
-}
-
-static int read_all(int fd, void *buf, size_t len)
-{
-	while (len > 0) {
-		ssize_t l = read(fd, buf, len);
-		if (l == 0)
-			return errmsg("eof reached; %zu bytes remaining", len);
-		else if (l > 0) {
-			buf += l;
-			len -= l;
-		} else if (errno == EINTR || errno == EAGAIN)
-			continue;
-		else
-			return sys_errmsg("reading failed; %zu bytes remaining", len);
-	}
-
-	return 0;
-}
-
-/*
- * Returns %-1 if consecutive bad blocks exceeds the
- * MAX_CONSECUTIVE_BAD_BLOCKS and returns %0 otherwise.
- */
-static int consecutive_bad_check(int eb)
-{
-	static int consecutive_bad_blocks = 1;
-	static int prev_bb = -1;
-
-	if (prev_bb == -1)
-		prev_bb = eb;
-
-	if (eb == prev_bb + 1)
-		consecutive_bad_blocks += 1;
-	else
-		consecutive_bad_blocks = 1;
-
-	prev_bb = eb;
-
-	if (consecutive_bad_blocks >= MAX_CONSECUTIVE_BAD_BLOCKS) {
-		if (!args.quiet)
-			printf("\n");
-		return errmsg("consecutive bad blocks exceed limit: %d, bad flash?",
-		              MAX_CONSECUTIVE_BAD_BLOCKS);
-	}
-
-	return 0;
-}
-
-/* TODO: we should actually torture the PEB before marking it as bad */
-static int mark_bad(const struct mtd_dev_info *mtd, struct ubi_scan_info *si, int eb)
-{
-	int err;
-
-	if (!args.yes) {
-		normsg_cont("mark it as bad? Continue (yes/no) ");
-		if (!answer_is_yes())
-			return -1;
-	}
-
-	if (!args.quiet)
-		normsg_cont("marking block %d bad", eb);
-
-	if (!args.quiet)
-		printf("\n");
-
-	if (!mtd->bb_allowed) {
-		if (!args.quiet)
-			printf("\n");
-		return errmsg("bad blocks not supported by this flash");
-	}
-
-	err = mtd_mark_bad(mtd, args.node_fd, eb);
-	if (err)
-		return err;
-
-	si->bad_cnt += 1;
-	si->ec[eb] = EB_BAD;
-
-	return consecutive_bad_check(eb);
-}
-
-static int flash_image(libmtd_t libmtd, const struct mtd_dev_info *mtd,
-		       const struct ubigen_info *ui, struct ubi_scan_info *si)
-{
-	int fd, img_ebs, eb, written_ebs = 0, divisor;
-	off_t st_size;
-
-	fd = open_file(&st_size);
-	if (fd < 0)
-		return fd;
-
-	img_ebs = st_size / mtd->eb_size;
-
-	if (img_ebs > si->good_cnt) {
-		sys_errmsg("file \"%s\" is too large (%lld bytes)",
-			   args.image, (long long)st_size);
-		goto out_close;
-	}
-
-	if (st_size % mtd->eb_size) {
-		return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of ""eraseblock size (%d bytes)",
-				  args.image, (long long)st_size, mtd->eb_size);
-		goto out_close;
-	}
-
-	verbose(args.verbose, "will write %d eraseblocks", img_ebs);
-	divisor = img_ebs;
-	for (eb = 0; eb < mtd->eb_cnt; eb++) {
-		int err, new_len;
-		char buf[mtd->eb_size];
-		long long ec;
-
-		if (!args.quiet && !args.verbose) {
-			printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete  ",
-			       eb, (long long)(eb + 1) * 100 / divisor);
-			fflush(stdout);
-		}
-
-		if (si->ec[eb] == EB_BAD) {
-			divisor += 1;
-			continue;
-		}
-
-		if (args.verbose) {
-			normsg_cont("eraseblock %d: erase", eb);
-			fflush(stdout);
-		}
-
-		err = mtd_erase(libmtd, mtd, args.node_fd, eb);
-		if (err) {
-			if (!args.quiet)
-				printf("\n");
-			sys_errmsg("failed to erase eraseblock %d", eb);
-
-			if (errno != EIO)
-				goto out_close;
-
-			if (mark_bad(mtd, si, eb))
-				goto out_close;
-
-			continue;
-		}
-
-		err = read_all(fd, buf, mtd->eb_size);
-		if (err) {
-			sys_errmsg("failed to read eraseblock %d from \"%s\"",
-				   written_ebs, args.image);
-			goto out_close;
-		}
-
-		if (args.override_ec)
-			ec = args.ec;
-		else if (si->ec[eb] <= EC_MAX)
-			ec = si->ec[eb] + 1;
-		else
-			ec = si->mean_ec;
-
-		if (args.verbose) {
-			printf(", change EC to %lld", ec);
-			fflush(stdout);
-		}
-
-		err = change_ech((struct ubi_ec_hdr *)buf, ui->image_seq, ec);
-		if (err) {
-			errmsg("bad EC header at eraseblock %d of \"%s\"",
-			       written_ebs, args.image);
-			goto out_close;
-		}
-
-		if (args.verbose) {
-			printf(", write data\n");
-			fflush(stdout);
-		}
-
-		new_len = drop_ffs(mtd, buf, mtd->eb_size);
-
-		err = mtd_write(mtd, args.node_fd, eb, 0, buf, new_len);
-		if (err) {
-			sys_errmsg("cannot write eraseblock %d", eb);
-
-			if (errno != EIO)
-				goto out_close;
-
-			err = mtd_torture(libmtd, mtd, args.node_fd, eb);
-			if (err) {
-				if (mark_bad(mtd, si, eb))
-					goto out_close;
-			}
-			continue;
-		}
-		if (++written_ebs >= img_ebs)
-			break;
-	}
-
-	if (!args.quiet && !args.verbose)
-		printf("\n");
-	close(fd);
-	return eb + 1;
-
-out_close:
-	close(fd);
-	return -1;
-}
-
-static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd,
-		  const struct ubigen_info *ui, struct ubi_scan_info *si,
-		  int start_eb, int novtbl)
-{
-	int eb, err, write_size;
-	struct ubi_ec_hdr *hdr;
-	struct ubi_vtbl_record *vtbl;
-	int eb1 = -1, eb2 = -1;
-	long long ec1 = -1, ec2 = -1;
-
-	write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1;
-	write_size /= mtd->subpage_size;
-	write_size *= mtd->subpage_size;
-	hdr = malloc(write_size);
-	if (!hdr)
-		return sys_errmsg("cannot allocate %d bytes of memory", write_size);
-	memset(hdr, 0xFF, write_size);
-
-	for (eb = start_eb; eb < mtd->eb_cnt; eb++) {
-		long long ec;
-
-		if (!args.quiet && !args.verbose) {
-			printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2lld %% complete  ",
-			       eb, (long long)(eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb));
-			fflush(stdout);
-		}
-
-		if (si->ec[eb] == EB_BAD)
-			continue;
-
-		if (args.override_ec)
-			ec = args.ec;
-		else if (si->ec[eb] <= EC_MAX)
-			ec = si->ec[eb] + 1;
-		else
-			ec = si->mean_ec;
-		ubigen_init_ec_hdr(ui, hdr, ec);
-
-		if (args.verbose) {
-			normsg_cont("eraseblock %d: erase", eb);
-			fflush(stdout);
-		}
-
-		err = mtd_erase(libmtd, mtd, args.node_fd, eb);
-		if (err) {
-			if (!args.quiet)
-				printf("\n");
-
-			sys_errmsg("failed to erase eraseblock %d", eb);
-			if (errno != EIO)
-				goto out_free;
-
-			if (mark_bad(mtd, si, eb))
-				goto out_free;
-			continue;
-		}
-
-		if ((eb1 == -1 || eb2 == -1) && !novtbl) {
-			if (eb1 == -1) {
-				eb1 = eb;
-				ec1 = ec;
-			} else if (eb2 == -1) {
-				eb2 = eb;
-				ec2 = ec;
-			}
-			if (args.verbose)
-				printf(", do not write EC, leave for vtbl\n");
-			continue;
-		}
-
-		if (args.verbose) {
-			printf(", write EC %lld\n", ec);
-			fflush(stdout);
-		}
-
-		err = mtd_write(mtd, args.node_fd, eb, 0, hdr, write_size);
-		if (err) {
-			if (!args.quiet && !args.verbose)
-				printf("\n");
-			sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d",
-				   write_size, eb);
-
-			if (errno != EIO) {
-				if (!args.subpage_size != mtd->min_io_size)
-					normsg("may be sub-page size is "
-					       "incorrect?");
-				goto out_free;
-			}
-
-			err = mtd_torture(libmtd, mtd, args.node_fd, eb);
-			if (err) {
-				if (mark_bad(mtd, si, eb))
-					goto out_free;
-			}
-			continue;
-
-		}
-	}
-
-	if (!args.quiet && !args.verbose)
-		printf("\n");
-
-	if (!novtbl) {
-		if (eb1 == -1 || eb2 == -1) {
-			errmsg("no eraseblocks for volume table");
-			goto out_free;
-		}
-
-		verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2);
-		vtbl = ubigen_create_empty_vtbl(ui);
-		if (!vtbl)
-			goto out_free;
-
-		err = ubigen_write_layout_vol(ui, eb1, eb2, ec1,  ec2, vtbl,
-					      args.node_fd);
-		free(vtbl);
-		if (err) {
-			errmsg("cannot write layout volume");
-			goto out_free;
-		}
-	}
-
-	free(hdr);
-	return 0;
-
-out_free:
-	free(hdr);
-	return -1;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err, verbose;
-	libmtd_t libmtd;
-	struct mtd_info mtd_info;
-	struct mtd_dev_info mtd;
-	libubi_t libubi;
-	struct ubigen_info ui;
-	struct ubi_scan_info *si;
-
-	libmtd = libmtd_open();
-	if (!libmtd)
-		return errmsg("MTD subsystem is not present");
-
-	err = parse_opt(argc, argv);
-	if (err)
-		goto out_close_mtd;
-
-	err = mtd_get_info(libmtd, &mtd_info);
-	if (err) {
-		if (errno == ENODEV)
-			errmsg("MTD is not present");
-		sys_errmsg("cannot get MTD information");
-		goto out_close_mtd;
-	}
-
-	err = mtd_get_dev_info(libmtd, args.node, &mtd);
-	if (err) {
-		sys_errmsg("cannot get information about \"%s\"", args.node);
-		goto out_close_mtd;
-	}
-
-	if (!is_power_of_2(mtd.min_io_size)) {
-		errmsg("min. I/O size is %d, but should be power of 2",
-		       mtd.min_io_size);
-		goto out_close;
-	}
-
-	if (!mtd_info.sysfs_supported) {
-		/*
-		 * Linux kernels older than 2.6.30 did not support sysfs
-		 * interface, and it is impossible to find out sub-page
-		 * size in these kernels. This is why users should
-		 * provide -s option.
-		 */
-		if (args.subpage_size == 0) {
-			warnmsg("your MTD system is old and it is impossible "
-				"to detect sub-page size. Use -s to get rid "
-				"of this warning");
-			normsg("assume sub-page to be %d", mtd.subpage_size);
-		} else {
-			mtd.subpage_size = args.subpage_size;
-			args.manual_subpage = 1;
-		}
-	} else if (args.subpage_size && args.subpage_size != mtd.subpage_size) {
-		mtd.subpage_size = args.subpage_size;
-		args.manual_subpage = 1;
-	}
-
-	if (args.manual_subpage) {
-		/* Do some sanity check */
-		if (args.subpage_size > mtd.min_io_size) {
-			errmsg("sub-page cannot be larger than min. I/O unit");
-			goto out_close;
-		}
-
-		if (mtd.min_io_size % args.subpage_size) {
-			errmsg("min. I/O unit size should be multiple of "
-			       "sub-page size");
-			goto out_close;
-		}
-	}
-
-	args.node_fd = open(args.node, O_RDWR);
-	if (args.node_fd == -1) {
-		sys_errmsg("cannot open \"%s\"", args.node);
-		goto out_close_mtd;
-	}
-
-	/* Validate VID header offset if it was specified */
-	if (args.vid_hdr_offs != 0) {
-		if (args.vid_hdr_offs % 8) {
-			errmsg("VID header offset has to be multiple of min. I/O unit size");
-			goto out_close;
-		}
-		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
-			errmsg("bad VID header offset");
-			goto out_close;
-		}
-	}
-
-	if (!mtd.writable) {
-		errmsg("mtd%d (%s) is a read-only device", mtd.mtd_num, args.node);
-		goto out_close;
-	}
-
-	/* Make sure this MTD device is not attached to UBI */
-	libubi = libubi_open();
-	if (libubi) {
-		int ubi_dev_num;
-
-		err = mtd_num2ubi_dev(libubi, mtd.mtd_num, &ubi_dev_num);
-		libubi_close(libubi);
-		if (!err) {
-			errmsg("please, first detach mtd%d (%s) from ubi%d",
-			       mtd.mtd_num, args.node, ubi_dev_num);
-			goto out_close;
-		}
-	}
-
-	if (!args.quiet) {
-		normsg_cont("mtd%d (%s), size ", mtd.mtd_num, mtd.type_str);
-		ubiutils_print_bytes(mtd.size, 1);
-		printf(", %d eraseblocks of ", mtd.eb_cnt);
-		ubiutils_print_bytes(mtd.eb_size, 1);
-		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
-	}
-
-	if (args.quiet)
-		verbose = 0;
-	else if (args.verbose)
-		verbose = 2;
-	else
-		verbose = 1;
-	err = ubi_scan(&mtd, args.node_fd, &si, verbose);
-	if (err) {
-		errmsg("failed to scan mtd%d (%s)", mtd.mtd_num, args.node);
-		goto out_close;
-	}
-
-	if (si->good_cnt == 0) {
-		errmsg("all %d eraseblocks are bad", si->bad_cnt);
-		goto out_free;
-	}
-
-	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
-		errmsg("too few non-bad eraseblocks (%d) on mtd%d",
-		       si->good_cnt, mtd.mtd_num);
-		goto out_free;
-	}
-
-	if (!args.quiet) {
-		if (si->ok_cnt)
-			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
-			       si->ok_cnt, si->mean_ec);
-		if (si->empty_cnt)
-			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
-		if (si->corrupted_cnt)
-			normsg("%d corrupted erase counters", si->corrupted_cnt);
-		print_bad_eraseblocks(&mtd, si);
-	}
-
-	if (si->alien_cnt) {
-		if (!args.yes || !args.quiet)
-			warnmsg("%d of %d eraseblocks contain non-ubifs data",
-				si->alien_cnt, si->good_cnt);
-		if (!args.yes && want_exit()) {
-			if (args.yes && !args.quiet)
-				printf("yes\n");
-			goto out_free;
-		}
-	}
-
-	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
-		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;
-
-		/*
-		 * Make sure the majority of eraseblocks have valid
-		 * erase counters.
-		 */
-		if (percent < 50) {
-			if (!args.yes || !args.quiet)
-				warnmsg("only %d of %d eraseblocks have valid erase counter",
-					si->ok_cnt, si->good_cnt);
-				normsg("erase counter 0 will be used for all eraseblocks");
-				normsg("note, arbitrary erase counter value may be specified using -e option");
-			if (!args.yes && want_exit()) {
-				if (args.yes && !args.quiet)
-					printf("yes\n");
-				goto out_free;
-			}
-			 args.ec = 0;
-			 args.override_ec = 1;
-		} else if (percent < 95) {
-			if (!args.yes || !args.quiet)
-				warnmsg("only %d of %d eraseblocks have valid erase counter",
-					si->ok_cnt, si->good_cnt);
-				normsg("mean erase counter %lld will be used for the rest of eraseblock",
-				       si->mean_ec);
-			if (!args.yes && want_exit()) {
-				if (args.yes && !args.quiet)
-					printf("yes\n");
-				goto out_free;
-			}
-			args.ec = si->mean_ec;
-			args.override_ec = 1;
-		}
-	}
-
-	if (!args.quiet && args.override_ec)
-		normsg("use erase counter %lld for all eraseblocks", args.ec);
-
-	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size,
-			 args.vid_hdr_offs, args.ubi_ver, args.image_seq);
-
-	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
-		/*
-		 * Hmm, what we read from flash and what we calculated using
-		 * min. I/O unit size and sub-page size differs.
-		 */
-		if (!args.yes || !args.quiet) {
-			warnmsg("VID header and data offsets on flash are %d and %d, "
-				"which is different to requested offsets %d and %d",
-				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
-				ui.data_offs);
-			normsg_cont("use new offsets %d and %d? (yes/no)  ",
-				    ui.vid_hdr_offs, ui.data_offs);
-		}
-		if (args.yes || answer_is_yes()) {
-			if (args.yes && !args.quiet)
-				printf("yes\n");
-		} else
-			ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, 0,
-					 si->vid_hdr_offs, args.ubi_ver,
-					 args.image_seq);
-		normsg("use offsets %d and %d",  ui.vid_hdr_offs, ui.data_offs);
-	}
-
-	if (args.image) {
-		err = flash_image(libmtd, &mtd, &ui, si);
-		if (err < 0)
-			goto out_free;
-
-		err = format(libmtd, &mtd, &ui, si, err, 1);
-		if (err)
-			goto out_free;
-	} else {
-		err = format(libmtd, &mtd, &ui, si, 0, args.novtbl);
-		if (err)
-			goto out_free;
-	}
-
-	ubi_scan_free(si);
-	close(args.node_fd);
-	libmtd_close(libmtd);
-	return 0;
-
-out_free:
-	ubi_scan_free(si);
-out_close:
-	close(args.node_fd);
-out_close_mtd:
-	libmtd_close(libmtd);
-	return -1;
-}
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/src/ubimkvol.c
deleted file mode 100644
index 25065e3..0000000
--- a/ubi-utils/src/ubimkvol.c
+++ /dev/null
@@ -1,295 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * An utility to create UBI volumes.
- *
- * Authors: Artem Bityutskiy <dedekind at infradead.org>
- *          Frank Haverkamp <haver at vnet.ibm.com>
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubimkvol"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int vol_id;
-	int vol_type;
-	long long bytes;
-	int lebs;
-	int alignment;
-	const char *name;
-	const char *node;
-	int maxavs;
-};
-
-static struct args args = {
-	.vol_type = UBI_DYNAMIC_VOLUME,
-	.bytes = -1,
-	.lebs = -1,
-	.alignment = 1,
-	.vol_id = UBI_VOL_NUM_AUTO,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to create UBI volumes.";
-
-static const char optionsstr[] =
-"-a, --alignment=<alignment>   volume alignment (default is 1)\n"
-"-n, --vol_id=<volume ID>      UBI volume ID, if not specified, the volume ID\n"
-"                              will be assigned automatically\n"
-"-N, --name=<name>             volume name\n"
-"-s, --size=<bytes>            volume size volume size in bytes, kilobytes (KiB)\n"
-"                              or megabytes (MiB)\n"
-"-S, --lebs=<LEBs count>       alternative way to give volume size in logical\n"
-"                              eraseblocks\n"
-"-m, --maxavsize               set volume size to maximum available size\n"
-"-t, --type=<static|dynamic>   volume type (dynamic, static), default is dynamic\n"
-"-h, -?, --help                print help message\n"
-"-V, --version                 print program version";
-
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]\n"
-"\t\t\t[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m]\n"
-"\t\t\t[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]\n"
-"\t\t\t[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]\n"
-"\t\t\t[--version] [--maxavsize]\n\n"
-"Example: " PROGRAM_NAME " /dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n"
-"         named \"config_data\" on UBI device /dev/ubi0.";
-
-static const struct option long_options[] = {
-	{ .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' },
-	{ .name = "vol_id",    .has_arg = 1, .flag = NULL, .val = 'n' },
-	{ .name = "name",      .has_arg = 1, .flag = NULL, .val = 'N' },
-	{ .name = "size",      .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "lebs",      .has_arg = 1, .flag = NULL, .val = 'S' },
-	{ .name = "type",      .has_arg = 1, .flag = NULL, .val = 't' },
-	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int param_sanity_check(void)
-{
-	int len;
-
-	if (args.bytes == -1 && !args.maxavs && args.lebs == -1)
-		return errmsg("volume size was not specified (use -h for help)");
-
-	if ((args.bytes != -1 && (args.maxavs || args.lebs != -1))  ||
-	    (args.lebs != -1  && (args.maxavs || args.bytes != -1)) ||
-	    (args.maxavs && (args.bytes != -1 || args.lebs != -1)))
-		return errmsg("size specified with more then one option");
-
-	if (args.name == NULL)
-		return errmsg("volume name was not specified (use -h for help)");
-
-	len = strlen(args.name);
-	if (len > UBI_MAX_VOLUME_NAME)
-		return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME);
-
-	return 0;
-}
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "a:n:N:s:S:t:h?Vm", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 't':
-			if (!strcmp(optarg, "dynamic"))
-				args.vol_type = UBI_DYNAMIC_VOLUME;
-			else if (!strcmp(optarg, "static"))
-				args.vol_type = UBI_STATIC_VOLUME;
-			else
-				return errmsg("bad volume type: \"%s\"", optarg);
-			break;
-
-		case 's':
-			args.bytes = ubiutils_get_bytes(optarg);
-			if (args.bytes <= 0)
-				return errmsg("bad volume size: \"%s\"", optarg);
-			break;
-
-		case 'S':
-			args.lebs = simple_strtoull(optarg, &error);
-			if (error || args.lebs <= 0)
-				return errmsg("bad LEB count: \"%s\"", optarg);
-			break;
-
-		case 'a':
-			args.alignment = simple_strtoul(optarg, &error);
-			if (error || args.alignment <= 0)
-				return errmsg("bad volume alignment: \"%s\"", optarg);
-			break;
-
-		case 'n':
-			args.vol_id = simple_strtoul(optarg, &error);
-			if (error || args.vol_id < 0)
-				return errmsg("bad volume ID: " "\"%s\"", optarg);
-			break;
-
-		case 'N':
-			args.name = optarg;
-			break;
-
-		case 'h':
-		case '?':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case 'm':
-			args.maxavs = 1;
-			break;
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		return errmsg("UBI device name was not specified (use -h for help)");
-	else if (optind != argc - 1)
-		return errmsg("more then one UBI device specified (use -h for help)");
-
-	args.node = argv[optind];
-
-	if (param_sanity_check())
-		return -1;
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_dev_info dev_info;
-	struct ubi_vol_info vol_info;
-	struct ubi_mkvol_request req;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return err;
-
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			return errmsg("UBI is not present in the system");
-		return sys_errmsg("cannot open libubi");
-	}
-
-	err = ubi_probe_node(libubi, args.node);
-	if (err == 2) {
-		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
-		       args.node);
-		goto out_libubi;
-	} else if (err < 0) {
-		if (errno == ENODEV)
-			errmsg("\"%s\" is not an UBI device node", args.node);
-		else
-			sys_errmsg("error while probing \"%s\"", args.node);
-		goto out_libubi;
-	}
-
-	err = ubi_get_dev_info(libubi, args.node, &dev_info);
-	if (err) {
-		sys_errmsg("cannot get information about UBI device \"%s\"",
-			   args.node);
-		goto out_libubi;
-	}
-
-	if (dev_info.avail_bytes == 0) {
-		errmsg("UBI device does not have free logical eraseblocks");
-		goto out_libubi;
-	}
-
-	if (args.maxavs) {
-		args.bytes = dev_info.avail_bytes;
-		printf("Set volume size to %lld\n", args.bytes);
-	}
-
-	if (args.lebs != -1) {
-		args.bytes = dev_info.leb_size;
-		args.bytes -= dev_info.leb_size % args.alignment;
-		args.bytes *= args.lebs;
-	}
-
-	req.vol_id = args.vol_id;
-	req.alignment = args.alignment;
-	req.bytes = args.bytes;
-	req.vol_type = args.vol_type;
-	req.name = args.name;
-
-	err = ubi_mkvol(libubi, args.node, &req);
-	if (err < 0) {
-		sys_errmsg("cannot UBI create volume");
-		goto out_libubi;
-	}
-
-	args.vol_id = req.vol_id;
-
-	/* Print information about the created device */
-	err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info);
-	if (err) {
-		sys_errmsg("cannot get information about newly created UBI volume");
-		goto out_libubi;
-	}
-
-	printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
-	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
-	printf("), LEB size ");
-	ubiutils_print_bytes(vol_info.leb_size, 1);
-	printf(", %s, name \"%s\", alignment %d\n",
-	       req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
-	       vol_info.name, vol_info.alignment);
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/src/ubinfo.c
deleted file mode 100644
index 8e14e6e..0000000
--- a/ubi-utils/src/ubinfo.c
+++ /dev/null
@@ -1,434 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nokia Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to get UBI information.
- *
- * Author: Artem Bityutskiy
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubinfo"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int devn;
-	int vol_id;
-	int all;
-	const char *node;
-	const char *vol_name;
-};
-
-static struct args args = {
-	.vol_id = -1,
-	.devn = -1,
-	.all = 0,
-	.node = NULL,
-	.vol_name = NULL,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to print UBI information.";
-
-static const char optionsstr[] =
-"-d, --devn=<UBI device number>  UBI device number to get information about\n"
-"-n, --vol_id=<volume ID>        ID of UBI volume to print information about\n"
-"-N, --name=<volume name>        name of UBI volume to print information about\n"
-"-a, --all                       print information about all devices and volumes,\n"
-"                                or about all volumes if the UBI device was\n"
-"                                specified\n"
-"-h, --help                      print help message\n"
-"-V, --version                   print program version";
-
-static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-d <UBI device number>] [-n <volume ID> | -N <volume name>] [-a] [-h] [-V]\n"
-"\t\t[--vol_id=<volume ID> | --name <volume name>] [--devn <UBI device number>] [--all] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]\n"
-"Usage 3: " PROGRAM_NAME " <UBI volume node file name> [-h] [-V] [--help] [--version]\n\n"
-"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n"
-"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n"
-"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n"
-"           device /dev/ubi0\n"
-"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n"
-"Example 5: " PROGRAM_NAME " -a - print all information\n";
-
-static const struct option long_options[] = {
-	{ .name = "devn",      .has_arg = 1, .flag = NULL, .val = 'd' },
-	{ .name = "vol_id",    .has_arg = 1, .flag = NULL, .val = 'n' },
-	{ .name = "name",      .has_arg = 1, .flag = NULL, .val = 'N' },
-	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
-	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "an:N:d:hV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'a':
-			args.all = 1;
-			break;
-
-		case 'n':
-			args.vol_id = simple_strtoul(optarg, &error);
-			if (error || args.vol_id < 0)
-				return errmsg("bad volume ID: " "\"%s\"", optarg);
-			break;
-
-		case 'N':
-			args.vol_name = optarg;
-			break;
-
-		case 'd':
-			args.devn = simple_strtoul(optarg, &error);
-			if (error || args.devn < 0)
-				return errmsg("bad UBI device number: \"%s\"", optarg);
-
-			break;
-
-		case 'h':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc - 1)
-		args.node = argv[optind];
-	else if (optind < argc)
-		return errmsg("more then one UBI device specified (use -h for help)");
-
-	return 0;
-}
-
-static int translate_dev(libubi_t libubi, const char *node)
-{
-	int err;
-
-	err = ubi_probe_node(libubi, node);
-	if (err == -1) {
-		if (errno != ENODEV)
-			return sys_errmsg("error while probing \"%s\"", node);
-		return errmsg("\"%s\" does not correspond to any UBI device or volume", node);
-	}
-
-	if (err == 1) {
-		struct ubi_dev_info dev_info;
-
-		err = ubi_get_dev_info(libubi, node, &dev_info);
-		if (err)
-			return sys_errmsg("cannot get information about UBI device \"%s\"", node);
-
-		args.devn = dev_info.dev_num;
-	} else {
-		struct ubi_vol_info vol_info;
-
-		err = ubi_get_vol_info(libubi, node, &vol_info);
-		if (err)
-			return sys_errmsg("cannot get information about UBI volume \"%s\"", node);
-
-		if (args.vol_id != -1)
-			return errmsg("both volume character device node (\"%s\") and "
-				      "volume ID (%d) are specify, use only one of them"
-				      "(use -h for help)", node, args.vol_id);
-
-		args.devn = vol_info.dev_num;
-		args.vol_id = vol_info.vol_id;
-	}
-
-	return 0;
-}
-
-static int get_vol_id_by_name(libubi_t libubi, int dev_num, const char *name)
-{
-	int err;
-	struct ubi_vol_info vol_info;
-
-	err = ubi_get_vol_info1_nm(libubi, dev_num, name, &vol_info);
-	if (err)
-		return sys_errmsg("cannot get information about volume \"%s\" on ubi%d\n", name, dev_num);
-
-	args.vol_id = vol_info.vol_id;
-
-	return 0;
-}
-
-static int print_vol_info(libubi_t libubi, int dev_num, int vol_id)
-{
-	int err;
-	struct ubi_vol_info vol_info;
-
-	err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info);
-	if (err)
-		return sys_errmsg("cannot get information about UBI volume %d on ubi%d",
-				  vol_id, dev_num);
-
-	printf("Volume ID:   %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num);
-	printf("Type:        %s\n",
-	       vol_info.type == UBI_DYNAMIC_VOLUME ?  "dynamic" : "static");
-	printf("Alignment:   %d\n", vol_info.alignment);
-
-	printf("Size:        %d LEBs (", vol_info.rsvd_lebs);
-	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
-	printf(")\n");
-
-	if (vol_info.type == UBI_STATIC_VOLUME) {
-		printf("Data bytes:  ");
-		ubiutils_print_bytes(vol_info.data_bytes, 1);
-		printf("\n");
-	}
-	printf("State:       %s\n", vol_info.corrupted ? "corrupted" : "OK");
-	printf("Name:        %s\n", vol_info.name);
-	printf("Character device major/minor: %d:%d\n",
-	       vol_info.major, vol_info.minor);
-
-	return 0;
-}
-
-static int print_dev_info(libubi_t libubi, int dev_num, int all)
-{
-	int i, err, first = 1;
-	struct ubi_dev_info dev_info;
-	struct ubi_vol_info vol_info;
-
-	err = ubi_get_dev_info1(libubi, dev_num, &dev_info);
-	if (err)
-		return sys_errmsg("cannot get information about UBI device %d", dev_num);
-
-	printf("ubi%d\n", dev_info.dev_num);
-	printf("Volumes count:                           %d\n", dev_info.vol_count);
-	printf("Logical eraseblock size:                 ");
-	ubiutils_print_bytes(dev_info.leb_size, 0);
-	printf("\n");
-
-	printf("Total amount of logical eraseblocks:     %d (", dev_info.total_lebs);
-	ubiutils_print_bytes(dev_info.total_bytes, 0);
-	printf(")\n");
-
-	printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs);
-	ubiutils_print_bytes(dev_info.avail_bytes, 0);
-	printf(")\n");
-
-	printf("Maximum count of volumes                 %d\n", dev_info.max_vol_count);
-	printf("Count of bad physical eraseblocks:       %d\n", dev_info.bad_count);
-	printf("Count of reserved physical eraseblocks:  %d\n", dev_info.bad_rsvd);
-	printf("Current maximum erase counter value:     %lld\n", dev_info.max_ec);
-	printf("Minimum input/output unit size:          %d %s\n",
-	       dev_info.min_io_size, dev_info.min_io_size > 1 ? "bytes" : "byte");
-	printf("Character device major/minor:            %d:%d\n",
-	       dev_info.major, dev_info.minor);
-
-	if (dev_info.vol_count == 0)
-		return 0;
-
-	printf("Present volumes:                         ");
-	for (i = dev_info.lowest_vol_id;
-	     i <= dev_info.highest_vol_id; i++) {
-		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
-					  i, dev_info.dev_num);
-		}
-
-		if (!first)
-			printf(", %d", i);
-		else {
-			printf("%d", i);
-			first = 0;
-		}
-	}
-	printf("\n");
-
-	if (!all)
-		return 0;
-
-	first = 1;
-	printf("\n");
-
-	for (i = dev_info.lowest_vol_id;
-	     i <= dev_info.highest_vol_id; i++) {
-		if(!first)
-			printf("-----------------------------------\n");
-		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
-					  i, dev_info.dev_num);
-		}
-		first = 0;
-
-		err = print_vol_info(libubi, dev_info.dev_num, i);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
-static int print_general_info(libubi_t libubi, int all)
-{
-	int i, err, first = 1;
-	struct ubi_info ubi_info;
-	struct ubi_dev_info dev_info;
-
-	err = ubi_get_info(libubi, &ubi_info);
-	if (err)
-		return sys_errmsg("cannot get UBI information");
-
-	printf("UBI version:                    %d\n", ubi_info.version);
-	printf("Count of UBI devices:           %d\n", ubi_info.dev_count);
-	if (ubi_info.ctrl_major != -1)
-		printf("UBI control device major/minor: %d:%d\n",
-		       ubi_info.ctrl_major, ubi_info.ctrl_minor);
-	else
-		printf("UBI control device is not supported by this kernel\n");
-
-	if (ubi_info.dev_count == 0)
-		return 0;
-
-	printf("Present UBI devices:            ");
-	for (i = ubi_info.lowest_dev_num;
-	     i <= ubi_info.highest_dev_num; i++) {
-		err = ubi_get_dev_info1(libubi, i, &dev_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-
-			printf("\n");
-			return sys_errmsg("libubi failed to probe UBI device %d", i);
-		}
-
-		if (!first)
-			printf(", ubi%d", i);
-		else {
-			printf("ubi%d", i);
-			first = 0;
-		}
-	}
-	printf("\n");
-
-	if (!all)
-		return 0;
-
-	first = 1;
-	printf("\n");
-
-	for (i = ubi_info.lowest_dev_num;
-	     i <= ubi_info.highest_dev_num; i++) {
-		if(!first)
-			printf("\n===================================\n\n");
-		first = 0;
-		err = print_dev_info(libubi, i, all);
-		if (err)
-			return err;
-	}
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			return errmsg("UBI is not present in the system");
-		return sys_errmsg("cannot open libubi");
-	}
-
-	if (args.node) {
-		/*
-		 * A character device was specified, translate this into UBI
-		 * device number and volume ID.
-		 */
-		err = translate_dev(libubi, args.node);
-		if (err)
-			goto out_libubi;
-	}
-
-	if (args.vol_name) {
-		err = get_vol_id_by_name(libubi, args.devn, args.vol_name);
-		if (err)
-			goto out_libubi;
-	}
-
-	if (args.vol_id != -1 && args.devn == -1) {
-		errmsg("volume ID is specified, but UBI device number is not "
-		       "(use -h for help)\n");
-		goto out_libubi;
-	}
-
-	if (args.devn != -1 && args.vol_id != -1) {
-		print_vol_info(libubi, args.devn, args.vol_id);
-		goto out;
-	}
-
-	if (args.devn == -1 && args.vol_id == -1)
-		err = print_general_info(libubi, args.all);
-	else if (args.devn != -1 && args.vol_id == -1)
-		err = print_dev_info(libubi, args.devn, args.all);
-
-	if (err)
-		goto out_libubi;
-
-out:
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/src/ubinize.c
deleted file mode 100644
index 3085b66..0000000
--- a/ubi-utils/src/ubinize.c
+++ /dev/null
@@ -1,628 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * Generate UBI images.
- *
- * Authors: Artem Bityutskiy
- *          Oliver Lohmann
- */
-
-#define PROGRAM_VERSION "1.2"
-#define PROGRAM_NAME    "ubinize"
-
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <getopt.h>
-#include <string.h>
-#include <fcntl.h>
-
-#include <mtd/ubi-media.h>
-#include <libubigen.h>
-#include <libiniparser.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-" - a tool to generate UBI images. An UBI image may contain one or more UBI "
-"volumes which have to be defined in the input configuration ini-file. The "
-"ini file defines all the UBI volumes - their characteristics and the and the "
-"contents, but it does not define the characteristics of the flash the UBI "
-"image is generated for. Instead, the flash characteristics are defined via "
-"the command-line options. Note, if not sure about some of the command-line "
-"parameters, do not specify them and let the utility to use default values.";
-
-static const char optionsstr[] =
-"-o, --output=<file name>     output file name\n"
-"-p, --peb-size=<bytes>       size of the physical eraseblock of the flash\n"
-"                             this UBI image is created for in bytes,\n"
-"                             kilobytes (KiB), or megabytes (MiB)\n"
-"                             (mandatory parameter)\n"
-"-m, --min-io-size=<bytes>    minimum input/output unit size of the flash\n"
-"                             in bytes\n"
-"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
-"                             headers, e.g. sub-page size in case of NAND\n"
-"                             flash (equivalent to the minimum input/output\n"
-"                             unit size by default)\n"
-"-O, --vid-hdr-offset=<num>   offset if the VID header from start of the\n"
-"                             physical eraseblock (default is the next\n"
-"                             minimum I/O unit or sub-page after the EC\n"
-"                             header)\n"
-"-e, --erase-counter=<num>    the erase counter value to put to EC headers\n"
-"                             (default is 0)\n"
-"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
-"                             (default is 1)\n"
-"-Q, --image-seq=<num>        32-bit UBI image sequence number to use\n"
-"                             (by default a random number is picked)\n"
-"-v, --verbose                be verbose\n"
-"-h, --help                   print help message\n"
-"-V, --version                print program version";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " [-o filename] [-p <bytes>] [-m <bytes>] [-s <bytes>] [-O <num>] [-e <num>]\n"
-"\t\t[-x <num>] [-Q <num>] [-v] [-h] [-V] [--output=<filename>] [--peb-size=<bytes>]\n"
-"\t\t[--min-io-size=<bytes>] [--sub-page-size=<bytes>] [--vid-hdr-offset=<num>]\n"
-"\t\t[--erase-counter=<num>] [--ubi-ver=<num>] [--image-seq=<num>] [--verbose] [--help]\n"
-"\t\t[--version] ini-file\n"
-"Example: " PROGRAM_NAME " -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image\n"
-"         'ubi.img' as described by configuration file 'cfg.ini'";
-
-static const char ini_doc[] = "INI-file format.\n"
-"The input configuration ini-file describes all the volumes which have to\n"
-"be included to the output UBI image. Each volume is described in its own\n"
-"section which may be named arbitrarily. The section consists on\n"
-"\"key=value\" pairs, for example:\n\n"
-"[jffs2-volume]\n"
-"mode=ubi\n"
-"image=../jffs2.img\n"
-"vol_id=1\n"
-"vol_size=30MiB\n"
-"vol_type=dynamic\n"
-"vol_name=jffs2_volume\n"
-"vol_flags=autoresize\n"
-"vol_alignment=1\n\n"
-"This example configuration file tells the utility to create an UBI image\n"
-"with one volume with ID 1, volume size 30MiB, the volume is dynamic, has\n"
-"name \"jffs2_volume\", \"autoresize\" volume flag, and alignment 1. The\n"
-"\"image=../jffs2.img\" line tells the utility to take the contents of the\n"
-"volume from the \"../jffs2.img\" file. The size of the image file has to be\n"
-"less or equivalent to the volume size (30MiB). The \"mode=ubi\" line is\n"
-"mandatory and just tells that the section describes an UBI volume - other\n"
-"section modes may be added in the future.\n"
-"Notes:\n"
-"  * size in vol_size might be specified kilobytes (KiB), megabytes (MiB),\n"
-"    gigabytes (GiB) or bytes (no modifier);\n"
-"  * if \"vol_size\" key is absent, the volume size is assumed to be\n"
-"    equivalent to the size of the image file (defined by \"image\" key);\n"
-"  * if the \"image\" is absent, the volume is assumed to be empty;\n"
-"  * volume alignment must not be greater than the logical eraseblock size;\n"
-"  * one ini file may contain arbitrary number of sections, the utility will\n"
-"    put all the volumes which are described by these section to the output\n"
-"    UBI image file.";
-
-static const struct option long_options[] = {
-	{ .name = "output",         .has_arg = 1, .flag = NULL, .val = 'o' },
-	{ .name = "peb-size",       .has_arg = 1, .flag = NULL, .val = 'p' },
-	{ .name = "min-io-size",    .has_arg = 1, .flag = NULL, .val = 'm' },
-	{ .name = "sub-page-size",  .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
-	{ .name = "erase-counter",  .has_arg = 1, .flag = NULL, .val = 'e' },
-	{ .name = "ubi-ver",        .has_arg = 1, .flag = NULL, .val = 'x' },
-	{ .name = "image-seq",      .has_arg = 1, .flag = NULL, .val = 'Q' },
-	{ .name = "verbose",        .has_arg = 0, .flag = NULL, .val = 'v' },
-	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0}
-};
-
-struct args {
-	const char *f_in;
-	const char *f_out;
-	int out_fd;
-	int peb_size;
-	int min_io_size;
-	int subpage_size;
-	int vid_hdr_offs;
-	int ec;
-	int ubi_ver;
-	uint32_t image_seq;
-	int verbose;
-	dictionary *dict;
-};
-
-static struct args args = {
-	.peb_size     = -1,
-	.min_io_size  = -1,
-	.subpage_size = -1,
-	.ubi_ver      = 1,
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	ubiutils_srand();
-	args.image_seq = rand();
-
-	while (1) {
-		int key, error = 0;
-		unsigned long int image_seq;
-
-		key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhV", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 'o':
-			args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY,
-					   S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH);
-			if (args.out_fd == -1)
-				return sys_errmsg("cannot open file \"%s\"", optarg);
-			args.f_out = optarg;
-			break;
-
-		case 'p':
-			args.peb_size = ubiutils_get_bytes(optarg);
-			if (args.peb_size <= 0)
-				return errmsg("bad physical eraseblock size: \"%s\"", optarg);
-			break;
-
-		case 'm':
-			args.min_io_size = ubiutils_get_bytes(optarg);
-			if (args.min_io_size <= 0)
-				return errmsg("bad min. I/O unit size: \"%s\"", optarg);
-			if (!is_power_of_2(args.min_io_size))
-				return errmsg("min. I/O unit size should be power of 2");
-			break;
-
-		case 's':
-			args.subpage_size = ubiutils_get_bytes(optarg);
-			if (args.subpage_size <= 0)
-				return errmsg("bad sub-page size: \"%s\"", optarg);
-			if (!is_power_of_2(args.subpage_size))
-				return errmsg("sub-page size should be power of 2");
-			break;
-
-		case 'O':
-			args.vid_hdr_offs = simple_strtoul(optarg, &error);
-			if (error || args.vid_hdr_offs < 0)
-				return errmsg("bad VID header offset: \"%s\"", optarg);
-			break;
-
-		case 'e':
-			args.ec = simple_strtoul(optarg, &error);
-			if (error || args.ec < 0)
-				return errmsg("bad erase counter value: \"%s\"", optarg);
-			break;
-
-		case 'x':
-			args.ubi_ver = simple_strtoul(optarg, &error);
-			if (error || args.ubi_ver < 0)
-				return errmsg("bad UBI version: \"%s\"", optarg);
-			break;
-
-		case 'Q':
-			image_seq = simple_strtoul(optarg, &error);
-			if (error || image_seq > 0xFFFFFFFF)
-				return errmsg("bad UBI image sequence number: \"%s\"", optarg);
-			args.image_seq = image_seq;
-			break;
-
-		case 'v':
-			args.verbose = 1;
-			break;
-
-		case 'h':
-			ubiutils_print_text(stdout, doc, 80);
-			printf("\n%s\n\n", ini_doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		return errmsg("input configuration file was not specified (use -h for help)");
-
-	if (optind != argc - 1)
-		return errmsg("more then one configuration file was specified (use -h for help)");
-
-	args.f_in = argv[optind];
-
-	if (args.peb_size < 0)
-		return errmsg("physical eraseblock size was not specified (use -h for help)");
-
-	if (args.peb_size > 1024*1024)
-		return errmsg("too high physical eraseblock size %d", args.peb_size);
-
-	if (args.min_io_size < 0)
-		return errmsg("min. I/O unit size was not specified (use -h for help)");
-
-	if (args.subpage_size < 0)
-		args.subpage_size = args.min_io_size;
-
-	if (args.subpage_size > args.min_io_size)
-		return errmsg("sub-page cannot be larger then min. I/O unit");
-
-	if (args.peb_size % args.min_io_size)
-		return errmsg("physical eraseblock should be multiple of min. I/O units");
-
-	if (args.min_io_size % args.subpage_size)
-		return errmsg("min. I/O unit size should be multiple of sub-page size");
-
-	if (!args.f_out)
-		return errmsg("output file was not specified (use -h for help)");
-
-	if (args.vid_hdr_offs) {
-		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE >= args.peb_size)
-			return errmsg("bad VID header position");
-		if (args.vid_hdr_offs % 8)
-			return errmsg("VID header offset has to be multiple of min. I/O unit size");
-	}
-
-	return 0;
-}
-
-static int read_section(const struct ubigen_info *ui, const char *sname,
-			struct ubigen_vol_info *vi, const char **img,
-			struct stat *st)
-{
-	char buf[256];
-	const char *p;
-
-	*img = NULL;
-
-	if (strlen(sname) > 128)
-		return errmsg("too long section name \"%s\"", sname);
-
-	/* Make sure mode is UBI, otherwise ignore this section */
-	sprintf(buf, "%s:mode", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (!p) {
-		errmsg("\"mode\" key not found in section \"%s\"", sname);
-		errmsg("the \"mode\" key is mandatory and has to be "
-		       "\"mode=ubi\" if the section describes an UBI volume");
-		return -1;
-	}
-
-	/* If mode is not UBI, skip this section */
-	if (strcmp(p, "ubi")) {
-		verbose(args.verbose, "skip non-ubi section \"%s\"", sname);
-		return 1;
-	}
-
-	verbose(args.verbose, "mode=ubi, keep parsing");
-
-	/* Fetch volume type */
-	sprintf(buf, "%s:vol_type", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (!p) {
-		normsg("volume type was not specified in "
-		       "section \"%s\", assume \"dynamic\"\n", sname);
-		vi->type = UBI_VID_DYNAMIC;
-	} else {
-		if (!strcmp(p, "static"))
-			vi->type = UBI_VID_STATIC;
-		else if (!strcmp(p, "dynamic"))
-			vi->type = UBI_VID_DYNAMIC;
-		else
-			return errmsg("invalid volume type \"%s\" in section  \"%s\"",
-				      p, sname);
-	}
-
-	verbose(args.verbose, "volume type: %s",
-		vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static");
-
-	/* Fetch the name of the volume image file */
-	sprintf(buf, "%s:image", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (p) {
-		*img = p;
-		if (stat(p, st))
-			return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"",
-					  p, sname);
-		if (st->st_size == 0)
-			return errmsg("empty file \"%s\" referred from section \"%s\"",
-				       p, sname);
-	} else if (vi->type == UBI_VID_STATIC)
-		return errmsg("image is not specified for static volume in section \"%s\"",
-			      sname);
-
-	/* Fetch volume id */
-	sprintf(buf, "%s:vol_id", sname);
-	vi->id = iniparser_getint(args.dict, buf, -1);
-	if (vi->id == -1)
-		return errmsg("\"vol_id\" key not found in section  \"%s\"", sname);
-	if (vi->id < 0)
-		return errmsg("negative volume ID %d in section \"%s\"",
-			      vi->id, sname);
-	if (vi->id >= ui->max_volumes)
-		return errmsg("too high volume ID %d in section \"%s\", max. is %d",
-			      vi->id, sname, ui->max_volumes);
-
-	verbose(args.verbose, "volume ID: %d", vi->id);
-
-	/* Fetch volume size */
-	sprintf(buf, "%s:vol_size", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (p) {
-		vi->bytes = ubiutils_get_bytes(p);
-		if (vi->bytes <= 0)
-			return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")",
-				      p, sname);
-
-		/* Make sure the image size is not larger than volume size */
-		if (*img && st->st_size > vi->bytes)
-			return errmsg("error in section \"%s\": size of the image file "
-				      "\"%s\" is %lld, which is larger than volume size %lld",
-				      sname, *img, (long long)st->st_size, vi->bytes);
-		verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
-	} else {
-		struct stat st;
-
-		if (!*img)
-			return errmsg("neither image file (\"image=\") nor volume size "
-				      "(\"vol_size=\") specified in section \"%s\"", sname);
-
-		if (stat(*img, &st))
-			return sys_errmsg("cannot stat \"%s\"", *img);
-
-		vi->bytes = st.st_size;
-
-		if (vi->bytes == 0)
-			return errmsg("file \"%s\" referred from section \"%s\" is empty",
-				      *img, sname);
-
-		normsg_cont("volume size was not specified in section \"%s\", assume"
-			    " minimum to fit image \"%s\"", sname, *img);
-		ubiutils_print_bytes(vi->bytes, 1);
-		printf("\n");
-	}
-
-	/* Fetch volume name */
-	sprintf(buf, "%s:vol_name", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (!p)
-		return errmsg("\"vol_name\" key not found in section \"%s\"", sname);
-
-	vi->name = p;
-	vi->name_len = strlen(p);
-	if (vi->name_len > UBI_VOL_NAME_MAX)
-		return errmsg("too long volume name in section \"%s\", max. is %d characters",
-			      vi->name, UBI_VOL_NAME_MAX);
-
-	verbose(args.verbose, "volume name: %s", p);
-
-	/* Fetch volume alignment */
-	sprintf(buf, "%s:vol_alignment", sname);
-	vi->alignment = iniparser_getint(args.dict, buf, -1);
-	if (vi->alignment == -1)
-		vi->alignment = 1;
-	else if (vi->id < 0)
-		return errmsg("negative volume alignement %d in section \"%s\"",
-			      vi->alignment, sname);
-
-	verbose(args.verbose, "volume alignment: %d", vi->alignment);
-
-	/* Fetch volume flags */
-	sprintf(buf, "%s:vol_flags", sname);
-	p = iniparser_getstring(args.dict, buf, NULL);
-	if (p) {
-		if (!strcmp(p, "autoresize")) {
-			verbose(args.verbose, "autoresize flags found");
-			vi->flags |= UBI_VTBL_AUTORESIZE_FLG;
-		} else {
-			return errmsg("unknown flags \"%s\" in section \"%s\"",
-				      p, sname);
-		}
-	}
-
-	/* Initialize the rest of the volume information */
-	vi->data_pad = ui->leb_size % vi->alignment;
-	vi->usable_leb_size = ui->leb_size - vi->data_pad;
-	if (vi->type == UBI_VID_DYNAMIC)
-		vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
-	else
-		vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
-	vi->compat = 0;
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err = -1, sects, i, autoresize_was_already = 0;
-	struct ubigen_info ui;
-	struct ubi_vtbl_record *vtbl;
-	struct ubigen_vol_info *vi;
-	off_t seek;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	ubigen_info_init(&ui, args.peb_size, args.min_io_size,
-			 args.subpage_size, args.vid_hdr_offs,
-			 args.ubi_ver, args.image_seq);
-
-	verbose(args.verbose, "LEB size:                  %d", ui.leb_size);
-	verbose(args.verbose, "PEB size:                  %d", ui.peb_size);
-	verbose(args.verbose, "min. I/O size:             %d", ui.min_io_size);
-	verbose(args.verbose, "sub-page size:             %d", args.subpage_size);
-	verbose(args.verbose, "VID offset:                %d", ui.vid_hdr_offs);
-	verbose(args.verbose, "data offset:               %d", ui.data_offs);
-	verbose(args.verbose, "UBI image sequence number: %u", ui.image_seq);
-
-	vtbl = ubigen_create_empty_vtbl(&ui);
-	if (!vtbl)
-		goto out;
-
-	args.dict = iniparser_load(args.f_in);
-	if (!args.dict) {
-		errmsg("cannot load the input ini file \"%s\"", args.f_in);
-		goto out_vtbl;
-	}
-
-	verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in);
-
-	/* Each section describes one volume */
-	sects = iniparser_getnsec(args.dict);
-	if (sects == -1) {
-		errmsg("ini-file parsing error (iniparser_getnsec)");
-		goto out_dict;
-	}
-
-	verbose(args.verbose, "count of sections: %d", sects);
-	if (sects == 0) {
-		errmsg("no sections found the ini-file \"%s\"", args.f_in);
-		goto out_dict;
-	}
-
-	if (sects > ui.max_volumes) {
-		errmsg("too many sections (%d) in the ini-file \"%s\"",
-		       sects, args.f_in);
-		normsg("each section corresponds to an UBI volume, maximum "
-		       "count of volumes is %d", ui.max_volumes);
-		goto out_dict;
-	}
-
-	vi = calloc(sizeof(struct ubigen_vol_info), sects);
-	if (!vi) {
-		errmsg("cannot allocate memory");
-		goto out_dict;
-	}
-
-	/*
-	 * Skip 2 PEBs at the beginning of the file for the volume table which
-	 * will be written later.
-	 */
-	seek = ui.peb_size * 2;
-	if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
-		sys_errmsg("cannot seek file \"%s\"", args.f_out);
-		goto out_free;
-	}
-
-	for (i = 0; i < sects; i++) {
-		const char *sname = iniparser_getsecname(args.dict, i);
-		const char *img = NULL;
-		struct stat st;
-		int fd, j;
-
-		if (!sname) {
-			errmsg("ini-file parsing error (iniparser_getsecname)");
-			goto out_free;
-		}
-
-		if (args.verbose)
-			printf("\n");
-		verbose(args.verbose, "parsing section \"%s\"", sname);
-
-		err = read_section(&ui, sname, &vi[i], &img, &st);
-		if (err == -1)
-			goto out_free;
-
-		verbose(args.verbose, "adding volume %d", vi[i].id);
-
-		/*
-		 * Make sure that volume ID and name is unique and that only
-		 * one volume has auto-resize flag
-		 */
-		for (j = 0; j < i; j++) {
-			if (vi[i].id == vi[j].id) {
-				errmsg("volume IDs must be unique, but ID %d "
-				       "in section \"%s\" is not",
-				       vi[i].id, sname);
-				goto out_free;
-			}
-
-			if (!strcmp(vi[i].name, vi[j].name)) {
-				errmsg("volume name must be unique, but name "
-				       "\"%s\" in section \"%s\" is not",
-				       vi[i].name, sname);
-				goto out_free;
-			}
-		}
-
-		if (vi[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
-			if (autoresize_was_already)
-				return errmsg("only one volume is allowed "
-					      "to have auto-resize flag");
-			autoresize_was_already = 1;
-		}
-
-		err = ubigen_add_volume(&ui, &vi[i], vtbl);
-		if (err) {
-			errmsg("cannot add volume for section \"%s\"", sname);
-			goto out_free;
-		}
-
-		if (img) {
-			fd = open(img, O_RDONLY);
-			if (fd == -1) {
-				sys_errmsg("cannot open \"%s\"", img);
-				goto out_free;
-			}
-
-			verbose(args.verbose, "writing volume %d", vi[i].id);
-			verbose(args.verbose, "image file: %s", img);
-
-			err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd);
-			close(fd);
-			if (err) {
-				errmsg("cannot write volume for section \"%s\"", sname);
-				goto out_free;
-			}
-		}
-
-		if (args.verbose)
-			printf("\n");
-	}
-
-	verbose(args.verbose, "writing layout volume");
-
-	err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
-	if (err) {
-		errmsg("cannot write layout volume");
-		goto out_free;
-	}
-
-	verbose(args.verbose, "done");
-
-	free(vi);
-	iniparser_freedict(args.dict);
-	free(vtbl);
-	close(args.out_fd);
-	return 0;
-
-out_free:
-	free(vi);
-out_dict:
-	iniparser_freedict(args.dict);
-out_vtbl:
-	free(vtbl);
-out:
-	close(args.out_fd);
-	remove(args.f_out);
-	return err;
-}
diff --git a/ubi-utils/src/ubirename.c b/ubi-utils/src/ubirename.c
deleted file mode 100644
index 070e32e..0000000
--- a/ubi-utils/src/ubirename.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (C) 2008 Logitech.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 51
- * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-/*
- * An utility to get rename UBI volumes.
- *
- * Author: Richard Titmuss
- */
-
-#define PROGRAM_VERSION "1.0"
-#define PROGRAM_NAME    "ubirename"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [<old name> <new name>|...]\n\n"
-"Example: " PROGRAM_NAME "/dev/ubi0 A B C D - rename volume A to B, and C to D\n\n"
-"This utility allows re-naming several volumes in one go atomically.\n"
-"For example, if you have volumes A and B, then you may rename A into B\n"
-"and B into A at one go, and the operation will be atomic. This allows\n"
-"implementing atomic UBI volumes upgrades. E.g., if you have volume A\n"
-"and want to upgrade it atomically, you create a temporary volume B,\n"
-"put your new data to B, then rename A to B and B to A, and then you\n"
-"may remove old volume B.\n"
-"It is also allowed to re-name multiple volumes at a time, but 16 max.\n"
-"renames at once, which means you may specify up to 32 volume names.\n"
-"If you have volumes A and B, and re-name A to B, bud do not re-name\n"
-"B to something else in the same request, old volume B will be removed\n"
-"and A will be renamed into B.\n";
-
-static int get_vol_id(libubi_t libubi, struct ubi_dev_info *dev_info,
-		       char *name)
-{
-	int err, i;
-	struct ubi_vol_info vol_info;
-
-	for (i=dev_info->lowest_vol_id; i<=dev_info->highest_vol_id; i++) {
-		err = ubi_get_vol_info1(libubi, dev_info->dev_num, i, &vol_info);
-		if (err == -1) {
-			if (errno == ENOENT)
-				continue;
-			return -1;
-		}
-
-		if (strcmp(name, vol_info.name) == 0)
-			return vol_info.vol_id;
-	}
-
-	return -1;
-}
-
-int main(int argc, char * const argv[])
-{
-	int i, err;
-	int count = 0;
-	libubi_t libubi;
-	struct ubi_dev_info dev_info;
-	struct ubi_rnvol_req rnvol;
-	const char *node;
-
-	if (argc < 3 || (argc & 1) == 1) {
-		errmsg("too few arguments");
-		fprintf(stderr, "%s\n", usage);
-		return -1;
-	}
-
-	if (argc > UBI_MAX_RNVOL + 2) {
-		errmsg("too many volumes to re-name, max. is %d",
-		       UBI_MAX_RNVOL);
-		return -1;
-	}
-
-	node = argv[1];
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			return errmsg("UBI is not present in the system");
-		return sys_errmsg("cannot open libubi");
-	}
-
-	err = ubi_probe_node(libubi, node);
-	if (err == 2) {
-		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
-		       node);
-		goto out_libubi;
-	} else if (err < 0) {
-		if (errno == ENODEV)
-			errmsg("\"%s\" is not an UBI device node", node);
-		else
-			sys_errmsg("error while probing \"%s\"", node);
-		goto out_libubi;
-	}
-
-	err = ubi_get_dev_info(libubi, node, &dev_info);
-	if (err == -1) {
-		sys_errmsg("cannot get information about UBI device \"%s\"", node);
-		goto out_libubi;
-	}
-
-	for (i = 2; i < argc; i += 2) {
-		err = get_vol_id(libubi, &dev_info, argv[i]);
-		if (err == -1) {
-			errmsg("\"%s\" volume not found", argv[i]);
-			goto out_libubi;
-		}
-
-		rnvol.ents[count].vol_id = err;
-		rnvol.ents[count].name_len = strlen(argv[i + 1]);
-		strcpy(rnvol.ents[count++].name, argv[i + 1]);
-	}
-
-	rnvol.count = count;
-
-	err = ubi_rnvols(libubi, node, &rnvol);
-	if (err == -1) {
-		sys_errmsg("cannot rename volumes");
-		goto out_libubi;
-	}
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/src/ubirmvol.c
deleted file mode 100644
index 5725d90..0000000
--- a/ubi-utils/src/ubirmvol.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * An utility to remove UBI volumes.
- *
- * Authors: Artem Bityutskiy <dedekind at infradead.org>
- *          Frank Haverkamp <haver at vnet.ibm.com>
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubirmvol"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int vol_id;
-	const char *node;
-	const char *name;
-};
-
-static struct args args = {
-	.vol_id = -1,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-				 " - a tool to remove UBI volumes.";
-
-static const char optionsstr[] =
-"-n, --vol_id=<volume id>   volume ID to remove\n"
-"-N, --name=<volume name>   volume name to remove\n"
-"-h, -?, --help             print help message\n"
-"-V, --version              print program version";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n"
-"         [-N <volume name>] [--name=<volume name>] [-h] [--help]\n\n"
-"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n"
-"         to /dev/ubi0\n"
-"         " PROGRAM_NAME "/dev/ubi0 -N my_vol - remove UBI named \"my_vol\" from UBI device\n"
-"         corresponding to /dev/ubi0";
-
-static const struct option long_options[] = {
-	{ .name = "vol_id",  .has_arg = 1, .flag = NULL, .val = 'n' },
-	{ .name = "name",    .has_arg = 1, .flag = NULL, .val = 'N' },
-	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int param_sanity_check(void)
-{
-	if (args.vol_id == -1 && !args.name) {
-		errmsg("please, specify either volume ID or volume name");
-		return -1;
-	}
-
-	if (args.vol_id != -1 && args.name) {
-		errmsg("please, specify either volume ID or volume name, not both");
-		return -1;
-	}
-
-	return 0;
-}
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "n:N:h?V", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-
-		case 'n':
-			args.vol_id = simple_strtoul(optarg, &error);
-			if (error || args.vol_id < 0) {
-				errmsg("bad volume ID: " "\"%s\"", optarg);
-				return -1;
-			}
-			break;
-
-		case 'N':
-			args.name = optarg;
-			break;
-
-		case 'h':
-		case '?':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			errmsg("parameter is missing");
-			return -1;
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc) {
-		errmsg("UBI device name was not specified (use -h for help)");
-		return -1;
-	} else if (optind != argc - 1) {
-		errmsg("more then one UBI device specified (use -h for help)");
-		return -1;
-	}
-
-	args.node = argv[optind];
-
-	if (param_sanity_check())
-		return -1;
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			return errmsg("UBI is not present in the system");
-		return sys_errmsg("cannot open libubi");
-	}
-
-	err = ubi_probe_node(libubi, args.node);
-	if (err == 2) {
-		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
-		       args.node);
-		goto out_libubi;
-	} else if (err < 0) {
-		if (errno == ENODEV)
-			errmsg("\"%s\" is not an UBI device node", args.node);
-		else
-			sys_errmsg("error while probing \"%s\"", args.node);
-		goto out_libubi;
-	}
-
-	if (args.name) {
-		struct ubi_dev_info dev_info;
-		struct ubi_vol_info vol_info;
-
-		err = ubi_get_dev_info(libubi, args.node, &dev_info);
-		if (err) {
-			sys_errmsg("cannot get information about UBI device \"%s\"",
-				   args.node);
-			goto out_libubi;
-		}
-
-		err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num,
-					   args.name, &vol_info);
-		if (err) {
-			sys_errmsg("cannot find UBI volume \"%s\"", args.name);
-			goto out_libubi;
-		}
-
-		args.vol_id = vol_info.vol_id;
-	}
-
-	err = ubi_rmvol(libubi, args.node, args.vol_id);
-	if (err) {
-		sys_errmsg("cannot UBI remove volume");
-		goto out_libubi;
-	}
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubirsvol.c b/ubi-utils/src/ubirsvol.c
deleted file mode 100644
index 65f579c..0000000
--- a/ubi-utils/src/ubirsvol.c
+++ /dev/null
@@ -1,245 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * An utility to resize UBI volumes.
- *
- * Authors: Artem Bityutskiy <dedekind at infradead.org>
- *          Frank Haverkamp <haver at vnet.ibm.com>
- */
-
-#define PROGRAM_VERSION "1.1"
-#define PROGRAM_NAME    "ubirsvol"
-
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <libubi.h>
-#include "common.h"
-#include "ubiutils-common.h"
-
-/* The variables below are set by command line arguments */
-struct args {
-	int vol_id;
-	const char *node;
-	const char *name;
-	long long bytes;
-	int lebs;
-};
-
-static struct args args = {
-	.vol_id = -1,
-	.bytes = -1,
-	.lebs = -1,
-};
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-				 " - a tool to resize UBI volumes.";
-
-static const char optionsstr[] =
-"-n, --vol_id=<volume id>   volume ID to resize\n"
-"-N, --name=<volume name>   volume name to resize\n"
-"-s, --size=<bytes>         volume size volume size in bytes, kilobytes (KiB)\n"
-"                           or megabytes (MiB)\n"
-"-S, --lebs=<LEBs count>    alternative way to give volume size in logical\n"
-"                           eraseblocks\n"
-"-h, -?, --help             print help message\n"
-"-V, --version              print program version";
-
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n"
-"         [-N <volume name>] [--name=<volume name>] [-s <bytes>] [-S <LEBs>] [-h] [--help]\n\n"
-"Example: " PROGRAM_NAME " /dev/ubi0 -n 1 -s 1MiB resize UBI volume 1 to 1 MiB on\n"
-"         UBI device corresponding to /dev/ubi0\n"
-"         " PROGRAM_NAME " /dev/ubi0 -N my_vol -s 1MiB - resize UBI volume named \"my_vol\" to 1 MiB\n"
-"	  on UBI device corresponding to /dev/ubi0";
-
-static const struct option long_options[] = {
-	{ .name = "vol_id",  .has_arg = 1, .flag = NULL, .val = 'n' },
-	{ .name = "name",    .has_arg = 1, .flag = NULL, .val = 'N' },
-	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ .name = "size",    .has_arg = 1, .flag = NULL, .val = 's' },
-	{ .name = "lebs",    .has_arg = 1, .flag = NULL, .val = 'S' },
-	{ NULL, 0, NULL, 0},
-};
-
-static int param_sanity_check(void)
-{
-	if (args.vol_id == -1 && !args.name) {
-		errmsg("please, specify either volume ID or volume name");
-		return -1;
-	}
-
-	if (args.vol_id != -1 && args.name) {
-		errmsg("please, specify either volume ID or volume name, not both");
-		return -1;
-	}
-
-	if (args.bytes == -1 && args.lebs == -1)
-		return errmsg("volume size was not specified (use -h for help)");
-
-	if (args.bytes != -1 && args.lebs != -1)
-		return errmsg("size specified with more then one option");
-
-	return 0;
-}
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "s:S:n:N:h?V", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 's':
-			args.bytes = ubiutils_get_bytes(optarg);
-			if (args.bytes <= 0)
-				return errmsg("bad volume size: \"%s\"", optarg);
-			break;
-
-		case 'S':
-			args.lebs = simple_strtoull(optarg, &error);
-			if (error || args.lebs <= 0)
-				return errmsg("bad LEB count: \"%s\"", optarg);
-			break;
-
-		case 'n':
-			args.vol_id = simple_strtoul(optarg, &error);
-			if (error || args.vol_id < 0) {
-				errmsg("bad volume ID: " "\"%s\"", optarg);
-				return -1;
-			}
-			break;
-
-		case 'N':
-			args.name = optarg;
-			break;
-
-		case 'h':
-		case '?':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			errmsg("parameter is missing");
-			return -1;
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc) {
-		errmsg("UBI device name was not specified (use -h for help)");
-		return -1;
-	} else if (optind != argc - 1) {
-		errmsg("more then one UBI device specified (use -h for help)");
-		return -1;
-	}
-
-	args.node = argv[optind];
-
-	if (param_sanity_check())
-		return -1;
-
-	return 0;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_dev_info dev_info;
-	struct ubi_vol_info vol_info;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open();
-	if (!libubi)
-		return sys_errmsg("cannot open libubi");
-
-	err = ubi_probe_node(libubi, args.node);
-	if (err == 2) {
-		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
-		       args.node);
-		goto out_libubi;
-	} else if (err < 0) {
-		if (errno == ENODEV)
-			errmsg("\"%s\" is not an UBI device node", args.node);
-		else
-			sys_errmsg("error while probing \"%s\"", args.node);
-	}
-
-	err = ubi_get_dev_info(libubi, args.node, &dev_info);
-	if (err) {
-		sys_errmsg("cannot get information about UBI device \"%s\"",
-			   args.node);
-		goto out_libubi;
-	}
-
-	if (args.name) {
-		err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num,
-					   args.name, &vol_info);
-		if (err) {
-			sys_errmsg("cannot find UBI volume \"%s\"", args.name);
-			goto out_libubi;
-		}
-
-		args.vol_id = vol_info.vol_id;
-	} else {
-		err = ubi_get_vol_info1(libubi, dev_info.dev_num,
-					   args.vol_id, &vol_info);
-		if (err) {
-			sys_errmsg("cannot find UBI volume ID %d", args.vol_id);
-			goto out_libubi;
-		}
-	}
-
-	if (args.lebs != -1)
-		args.bytes = vol_info.leb_size * args.lebs;
-
-	err = ubi_rsvol(libubi, args.node, args.vol_id, args.bytes);
-	if (err) {
-		sys_errmsg("cannot UBI resize volume");
-		goto out_libubi;
-	}
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/src/ubiupdatevol.c
deleted file mode 100644
index 24f38fe..0000000
--- a/ubi-utils/src/ubiupdatevol.c
+++ /dev/null
@@ -1,324 +0,0 @@
-/*
- * Copyright (c) International Business Machines Corp., 2006
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * An utility to update UBI volumes.
- *
- * Authors: Frank Haverkamp
- *          Joshua W. Boyer
- *          Artem Bityutskiy
- */
-
-#define PROGRAM_VERSION "1.2"
-#define PROGRAM_NAME    "ubiupdatevol"
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <getopt.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-#include <libubi.h>
-#include "common.h"
-
-struct args {
-	int truncate;
-	const char *node;
-	const char *img;
-	/* For deprecated -d and -B options handling */
-	char dev_name[256];
-	int size;
-	int use_stdin;
-};
-
-static struct args args;
-
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
-			 " - a tool to write data to UBI volumes.";
-
-static const char optionsstr[] =
-"-t, --truncate             truncate volume (wipe it out)\n"
-"-s, --size=<bytes>         bytes in input, if not reading from file\n"
-"-h, --help                 print help message\n"
-"-V, --version              print program version";
-
-static const char usage[] =
-"Usage: " PROGRAM_NAME " <UBI volume node file name> [-t] [-s <size>] [-h] [-V] [--truncate]\n"
-"\t\t\t[--size=<size>] [--help] [--version] <image file>\n\n"
-"Example 1: " PROGRAM_NAME " /dev/ubi0_1 fs.img - write file \"fs.img\" to UBI volume /dev/ubi0_1\n"
-"Example 2: " PROGRAM_NAME " /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1";
-
-static const struct option long_options[] = {
-	{ .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' },
-	{ .name = "help",     .has_arg = 0, .flag = NULL, .val = 'h' },
-	{ .name = "version",  .has_arg = 0, .flag = NULL, .val = 'V' },
-	{ .name = "size",     .has_arg = 1, .flag = NULL, .val = 's' },
-	{ NULL, 0, NULL, 0}
-};
-
-static int parse_opt(int argc, char * const argv[])
-{
-	while (1) {
-		int key, error = 0;
-
-		key = getopt_long(argc, argv, "ts:h?V", long_options, NULL);
-		if (key == -1)
-			break;
-
-		switch (key) {
-		case 't':
-			args.truncate = 1;
-			break;
-
-		case 's':
-			args.size = simple_strtoul(optarg, &error);
-			if (error || args.size < 0)
-				return errmsg("bad size: " "\"%s\"", optarg);
-			break;
-
-		case 'h':
-		case '?':
-			printf("%s\n\n", doc);
-			printf("%s\n\n", usage);
-			printf("%s\n", optionsstr);
-			exit(EXIT_SUCCESS);
-
-		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
-			exit(EXIT_SUCCESS);
-
-		case ':':
-			return errmsg("parameter is missing");
-
-		default:
-			fprintf(stderr, "Use -h for help\n");
-			return -1;
-		}
-	}
-
-	if (optind == argc)
-		return errmsg("UBI device name was not specified (use -h for help)");
-	else if (optind != argc - 2 && !args.truncate)
-		return errmsg("specify UBI device name and image file name as first 2 "
-			      "parameters (use -h for help)");
-
-	args.node = argv[optind];
-	args.img  = argv[optind + 1];
-
-	if (args.img && args.truncate)
-		return errmsg("You can't truncate and specify an image (use -h for help)");
-
-	if (args.img && !args.truncate) {
-		if (strcmp(args.img, "-") == 0)
-			args.use_stdin = 1;
-		if (args.use_stdin && !args.size)
-			return errmsg("file size must be specified if input is stdin");
-	}
-
-	return 0;
-}
-
-static int truncate_volume(libubi_t libubi)
-{
-	int err, fd;
-
-	fd = open(args.node, O_RDWR);
-	if (fd == -1)
-		return sys_errmsg("cannot open \"%s\"", args.node);
-
-	err = ubi_update_start(libubi, fd, 0);
-	if (err) {
-		sys_errmsg("cannot truncate volume \"%s\"", args.node);
-		close(fd);
-		return -1;
-	}
-
-	close(fd);
-	return 0;
-}
-
-static int ubi_write(int fd, const void *buf, int len)
-{
-	int ret;
-
-	while (len) {
-		ret = write(fd, buf, len);
-		if (ret < 0) {
-			if (errno == EINTR) {
-				warnmsg("do not interrupt me!");
-				continue;
-			}
-			return sys_errmsg("cannot write %d bytes to volume \"%s\"",
-					  len, args.node);
-		}
-
-		if (ret == 0)
-			return errmsg("cannot write %d bytes to volume \"%s\"", len, args.node);
-
-		len -= ret;
-		buf += ret;
-	}
-
-	return 0;
-}
-
-static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info)
-{
-	int err, fd, ifd;
-	long long bytes;
-	char *buf;
-
-	buf = malloc(vol_info->leb_size);
-	if (!buf)
-		return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size);
-
-	if (!args.size) {
-		struct stat st;
-		err = stat(args.img, &st);
-		if (err < 0) {
-			errmsg("stat failed on \"%s\"", args.img);
-			goto out_free;
-		}
-
-		bytes = st.st_size;
-	} else
-		bytes = args.size;
-
-	if (bytes > vol_info->rsvd_bytes) {
-		errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
-		       args.img, bytes, args.node, vol_info->rsvd_bytes);
-		goto out_free;
-	}
-
-	fd = open(args.node, O_RDWR);
-	if (fd == -1) {
-		sys_errmsg("cannot open UBI volume \"%s\"", args.node);
-		goto out_free;
-	}
-
-	if (args.use_stdin)
-		ifd = STDIN_FILENO;
-	else {
-		ifd = open(args.img, O_RDONLY);
-		if (ifd == -1) {
-			sys_errmsg("cannot open \"%s\"", args.img);
-			goto out_close1;
-		}
-	}
-
-	err = ubi_update_start(libubi, fd, bytes);
-	if (err) {
-		sys_errmsg("cannot start volume \"%s\" update", args.node);
-		goto out_close;
-	}
-
-	while (bytes) {
-		int ret, to_copy = vol_info->leb_size;
-
-		if (to_copy > bytes)
-			to_copy = bytes;
-
-		ret = read(ifd, buf, to_copy);
-		if (ret <= 0) {
-			if (errno == EINTR) {
-				warnmsg("do not interrupt me!");
-				continue;
-			} else {
-				sys_errmsg("cannot read %d bytes from \"%s\"",
-						to_copy, args.img);
-				goto out_close;
-			}
-		}
-
-		err = ubi_write(fd, buf, ret);
-		if (err)
-			goto out_close;
-		bytes -= ret;
-	}
-
-	close(ifd);
-	close(fd);
-	free(buf);
-	return 0;
-
-out_close:
-	close(ifd);
-out_close1:
-	close(fd);
-out_free:
-	free(buf);
-	return -1;
-}
-
-int main(int argc, char * const argv[])
-{
-	int err;
-	libubi_t libubi;
-	struct ubi_vol_info vol_info;
-
-	err = parse_opt(argc, argv);
-	if (err)
-		return -1;
-
-	libubi = libubi_open();
-	if (!libubi) {
-		if (errno == 0)
-			errmsg("UBI is not present in the system");
-		else
-			sys_errmsg("cannot open libubi");
-		goto out_libubi;
-	}
-
-	err = ubi_probe_node(libubi, args.node);
-	if (err == 1) {
-		errmsg("\"%s\" is an UBI device node, not an UBI volume node",
-		       args.node);
-		goto out_libubi;
-	} else if (err < 0) {
-		if (errno == ENODEV)
-			errmsg("\"%s\" is not an UBI volume node", args.node);
-		else
-			sys_errmsg("error while probing \"%s\"", args.node);
-		goto out_libubi;
-	}
-
-	err = ubi_get_vol_info(libubi, args.node, &vol_info);
-	if (err) {
-		sys_errmsg("cannot get information about UBI volume \"%s\"",
-			   args.node);
-		goto out_libubi;
-	}
-
-	if (args.truncate)
-		err = truncate_volume(libubi);
-	else
-		err = update_volume(libubi, &vol_info);
-	if (err)
-		goto out_libubi;
-
-	libubi_close(libubi);
-	return 0;
-
-out_libubi:
-	libubi_close(libubi);
-	return -1;
-}
diff --git a/ubi-utils/src/ubiutils-common.c b/ubi-utils/src/ubiutils-common.c
deleted file mode 100644
index 6609a6b..0000000
--- a/ubi-utils/src/ubiutils-common.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Nokia Corporation
- *
- * 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.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-/*
- * This file contains various common stuff used by UBI utilities.
- *
- * Authors: Artem Bityutskiy
- *          Adrian Hunter
- */
-
-#define PROGRAM_NAME "ubiutils"
-
-#include <sys/time.h>
-#include <sys/types.h>
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include "common.h"
-
-/**
- * get_multiplier - convert size specifier to an integer multiplier.
- * @str: the size specifier string
- *
- * This function parses the @str size specifier, which may be one of
- * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
- * size multiplier in case of success and %-1 in case of failure.
- */
-static int get_multiplier(const char *str)
-{
-	if (!str)
-		return 1;
-
-	/* Remove spaces before the specifier */
-	while (*str == ' ' || *str == '\t')
-		str += 1;
-
-	if (!strcmp(str, "KiB"))
-		return 1024;
-	if (!strcmp(str, "MiB"))
-		return 1024 * 1024;
-	if (!strcmp(str, "GiB"))
-		return 1024 * 1024 * 1024;
-
-	return -1;
-}
-
-/**
- * ubiutils_get_bytes - convert a string containing amount of bytes into an
- * integer
- * @str: string to convert
- *
- * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
- * size specifiers. Returns positive amount of bytes in case of success and %-1
- * in case of failure.
- */
-long long ubiutils_get_bytes(const char *str)
-{
-	char *endp;
-	long long bytes = strtoull(str, &endp, 0);
-
-	if (endp == str || bytes < 0) {
-		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
-		return -1;
-	}
-
-	if (*endp != '\0') {
-		int mult = get_multiplier(endp);
-
-		if (mult == -1) {
-			fprintf(stderr, "bad size specifier: \"%s\" - "
-			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
-			return -1;
-		}
-		bytes *= mult;
-	}
-
-	return bytes;
-}
-
-/**
- * ubiutils_print_bytes - print bytes.
- * @bytes: variable to print
- * @bracket: whether brackets have to be put or not
- *
- * This is a helper function which prints amount of bytes in a human-readable
- * form, i.e., it prints the exact amount of bytes following by the approximate
- * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
- * is.
- */
-void ubiutils_print_bytes(long long bytes, int bracket)
-{
-	const char *p;
-
-	if (bracket)
-		p = " (";
-	else
-		p = ", ";
-
-	printf("%lld bytes", bytes);
-
-	if (bytes > 1024 * 1024 * 1024)
-		printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
-	else if (bytes > 1024 * 1024)
-		printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
-	else if (bytes > 1024 && bytes != 0)
-		printf("%s%.1f KiB", p, (double)bytes / 1024);
-	else
-		return;
-
-	if (bracket)
-		printf(")");
-}
-
-/**
- * ubiutils_print_text - print text and fold it.
- * @stream: file stream to print to
- * @text: text to print
- * @width: maximum allowed text width
- *
- * Print text and fold it so that each line would not have more then @width
- * characters.
- */
-void ubiutils_print_text(FILE *stream, const char *text, int width)
-{
-	int pos, bpos = 0;
-	const char *p;
-	char line[1024];
-
-	if (width > 1023) {
-		fprintf(stream, "%s\n", text);
-		return;
-	}
-	p = text;
-	pos = 0;
-	while (p[pos]) {
-		while (!isspace(p[pos])) {
-			line[pos] = p[pos];
-			if (!p[pos])
-				break;
-			++pos;
-			if (pos == width) {
-				line[pos] = '\0';
-				fprintf(stream, "%s\n", line);
-				p += pos;
-				pos = 0;
-			}
-		}
-		while (pos < width) {
-			line[pos] = p[pos];
-			if (!p[pos]) {
-				bpos = pos;
-				break;
-			}
-			if (isspace(p[pos]))
-				bpos = pos;
-			++pos;
-		}
-		line[bpos] = '\0';
-		fprintf(stream, "%s\n", line);
-		p += bpos;
-		pos = 0;
-		while (p[pos] && isspace(p[pos]))
-			++p;
-	}
-}
-
-/**
- * ubiutils_srand - randomly seed the standard pseudo-random generator.
- *
- * This helper function seeds the standard libc pseudo-random generator with a
- * more or less random value to make sure the 'rand()' call does not return the
- * same sequence every time UBI utilities run. Returns zero in case of success
- * and a %-1 in case of error.
- */
-int ubiutils_srand(void)
-{
-	struct timeval tv;
-	struct timezone tz;
-	unsigned int seed;
-
-	/*
-	 * Just assume that a combination of the PID + current time is a
-	 * reasonably random number.
-	 */
-	if (gettimeofday(&tv, &tz))
-		return -1;
-
-	seed = (unsigned int)tv.tv_sec;
-	seed += (unsigned int)tv.tv_usec;
-	seed *= getpid();
-	seed %= RAND_MAX;
-	srand(seed);
-	return 0;
-}
diff --git a/ubi-utils/ubiattach.c b/ubi-utils/ubiattach.c
new file mode 100644
index 0000000..4f18e99
--- /dev/null
+++ b/ubi-utils/ubiattach.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to attach MTD devices to UBI.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubiattach"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+#define DEFAULT_CTRL_DEV "/dev/ubi_ctrl"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int devn;
+	int mtdn;
+	int vidoffs;
+	const char *node;
+	const char *dev;
+};
+
+static struct args args = {
+	.devn = UBI_DEV_NUM_AUTO,
+	.mtdn = -1,
+	.vidoffs = 0,
+	.node = NULL,
+	.dev = NULL,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to attach MTD device to UBI.";
+
+static const char optionsstr[] =
+"-d, --devn=<number>   the number to assign to the newly created UBI device\n"
+"                      (assigned automatically if this is not specified)\n"
+"-p, --dev-path=<path> path to MTD device node to attach\n"
+"-m, --mtdn=<number>   MTD device number to attach (alternative method, e.g\n"
+"                      if the character device node does not exist)\n"
+"-O, --vid-hdr-offset  VID header offset (do not specify this unless you really\n"
+"                      know what you are doing, the default should be optimal)\n"
+"-h, --help            print help message\n"
+"-V, --version         print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n"
+"\t[-m <MTD device number>] [-d <UBI device number>] [-p <path to device>]\n"
+"\t[--mtdn=<MTD device number>] [--devn=<UBI device number>]\n"
+"\t[--dev-path=<path to device>]\n"
+"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n"
+"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - attach /dev/mtd0 to UBI\n"
+"Example 2: " PROGRAM_NAME " -m 0 - attach MTD device 0 (mtd0) to UBI\n"
+"Example 3: " PROGRAM_NAME " -m 0 -d 3 - attach MTD device 0 (mtd0) to UBI\n"
+"           and create UBI device number 3 (ubi3)";
+
+static const struct option long_options[] = {
+	{ .name = "devn",           .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "dev-path",       .has_arg = 1, .flag = NULL, .val = 'p' },
+	{ .name = "mtdn",           .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "p:m:d:O:hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'p':
+			args.dev = optarg;
+			break;
+		case 'd':
+			args.devn = simple_strtoul(optarg, &error);
+			if (error || args.devn < 0)
+				return errmsg("bad UBI device number: \"%s\"", optarg);
+
+			break;
+
+		case 'm':
+			args.mtdn = simple_strtoul(optarg, &error);
+			if (error || args.mtdn < 0)
+				return errmsg("bad MTD device number: \"%s\"", optarg);
+
+			break;
+
+		case 'O':
+			args.vidoffs = simple_strtoul(optarg, &error);
+			if (error || args.vidoffs <= 0)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+
+			break;
+
+		case 'h':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		args.node = DEFAULT_CTRL_DEV;
+	else if (optind != argc - 1)
+		return errmsg("more then one UBI control device specified (use -h for help)");
+	else
+		args.node = argv[optind];
+
+	if (args.mtdn == -1 && args.dev == NULL)
+		return errmsg("MTD device to attach was not specified (use -h for help)");
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_info ubi_info;
+	struct ubi_dev_info dev_info;
+	struct ubi_attach_request req;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			return errmsg("UBI is not present in the system");
+		return sys_errmsg("cannot open libubi");
+	}
+
+	/*
+	 * Make sure the kernel is fresh enough and this feature is supported.
+	 */
+	err = ubi_get_info(libubi, &ubi_info);
+	if (err) {
+		sys_errmsg("cannot get UBI information");
+		goto out_libubi;
+	}
+
+	if (ubi_info.ctrl_major == -1) {
+		errmsg("MTD attach/detach feature is not supported by your kernel");
+		goto out_libubi;
+	}
+
+	req.dev_num = args.devn;
+	req.mtd_num = args.mtdn;
+	req.vid_hdr_offset = args.vidoffs;
+	req.mtd_dev_node = args.dev;
+
+	err = ubi_attach(libubi, args.node, &req);
+	if (err) {
+		if (args.dev)
+			sys_errmsg("cannot attach \"%s\"", args.dev);
+		else
+			sys_errmsg("cannot attach mtd%d", args.mtdn);
+		goto out_libubi;
+	}
+
+	/* Print some information about the new UBI device */
+	err = ubi_get_dev_info1(libubi, req.dev_num, &dev_info);
+	if (err) {
+		sys_errmsg("cannot get information about newly created UBI device");
+		goto out_libubi;
+	}
+
+	printf("UBI device number %d, total %d LEBs (", dev_info.dev_num, dev_info.total_lebs);
+	ubiutils_print_bytes(dev_info.total_bytes, 0);
+	printf("), available %d LEBs (", dev_info.avail_lebs);
+	ubiutils_print_bytes(dev_info.avail_bytes, 0);
+	printf("), LEB size ");
+	ubiutils_print_bytes(dev_info.leb_size, 1);
+	printf("\n");
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubicrc32.c b/ubi-utils/ubicrc32.c
new file mode 100644
index 0000000..73ec595
--- /dev/null
+++ b/ubi-utils/ubicrc32.c
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Calculate CRC32 with UBI start value (0xFFFFFFFF) for a given binary image.
+ *
+ * Author: Oliver Lohmann
+ */
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME    "ubicrc32"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <mtd/ubi-media.h>
+#include <crc32.h>
+
+#include "common.h"
+
+#define BUFSIZE 4096
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
+
+static const char optionsstr[] =
+"-h, --help                    print help message\n"
+"-V, --version                 print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <file to calculate CRC32 for> [-h] [--help]";
+
+static const struct option long_options[] = {
+	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key;
+
+		key = getopt_long(argc, argv, "hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'h':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err = 0;
+	uint32_t crc = UBI_CRC32_INIT;
+	char buf[BUFSIZE];
+	FILE *fp;
+
+	if (argc > 1) {
+		fp = fopen(argv[1], "r");
+		if (!fp)
+			return sys_errmsg("cannot open \"%s\"", argv[1]);
+	} else
+		fp = stdin;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return err;
+
+	while (!feof(fp)) {
+		size_t read;
+
+		read = fread(buf, 1, BUFSIZE, fp);
+		if (ferror(fp)) {
+			sys_errmsg("cannot read input file");
+			err = -1;
+			goto out_close;
+		}
+		crc = mtd_crc32(crc, buf, read);
+	}
+
+	printf("0x%08x\n", crc);
+
+out_close:
+	if (fp != stdin)
+		fclose(fp);
+	return err;
+}
diff --git a/ubi-utils/ubidetach.c b/ubi-utils/ubidetach.c
new file mode 100644
index 0000000..668f1bd
--- /dev/null
+++ b/ubi-utils/ubidetach.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2007 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to delete UBI devices (detach MTD devices from UBI).
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubidetach"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+#define DEFAULT_CTRL_DEV "/dev/ubi_ctrl"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int devn;
+	int mtdn;
+	const char *node;
+	const char *dev;
+};
+
+static struct args args = {
+	.devn = UBI_DEV_NUM_AUTO,
+	.mtdn = -1,
+	.node = NULL,
+	.dev = NULL,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+" - tool to remove UBI devices (detach MTD devices from UBI)";
+
+static const char optionsstr[] =
+"-d, --devn=<UBI device number>  UBI device number to delete\n"
+"-p, --dev-path=<path to device> or alternatively, MTD device node path to detach\n"
+"-m, --mtdn=<MTD device number>  or alternatively, MTD device number to detach\n"
+"-h, --help                      print help message\n"
+"-V, --version                   print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " [<UBI control device node file name>]\n"
+"\t[-d <UBI device number>] [-m <MTD device number>] [-p <path to device>]\n"
+"\t[--devn=<UBI device number>] [--mtdn=<MTD device number>]\n"
+"\t[--dev-path=<path to device>]\n"
+"UBI control device defaults to " DEFAULT_CTRL_DEV " if not supplied.\n"
+"Example 1: " PROGRAM_NAME " -p /dev/mtd0 - detach MTD device /dev/mtd0\n"
+"Example 2: " PROGRAM_NAME " -d 2 - delete UBI device 2 (ubi2)\n"
+"Example 3: " PROGRAM_NAME " -m 0 - detach MTD device 0 (mtd0)";
+
+static const struct option long_options[] = {
+	{ .name = "devn",     .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "dev-path", .has_arg = 1, .flag = NULL, .val = 'p' },
+	{ .name = "mtdn",     .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "help",     .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",  .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "p:m:d:hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'p':
+			args.dev = optarg;
+			break;
+		case 'd':
+			args.devn = simple_strtoul(optarg, &error);
+			if (error || args.devn < 0)
+				return errmsg("bad UBI device number: \"%s\"", optarg);
+
+			break;
+
+		case 'm':
+			args.mtdn = simple_strtoul(optarg, &error);
+			if (error || args.mtdn < 0)
+				return errmsg("bad MTD device number: \"%s\"", optarg);
+
+			break;
+
+		case 'h':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		args.node = DEFAULT_CTRL_DEV;
+	else if (optind != argc - 1)
+		return errmsg("more then one UBI control device specified (use -h for help)");
+	else
+		args.node = argv[optind];
+
+	if (args.mtdn == -1 && args.devn == -1 && args.dev == NULL)
+		return errmsg("neither MTD nor UBI devices were specified (use -h for help)");
+
+	if (args.devn != -1) {
+		if (args.mtdn != -1 || args.dev != NULL)
+			return errmsg("specify either MTD or UBI device (use -h for help)");
+
+	} else if (args.mtdn != -1 && args.dev != NULL)
+		return errmsg("specify either MTD number or device node (use -h for help)");
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_info ubi_info;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			return errmsg("UBI is not present in the system");
+		return sys_errmsg("cannot open libubi");
+	}
+
+	/*
+	 * Make sure the kernel is fresh enough and this feature is supported.
+	 */
+	err = ubi_get_info(libubi, &ubi_info);
+	if (err) {
+		sys_errmsg("cannot get UBI information");
+		goto out_libubi;
+	}
+
+	if (ubi_info.ctrl_major == -1) {
+		errmsg("MTD detach/detach feature is not supported by your kernel");
+		goto out_libubi;
+	}
+
+	if (args.devn != -1) {
+		err = ubi_remove_dev(libubi, args.node, args.devn);
+		if (err) {
+			sys_errmsg("cannot remove ubi%d", args.devn);
+			goto out_libubi;
+		}
+	} else {
+		if (args.dev != NULL) {
+			err = ubi_detach(libubi, args.node, args.dev);
+			if (err) {
+				sys_errmsg("cannot detach \"%s\"", args.dev);
+				goto out_libubi;
+			}
+		} else {
+			err = ubi_detach_mtd(libubi, args.node, args.mtdn);
+			if (err) {
+				sys_errmsg("cannot detach mtd%d", args.mtdn);
+				goto out_libubi;
+			}
+		}
+	}
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
+
diff --git a/ubi-utils/ubiformat.c b/ubi-utils/ubiformat.c
new file mode 100644
index 0000000..c4b944a
--- /dev/null
+++ b/ubi-utils/ubiformat.c
@@ -0,0 +1,950 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to format MTD devices into UBI and flash UBI images.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+/*
+ * Maximum amount of consequtive eraseblocks which are considered as normal by
+ * this utility. Otherwise it is assume that something is wrong with the flash
+ * or the driver, and eraseblocks are stopped being marked as bad.
+ */
+#define MAX_CONSECUTIVE_BAD_BLOCKS 4
+
+#define PROGRAM_VERSION "1.5"
+#define PROGRAM_NAME    "ubiformat"
+
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <fcntl.h>
+
+#include <libubi.h>
+#include <libmtd.h>
+#include <libscan.h>
+#include <libubigen.h>
+#include <mtd_swab.h>
+#include <crc32.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	unsigned int yes:1;
+	unsigned int quiet:1;
+	unsigned int verbose:1;
+	unsigned int override_ec:1;
+	unsigned int novtbl:1;
+	unsigned int manual_subpage;
+	int subpage_size;
+	int vid_hdr_offs;
+	int ubi_ver;
+	uint32_t image_seq;
+	off_t image_sz;
+	long long ec;
+	const char *image;
+	const char *node;
+	int node_fd;
+};
+
+static struct args args =
+{
+	.ubi_ver   = 1,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+		" - a tool to format MTD devices and flash UBI images";
+
+static const char optionsstr[] =
+"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
+"                             headers, e.g. sub-page size in case of NAND\n"
+"                             flash (equivalent to the minimum input/output\n"
+"                             unit size by default)\n"
+"-O, --vid-hdr-offset=<offs>  offset if the VID header from start of the\n"
+"                             physical eraseblock (default is the next\n"
+"                             minimum I/O unit or sub-page after the EC\n"
+"                             header)\n"
+"-n, --no-volume-table        only erase all eraseblock and preserve erase\n"
+"                             counters, do not write empty volume table\n"
+"-f, --flash-image=<file>     flash image file, or '-' for stdin\n"
+"-S, --image-size=<bytes>     bytes in input, if not reading from file\n"
+"-e, --erase-counter=<value>  use <value> as the erase counter value for all\n"
+"                             eraseblocks\n"
+"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
+"                             (default is 1)\n"
+"-Q, --image-seq=<num>        32-bit UBI image sequence number to use\n"
+"                             (by default a random number is picked)\n"
+"-y, --yes                    assume the answer is \"yes\" for all question\n"
+"                             this program would otherwise ask\n"
+"-q, --quiet                  suppress progress percentage information\n"
+"-v, --verbose                be verbose\n"
+"-h, -?, --help               print help message\n"
+"-V, --version                print program version\n";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <MTD device node file name> [-s <bytes>] [-O <offs>] [-n]\n"
+"\t\t\t[-f <file>] [-S <bytes>] [-e <value>] [-x <num>] [-y] [-q] [-v] [-h] [-v]\n"
+"\t\t\t[--sub-page-size=<bytes>] [--vid-hdr-offset=<offs>] [--no-volume-table]\n"
+"\t\t\t[--flash-image=<file>] [--image-size=<bytes>] [--erase-counter=<value>]\n"
+"\t\t\t[--ubi-ver=<num>] [--yes] [--quiet] [--verbose] [--help] [--version]\n\n"
+"Example 1: " PROGRAM_NAME " /dev/mtd0 -y - format MTD device number 0 and do\n"
+"           not ask questions.\n"
+"Example 2: " PROGRAM_NAME " /dev/mtd0 -q -e 0 - format MTD device number 0,\n"
+"           be quiet and force erase counter value 0.";
+
+static const struct option long_options[] = {
+	{ .name = "sub-page-size",   .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "vid-hdr-offset",  .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "no-volume-table", .has_arg = 0, .flag = NULL, .val = 'n' },
+	{ .name = "flash-image",     .has_arg = 1, .flag = NULL, .val = 'f' },
+	{ .name = "image-size",      .has_arg = 1, .flag = NULL, .val = 'S' },
+	{ .name = "yes",             .has_arg = 0, .flag = NULL, .val = 'y' },
+	{ .name = "erase-counter",   .has_arg = 1, .flag = NULL, .val = 'e' },
+	{ .name = "quiet",           .has_arg = 0, .flag = NULL, .val = 'q' },
+	{ .name = "verbose",         .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "ubi-ver",         .has_arg = 1, .flag = NULL, .val = 'x' },
+	{ .name = "help",            .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",         .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	ubiutils_srand();
+	args.image_seq = rand();
+
+	while (1) {
+		int key, error = 0;
+		unsigned long int image_seq;
+
+		key = getopt_long(argc, argv, "nh?Vyqve:x:s:O:f:S:", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 's':
+			args.subpage_size = ubiutils_get_bytes(optarg);
+			if (args.subpage_size <= 0)
+				return errmsg("bad sub-page size: \"%s\"", optarg);
+			if (!is_power_of_2(args.subpage_size))
+				return errmsg("sub-page size should be power of 2");
+			break;
+
+		case 'O':
+			args.vid_hdr_offs = simple_strtoul(optarg, &error);
+			if (error || args.vid_hdr_offs <= 0)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+			break;
+
+		case 'e':
+			args.ec = simple_strtoull(optarg, &error);
+			if (error || args.ec < 0)
+				return errmsg("bad erase counter value: \"%s\"", optarg);
+			if (args.ec >= EC_MAX)
+				return errmsg("too high erase %llu, counter, max is %u", args.ec, EC_MAX);
+			args.override_ec = 1;
+			break;
+
+		case 'f':
+			args.image = optarg;
+			break;
+
+		case 'S':
+			args.image_sz = ubiutils_get_bytes(optarg);
+			if (args.image_sz <= 0)
+				return errmsg("bad image-size: \"%s\"", optarg);
+			break;
+
+		case 'n':
+			args.novtbl = 1;
+			break;
+
+		case 'y':
+			args.yes = 1;
+			break;
+
+		case 'q':
+			args.quiet = 1;
+			break;
+
+		case 'x':
+			args.ubi_ver = simple_strtoul(optarg, &error);
+			if (error || args.ubi_ver < 0)
+				return errmsg("bad UBI version: \"%s\"", optarg);
+			break;
+
+		case 'Q':
+			image_seq = simple_strtoul(optarg, &error);
+			if (error || image_seq > 0xFFFFFFFF)
+				return errmsg("bad UBI image sequence number: \"%s\"", optarg);
+			args.image_seq = image_seq;
+			break;
+
+
+		case 'v':
+			args.verbose = 1;
+			break;
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case 'h':
+		case '?':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (args.quiet && args.verbose)
+		return errmsg("using \"-q\" and \"-v\" at the same time does not make sense");
+
+	if (optind == argc)
+		return errmsg("MTD device name was not specified (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one MTD device specified (use -h for help)");
+
+	if (args.image && args.novtbl)
+		return errmsg("-n cannot be used together with -f");
+
+
+	args.node = argv[optind];
+	return 0;
+}
+
+static int want_exit(void)
+{
+	char buf[4];
+
+	while (1) {
+		normsg_cont("continue? (yes/no)  ");
+		if (scanf("%3s", buf) == EOF) {
+			sys_errmsg("scanf returned unexpected EOF, assume \"yes\"");
+			return 1;
+		}
+		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
+			return 0;
+		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
+			return 1;
+	}
+}
+
+static int answer_is_yes(void)
+{
+	char buf[4];
+
+	while (1) {
+		if (scanf("%3s", buf) == EOF) {
+			sys_errmsg("scanf returned unexpected EOF, assume \"no\"");
+			return 0;
+		}
+		if (!strncmp(buf, "yes", 3) || !strncmp(buf, "y", 1))
+			return 1;
+		if (!strncmp(buf, "no", 2) || !strncmp(buf, "n", 1))
+			return 0;
+	}
+}
+
+static void print_bad_eraseblocks(const struct mtd_dev_info *mtd,
+				  const struct ubi_scan_info *si)
+{
+	int first = 1, eb;
+
+	if (si->bad_cnt == 0)
+		return;
+
+	normsg_cont("%d bad eraseblocks found, numbers: ", si->bad_cnt);
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		if (si->ec[eb] != EB_BAD)
+			continue;
+		if (first) {
+			printf("%d", eb);
+			first = 0;
+		} else
+			printf(", %d", eb);
+	}
+	printf("\n");
+}
+
+static int change_ech(struct ubi_ec_hdr *hdr, uint32_t image_seq,
+		      long long ec)
+{
+	uint32_t crc;
+
+	/* Check the EC header */
+	if (be32_to_cpu(hdr->magic) != UBI_EC_HDR_MAGIC)
+		return errmsg("bad UBI magic %#08x, should be %#08x",
+			      be32_to_cpu(hdr->magic), UBI_EC_HDR_MAGIC);
+
+	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	if (be32_to_cpu(hdr->hdr_crc) != crc)
+		return errmsg("bad CRC %#08x, should be %#08x\n",
+			      crc, be32_to_cpu(hdr->hdr_crc));
+
+	hdr->image_seq = cpu_to_be32(image_seq);
+	hdr->ec = cpu_to_be64(ec);
+	crc = mtd_crc32(UBI_CRC32_INIT, hdr, UBI_EC_HDR_SIZE_CRC);
+	hdr->hdr_crc = cpu_to_be32(crc);
+
+	return 0;
+}
+
+static int drop_ffs(const struct mtd_dev_info *mtd, const void *buf, int len)
+{
+	int i;
+
+        for (i = len - 1; i >= 0; i--)
+		if (((const uint8_t *)buf)[i] != 0xFF)
+		      break;
+
+        /* The resulting length must be aligned to the minimum flash I/O size */
+        len = i + 1;
+	len = (len + mtd->min_io_size - 1) / mtd->min_io_size;
+	len *=  mtd->min_io_size;
+        return len;
+}
+
+static int open_file(off_t *sz)
+{
+	int fd;
+
+	if (!strcmp(args.image, "-")) {
+		if (args.image_sz == 0)
+			return errmsg("must use '-S' with non-zero value when reading from stdin");
+
+		*sz = args.image_sz;
+		fd  = dup(STDIN_FILENO);
+		if (fd < 0)
+			return sys_errmsg("failed to dup stdin");
+	} else {
+		struct stat st;
+
+		if (stat(args.image, &st))
+			return sys_errmsg("cannot open \"%s\"", args.image);
+
+		*sz = st.st_size;
+		fd  = open(args.image, O_RDONLY);
+		if (fd == -1)
+			return sys_errmsg("cannot open \"%s\"", args.image);
+	}
+
+	return fd;
+}
+
+static int read_all(int fd, void *buf, size_t len)
+{
+	while (len > 0) {
+		ssize_t l = read(fd, buf, len);
+		if (l == 0)
+			return errmsg("eof reached; %zu bytes remaining", len);
+		else if (l > 0) {
+			buf += l;
+			len -= l;
+		} else if (errno == EINTR || errno == EAGAIN)
+			continue;
+		else
+			return sys_errmsg("reading failed; %zu bytes remaining", len);
+	}
+
+	return 0;
+}
+
+/*
+ * Returns %-1 if consecutive bad blocks exceeds the
+ * MAX_CONSECUTIVE_BAD_BLOCKS and returns %0 otherwise.
+ */
+static int consecutive_bad_check(int eb)
+{
+	static int consecutive_bad_blocks = 1;
+	static int prev_bb = -1;
+
+	if (prev_bb == -1)
+		prev_bb = eb;
+
+	if (eb == prev_bb + 1)
+		consecutive_bad_blocks += 1;
+	else
+		consecutive_bad_blocks = 1;
+
+	prev_bb = eb;
+
+	if (consecutive_bad_blocks >= MAX_CONSECUTIVE_BAD_BLOCKS) {
+		if (!args.quiet)
+			printf("\n");
+		return errmsg("consecutive bad blocks exceed limit: %d, bad flash?",
+		              MAX_CONSECUTIVE_BAD_BLOCKS);
+	}
+
+	return 0;
+}
+
+/* TODO: we should actually torture the PEB before marking it as bad */
+static int mark_bad(const struct mtd_dev_info *mtd, struct ubi_scan_info *si, int eb)
+{
+	int err;
+
+	if (!args.yes) {
+		normsg_cont("mark it as bad? Continue (yes/no) ");
+		if (!answer_is_yes())
+			return -1;
+	}
+
+	if (!args.quiet)
+		normsg_cont("marking block %d bad", eb);
+
+	if (!args.quiet)
+		printf("\n");
+
+	if (!mtd->bb_allowed) {
+		if (!args.quiet)
+			printf("\n");
+		return errmsg("bad blocks not supported by this flash");
+	}
+
+	err = mtd_mark_bad(mtd, args.node_fd, eb);
+	if (err)
+		return err;
+
+	si->bad_cnt += 1;
+	si->ec[eb] = EB_BAD;
+
+	return consecutive_bad_check(eb);
+}
+
+static int flash_image(libmtd_t libmtd, const struct mtd_dev_info *mtd,
+		       const struct ubigen_info *ui, struct ubi_scan_info *si)
+{
+	int fd, img_ebs, eb, written_ebs = 0, divisor;
+	off_t st_size;
+
+	fd = open_file(&st_size);
+	if (fd < 0)
+		return fd;
+
+	img_ebs = st_size / mtd->eb_size;
+
+	if (img_ebs > si->good_cnt) {
+		sys_errmsg("file \"%s\" is too large (%lld bytes)",
+			   args.image, (long long)st_size);
+		goto out_close;
+	}
+
+	if (st_size % mtd->eb_size) {
+		return sys_errmsg("file \"%s\" (size %lld bytes) is not multiple of ""eraseblock size (%d bytes)",
+				  args.image, (long long)st_size, mtd->eb_size);
+		goto out_close;
+	}
+
+	verbose(args.verbose, "will write %d eraseblocks", img_ebs);
+	divisor = img_ebs;
+	for (eb = 0; eb < mtd->eb_cnt; eb++) {
+		int err, new_len;
+		char buf[mtd->eb_size];
+		long long ec;
+
+		if (!args.quiet && !args.verbose) {
+			printf("\r" PROGRAM_NAME ": flashing eraseblock %d -- %2lld %% complete  ",
+			       eb, (long long)(eb + 1) * 100 / divisor);
+			fflush(stdout);
+		}
+
+		if (si->ec[eb] == EB_BAD) {
+			divisor += 1;
+			continue;
+		}
+
+		if (args.verbose) {
+			normsg_cont("eraseblock %d: erase", eb);
+			fflush(stdout);
+		}
+
+		err = mtd_erase(libmtd, mtd, args.node_fd, eb);
+		if (err) {
+			if (!args.quiet)
+				printf("\n");
+			sys_errmsg("failed to erase eraseblock %d", eb);
+
+			if (errno != EIO)
+				goto out_close;
+
+			if (mark_bad(mtd, si, eb))
+				goto out_close;
+
+			continue;
+		}
+
+		err = read_all(fd, buf, mtd->eb_size);
+		if (err) {
+			sys_errmsg("failed to read eraseblock %d from \"%s\"",
+				   written_ebs, args.image);
+			goto out_close;
+		}
+
+		if (args.override_ec)
+			ec = args.ec;
+		else if (si->ec[eb] <= EC_MAX)
+			ec = si->ec[eb] + 1;
+		else
+			ec = si->mean_ec;
+
+		if (args.verbose) {
+			printf(", change EC to %lld", ec);
+			fflush(stdout);
+		}
+
+		err = change_ech((struct ubi_ec_hdr *)buf, ui->image_seq, ec);
+		if (err) {
+			errmsg("bad EC header at eraseblock %d of \"%s\"",
+			       written_ebs, args.image);
+			goto out_close;
+		}
+
+		if (args.verbose) {
+			printf(", write data\n");
+			fflush(stdout);
+		}
+
+		new_len = drop_ffs(mtd, buf, mtd->eb_size);
+
+		err = mtd_write(mtd, args.node_fd, eb, 0, buf, new_len);
+		if (err) {
+			sys_errmsg("cannot write eraseblock %d", eb);
+
+			if (errno != EIO)
+				goto out_close;
+
+			err = mtd_torture(libmtd, mtd, args.node_fd, eb);
+			if (err) {
+				if (mark_bad(mtd, si, eb))
+					goto out_close;
+			}
+			continue;
+		}
+		if (++written_ebs >= img_ebs)
+			break;
+	}
+
+	if (!args.quiet && !args.verbose)
+		printf("\n");
+	close(fd);
+	return eb + 1;
+
+out_close:
+	close(fd);
+	return -1;
+}
+
+static int format(libmtd_t libmtd, const struct mtd_dev_info *mtd,
+		  const struct ubigen_info *ui, struct ubi_scan_info *si,
+		  int start_eb, int novtbl)
+{
+	int eb, err, write_size;
+	struct ubi_ec_hdr *hdr;
+	struct ubi_vtbl_record *vtbl;
+	int eb1 = -1, eb2 = -1;
+	long long ec1 = -1, ec2 = -1;
+
+	write_size = UBI_EC_HDR_SIZE + mtd->subpage_size - 1;
+	write_size /= mtd->subpage_size;
+	write_size *= mtd->subpage_size;
+	hdr = malloc(write_size);
+	if (!hdr)
+		return sys_errmsg("cannot allocate %d bytes of memory", write_size);
+	memset(hdr, 0xFF, write_size);
+
+	for (eb = start_eb; eb < mtd->eb_cnt; eb++) {
+		long long ec;
+
+		if (!args.quiet && !args.verbose) {
+			printf("\r" PROGRAM_NAME ": formatting eraseblock %d -- %2lld %% complete  ",
+			       eb, (long long)(eb + 1 - start_eb) * 100 / (mtd->eb_cnt - start_eb));
+			fflush(stdout);
+		}
+
+		if (si->ec[eb] == EB_BAD)
+			continue;
+
+		if (args.override_ec)
+			ec = args.ec;
+		else if (si->ec[eb] <= EC_MAX)
+			ec = si->ec[eb] + 1;
+		else
+			ec = si->mean_ec;
+		ubigen_init_ec_hdr(ui, hdr, ec);
+
+		if (args.verbose) {
+			normsg_cont("eraseblock %d: erase", eb);
+			fflush(stdout);
+		}
+
+		err = mtd_erase(libmtd, mtd, args.node_fd, eb);
+		if (err) {
+			if (!args.quiet)
+				printf("\n");
+
+			sys_errmsg("failed to erase eraseblock %d", eb);
+			if (errno != EIO)
+				goto out_free;
+
+			if (mark_bad(mtd, si, eb))
+				goto out_free;
+			continue;
+		}
+
+		if ((eb1 == -1 || eb2 == -1) && !novtbl) {
+			if (eb1 == -1) {
+				eb1 = eb;
+				ec1 = ec;
+			} else if (eb2 == -1) {
+				eb2 = eb;
+				ec2 = ec;
+			}
+			if (args.verbose)
+				printf(", do not write EC, leave for vtbl\n");
+			continue;
+		}
+
+		if (args.verbose) {
+			printf(", write EC %lld\n", ec);
+			fflush(stdout);
+		}
+
+		err = mtd_write(mtd, args.node_fd, eb, 0, hdr, write_size);
+		if (err) {
+			if (!args.quiet && !args.verbose)
+				printf("\n");
+			sys_errmsg("cannot write EC header (%d bytes buffer) to eraseblock %d",
+				   write_size, eb);
+
+			if (errno != EIO) {
+				if (!args.subpage_size != mtd->min_io_size)
+					normsg("may be sub-page size is "
+					       "incorrect?");
+				goto out_free;
+			}
+
+			err = mtd_torture(libmtd, mtd, args.node_fd, eb);
+			if (err) {
+				if (mark_bad(mtd, si, eb))
+					goto out_free;
+			}
+			continue;
+
+		}
+	}
+
+	if (!args.quiet && !args.verbose)
+		printf("\n");
+
+	if (!novtbl) {
+		if (eb1 == -1 || eb2 == -1) {
+			errmsg("no eraseblocks for volume table");
+			goto out_free;
+		}
+
+		verbose(args.verbose, "write volume table to eraseblocks %d and %d", eb1, eb2);
+		vtbl = ubigen_create_empty_vtbl(ui);
+		if (!vtbl)
+			goto out_free;
+
+		err = ubigen_write_layout_vol(ui, eb1, eb2, ec1,  ec2, vtbl,
+					      args.node_fd);
+		free(vtbl);
+		if (err) {
+			errmsg("cannot write layout volume");
+			goto out_free;
+		}
+	}
+
+	free(hdr);
+	return 0;
+
+out_free:
+	free(hdr);
+	return -1;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err, verbose;
+	libmtd_t libmtd;
+	struct mtd_info mtd_info;
+	struct mtd_dev_info mtd;
+	libubi_t libubi;
+	struct ubigen_info ui;
+	struct ubi_scan_info *si;
+
+	libmtd = libmtd_open();
+	if (!libmtd)
+		return errmsg("MTD subsystem is not present");
+
+	err = parse_opt(argc, argv);
+	if (err)
+		goto out_close_mtd;
+
+	err = mtd_get_info(libmtd, &mtd_info);
+	if (err) {
+		if (errno == ENODEV)
+			errmsg("MTD is not present");
+		sys_errmsg("cannot get MTD information");
+		goto out_close_mtd;
+	}
+
+	err = mtd_get_dev_info(libmtd, args.node, &mtd);
+	if (err) {
+		sys_errmsg("cannot get information about \"%s\"", args.node);
+		goto out_close_mtd;
+	}
+
+	if (!is_power_of_2(mtd.min_io_size)) {
+		errmsg("min. I/O size is %d, but should be power of 2",
+		       mtd.min_io_size);
+		goto out_close;
+	}
+
+	if (!mtd_info.sysfs_supported) {
+		/*
+		 * Linux kernels older than 2.6.30 did not support sysfs
+		 * interface, and it is impossible to find out sub-page
+		 * size in these kernels. This is why users should
+		 * provide -s option.
+		 */
+		if (args.subpage_size == 0) {
+			warnmsg("your MTD system is old and it is impossible "
+				"to detect sub-page size. Use -s to get rid "
+				"of this warning");
+			normsg("assume sub-page to be %d", mtd.subpage_size);
+		} else {
+			mtd.subpage_size = args.subpage_size;
+			args.manual_subpage = 1;
+		}
+	} else if (args.subpage_size && args.subpage_size != mtd.subpage_size) {
+		mtd.subpage_size = args.subpage_size;
+		args.manual_subpage = 1;
+	}
+
+	if (args.manual_subpage) {
+		/* Do some sanity check */
+		if (args.subpage_size > mtd.min_io_size) {
+			errmsg("sub-page cannot be larger than min. I/O unit");
+			goto out_close;
+		}
+
+		if (mtd.min_io_size % args.subpage_size) {
+			errmsg("min. I/O unit size should be multiple of "
+			       "sub-page size");
+			goto out_close;
+		}
+	}
+
+	args.node_fd = open(args.node, O_RDWR);
+	if (args.node_fd == -1) {
+		sys_errmsg("cannot open \"%s\"", args.node);
+		goto out_close_mtd;
+	}
+
+	/* Validate VID header offset if it was specified */
+	if (args.vid_hdr_offs != 0) {
+		if (args.vid_hdr_offs % 8) {
+			errmsg("VID header offset has to be multiple of min. I/O unit size");
+			goto out_close;
+		}
+		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE > mtd.eb_size) {
+			errmsg("bad VID header offset");
+			goto out_close;
+		}
+	}
+
+	if (!mtd.writable) {
+		errmsg("mtd%d (%s) is a read-only device", mtd.mtd_num, args.node);
+		goto out_close;
+	}
+
+	/* Make sure this MTD device is not attached to UBI */
+	libubi = libubi_open();
+	if (libubi) {
+		int ubi_dev_num;
+
+		err = mtd_num2ubi_dev(libubi, mtd.mtd_num, &ubi_dev_num);
+		libubi_close(libubi);
+		if (!err) {
+			errmsg("please, first detach mtd%d (%s) from ubi%d",
+			       mtd.mtd_num, args.node, ubi_dev_num);
+			goto out_close;
+		}
+	}
+
+	if (!args.quiet) {
+		normsg_cont("mtd%d (%s), size ", mtd.mtd_num, mtd.type_str);
+		ubiutils_print_bytes(mtd.size, 1);
+		printf(", %d eraseblocks of ", mtd.eb_cnt);
+		ubiutils_print_bytes(mtd.eb_size, 1);
+		printf(", min. I/O size %d bytes\n", mtd.min_io_size);
+	}
+
+	if (args.quiet)
+		verbose = 0;
+	else if (args.verbose)
+		verbose = 2;
+	else
+		verbose = 1;
+	err = ubi_scan(&mtd, args.node_fd, &si, verbose);
+	if (err) {
+		errmsg("failed to scan mtd%d (%s)", mtd.mtd_num, args.node);
+		goto out_close;
+	}
+
+	if (si->good_cnt == 0) {
+		errmsg("all %d eraseblocks are bad", si->bad_cnt);
+		goto out_free;
+	}
+
+	if (si->good_cnt < 2 && (!args.novtbl || args.image)) {
+		errmsg("too few non-bad eraseblocks (%d) on mtd%d",
+		       si->good_cnt, mtd.mtd_num);
+		goto out_free;
+	}
+
+	if (!args.quiet) {
+		if (si->ok_cnt)
+			normsg("%d eraseblocks have valid erase counter, mean value is %lld",
+			       si->ok_cnt, si->mean_ec);
+		if (si->empty_cnt)
+			normsg("%d eraseblocks are supposedly empty", si->empty_cnt);
+		if (si->corrupted_cnt)
+			normsg("%d corrupted erase counters", si->corrupted_cnt);
+		print_bad_eraseblocks(&mtd, si);
+	}
+
+	if (si->alien_cnt) {
+		if (!args.yes || !args.quiet)
+			warnmsg("%d of %d eraseblocks contain non-ubifs data",
+				si->alien_cnt, si->good_cnt);
+		if (!args.yes && want_exit()) {
+			if (args.yes && !args.quiet)
+				printf("yes\n");
+			goto out_free;
+		}
+	}
+
+	if (!args.override_ec && si->empty_cnt < si->good_cnt) {
+		int percent = ((double)si->ok_cnt)/si->good_cnt * 100;
+
+		/*
+		 * Make sure the majority of eraseblocks have valid
+		 * erase counters.
+		 */
+		if (percent < 50) {
+			if (!args.yes || !args.quiet)
+				warnmsg("only %d of %d eraseblocks have valid erase counter",
+					si->ok_cnt, si->good_cnt);
+				normsg("erase counter 0 will be used for all eraseblocks");
+				normsg("note, arbitrary erase counter value may be specified using -e option");
+			if (!args.yes && want_exit()) {
+				if (args.yes && !args.quiet)
+					printf("yes\n");
+				goto out_free;
+			}
+			 args.ec = 0;
+			 args.override_ec = 1;
+		} else if (percent < 95) {
+			if (!args.yes || !args.quiet)
+				warnmsg("only %d of %d eraseblocks have valid erase counter",
+					si->ok_cnt, si->good_cnt);
+				normsg("mean erase counter %lld will be used for the rest of eraseblock",
+				       si->mean_ec);
+			if (!args.yes && want_exit()) {
+				if (args.yes && !args.quiet)
+					printf("yes\n");
+				goto out_free;
+			}
+			args.ec = si->mean_ec;
+			args.override_ec = 1;
+		}
+	}
+
+	if (!args.quiet && args.override_ec)
+		normsg("use erase counter %lld for all eraseblocks", args.ec);
+
+	ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, mtd.subpage_size,
+			 args.vid_hdr_offs, args.ubi_ver, args.image_seq);
+
+	if (si->vid_hdr_offs != -1 && ui.vid_hdr_offs != si->vid_hdr_offs) {
+		/*
+		 * Hmm, what we read from flash and what we calculated using
+		 * min. I/O unit size and sub-page size differs.
+		 */
+		if (!args.yes || !args.quiet) {
+			warnmsg("VID header and data offsets on flash are %d and %d, "
+				"which is different to requested offsets %d and %d",
+				si->vid_hdr_offs, si->data_offs, ui.vid_hdr_offs,
+				ui.data_offs);
+			normsg_cont("use new offsets %d and %d? (yes/no)  ",
+				    ui.vid_hdr_offs, ui.data_offs);
+		}
+		if (args.yes || answer_is_yes()) {
+			if (args.yes && !args.quiet)
+				printf("yes\n");
+		} else
+			ubigen_info_init(&ui, mtd.eb_size, mtd.min_io_size, 0,
+					 si->vid_hdr_offs, args.ubi_ver,
+					 args.image_seq);
+		normsg("use offsets %d and %d",  ui.vid_hdr_offs, ui.data_offs);
+	}
+
+	if (args.image) {
+		err = flash_image(libmtd, &mtd, &ui, si);
+		if (err < 0)
+			goto out_free;
+
+		err = format(libmtd, &mtd, &ui, si, err, 1);
+		if (err)
+			goto out_free;
+	} else {
+		err = format(libmtd, &mtd, &ui, si, 0, args.novtbl);
+		if (err)
+			goto out_free;
+	}
+
+	ubi_scan_free(si);
+	close(args.node_fd);
+	libmtd_close(libmtd);
+	return 0;
+
+out_free:
+	ubi_scan_free(si);
+out_close:
+	close(args.node_fd);
+out_close_mtd:
+	libmtd_close(libmtd);
+	return -1;
+}
diff --git a/ubi-utils/ubimkvol.c b/ubi-utils/ubimkvol.c
new file mode 100644
index 0000000..25065e3
--- /dev/null
+++ b/ubi-utils/ubimkvol.c
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to create UBI volumes.
+ *
+ * Authors: Artem Bityutskiy <dedekind at infradead.org>
+ *          Frank Haverkamp <haver at vnet.ibm.com>
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubimkvol"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int vol_id;
+	int vol_type;
+	long long bytes;
+	int lebs;
+	int alignment;
+	const char *name;
+	const char *node;
+	int maxavs;
+};
+
+static struct args args = {
+	.vol_type = UBI_DYNAMIC_VOLUME,
+	.bytes = -1,
+	.lebs = -1,
+	.alignment = 1,
+	.vol_id = UBI_VOL_NUM_AUTO,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to create UBI volumes.";
+
+static const char optionsstr[] =
+"-a, --alignment=<alignment>   volume alignment (default is 1)\n"
+"-n, --vol_id=<volume ID>      UBI volume ID, if not specified, the volume ID\n"
+"                              will be assigned automatically\n"
+"-N, --name=<name>             volume name\n"
+"-s, --size=<bytes>            volume size volume size in bytes, kilobytes (KiB)\n"
+"                              or megabytes (MiB)\n"
+"-S, --lebs=<LEBs count>       alternative way to give volume size in logical\n"
+"                              eraseblocks\n"
+"-m, --maxavsize               set volume size to maximum available size\n"
+"-t, --type=<static|dynamic>   volume type (dynamic, static), default is dynamic\n"
+"-h, -?, --help                print help message\n"
+"-V, --version                 print program version";
+
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [-h] [-a <alignment>] [-n <volume ID>] [-N <name>]\n"
+"\t\t\t[-s <bytes>] [-S <LEBs>] [-t <static|dynamic>] [-V] [-m]\n"
+"\t\t\t[--alignment=<alignment>][--vol_id=<volume ID>] [--name=<name>]\n"
+"\t\t\t[--size=<bytes>] [--lebs=<LEBs>] [--type=<static|dynamic>] [--help]\n"
+"\t\t\t[--version] [--maxavsize]\n\n"
+"Example: " PROGRAM_NAME " /dev/ubi0 -s 20MiB -N config_data - create a 20 Megabytes volume\n"
+"         named \"config_data\" on UBI device /dev/ubi0.";
+
+static const struct option long_options[] = {
+	{ .name = "alignment", .has_arg = 1, .flag = NULL, .val = 'a' },
+	{ .name = "vol_id",    .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "name",      .has_arg = 1, .flag = NULL, .val = 'N' },
+	{ .name = "size",      .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "lebs",      .has_arg = 1, .flag = NULL, .val = 'S' },
+	{ .name = "type",      .has_arg = 1, .flag = NULL, .val = 't' },
+	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ .name = "maxavsize", .has_arg = 0, .flag = NULL, .val = 'm' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int param_sanity_check(void)
+{
+	int len;
+
+	if (args.bytes == -1 && !args.maxavs && args.lebs == -1)
+		return errmsg("volume size was not specified (use -h for help)");
+
+	if ((args.bytes != -1 && (args.maxavs || args.lebs != -1))  ||
+	    (args.lebs != -1  && (args.maxavs || args.bytes != -1)) ||
+	    (args.maxavs && (args.bytes != -1 || args.lebs != -1)))
+		return errmsg("size specified with more then one option");
+
+	if (args.name == NULL)
+		return errmsg("volume name was not specified (use -h for help)");
+
+	len = strlen(args.name);
+	if (len > UBI_MAX_VOLUME_NAME)
+		return errmsg("too long name (%d symbols), max is %d", len, UBI_MAX_VOLUME_NAME);
+
+	return 0;
+}
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "a:n:N:s:S:t:h?Vm", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 't':
+			if (!strcmp(optarg, "dynamic"))
+				args.vol_type = UBI_DYNAMIC_VOLUME;
+			else if (!strcmp(optarg, "static"))
+				args.vol_type = UBI_STATIC_VOLUME;
+			else
+				return errmsg("bad volume type: \"%s\"", optarg);
+			break;
+
+		case 's':
+			args.bytes = ubiutils_get_bytes(optarg);
+			if (args.bytes <= 0)
+				return errmsg("bad volume size: \"%s\"", optarg);
+			break;
+
+		case 'S':
+			args.lebs = simple_strtoull(optarg, &error);
+			if (error || args.lebs <= 0)
+				return errmsg("bad LEB count: \"%s\"", optarg);
+			break;
+
+		case 'a':
+			args.alignment = simple_strtoul(optarg, &error);
+			if (error || args.alignment <= 0)
+				return errmsg("bad volume alignment: \"%s\"", optarg);
+			break;
+
+		case 'n':
+			args.vol_id = simple_strtoul(optarg, &error);
+			if (error || args.vol_id < 0)
+				return errmsg("bad volume ID: " "\"%s\"", optarg);
+			break;
+
+		case 'N':
+			args.name = optarg;
+			break;
+
+		case 'h':
+		case '?':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case 'm':
+			args.maxavs = 1;
+			break;
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		return errmsg("UBI device name was not specified (use -h for help)");
+	else if (optind != argc - 1)
+		return errmsg("more then one UBI device specified (use -h for help)");
+
+	args.node = argv[optind];
+
+	if (param_sanity_check())
+		return -1;
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_dev_info dev_info;
+	struct ubi_vol_info vol_info;
+	struct ubi_mkvol_request req;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return err;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			return errmsg("UBI is not present in the system");
+		return sys_errmsg("cannot open libubi");
+	}
+
+	err = ubi_probe_node(libubi, args.node);
+	if (err == 2) {
+		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+		       args.node);
+		goto out_libubi;
+	} else if (err < 0) {
+		if (errno == ENODEV)
+			errmsg("\"%s\" is not an UBI device node", args.node);
+		else
+			sys_errmsg("error while probing \"%s\"", args.node);
+		goto out_libubi;
+	}
+
+	err = ubi_get_dev_info(libubi, args.node, &dev_info);
+	if (err) {
+		sys_errmsg("cannot get information about UBI device \"%s\"",
+			   args.node);
+		goto out_libubi;
+	}
+
+	if (dev_info.avail_bytes == 0) {
+		errmsg("UBI device does not have free logical eraseblocks");
+		goto out_libubi;
+	}
+
+	if (args.maxavs) {
+		args.bytes = dev_info.avail_bytes;
+		printf("Set volume size to %lld\n", args.bytes);
+	}
+
+	if (args.lebs != -1) {
+		args.bytes = dev_info.leb_size;
+		args.bytes -= dev_info.leb_size % args.alignment;
+		args.bytes *= args.lebs;
+	}
+
+	req.vol_id = args.vol_id;
+	req.alignment = args.alignment;
+	req.bytes = args.bytes;
+	req.vol_type = args.vol_type;
+	req.name = args.name;
+
+	err = ubi_mkvol(libubi, args.node, &req);
+	if (err < 0) {
+		sys_errmsg("cannot UBI create volume");
+		goto out_libubi;
+	}
+
+	args.vol_id = req.vol_id;
+
+	/* Print information about the created device */
+	err = ubi_get_vol_info1(libubi, dev_info.dev_num, args.vol_id, &vol_info);
+	if (err) {
+		sys_errmsg("cannot get information about newly created UBI volume");
+		goto out_libubi;
+	}
+
+	printf("Volume ID %d, size %d LEBs (", vol_info.vol_id, vol_info.rsvd_lebs);
+	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+	printf("), LEB size ");
+	ubiutils_print_bytes(vol_info.leb_size, 1);
+	printf(", %s, name \"%s\", alignment %d\n",
+	       req.vol_type == UBI_DYNAMIC_VOLUME ? "dynamic" : "static",
+	       vol_info.name, vol_info.alignment);
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubinfo.c b/ubi-utils/ubinfo.c
new file mode 100644
index 0000000..8e14e6e
--- /dev/null
+++ b/ubi-utils/ubinfo.c
@@ -0,0 +1,434 @@
+/*
+ * Copyright (C) 2007, 2008 Nokia Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to get UBI information.
+ *
+ * Author: Artem Bityutskiy
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubinfo"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int devn;
+	int vol_id;
+	int all;
+	const char *node;
+	const char *vol_name;
+};
+
+static struct args args = {
+	.vol_id = -1,
+	.devn = -1,
+	.all = 0,
+	.node = NULL,
+	.vol_name = NULL,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to print UBI information.";
+
+static const char optionsstr[] =
+"-d, --devn=<UBI device number>  UBI device number to get information about\n"
+"-n, --vol_id=<volume ID>        ID of UBI volume to print information about\n"
+"-N, --name=<volume name>        name of UBI volume to print information about\n"
+"-a, --all                       print information about all devices and volumes,\n"
+"                                or about all volumes if the UBI device was\n"
+"                                specified\n"
+"-h, --help                      print help message\n"
+"-V, --version                   print program version";
+
+static const char usage[] =
+"Usage 1: " PROGRAM_NAME " [-d <UBI device number>] [-n <volume ID> | -N <volume name>] [-a] [-h] [-V]\n"
+"\t\t[--vol_id=<volume ID> | --name <volume name>] [--devn <UBI device number>] [--all] [--help] [--version]\n"
+"Usage 2: " PROGRAM_NAME " <UBI device node file name> [-a] [-h] [-V] [--all] [--help] [--version]\n"
+"Usage 3: " PROGRAM_NAME " <UBI volume node file name> [-h] [-V] [--help] [--version]\n\n"
+"Example 1: " PROGRAM_NAME " - (no arguments) print general UBI information\n"
+"Example 2: " PROGRAM_NAME " -d 1 - print information about UBI device number 1\n"
+"Example 3: " PROGRAM_NAME " /dev/ubi0 -a - print information about all volumes of UBI\n"
+"           device /dev/ubi0\n"
+"Example 4: " PROGRAM_NAME " /dev/ubi1_0 - print information about UBI volume /dev/ubi1_0\n"
+"Example 5: " PROGRAM_NAME " -a - print all information\n";
+
+static const struct option long_options[] = {
+	{ .name = "devn",      .has_arg = 1, .flag = NULL, .val = 'd' },
+	{ .name = "vol_id",    .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "name",      .has_arg = 1, .flag = NULL, .val = 'N' },
+	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
+	{ .name = "help",      .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",   .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "an:N:d:hV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'a':
+			args.all = 1;
+			break;
+
+		case 'n':
+			args.vol_id = simple_strtoul(optarg, &error);
+			if (error || args.vol_id < 0)
+				return errmsg("bad volume ID: " "\"%s\"", optarg);
+			break;
+
+		case 'N':
+			args.vol_name = optarg;
+			break;
+
+		case 'd':
+			args.devn = simple_strtoul(optarg, &error);
+			if (error || args.devn < 0)
+				return errmsg("bad UBI device number: \"%s\"", optarg);
+
+			break;
+
+		case 'h':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc - 1)
+		args.node = argv[optind];
+	else if (optind < argc)
+		return errmsg("more then one UBI device specified (use -h for help)");
+
+	return 0;
+}
+
+static int translate_dev(libubi_t libubi, const char *node)
+{
+	int err;
+
+	err = ubi_probe_node(libubi, node);
+	if (err == -1) {
+		if (errno != ENODEV)
+			return sys_errmsg("error while probing \"%s\"", node);
+		return errmsg("\"%s\" does not correspond to any UBI device or volume", node);
+	}
+
+	if (err == 1) {
+		struct ubi_dev_info dev_info;
+
+		err = ubi_get_dev_info(libubi, node, &dev_info);
+		if (err)
+			return sys_errmsg("cannot get information about UBI device \"%s\"", node);
+
+		args.devn = dev_info.dev_num;
+	} else {
+		struct ubi_vol_info vol_info;
+
+		err = ubi_get_vol_info(libubi, node, &vol_info);
+		if (err)
+			return sys_errmsg("cannot get information about UBI volume \"%s\"", node);
+
+		if (args.vol_id != -1)
+			return errmsg("both volume character device node (\"%s\") and "
+				      "volume ID (%d) are specify, use only one of them"
+				      "(use -h for help)", node, args.vol_id);
+
+		args.devn = vol_info.dev_num;
+		args.vol_id = vol_info.vol_id;
+	}
+
+	return 0;
+}
+
+static int get_vol_id_by_name(libubi_t libubi, int dev_num, const char *name)
+{
+	int err;
+	struct ubi_vol_info vol_info;
+
+	err = ubi_get_vol_info1_nm(libubi, dev_num, name, &vol_info);
+	if (err)
+		return sys_errmsg("cannot get information about volume \"%s\" on ubi%d\n", name, dev_num);
+
+	args.vol_id = vol_info.vol_id;
+
+	return 0;
+}
+
+static int print_vol_info(libubi_t libubi, int dev_num, int vol_id)
+{
+	int err;
+	struct ubi_vol_info vol_info;
+
+	err = ubi_get_vol_info1(libubi, dev_num, vol_id, &vol_info);
+	if (err)
+		return sys_errmsg("cannot get information about UBI volume %d on ubi%d",
+				  vol_id, dev_num);
+
+	printf("Volume ID:   %d (on ubi%d)\n", vol_info.vol_id, vol_info.dev_num);
+	printf("Type:        %s\n",
+	       vol_info.type == UBI_DYNAMIC_VOLUME ?  "dynamic" : "static");
+	printf("Alignment:   %d\n", vol_info.alignment);
+
+	printf("Size:        %d LEBs (", vol_info.rsvd_lebs);
+	ubiutils_print_bytes(vol_info.rsvd_bytes, 0);
+	printf(")\n");
+
+	if (vol_info.type == UBI_STATIC_VOLUME) {
+		printf("Data bytes:  ");
+		ubiutils_print_bytes(vol_info.data_bytes, 1);
+		printf("\n");
+	}
+	printf("State:       %s\n", vol_info.corrupted ? "corrupted" : "OK");
+	printf("Name:        %s\n", vol_info.name);
+	printf("Character device major/minor: %d:%d\n",
+	       vol_info.major, vol_info.minor);
+
+	return 0;
+}
+
+static int print_dev_info(libubi_t libubi, int dev_num, int all)
+{
+	int i, err, first = 1;
+	struct ubi_dev_info dev_info;
+	struct ubi_vol_info vol_info;
+
+	err = ubi_get_dev_info1(libubi, dev_num, &dev_info);
+	if (err)
+		return sys_errmsg("cannot get information about UBI device %d", dev_num);
+
+	printf("ubi%d\n", dev_info.dev_num);
+	printf("Volumes count:                           %d\n", dev_info.vol_count);
+	printf("Logical eraseblock size:                 ");
+	ubiutils_print_bytes(dev_info.leb_size, 0);
+	printf("\n");
+
+	printf("Total amount of logical eraseblocks:     %d (", dev_info.total_lebs);
+	ubiutils_print_bytes(dev_info.total_bytes, 0);
+	printf(")\n");
+
+	printf("Amount of available logical eraseblocks: %d (", dev_info.avail_lebs);
+	ubiutils_print_bytes(dev_info.avail_bytes, 0);
+	printf(")\n");
+
+	printf("Maximum count of volumes                 %d\n", dev_info.max_vol_count);
+	printf("Count of bad physical eraseblocks:       %d\n", dev_info.bad_count);
+	printf("Count of reserved physical eraseblocks:  %d\n", dev_info.bad_rsvd);
+	printf("Current maximum erase counter value:     %lld\n", dev_info.max_ec);
+	printf("Minimum input/output unit size:          %d %s\n",
+	       dev_info.min_io_size, dev_info.min_io_size > 1 ? "bytes" : "byte");
+	printf("Character device major/minor:            %d:%d\n",
+	       dev_info.major, dev_info.minor);
+
+	if (dev_info.vol_count == 0)
+		return 0;
+
+	printf("Present volumes:                         ");
+	for (i = dev_info.lowest_vol_id;
+	     i <= dev_info.highest_vol_id; i++) {
+		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
+					  i, dev_info.dev_num);
+		}
+
+		if (!first)
+			printf(", %d", i);
+		else {
+			printf("%d", i);
+			first = 0;
+		}
+	}
+	printf("\n");
+
+	if (!all)
+		return 0;
+
+	first = 1;
+	printf("\n");
+
+	for (i = dev_info.lowest_vol_id;
+	     i <= dev_info.highest_vol_id; i++) {
+		if(!first)
+			printf("-----------------------------------\n");
+		err = ubi_get_vol_info1(libubi, dev_info.dev_num, i, &vol_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			return sys_errmsg("libubi failed to probe volume %d on ubi%d",
+					  i, dev_info.dev_num);
+		}
+		first = 0;
+
+		err = print_vol_info(libubi, dev_info.dev_num, i);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
+static int print_general_info(libubi_t libubi, int all)
+{
+	int i, err, first = 1;
+	struct ubi_info ubi_info;
+	struct ubi_dev_info dev_info;
+
+	err = ubi_get_info(libubi, &ubi_info);
+	if (err)
+		return sys_errmsg("cannot get UBI information");
+
+	printf("UBI version:                    %d\n", ubi_info.version);
+	printf("Count of UBI devices:           %d\n", ubi_info.dev_count);
+	if (ubi_info.ctrl_major != -1)
+		printf("UBI control device major/minor: %d:%d\n",
+		       ubi_info.ctrl_major, ubi_info.ctrl_minor);
+	else
+		printf("UBI control device is not supported by this kernel\n");
+
+	if (ubi_info.dev_count == 0)
+		return 0;
+
+	printf("Present UBI devices:            ");
+	for (i = ubi_info.lowest_dev_num;
+	     i <= ubi_info.highest_dev_num; i++) {
+		err = ubi_get_dev_info1(libubi, i, &dev_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+
+			printf("\n");
+			return sys_errmsg("libubi failed to probe UBI device %d", i);
+		}
+
+		if (!first)
+			printf(", ubi%d", i);
+		else {
+			printf("ubi%d", i);
+			first = 0;
+		}
+	}
+	printf("\n");
+
+	if (!all)
+		return 0;
+
+	first = 1;
+	printf("\n");
+
+	for (i = ubi_info.lowest_dev_num;
+	     i <= ubi_info.highest_dev_num; i++) {
+		if(!first)
+			printf("\n===================================\n\n");
+		first = 0;
+		err = print_dev_info(libubi, i, all);
+		if (err)
+			return err;
+	}
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			return errmsg("UBI is not present in the system");
+		return sys_errmsg("cannot open libubi");
+	}
+
+	if (args.node) {
+		/*
+		 * A character device was specified, translate this into UBI
+		 * device number and volume ID.
+		 */
+		err = translate_dev(libubi, args.node);
+		if (err)
+			goto out_libubi;
+	}
+
+	if (args.vol_name) {
+		err = get_vol_id_by_name(libubi, args.devn, args.vol_name);
+		if (err)
+			goto out_libubi;
+	}
+
+	if (args.vol_id != -1 && args.devn == -1) {
+		errmsg("volume ID is specified, but UBI device number is not "
+		       "(use -h for help)\n");
+		goto out_libubi;
+	}
+
+	if (args.devn != -1 && args.vol_id != -1) {
+		print_vol_info(libubi, args.devn, args.vol_id);
+		goto out;
+	}
+
+	if (args.devn == -1 && args.vol_id == -1)
+		err = print_general_info(libubi, args.all);
+	else if (args.devn != -1 && args.vol_id == -1)
+		err = print_dev_info(libubi, args.devn, args.all);
+
+	if (err)
+		goto out_libubi;
+
+out:
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
new file mode 100644
index 0000000..3085b66
--- /dev/null
+++ b/ubi-utils/ubinize.c
@@ -0,0 +1,628 @@
+/*
+ * Copyright (C) 2008 Nokia Corporation
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * Generate UBI images.
+ *
+ * Authors: Artem Bityutskiy
+ *          Oliver Lohmann
+ */
+
+#define PROGRAM_VERSION "1.2"
+#define PROGRAM_NAME    "ubinize"
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <string.h>
+#include <fcntl.h>
+
+#include <mtd/ubi-media.h>
+#include <libubigen.h>
+#include <libiniparser.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+" - a tool to generate UBI images. An UBI image may contain one or more UBI "
+"volumes which have to be defined in the input configuration ini-file. The "
+"ini file defines all the UBI volumes - their characteristics and the and the "
+"contents, but it does not define the characteristics of the flash the UBI "
+"image is generated for. Instead, the flash characteristics are defined via "
+"the command-line options. Note, if not sure about some of the command-line "
+"parameters, do not specify them and let the utility to use default values.";
+
+static const char optionsstr[] =
+"-o, --output=<file name>     output file name\n"
+"-p, --peb-size=<bytes>       size of the physical eraseblock of the flash\n"
+"                             this UBI image is created for in bytes,\n"
+"                             kilobytes (KiB), or megabytes (MiB)\n"
+"                             (mandatory parameter)\n"
+"-m, --min-io-size=<bytes>    minimum input/output unit size of the flash\n"
+"                             in bytes\n"
+"-s, --sub-page-size=<bytes>  minimum input/output unit used for UBI\n"
+"                             headers, e.g. sub-page size in case of NAND\n"
+"                             flash (equivalent to the minimum input/output\n"
+"                             unit size by default)\n"
+"-O, --vid-hdr-offset=<num>   offset if the VID header from start of the\n"
+"                             physical eraseblock (default is the next\n"
+"                             minimum I/O unit or sub-page after the EC\n"
+"                             header)\n"
+"-e, --erase-counter=<num>    the erase counter value to put to EC headers\n"
+"                             (default is 0)\n"
+"-x, --ubi-ver=<num>          UBI version number to put to EC headers\n"
+"                             (default is 1)\n"
+"-Q, --image-seq=<num>        32-bit UBI image sequence number to use\n"
+"                             (by default a random number is picked)\n"
+"-v, --verbose                be verbose\n"
+"-h, --help                   print help message\n"
+"-V, --version                print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " [-o filename] [-p <bytes>] [-m <bytes>] [-s <bytes>] [-O <num>] [-e <num>]\n"
+"\t\t[-x <num>] [-Q <num>] [-v] [-h] [-V] [--output=<filename>] [--peb-size=<bytes>]\n"
+"\t\t[--min-io-size=<bytes>] [--sub-page-size=<bytes>] [--vid-hdr-offset=<num>]\n"
+"\t\t[--erase-counter=<num>] [--ubi-ver=<num>] [--image-seq=<num>] [--verbose] [--help]\n"
+"\t\t[--version] ini-file\n"
+"Example: " PROGRAM_NAME " -o ubi.img -p 16KiB -m 512 -s 256 cfg.ini - create UBI image\n"
+"         'ubi.img' as described by configuration file 'cfg.ini'";
+
+static const char ini_doc[] = "INI-file format.\n"
+"The input configuration ini-file describes all the volumes which have to\n"
+"be included to the output UBI image. Each volume is described in its own\n"
+"section which may be named arbitrarily. The section consists on\n"
+"\"key=value\" pairs, for example:\n\n"
+"[jffs2-volume]\n"
+"mode=ubi\n"
+"image=../jffs2.img\n"
+"vol_id=1\n"
+"vol_size=30MiB\n"
+"vol_type=dynamic\n"
+"vol_name=jffs2_volume\n"
+"vol_flags=autoresize\n"
+"vol_alignment=1\n\n"
+"This example configuration file tells the utility to create an UBI image\n"
+"with one volume with ID 1, volume size 30MiB, the volume is dynamic, has\n"
+"name \"jffs2_volume\", \"autoresize\" volume flag, and alignment 1. The\n"
+"\"image=../jffs2.img\" line tells the utility to take the contents of the\n"
+"volume from the \"../jffs2.img\" file. The size of the image file has to be\n"
+"less or equivalent to the volume size (30MiB). The \"mode=ubi\" line is\n"
+"mandatory and just tells that the section describes an UBI volume - other\n"
+"section modes may be added in the future.\n"
+"Notes:\n"
+"  * size in vol_size might be specified kilobytes (KiB), megabytes (MiB),\n"
+"    gigabytes (GiB) or bytes (no modifier);\n"
+"  * if \"vol_size\" key is absent, the volume size is assumed to be\n"
+"    equivalent to the size of the image file (defined by \"image\" key);\n"
+"  * if the \"image\" is absent, the volume is assumed to be empty;\n"
+"  * volume alignment must not be greater than the logical eraseblock size;\n"
+"  * one ini file may contain arbitrary number of sections, the utility will\n"
+"    put all the volumes which are described by these section to the output\n"
+"    UBI image file.";
+
+static const struct option long_options[] = {
+	{ .name = "output",         .has_arg = 1, .flag = NULL, .val = 'o' },
+	{ .name = "peb-size",       .has_arg = 1, .flag = NULL, .val = 'p' },
+	{ .name = "min-io-size",    .has_arg = 1, .flag = NULL, .val = 'm' },
+	{ .name = "sub-page-size",  .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "vid-hdr-offset", .has_arg = 1, .flag = NULL, .val = 'O' },
+	{ .name = "erase-counter",  .has_arg = 1, .flag = NULL, .val = 'e' },
+	{ .name = "ubi-ver",        .has_arg = 1, .flag = NULL, .val = 'x' },
+	{ .name = "image-seq",      .has_arg = 1, .flag = NULL, .val = 'Q' },
+	{ .name = "verbose",        .has_arg = 0, .flag = NULL, .val = 'v' },
+	{ .name = "help",           .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",        .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0}
+};
+
+struct args {
+	const char *f_in;
+	const char *f_out;
+	int out_fd;
+	int peb_size;
+	int min_io_size;
+	int subpage_size;
+	int vid_hdr_offs;
+	int ec;
+	int ubi_ver;
+	uint32_t image_seq;
+	int verbose;
+	dictionary *dict;
+};
+
+static struct args args = {
+	.peb_size     = -1,
+	.min_io_size  = -1,
+	.subpage_size = -1,
+	.ubi_ver      = 1,
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	ubiutils_srand();
+	args.image_seq = rand();
+
+	while (1) {
+		int key, error = 0;
+		unsigned long int image_seq;
+
+		key = getopt_long(argc, argv, "o:p:m:s:O:e:x:Q:vhV", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 'o':
+			args.out_fd = open(optarg, O_CREAT | O_TRUNC | O_WRONLY,
+					   S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP | S_IROTH);
+			if (args.out_fd == -1)
+				return sys_errmsg("cannot open file \"%s\"", optarg);
+			args.f_out = optarg;
+			break;
+
+		case 'p':
+			args.peb_size = ubiutils_get_bytes(optarg);
+			if (args.peb_size <= 0)
+				return errmsg("bad physical eraseblock size: \"%s\"", optarg);
+			break;
+
+		case 'm':
+			args.min_io_size = ubiutils_get_bytes(optarg);
+			if (args.min_io_size <= 0)
+				return errmsg("bad min. I/O unit size: \"%s\"", optarg);
+			if (!is_power_of_2(args.min_io_size))
+				return errmsg("min. I/O unit size should be power of 2");
+			break;
+
+		case 's':
+			args.subpage_size = ubiutils_get_bytes(optarg);
+			if (args.subpage_size <= 0)
+				return errmsg("bad sub-page size: \"%s\"", optarg);
+			if (!is_power_of_2(args.subpage_size))
+				return errmsg("sub-page size should be power of 2");
+			break;
+
+		case 'O':
+			args.vid_hdr_offs = simple_strtoul(optarg, &error);
+			if (error || args.vid_hdr_offs < 0)
+				return errmsg("bad VID header offset: \"%s\"", optarg);
+			break;
+
+		case 'e':
+			args.ec = simple_strtoul(optarg, &error);
+			if (error || args.ec < 0)
+				return errmsg("bad erase counter value: \"%s\"", optarg);
+			break;
+
+		case 'x':
+			args.ubi_ver = simple_strtoul(optarg, &error);
+			if (error || args.ubi_ver < 0)
+				return errmsg("bad UBI version: \"%s\"", optarg);
+			break;
+
+		case 'Q':
+			image_seq = simple_strtoul(optarg, &error);
+			if (error || image_seq > 0xFFFFFFFF)
+				return errmsg("bad UBI image sequence number: \"%s\"", optarg);
+			args.image_seq = image_seq;
+			break;
+
+		case 'v':
+			args.verbose = 1;
+			break;
+
+		case 'h':
+			ubiutils_print_text(stdout, doc, 80);
+			printf("\n%s\n\n", ini_doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		return errmsg("input configuration file was not specified (use -h for help)");
+
+	if (optind != argc - 1)
+		return errmsg("more then one configuration file was specified (use -h for help)");
+
+	args.f_in = argv[optind];
+
+	if (args.peb_size < 0)
+		return errmsg("physical eraseblock size was not specified (use -h for help)");
+
+	if (args.peb_size > 1024*1024)
+		return errmsg("too high physical eraseblock size %d", args.peb_size);
+
+	if (args.min_io_size < 0)
+		return errmsg("min. I/O unit size was not specified (use -h for help)");
+
+	if (args.subpage_size < 0)
+		args.subpage_size = args.min_io_size;
+
+	if (args.subpage_size > args.min_io_size)
+		return errmsg("sub-page cannot be larger then min. I/O unit");
+
+	if (args.peb_size % args.min_io_size)
+		return errmsg("physical eraseblock should be multiple of min. I/O units");
+
+	if (args.min_io_size % args.subpage_size)
+		return errmsg("min. I/O unit size should be multiple of sub-page size");
+
+	if (!args.f_out)
+		return errmsg("output file was not specified (use -h for help)");
+
+	if (args.vid_hdr_offs) {
+		if (args.vid_hdr_offs + (int)UBI_VID_HDR_SIZE >= args.peb_size)
+			return errmsg("bad VID header position");
+		if (args.vid_hdr_offs % 8)
+			return errmsg("VID header offset has to be multiple of min. I/O unit size");
+	}
+
+	return 0;
+}
+
+static int read_section(const struct ubigen_info *ui, const char *sname,
+			struct ubigen_vol_info *vi, const char **img,
+			struct stat *st)
+{
+	char buf[256];
+	const char *p;
+
+	*img = NULL;
+
+	if (strlen(sname) > 128)
+		return errmsg("too long section name \"%s\"", sname);
+
+	/* Make sure mode is UBI, otherwise ignore this section */
+	sprintf(buf, "%s:mode", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (!p) {
+		errmsg("\"mode\" key not found in section \"%s\"", sname);
+		errmsg("the \"mode\" key is mandatory and has to be "
+		       "\"mode=ubi\" if the section describes an UBI volume");
+		return -1;
+	}
+
+	/* If mode is not UBI, skip this section */
+	if (strcmp(p, "ubi")) {
+		verbose(args.verbose, "skip non-ubi section \"%s\"", sname);
+		return 1;
+	}
+
+	verbose(args.verbose, "mode=ubi, keep parsing");
+
+	/* Fetch volume type */
+	sprintf(buf, "%s:vol_type", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (!p) {
+		normsg("volume type was not specified in "
+		       "section \"%s\", assume \"dynamic\"\n", sname);
+		vi->type = UBI_VID_DYNAMIC;
+	} else {
+		if (!strcmp(p, "static"))
+			vi->type = UBI_VID_STATIC;
+		else if (!strcmp(p, "dynamic"))
+			vi->type = UBI_VID_DYNAMIC;
+		else
+			return errmsg("invalid volume type \"%s\" in section  \"%s\"",
+				      p, sname);
+	}
+
+	verbose(args.verbose, "volume type: %s",
+		vi->type == UBI_VID_DYNAMIC ? "dynamic" : "static");
+
+	/* Fetch the name of the volume image file */
+	sprintf(buf, "%s:image", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (p) {
+		*img = p;
+		if (stat(p, st))
+			return sys_errmsg("cannot stat \"%s\" referred from section \"%s\"",
+					  p, sname);
+		if (st->st_size == 0)
+			return errmsg("empty file \"%s\" referred from section \"%s\"",
+				       p, sname);
+	} else if (vi->type == UBI_VID_STATIC)
+		return errmsg("image is not specified for static volume in section \"%s\"",
+			      sname);
+
+	/* Fetch volume id */
+	sprintf(buf, "%s:vol_id", sname);
+	vi->id = iniparser_getint(args.dict, buf, -1);
+	if (vi->id == -1)
+		return errmsg("\"vol_id\" key not found in section  \"%s\"", sname);
+	if (vi->id < 0)
+		return errmsg("negative volume ID %d in section \"%s\"",
+			      vi->id, sname);
+	if (vi->id >= ui->max_volumes)
+		return errmsg("too high volume ID %d in section \"%s\", max. is %d",
+			      vi->id, sname, ui->max_volumes);
+
+	verbose(args.verbose, "volume ID: %d", vi->id);
+
+	/* Fetch volume size */
+	sprintf(buf, "%s:vol_size", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (p) {
+		vi->bytes = ubiutils_get_bytes(p);
+		if (vi->bytes <= 0)
+			return errmsg("bad \"vol_size\" key value \"%s\" (section \"%s\")",
+				      p, sname);
+
+		/* Make sure the image size is not larger than volume size */
+		if (*img && st->st_size > vi->bytes)
+			return errmsg("error in section \"%s\": size of the image file "
+				      "\"%s\" is %lld, which is larger than volume size %lld",
+				      sname, *img, (long long)st->st_size, vi->bytes);
+		verbose(args.verbose, "volume size: %lld bytes", vi->bytes);
+	} else {
+		struct stat st;
+
+		if (!*img)
+			return errmsg("neither image file (\"image=\") nor volume size "
+				      "(\"vol_size=\") specified in section \"%s\"", sname);
+
+		if (stat(*img, &st))
+			return sys_errmsg("cannot stat \"%s\"", *img);
+
+		vi->bytes = st.st_size;
+
+		if (vi->bytes == 0)
+			return errmsg("file \"%s\" referred from section \"%s\" is empty",
+				      *img, sname);
+
+		normsg_cont("volume size was not specified in section \"%s\", assume"
+			    " minimum to fit image \"%s\"", sname, *img);
+		ubiutils_print_bytes(vi->bytes, 1);
+		printf("\n");
+	}
+
+	/* Fetch volume name */
+	sprintf(buf, "%s:vol_name", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (!p)
+		return errmsg("\"vol_name\" key not found in section \"%s\"", sname);
+
+	vi->name = p;
+	vi->name_len = strlen(p);
+	if (vi->name_len > UBI_VOL_NAME_MAX)
+		return errmsg("too long volume name in section \"%s\", max. is %d characters",
+			      vi->name, UBI_VOL_NAME_MAX);
+
+	verbose(args.verbose, "volume name: %s", p);
+
+	/* Fetch volume alignment */
+	sprintf(buf, "%s:vol_alignment", sname);
+	vi->alignment = iniparser_getint(args.dict, buf, -1);
+	if (vi->alignment == -1)
+		vi->alignment = 1;
+	else if (vi->id < 0)
+		return errmsg("negative volume alignement %d in section \"%s\"",
+			      vi->alignment, sname);
+
+	verbose(args.verbose, "volume alignment: %d", vi->alignment);
+
+	/* Fetch volume flags */
+	sprintf(buf, "%s:vol_flags", sname);
+	p = iniparser_getstring(args.dict, buf, NULL);
+	if (p) {
+		if (!strcmp(p, "autoresize")) {
+			verbose(args.verbose, "autoresize flags found");
+			vi->flags |= UBI_VTBL_AUTORESIZE_FLG;
+		} else {
+			return errmsg("unknown flags \"%s\" in section \"%s\"",
+				      p, sname);
+		}
+	}
+
+	/* Initialize the rest of the volume information */
+	vi->data_pad = ui->leb_size % vi->alignment;
+	vi->usable_leb_size = ui->leb_size - vi->data_pad;
+	if (vi->type == UBI_VID_DYNAMIC)
+		vi->used_ebs = (vi->bytes + vi->usable_leb_size - 1) / vi->usable_leb_size;
+	else
+		vi->used_ebs = (st->st_size + vi->usable_leb_size - 1) / vi->usable_leb_size;
+	vi->compat = 0;
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err = -1, sects, i, autoresize_was_already = 0;
+	struct ubigen_info ui;
+	struct ubi_vtbl_record *vtbl;
+	struct ubigen_vol_info *vi;
+	off_t seek;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	ubigen_info_init(&ui, args.peb_size, args.min_io_size,
+			 args.subpage_size, args.vid_hdr_offs,
+			 args.ubi_ver, args.image_seq);
+
+	verbose(args.verbose, "LEB size:                  %d", ui.leb_size);
+	verbose(args.verbose, "PEB size:                  %d", ui.peb_size);
+	verbose(args.verbose, "min. I/O size:             %d", ui.min_io_size);
+	verbose(args.verbose, "sub-page size:             %d", args.subpage_size);
+	verbose(args.verbose, "VID offset:                %d", ui.vid_hdr_offs);
+	verbose(args.verbose, "data offset:               %d", ui.data_offs);
+	verbose(args.verbose, "UBI image sequence number: %u", ui.image_seq);
+
+	vtbl = ubigen_create_empty_vtbl(&ui);
+	if (!vtbl)
+		goto out;
+
+	args.dict = iniparser_load(args.f_in);
+	if (!args.dict) {
+		errmsg("cannot load the input ini file \"%s\"", args.f_in);
+		goto out_vtbl;
+	}
+
+	verbose(args.verbose, "loaded the ini-file \"%s\"", args.f_in);
+
+	/* Each section describes one volume */
+	sects = iniparser_getnsec(args.dict);
+	if (sects == -1) {
+		errmsg("ini-file parsing error (iniparser_getnsec)");
+		goto out_dict;
+	}
+
+	verbose(args.verbose, "count of sections: %d", sects);
+	if (sects == 0) {
+		errmsg("no sections found the ini-file \"%s\"", args.f_in);
+		goto out_dict;
+	}
+
+	if (sects > ui.max_volumes) {
+		errmsg("too many sections (%d) in the ini-file \"%s\"",
+		       sects, args.f_in);
+		normsg("each section corresponds to an UBI volume, maximum "
+		       "count of volumes is %d", ui.max_volumes);
+		goto out_dict;
+	}
+
+	vi = calloc(sizeof(struct ubigen_vol_info), sects);
+	if (!vi) {
+		errmsg("cannot allocate memory");
+		goto out_dict;
+	}
+
+	/*
+	 * Skip 2 PEBs at the beginning of the file for the volume table which
+	 * will be written later.
+	 */
+	seek = ui.peb_size * 2;
+	if (lseek(args.out_fd, seek, SEEK_SET) != seek) {
+		sys_errmsg("cannot seek file \"%s\"", args.f_out);
+		goto out_free;
+	}
+
+	for (i = 0; i < sects; i++) {
+		const char *sname = iniparser_getsecname(args.dict, i);
+		const char *img = NULL;
+		struct stat st;
+		int fd, j;
+
+		if (!sname) {
+			errmsg("ini-file parsing error (iniparser_getsecname)");
+			goto out_free;
+		}
+
+		if (args.verbose)
+			printf("\n");
+		verbose(args.verbose, "parsing section \"%s\"", sname);
+
+		err = read_section(&ui, sname, &vi[i], &img, &st);
+		if (err == -1)
+			goto out_free;
+
+		verbose(args.verbose, "adding volume %d", vi[i].id);
+
+		/*
+		 * Make sure that volume ID and name is unique and that only
+		 * one volume has auto-resize flag
+		 */
+		for (j = 0; j < i; j++) {
+			if (vi[i].id == vi[j].id) {
+				errmsg("volume IDs must be unique, but ID %d "
+				       "in section \"%s\" is not",
+				       vi[i].id, sname);
+				goto out_free;
+			}
+
+			if (!strcmp(vi[i].name, vi[j].name)) {
+				errmsg("volume name must be unique, but name "
+				       "\"%s\" in section \"%s\" is not",
+				       vi[i].name, sname);
+				goto out_free;
+			}
+		}
+
+		if (vi[i].flags & UBI_VTBL_AUTORESIZE_FLG) {
+			if (autoresize_was_already)
+				return errmsg("only one volume is allowed "
+					      "to have auto-resize flag");
+			autoresize_was_already = 1;
+		}
+
+		err = ubigen_add_volume(&ui, &vi[i], vtbl);
+		if (err) {
+			errmsg("cannot add volume for section \"%s\"", sname);
+			goto out_free;
+		}
+
+		if (img) {
+			fd = open(img, O_RDONLY);
+			if (fd == -1) {
+				sys_errmsg("cannot open \"%s\"", img);
+				goto out_free;
+			}
+
+			verbose(args.verbose, "writing volume %d", vi[i].id);
+			verbose(args.verbose, "image file: %s", img);
+
+			err = ubigen_write_volume(&ui, &vi[i], args.ec, st.st_size, fd, args.out_fd);
+			close(fd);
+			if (err) {
+				errmsg("cannot write volume for section \"%s\"", sname);
+				goto out_free;
+			}
+		}
+
+		if (args.verbose)
+			printf("\n");
+	}
+
+	verbose(args.verbose, "writing layout volume");
+
+	err = ubigen_write_layout_vol(&ui, 0, 1, args.ec, args.ec, vtbl, args.out_fd);
+	if (err) {
+		errmsg("cannot write layout volume");
+		goto out_free;
+	}
+
+	verbose(args.verbose, "done");
+
+	free(vi);
+	iniparser_freedict(args.dict);
+	free(vtbl);
+	close(args.out_fd);
+	return 0;
+
+out_free:
+	free(vi);
+out_dict:
+	iniparser_freedict(args.dict);
+out_vtbl:
+	free(vtbl);
+out:
+	close(args.out_fd);
+	remove(args.f_out);
+	return err;
+}
diff --git a/ubi-utils/ubirename.c b/ubi-utils/ubirename.c
new file mode 100644
index 0000000..070e32e
--- /dev/null
+++ b/ubi-utils/ubirename.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008 Logitech.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published by
+ * the Free Software Foundation.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * An utility to get rename UBI volumes.
+ *
+ * Author: Richard Titmuss
+ */
+
+#define PROGRAM_VERSION "1.0"
+#define PROGRAM_NAME    "ubirename"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [<old name> <new name>|...]\n\n"
+"Example: " PROGRAM_NAME "/dev/ubi0 A B C D - rename volume A to B, and C to D\n\n"
+"This utility allows re-naming several volumes in one go atomically.\n"
+"For example, if you have volumes A and B, then you may rename A into B\n"
+"and B into A at one go, and the operation will be atomic. This allows\n"
+"implementing atomic UBI volumes upgrades. E.g., if you have volume A\n"
+"and want to upgrade it atomically, you create a temporary volume B,\n"
+"put your new data to B, then rename A to B and B to A, and then you\n"
+"may remove old volume B.\n"
+"It is also allowed to re-name multiple volumes at a time, but 16 max.\n"
+"renames at once, which means you may specify up to 32 volume names.\n"
+"If you have volumes A and B, and re-name A to B, bud do not re-name\n"
+"B to something else in the same request, old volume B will be removed\n"
+"and A will be renamed into B.\n";
+
+static int get_vol_id(libubi_t libubi, struct ubi_dev_info *dev_info,
+		       char *name)
+{
+	int err, i;
+	struct ubi_vol_info vol_info;
+
+	for (i=dev_info->lowest_vol_id; i<=dev_info->highest_vol_id; i++) {
+		err = ubi_get_vol_info1(libubi, dev_info->dev_num, i, &vol_info);
+		if (err == -1) {
+			if (errno == ENOENT)
+				continue;
+			return -1;
+		}
+
+		if (strcmp(name, vol_info.name) == 0)
+			return vol_info.vol_id;
+	}
+
+	return -1;
+}
+
+int main(int argc, char * const argv[])
+{
+	int i, err;
+	int count = 0;
+	libubi_t libubi;
+	struct ubi_dev_info dev_info;
+	struct ubi_rnvol_req rnvol;
+	const char *node;
+
+	if (argc < 3 || (argc & 1) == 1) {
+		errmsg("too few arguments");
+		fprintf(stderr, "%s\n", usage);
+		return -1;
+	}
+
+	if (argc > UBI_MAX_RNVOL + 2) {
+		errmsg("too many volumes to re-name, max. is %d",
+		       UBI_MAX_RNVOL);
+		return -1;
+	}
+
+	node = argv[1];
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			return errmsg("UBI is not present in the system");
+		return sys_errmsg("cannot open libubi");
+	}
+
+	err = ubi_probe_node(libubi, node);
+	if (err == 2) {
+		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+		       node);
+		goto out_libubi;
+	} else if (err < 0) {
+		if (errno == ENODEV)
+			errmsg("\"%s\" is not an UBI device node", node);
+		else
+			sys_errmsg("error while probing \"%s\"", node);
+		goto out_libubi;
+	}
+
+	err = ubi_get_dev_info(libubi, node, &dev_info);
+	if (err == -1) {
+		sys_errmsg("cannot get information about UBI device \"%s\"", node);
+		goto out_libubi;
+	}
+
+	for (i = 2; i < argc; i += 2) {
+		err = get_vol_id(libubi, &dev_info, argv[i]);
+		if (err == -1) {
+			errmsg("\"%s\" volume not found", argv[i]);
+			goto out_libubi;
+		}
+
+		rnvol.ents[count].vol_id = err;
+		rnvol.ents[count].name_len = strlen(argv[i + 1]);
+		strcpy(rnvol.ents[count++].name, argv[i + 1]);
+	}
+
+	rnvol.count = count;
+
+	err = ubi_rnvols(libubi, node, &rnvol);
+	if (err == -1) {
+		sys_errmsg("cannot rename volumes");
+		goto out_libubi;
+	}
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubirmvol.c b/ubi-utils/ubirmvol.c
new file mode 100644
index 0000000..5725d90
--- /dev/null
+++ b/ubi-utils/ubirmvol.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to remove UBI volumes.
+ *
+ * Authors: Artem Bityutskiy <dedekind at infradead.org>
+ *          Frank Haverkamp <haver at vnet.ibm.com>
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubirmvol"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int vol_id;
+	const char *node;
+	const char *name;
+};
+
+static struct args args = {
+	.vol_id = -1,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+				 " - a tool to remove UBI volumes.";
+
+static const char optionsstr[] =
+"-n, --vol_id=<volume id>   volume ID to remove\n"
+"-N, --name=<volume name>   volume name to remove\n"
+"-h, -?, --help             print help message\n"
+"-V, --version              print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n"
+"         [-N <volume name>] [--name=<volume name>] [-h] [--help]\n\n"
+"Example: " PROGRAM_NAME "/dev/ubi0 -n 1 - remove UBI volume 1 from UBI device corresponding\n"
+"         to /dev/ubi0\n"
+"         " PROGRAM_NAME "/dev/ubi0 -N my_vol - remove UBI named \"my_vol\" from UBI device\n"
+"         corresponding to /dev/ubi0";
+
+static const struct option long_options[] = {
+	{ .name = "vol_id",  .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "name",    .has_arg = 1, .flag = NULL, .val = 'N' },
+	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int param_sanity_check(void)
+{
+	if (args.vol_id == -1 && !args.name) {
+		errmsg("please, specify either volume ID or volume name");
+		return -1;
+	}
+
+	if (args.vol_id != -1 && args.name) {
+		errmsg("please, specify either volume ID or volume name, not both");
+		return -1;
+	}
+
+	return 0;
+}
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "n:N:h?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+
+		case 'n':
+			args.vol_id = simple_strtoul(optarg, &error);
+			if (error || args.vol_id < 0) {
+				errmsg("bad volume ID: " "\"%s\"", optarg);
+				return -1;
+			}
+			break;
+
+		case 'N':
+			args.name = optarg;
+			break;
+
+		case 'h':
+		case '?':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			errmsg("parameter is missing");
+			return -1;
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc) {
+		errmsg("UBI device name was not specified (use -h for help)");
+		return -1;
+	} else if (optind != argc - 1) {
+		errmsg("more then one UBI device specified (use -h for help)");
+		return -1;
+	}
+
+	args.node = argv[optind];
+
+	if (param_sanity_check())
+		return -1;
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			return errmsg("UBI is not present in the system");
+		return sys_errmsg("cannot open libubi");
+	}
+
+	err = ubi_probe_node(libubi, args.node);
+	if (err == 2) {
+		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+		       args.node);
+		goto out_libubi;
+	} else if (err < 0) {
+		if (errno == ENODEV)
+			errmsg("\"%s\" is not an UBI device node", args.node);
+		else
+			sys_errmsg("error while probing \"%s\"", args.node);
+		goto out_libubi;
+	}
+
+	if (args.name) {
+		struct ubi_dev_info dev_info;
+		struct ubi_vol_info vol_info;
+
+		err = ubi_get_dev_info(libubi, args.node, &dev_info);
+		if (err) {
+			sys_errmsg("cannot get information about UBI device \"%s\"",
+				   args.node);
+			goto out_libubi;
+		}
+
+		err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num,
+					   args.name, &vol_info);
+		if (err) {
+			sys_errmsg("cannot find UBI volume \"%s\"", args.name);
+			goto out_libubi;
+		}
+
+		args.vol_id = vol_info.vol_id;
+	}
+
+	err = ubi_rmvol(libubi, args.node, args.vol_id);
+	if (err) {
+		sys_errmsg("cannot UBI remove volume");
+		goto out_libubi;
+	}
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubirsvol.c b/ubi-utils/ubirsvol.c
new file mode 100644
index 0000000..65f579c
--- /dev/null
+++ b/ubi-utils/ubirsvol.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to resize UBI volumes.
+ *
+ * Authors: Artem Bityutskiy <dedekind at infradead.org>
+ *          Frank Haverkamp <haver at vnet.ibm.com>
+ */
+
+#define PROGRAM_VERSION "1.1"
+#define PROGRAM_NAME    "ubirsvol"
+
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libubi.h>
+#include "common.h"
+#include "ubiutils-common.h"
+
+/* The variables below are set by command line arguments */
+struct args {
+	int vol_id;
+	const char *node;
+	const char *name;
+	long long bytes;
+	int lebs;
+};
+
+static struct args args = {
+	.vol_id = -1,
+	.bytes = -1,
+	.lebs = -1,
+};
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+				 " - a tool to resize UBI volumes.";
+
+static const char optionsstr[] =
+"-n, --vol_id=<volume id>   volume ID to resize\n"
+"-N, --name=<volume name>   volume name to resize\n"
+"-s, --size=<bytes>         volume size volume size in bytes, kilobytes (KiB)\n"
+"                           or megabytes (MiB)\n"
+"-S, --lebs=<LEBs count>    alternative way to give volume size in logical\n"
+"                           eraseblocks\n"
+"-h, -?, --help             print help message\n"
+"-V, --version              print program version";
+
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI device node file name> [-n <volume id>] [--vol_id=<volume id>]\n\n"
+"         [-N <volume name>] [--name=<volume name>] [-s <bytes>] [-S <LEBs>] [-h] [--help]\n\n"
+"Example: " PROGRAM_NAME " /dev/ubi0 -n 1 -s 1MiB resize UBI volume 1 to 1 MiB on\n"
+"         UBI device corresponding to /dev/ubi0\n"
+"         " PROGRAM_NAME " /dev/ubi0 -N my_vol -s 1MiB - resize UBI volume named \"my_vol\" to 1 MiB\n"
+"	  on UBI device corresponding to /dev/ubi0";
+
+static const struct option long_options[] = {
+	{ .name = "vol_id",  .has_arg = 1, .flag = NULL, .val = 'n' },
+	{ .name = "name",    .has_arg = 1, .flag = NULL, .val = 'N' },
+	{ .name = "help",    .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version", .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ .name = "size",    .has_arg = 1, .flag = NULL, .val = 's' },
+	{ .name = "lebs",    .has_arg = 1, .flag = NULL, .val = 'S' },
+	{ NULL, 0, NULL, 0},
+};
+
+static int param_sanity_check(void)
+{
+	if (args.vol_id == -1 && !args.name) {
+		errmsg("please, specify either volume ID or volume name");
+		return -1;
+	}
+
+	if (args.vol_id != -1 && args.name) {
+		errmsg("please, specify either volume ID or volume name, not both");
+		return -1;
+	}
+
+	if (args.bytes == -1 && args.lebs == -1)
+		return errmsg("volume size was not specified (use -h for help)");
+
+	if (args.bytes != -1 && args.lebs != -1)
+		return errmsg("size specified with more then one option");
+
+	return 0;
+}
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "s:S:n:N:h?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 's':
+			args.bytes = ubiutils_get_bytes(optarg);
+			if (args.bytes <= 0)
+				return errmsg("bad volume size: \"%s\"", optarg);
+			break;
+
+		case 'S':
+			args.lebs = simple_strtoull(optarg, &error);
+			if (error || args.lebs <= 0)
+				return errmsg("bad LEB count: \"%s\"", optarg);
+			break;
+
+		case 'n':
+			args.vol_id = simple_strtoul(optarg, &error);
+			if (error || args.vol_id < 0) {
+				errmsg("bad volume ID: " "\"%s\"", optarg);
+				return -1;
+			}
+			break;
+
+		case 'N':
+			args.name = optarg;
+			break;
+
+		case 'h':
+		case '?':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			errmsg("parameter is missing");
+			return -1;
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc) {
+		errmsg("UBI device name was not specified (use -h for help)");
+		return -1;
+	} else if (optind != argc - 1) {
+		errmsg("more then one UBI device specified (use -h for help)");
+		return -1;
+	}
+
+	args.node = argv[optind];
+
+	if (param_sanity_check())
+		return -1;
+
+	return 0;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_dev_info dev_info;
+	struct ubi_vol_info vol_info;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi)
+		return sys_errmsg("cannot open libubi");
+
+	err = ubi_probe_node(libubi, args.node);
+	if (err == 2) {
+		errmsg("\"%s\" is an UBI volume node, not an UBI device node",
+		       args.node);
+		goto out_libubi;
+	} else if (err < 0) {
+		if (errno == ENODEV)
+			errmsg("\"%s\" is not an UBI device node", args.node);
+		else
+			sys_errmsg("error while probing \"%s\"", args.node);
+	}
+
+	err = ubi_get_dev_info(libubi, args.node, &dev_info);
+	if (err) {
+		sys_errmsg("cannot get information about UBI device \"%s\"",
+			   args.node);
+		goto out_libubi;
+	}
+
+	if (args.name) {
+		err = ubi_get_vol_info1_nm(libubi, dev_info.dev_num,
+					   args.name, &vol_info);
+		if (err) {
+			sys_errmsg("cannot find UBI volume \"%s\"", args.name);
+			goto out_libubi;
+		}
+
+		args.vol_id = vol_info.vol_id;
+	} else {
+		err = ubi_get_vol_info1(libubi, dev_info.dev_num,
+					   args.vol_id, &vol_info);
+		if (err) {
+			sys_errmsg("cannot find UBI volume ID %d", args.vol_id);
+			goto out_libubi;
+		}
+	}
+
+	if (args.lebs != -1)
+		args.bytes = vol_info.leb_size * args.lebs;
+
+	err = ubi_rsvol(libubi, args.node, args.vol_id, args.bytes);
+	if (err) {
+		sys_errmsg("cannot UBI resize volume");
+		goto out_libubi;
+	}
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubiupdatevol.c b/ubi-utils/ubiupdatevol.c
new file mode 100644
index 0000000..24f38fe
--- /dev/null
+++ b/ubi-utils/ubiupdatevol.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) International Business Machines Corp., 2006
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * An utility to update UBI volumes.
+ *
+ * Authors: Frank Haverkamp
+ *          Joshua W. Boyer
+ *          Artem Bityutskiy
+ */
+
+#define PROGRAM_VERSION "1.2"
+#define PROGRAM_NAME    "ubiupdatevol"
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <getopt.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <libubi.h>
+#include "common.h"
+
+struct args {
+	int truncate;
+	const char *node;
+	const char *img;
+	/* For deprecated -d and -B options handling */
+	char dev_name[256];
+	int size;
+	int use_stdin;
+};
+
+static struct args args;
+
+static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+			 " - a tool to write data to UBI volumes.";
+
+static const char optionsstr[] =
+"-t, --truncate             truncate volume (wipe it out)\n"
+"-s, --size=<bytes>         bytes in input, if not reading from file\n"
+"-h, --help                 print help message\n"
+"-V, --version              print program version";
+
+static const char usage[] =
+"Usage: " PROGRAM_NAME " <UBI volume node file name> [-t] [-s <size>] [-h] [-V] [--truncate]\n"
+"\t\t\t[--size=<size>] [--help] [--version] <image file>\n\n"
+"Example 1: " PROGRAM_NAME " /dev/ubi0_1 fs.img - write file \"fs.img\" to UBI volume /dev/ubi0_1\n"
+"Example 2: " PROGRAM_NAME " /dev/ubi0_1 -t - wipe out UBI volume /dev/ubi0_1";
+
+static const struct option long_options[] = {
+	{ .name = "truncate", .has_arg = 0, .flag = NULL, .val = 't' },
+	{ .name = "help",     .has_arg = 0, .flag = NULL, .val = 'h' },
+	{ .name = "version",  .has_arg = 0, .flag = NULL, .val = 'V' },
+	{ .name = "size",     .has_arg = 1, .flag = NULL, .val = 's' },
+	{ NULL, 0, NULL, 0}
+};
+
+static int parse_opt(int argc, char * const argv[])
+{
+	while (1) {
+		int key, error = 0;
+
+		key = getopt_long(argc, argv, "ts:h?V", long_options, NULL);
+		if (key == -1)
+			break;
+
+		switch (key) {
+		case 't':
+			args.truncate = 1;
+			break;
+
+		case 's':
+			args.size = simple_strtoul(optarg, &error);
+			if (error || args.size < 0)
+				return errmsg("bad size: " "\"%s\"", optarg);
+			break;
+
+		case 'h':
+		case '?':
+			printf("%s\n\n", doc);
+			printf("%s\n\n", usage);
+			printf("%s\n", optionsstr);
+			exit(EXIT_SUCCESS);
+
+		case 'V':
+			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			exit(EXIT_SUCCESS);
+
+		case ':':
+			return errmsg("parameter is missing");
+
+		default:
+			fprintf(stderr, "Use -h for help\n");
+			return -1;
+		}
+	}
+
+	if (optind == argc)
+		return errmsg("UBI device name was not specified (use -h for help)");
+	else if (optind != argc - 2 && !args.truncate)
+		return errmsg("specify UBI device name and image file name as first 2 "
+			      "parameters (use -h for help)");
+
+	args.node = argv[optind];
+	args.img  = argv[optind + 1];
+
+	if (args.img && args.truncate)
+		return errmsg("You can't truncate and specify an image (use -h for help)");
+
+	if (args.img && !args.truncate) {
+		if (strcmp(args.img, "-") == 0)
+			args.use_stdin = 1;
+		if (args.use_stdin && !args.size)
+			return errmsg("file size must be specified if input is stdin");
+	}
+
+	return 0;
+}
+
+static int truncate_volume(libubi_t libubi)
+{
+	int err, fd;
+
+	fd = open(args.node, O_RDWR);
+	if (fd == -1)
+		return sys_errmsg("cannot open \"%s\"", args.node);
+
+	err = ubi_update_start(libubi, fd, 0);
+	if (err) {
+		sys_errmsg("cannot truncate volume \"%s\"", args.node);
+		close(fd);
+		return -1;
+	}
+
+	close(fd);
+	return 0;
+}
+
+static int ubi_write(int fd, const void *buf, int len)
+{
+	int ret;
+
+	while (len) {
+		ret = write(fd, buf, len);
+		if (ret < 0) {
+			if (errno == EINTR) {
+				warnmsg("do not interrupt me!");
+				continue;
+			}
+			return sys_errmsg("cannot write %d bytes to volume \"%s\"",
+					  len, args.node);
+		}
+
+		if (ret == 0)
+			return errmsg("cannot write %d bytes to volume \"%s\"", len, args.node);
+
+		len -= ret;
+		buf += ret;
+	}
+
+	return 0;
+}
+
+static int update_volume(libubi_t libubi, struct ubi_vol_info *vol_info)
+{
+	int err, fd, ifd;
+	long long bytes;
+	char *buf;
+
+	buf = malloc(vol_info->leb_size);
+	if (!buf)
+		return errmsg("cannot allocate %d bytes of memory", vol_info->leb_size);
+
+	if (!args.size) {
+		struct stat st;
+		err = stat(args.img, &st);
+		if (err < 0) {
+			errmsg("stat failed on \"%s\"", args.img);
+			goto out_free;
+		}
+
+		bytes = st.st_size;
+	} else
+		bytes = args.size;
+
+	if (bytes > vol_info->rsvd_bytes) {
+		errmsg("\"%s\" (size %lld) will not fit volume \"%s\" (size %lld)",
+		       args.img, bytes, args.node, vol_info->rsvd_bytes);
+		goto out_free;
+	}
+
+	fd = open(args.node, O_RDWR);
+	if (fd == -1) {
+		sys_errmsg("cannot open UBI volume \"%s\"", args.node);
+		goto out_free;
+	}
+
+	if (args.use_stdin)
+		ifd = STDIN_FILENO;
+	else {
+		ifd = open(args.img, O_RDONLY);
+		if (ifd == -1) {
+			sys_errmsg("cannot open \"%s\"", args.img);
+			goto out_close1;
+		}
+	}
+
+	err = ubi_update_start(libubi, fd, bytes);
+	if (err) {
+		sys_errmsg("cannot start volume \"%s\" update", args.node);
+		goto out_close;
+	}
+
+	while (bytes) {
+		int ret, to_copy = vol_info->leb_size;
+
+		if (to_copy > bytes)
+			to_copy = bytes;
+
+		ret = read(ifd, buf, to_copy);
+		if (ret <= 0) {
+			if (errno == EINTR) {
+				warnmsg("do not interrupt me!");
+				continue;
+			} else {
+				sys_errmsg("cannot read %d bytes from \"%s\"",
+						to_copy, args.img);
+				goto out_close;
+			}
+		}
+
+		err = ubi_write(fd, buf, ret);
+		if (err)
+			goto out_close;
+		bytes -= ret;
+	}
+
+	close(ifd);
+	close(fd);
+	free(buf);
+	return 0;
+
+out_close:
+	close(ifd);
+out_close1:
+	close(fd);
+out_free:
+	free(buf);
+	return -1;
+}
+
+int main(int argc, char * const argv[])
+{
+	int err;
+	libubi_t libubi;
+	struct ubi_vol_info vol_info;
+
+	err = parse_opt(argc, argv);
+	if (err)
+		return -1;
+
+	libubi = libubi_open();
+	if (!libubi) {
+		if (errno == 0)
+			errmsg("UBI is not present in the system");
+		else
+			sys_errmsg("cannot open libubi");
+		goto out_libubi;
+	}
+
+	err = ubi_probe_node(libubi, args.node);
+	if (err == 1) {
+		errmsg("\"%s\" is an UBI device node, not an UBI volume node",
+		       args.node);
+		goto out_libubi;
+	} else if (err < 0) {
+		if (errno == ENODEV)
+			errmsg("\"%s\" is not an UBI volume node", args.node);
+		else
+			sys_errmsg("error while probing \"%s\"", args.node);
+		goto out_libubi;
+	}
+
+	err = ubi_get_vol_info(libubi, args.node, &vol_info);
+	if (err) {
+		sys_errmsg("cannot get information about UBI volume \"%s\"",
+			   args.node);
+		goto out_libubi;
+	}
+
+	if (args.truncate)
+		err = truncate_volume(libubi);
+	else
+		err = update_volume(libubi, &vol_info);
+	if (err)
+		goto out_libubi;
+
+	libubi_close(libubi);
+	return 0;
+
+out_libubi:
+	libubi_close(libubi);
+	return -1;
+}
diff --git a/ubi-utils/ubiutils-common.c b/ubi-utils/ubiutils-common.c
new file mode 100644
index 0000000..6609a6b
--- /dev/null
+++ b/ubi-utils/ubiutils-common.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) 2007, 2008 Nokia Corporation
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file contains various common stuff used by UBI utilities.
+ *
+ * Authors: Artem Bityutskiy
+ *          Adrian Hunter
+ */
+
+#define PROGRAM_NAME "ubiutils"
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "common.h"
+
+/**
+ * get_multiplier - convert size specifier to an integer multiplier.
+ * @str: the size specifier string
+ *
+ * This function parses the @str size specifier, which may be one of
+ * 'KiB', 'MiB', or 'GiB' into an integer multiplier. Returns positive
+ * size multiplier in case of success and %-1 in case of failure.
+ */
+static int get_multiplier(const char *str)
+{
+	if (!str)
+		return 1;
+
+	/* Remove spaces before the specifier */
+	while (*str == ' ' || *str == '\t')
+		str += 1;
+
+	if (!strcmp(str, "KiB"))
+		return 1024;
+	if (!strcmp(str, "MiB"))
+		return 1024 * 1024;
+	if (!strcmp(str, "GiB"))
+		return 1024 * 1024 * 1024;
+
+	return -1;
+}
+
+/**
+ * ubiutils_get_bytes - convert a string containing amount of bytes into an
+ * integer
+ * @str: string to convert
+ *
+ * This function parses @str which may have one of 'KiB', 'MiB', or 'GiB'
+ * size specifiers. Returns positive amount of bytes in case of success and %-1
+ * in case of failure.
+ */
+long long ubiutils_get_bytes(const char *str)
+{
+	char *endp;
+	long long bytes = strtoull(str, &endp, 0);
+
+	if (endp == str || bytes < 0) {
+		fprintf(stderr, "incorrect amount of bytes: \"%s\"\n", str);
+		return -1;
+	}
+
+	if (*endp != '\0') {
+		int mult = get_multiplier(endp);
+
+		if (mult == -1) {
+			fprintf(stderr, "bad size specifier: \"%s\" - "
+			        "should be 'KiB', 'MiB' or 'GiB'\n", endp);
+			return -1;
+		}
+		bytes *= mult;
+	}
+
+	return bytes;
+}
+
+/**
+ * ubiutils_print_bytes - print bytes.
+ * @bytes: variable to print
+ * @bracket: whether brackets have to be put or not
+ *
+ * This is a helper function which prints amount of bytes in a human-readable
+ * form, i.e., it prints the exact amount of bytes following by the approximate
+ * amount of Kilobytes, Megabytes, or Gigabytes, depending on how big @bytes
+ * is.
+ */
+void ubiutils_print_bytes(long long bytes, int bracket)
+{
+	const char *p;
+
+	if (bracket)
+		p = " (";
+	else
+		p = ", ";
+
+	printf("%lld bytes", bytes);
+
+	if (bytes > 1024 * 1024 * 1024)
+		printf("%s%.1f GiB", p, (double)bytes / (1024 * 1024 * 1024));
+	else if (bytes > 1024 * 1024)
+		printf("%s%.1f MiB", p, (double)bytes / (1024 * 1024));
+	else if (bytes > 1024 && bytes != 0)
+		printf("%s%.1f KiB", p, (double)bytes / 1024);
+	else
+		return;
+
+	if (bracket)
+		printf(")");
+}
+
+/**
+ * ubiutils_print_text - print text and fold it.
+ * @stream: file stream to print to
+ * @text: text to print
+ * @width: maximum allowed text width
+ *
+ * Print text and fold it so that each line would not have more then @width
+ * characters.
+ */
+void ubiutils_print_text(FILE *stream, const char *text, int width)
+{
+	int pos, bpos = 0;
+	const char *p;
+	char line[1024];
+
+	if (width > 1023) {
+		fprintf(stream, "%s\n", text);
+		return;
+	}
+	p = text;
+	pos = 0;
+	while (p[pos]) {
+		while (!isspace(p[pos])) {
+			line[pos] = p[pos];
+			if (!p[pos])
+				break;
+			++pos;
+			if (pos == width) {
+				line[pos] = '\0';
+				fprintf(stream, "%s\n", line);
+				p += pos;
+				pos = 0;
+			}
+		}
+		while (pos < width) {
+			line[pos] = p[pos];
+			if (!p[pos]) {
+				bpos = pos;
+				break;
+			}
+			if (isspace(p[pos]))
+				bpos = pos;
+			++pos;
+		}
+		line[bpos] = '\0';
+		fprintf(stream, "%s\n", line);
+		p += bpos;
+		pos = 0;
+		while (p[pos] && isspace(p[pos]))
+			++p;
+	}
+}
+
+/**
+ * ubiutils_srand - randomly seed the standard pseudo-random generator.
+ *
+ * This helper function seeds the standard libc pseudo-random generator with a
+ * more or less random value to make sure the 'rand()' call does not return the
+ * same sequence every time UBI utilities run. Returns zero in case of success
+ * and a %-1 in case of error.
+ */
+int ubiutils_srand(void)
+{
+	struct timeval tv;
+	struct timezone tz;
+	unsigned int seed;
+
+	/*
+	 * Just assume that a combination of the PID + current time is a
+	 * reasonably random number.
+	 */
+	if (gettimeofday(&tv, &tz))
+		return -1;
+
+	seed = (unsigned int)tv.tv_sec;
+	seed += (unsigned int)tv.tv_usec;
+	seed *= getpid();
+	seed %= RAND_MAX;
+	srand(seed);
+	return 0;
+}
-- 
1.7.5.3



From vapier at gentoo.org  Sat Jun 25 02:32:37 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 02:32:37 -0400
Subject: [PATCH] rewrite build system to avoid recursion
In-Reply-To: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
Message-ID: <BANLkTinmFuH-40b855YMqcHSfy7bg=DE_A@mail.gmail.com>

On Sat, Jun 25, 2011 at 02:30, Mike Frysinger wrote:
> The ubi-utils/src/ subdir is tossed as it just complicates things for no
> real gain.
>
> ?ubi-utils/dictionary.c ? ? ? ? ?| ?405 ++++++++++++
> ?ubi-utils/dictionary.h ? ? ? ? ?| ?174 +++++
> ?ubi-utils/libiniparser.c ? ? ? ?| ?646 ++++++++++++++++++
> ?ubi-utils/libscan.c ? ? ? ? ? ? | ?225 +++++++
> ?ubi-utils/libubi.c ? ? ? ? ? ? ?| 1372 +++++++++++++++++++++++++++++++++++++++
> ?ubi-utils/libubi_int.h ? ? ? ? ?| ?131 ++++
> ?ubi-utils/libubigen.c ? ? ? ? ? | ?315 +++++++++
> ?ubi-utils/mtdinfo.c ? ? ? ? ? ? | ?446 +++++++++++++
> ?ubi-utils/src/dictionary.c ? ? ?| ?405 ------------
> ?ubi-utils/src/dictionary.h ? ? ?| ?174 -----
> ?ubi-utils/src/libiniparser.c ? ?| ?646 ------------------
> ?ubi-utils/src/libscan.c ? ? ? ? | ?225 -------
> ?ubi-utils/src/libubi.c ? ? ? ? ?| 1372 ---------------------------------------
> ?ubi-utils/src/libubi_int.h ? ? ?| ?131 ----
> ?ubi-utils/src/libubigen.c ? ? ? | ?315 ---------
> ?ubi-utils/src/mtdinfo.c ? ? ? ? | ?446 -------------
> ?ubi-utils/src/ubiattach.c ? ? ? | ?225 -------
> ?ubi-utils/src/ubicrc32.c ? ? ? ?| ?124 ----
> ?ubi-utils/src/ubidetach.c ? ? ? | ?208 ------
> ?ubi-utils/src/ubiformat.c ? ? ? | ?950 ---------------------------
> ?ubi-utils/src/ubimkvol.c ? ? ? ?| ?295 ---------
> ?ubi-utils/src/ubinfo.c ? ? ? ? ?| ?434 -------------
> ?ubi-utils/src/ubinize.c ? ? ? ? | ?628 ------------------
> ?ubi-utils/src/ubirename.c ? ? ? | ?147 -----
> ?ubi-utils/src/ubirmvol.c ? ? ? ?| ?211 ------
> ?ubi-utils/src/ubirsvol.c ? ? ? ?| ?245 -------
> ?ubi-utils/src/ubiupdatevol.c ? ?| ?324 ---------
> ?ubi-utils/src/ubiutils-common.c | ?211 ------
> ?ubi-utils/ubiattach.c ? ? ? ? ? | ?225 +++++++
> ?ubi-utils/ubicrc32.c ? ? ? ? ? ?| ?124 ++++
> ?ubi-utils/ubidetach.c ? ? ? ? ? | ?208 ++++++
> ?ubi-utils/ubiformat.c ? ? ? ? ? | ?950 +++++++++++++++++++++++++++
> ?ubi-utils/ubimkvol.c ? ? ? ? ? ?| ?295 +++++++++
> ?ubi-utils/ubinfo.c ? ? ? ? ? ? ?| ?434 +++++++++++++
> ?ubi-utils/ubinize.c ? ? ? ? ? ? | ?628 ++++++++++++++++++
> ?ubi-utils/ubirename.c ? ? ? ? ? | ?147 +++++
> ?ubi-utils/ubirmvol.c ? ? ? ? ? ?| ?211 ++++++
> ?ubi-utils/ubirsvol.c ? ? ? ? ? ?| ?245 +++++++
> ?ubi-utils/ubiupdatevol.c ? ? ? ?| ?324 +++++++++
> ?ubi-utils/ubiutils-common.c ? ? | ?211 ++++++
> ?45 files changed, 7804 insertions(+), 7866 deletions(-)

ugh, i really have to remember to use the -M flag with these things.
this is all just renaming.
-mike

From dedekind1 at gmail.com  Sat Jun 25 02:35:13 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 09:35:13 +0300
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <4E04F5D0.9090900@oracle.com>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
	<1308947172.13493.37.camel@koala> <4E04F5D0.9090900@oracle.com>
Message-ID: <1308983721.23868.2.camel@koala>

On Fri, 2011-06-24 at 13:38 -0700, Randy Dunlap wrote:
> On 06/24/11 13:26, Artem Bityutskiy wrote:
> > On Fri, 2011-06-24 at 09:04 -0700, Randy Dunlap wrote:
> >> On Fri, 24 Jun 2011 15:58:22 +1000 Stephen Rothwell wrote:
> >>
> >>> Hi all,
> >>>
> >>> Changes since 20110623:
> >>>
> >>> My fixes tree includes:
> >>> 	(as an experiment) the early part of mmotm-2011-06-22-13-05
> >>> 	STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
> >>
> >>
> >> When CONFIG_MTD=m, CONFIG_MTD_OF_PARTS=y:
> >>
> >> drivers/mtd/ofpart.o: In function `init_module':
> >> ofpart.c:(.init.text+0x0): multiple definition of `init_module'
> >> drivers/mtd/mtdcore.o:(.init.text+0x43): first defined here
> > 
> > I guess this is some old issue? I do not think ofpart can be compiled-in
> > if the mtd core is a module...
> 
> [adding driver author, Vitaly]
> 
> No, it's a current issue.

I meant that the subject suggests this is about linux-next, but this
problem should be in upstream.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier at gentoo.org  Sat Jun 25 02:52:50 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 02:52:50 -0400
Subject: [PATCH 2/2] autogenerate version.h from build system
In-Reply-To: <1308984770-6594-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1308984770-6594-1-git-send-email-vapier@gentoo.org>
Message-ID: <1308984770-6594-2-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
 .gitignore       |    1 +
 Makefile         |    8 ++++++++
 common.mk        |    2 +-
 flash_erase.c    |    1 -
 include/common.h |    1 +
 nanddump.c       |    1 -
 nandwrite.c      |    1 -
 7 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 849265d..86aee63 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,6 +50,7 @@
 #
 # Generated include files
 #
+/include/version.h
 
 # stgit generated dirs
 patches-*
diff --git a/Makefile b/Makefile
index bd5ada3..381b59f 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
 
 # -*- sh -*-
 
+VERSION = 1.4.5
+
 CPPFLAGS += -I./include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
 
 ifeq ($(WITHOUT_XATTR), 1)
@@ -49,6 +51,7 @@ endif
 	find $(BUILDDIR)/ -xdev \
 		'(' -name '*.[ao]' -o -name '.*.c.dep' ')' \
 		-exec rm -f {} +
+	rm -f $(BUILDDIR)/include/version.h
 	$(MAKE) -C $(TESTS) clean
 
 install:: ${BINS} ${SCRIPTS}
@@ -63,6 +66,11 @@ tests::
 cscope:
 	cscope -bR
 
+$(BUILDDIR)/include/version.h: $(BUILDDIR)/include/version.h.tmp
+	$(Q)cmp -s $@ $@.tmp && rm -f $@.tmp || mv $@.tmp $@
+$(BUILDDIR)/include/version.h.tmp:
+	$(Q)echo '#define VERSION "$(VERSION)"' > $@
+
 #
 # Utils in top level
 #
diff --git a/common.mk b/common.mk
index d0e207d..63cbf04 100644
--- a/common.mk
+++ b/common.mk
@@ -75,7 +75,7 @@ $(BUILDDIR)/%.a:
 	$(Q)$(AR) cr $@ $^
 	$(Q)$(RANLIB) $@
 
-$(BUILDDIR)/%.o: %.c
+$(BUILDDIR)/%.o: %.c $(BUILDDIR)/include/version.h
 ifneq ($(BUILDDIR),$(CURDIR))
 	$(Q)mkdir -p $(dir $@)
 endif
diff --git a/flash_erase.c b/flash_erase.c
index e0d2d4c..220f85a 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -19,7 +19,6 @@
  */
 
 #define PROGRAM_NAME "flash_erase"
-#define VERSION "2.1.0"
 
 #include <inttypes.h>
 #include <stdio.h>
diff --git a/include/common.h b/include/common.h
index 7ea282c..65ec086 100644
--- a/include/common.h
+++ b/include/common.h
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
+#include "version.h"
 
 #ifndef PROGRAM_NAME
 # error "You must define PROGRAM_NAME before including this header"
diff --git a/nanddump.c b/nanddump.c
index 0367d83..edbcb78 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -14,7 +14,6 @@
  */
 
 #define PROGRAM_NAME "nanddump"
-#define VERSION "1.31"
 
 #define _GNU_SOURCE
 #include <ctype.h>
diff --git a/nandwrite.c b/nandwrite.c
index 6e986c5..1700d61 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -20,7 +20,6 @@
  */
 
 #define PROGRAM_NAME "nandwrite"
-#define VERSION "$Revision: 1.32 $"
 
 #define _GNU_SOURCE
 #include <ctype.h>
-- 
1.7.5.3



From vapier at gentoo.org  Sat Jun 25 02:52:49 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 02:52:49 -0400
Subject: [PATCH 1/2 v2] rewrite build system to avoid recursion
In-Reply-To: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
Message-ID: <1308984770-6594-1-git-send-email-vapier@gentoo.org>

The ubi-utils/src/ subdir is tossed as it just complicates things for no
real gain.

The top level clean is replaced with a `find -delete` on objects, so it
might prune more than necessary, but many projects now do this sort of
thing and no one complained there.

A "mkdep" helper generates the actual rule, and the variables are used
with "foreach" to expand these automatically.

While we're gutting things, also through in kbuild style output while
building to make things more legible.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- use -M when creating patch
	- add xprintf to autosize quiet output

 Makefile                              |   81 ++++++++++++++++++++++++---------
 common.mk                             |   48 +++++++++++++-------
 lib/Makefile                          |   22 ---------
 mkfs.ubifs/Makefile                   |   29 ------------
 ubi-utils/Makefile                    |   60 ------------------------
 ubi-utils/{src => }/dictionary.c      |    0
 ubi-utils/{src => }/dictionary.h      |    0
 ubi-utils/{src => }/libiniparser.c    |    0
 ubi-utils/{src => }/libscan.c         |    0
 ubi-utils/{src => }/libubi.c          |    0
 ubi-utils/{src => }/libubi_int.h      |    0
 ubi-utils/{src => }/libubigen.c       |    0
 ubi-utils/{src => }/mtdinfo.c         |    0
 ubi-utils/{src => }/ubiattach.c       |    0
 ubi-utils/{src => }/ubicrc32.c        |    0
 ubi-utils/{src => }/ubidetach.c       |    0
 ubi-utils/{src => }/ubiformat.c       |    0
 ubi-utils/{src => }/ubimkvol.c        |    0
 ubi-utils/{src => }/ubinfo.c          |    0
 ubi-utils/{src => }/ubinize.c         |    0
 ubi-utils/{src => }/ubirename.c       |    0
 ubi-utils/{src => }/ubirmvol.c        |    0
 ubi-utils/{src => }/ubirsvol.c        |    0
 ubi-utils/{src => }/ubiupdatevol.c    |    0
 ubi-utils/{src => }/ubiutils-common.c |    0
 25 files changed, 90 insertions(+), 150 deletions(-)
 delete mode 100644 lib/Makefile
 delete mode 100644 mkfs.ubifs/Makefile
 delete mode 100644 ubi-utils/Makefile
 rename ubi-utils/{src => }/dictionary.c (100%)
 rename ubi-utils/{src => }/dictionary.h (100%)
 rename ubi-utils/{src => }/libiniparser.c (100%)
 rename ubi-utils/{src => }/libscan.c (100%)
 rename ubi-utils/{src => }/libubi.c (100%)
 rename ubi-utils/{src => }/libubi_int.h (100%)
 rename ubi-utils/{src => }/libubigen.c (100%)
 rename ubi-utils/{src => }/mtdinfo.c (100%)
 rename ubi-utils/{src => }/ubiattach.c (100%)
 rename ubi-utils/{src => }/ubicrc32.c (100%)
 rename ubi-utils/{src => }/ubidetach.c (100%)
 rename ubi-utils/{src => }/ubiformat.c (100%)
 rename ubi-utils/{src => }/ubimkvol.c (100%)
 rename ubi-utils/{src => }/ubinfo.c (100%)
 rename ubi-utils/{src => }/ubinize.c (100%)
 rename ubi-utils/{src => }/ubirename.c (100%)
 rename ubi-utils/{src => }/ubirmvol.c (100%)
 rename ubi-utils/{src => }/ubirsvol.c (100%)
 rename ubi-utils/{src => }/ubiupdatevol.c (100%)
 rename ubi-utils/{src => }/ubiutils-common.c (100%)

diff --git a/Makefile b/Makefile
index d69206a..bd5ada3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 
 # -*- sh -*-
 
-CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
+CPPFLAGS += -I./include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
 
 ifeq ($(WITHOUT_XATTR), 1)
   CPPFLAGS += -DWITHOUT_XATTR
@@ -12,10 +12,10 @@ else
   LZOLDLIBS = -llzo2
 endif
 
-SUBDIRS = lib ubi-utils mkfs.ubifs
 TESTS = tests
 
-TARGETS = ftl_format flash_erase nanddump doc_loadbios \
+MTD_BINS = \
+	ftl_format flash_erase nanddump doc_loadbios \
 	ftl_check mkfs.jffs2 flash_lock flash_unlock flash_info \
 	flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \
 	jffs2dump \
@@ -23,16 +23,21 @@ TARGETS = ftl_format flash_erase nanddump doc_loadbios \
 	rfddump rfdformat \
 	serve_image recv_image \
 	sumtool #jffs2reader
+UBI_BINS = \
+	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
+
+BINS = $(MTD_BINS)
+BINS += mkfs.ubifs/mkfs.ubifs
+BINS += $(addprefix ubi-utils/,$(UBI_BINS))
 SCRIPTS = flash_eraseall
 
-LDLIBS = -L$(BUILDDIR)/lib -lmtd
-LDDEPS = $(BUILDDIR)/lib/libmtd.a
+TARGETS = $(BINS)
+TARGETS += lib/libmtd.a
+TARGETS += ubi-utils/libubi.a
 
 include common.mk
 
-# mkfs.ubifs needs -lubi which is in ubi-utils/
-subdirs_mkfs.ubifs_all: subdirs_ubi-utils_all
-
 clean::
 ifneq ($(BUILDDIR)/.git,)
 ifneq ($(BUILDDIR),.)
@@ -41,23 +46,14 @@ ifneq ($(BUILDDIR),$(CURDIR))
 endif
 endif
 endif
+	find $(BUILDDIR)/ -xdev \
+		'(' -name '*.[ao]' -o -name '.*.c.dep' ')' \
+		-exec rm -f {} +
 	$(MAKE) -C $(TESTS) clean
 
-$(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\
-	compr_rtime.o mkfs.jffs2.o compr_zlib.o compr_lzo.o \
-	compr.o rbtree.o)
-LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
-
-$(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o
-LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
-
-$(BUILDDIR)/lib/libmtd.a: subdirs_lib_all ;
-
-install:: ${TARGETS} ${SCRIPTS}
+install:: ${BINS} ${SCRIPTS}
 	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
+	install -m 0755 ${BINS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
 	mkdir -p ${DESTDIR}/${MANDIR}/man1
 	gzip -9c mkfs.jffs2.1 > ${DESTDIR}/${MANDIR}/man1/mkfs.jffs2.1.gz
 
@@ -66,3 +62,44 @@ tests::
 
 cscope:
 	cscope -bR
+
+#
+# Utils in top level
+#
+obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o compr_lzo.o compr.o rbtree.o
+LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
+
+LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
+
+$(foreach v,$(MTD_BINS),$(eval $(call mkdep,,$(v))))
+
+#
+# Common libmtd
+#
+obj-libmtd.a = libmtd.o libmtd_legacy.o libcrc32.o libfec.o
+$(call _mkdep,lib/,libmtd.a)
+
+#
+# Utils in mkfs.ubifs subdir
+#
+obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o \
+	hashtable/hashtable.o hashtable/hashtable_itr.o
+LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid
+$(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
+
+#
+# Utils in ubi-utils/ subdir
+#
+obj-libiniparser.a = libiniparser.o dictionary.o
+obj-libscan.a      = libscan.o
+obj-libubi.a       = libubi.o
+obj-libubigen.a    = libubigen.o
+
+obj-mtdinfo   = libubigen.a
+obj-ubinize   = libubigen.a libiniparser.a
+obj-ubiformat = libubigen.a libscan.a
+
+$(foreach v,libubi.a libubigen.a libiniparser.a libscan.a,$(eval $(call _mkdep,ubi-utils/,$(v))))
+$(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-common.o)))
diff --git a/common.mk b/common.mk
index 0f3d447..d0e207d 100644
--- a/common.mk
+++ b/common.mk
@@ -39,34 +39,48 @@ override BUILDDIR := $(patsubst %/,%,$(BUILDDIR))
 
 override TARGETS := $(addprefix $(BUILDDIR)/,$(TARGETS))
 
-SUBDIRS_ALL = $(patsubst %,subdirs_%_all,$(SUBDIRS))
-SUBDIRS_CLEAN = $(patsubst %,subdirs_%_clean,$(SUBDIRS))
-SUBDIRS_INSTALL = $(patsubst %,subdirs_%_install,$(SUBDIRS))
+ifeq ($(V),1)
+XECHO = @:
+XPRINTF = @:
+Q =
+else
+XECHO = @echo
+XPRINTF = @printf
+Q = @
+endif
+define BECHO
+$(XPRINTF) '  %-7s %s\n' "$1" "$(subst $(BUILDDIR)/,,$@)"
+endef
 
-all:: $(TARGETS) $(SUBDIRS_ALL)
+all:: $(TARGETS)
 
-clean:: $(SUBDIRS_CLEAN)
+clean::
 	rm -f $(BUILDDIR)/*.o $(TARGETS) $(BUILDDIR)/.*.c.dep
 
-install:: $(TARGETS) $(SUBDIRS_INSTALL)
+install:: $(TARGETS)
 
-%: %.o $(LDDEPS) $(LDDEPS_$(notdir $@))
-	$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))
+define _mkdep
+$(BUILDDIR)/$1$2: $(addprefix $(BUILDDIR)/$1,$(obj-$2) $3) $(addprefix $(BUILDDIR)/,$4)
+endef
+define mkdep
+$(call _mkdep,$1,$2,$3 $2.o,$4 lib/libmtd.a)
+endef
+
+%: %.o $(LDDEPS)
+	$(call BECHO,LD)
+	$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))
 
 $(BUILDDIR)/%.a:
-	$(AR) crv $@ $^
-	$(RANLIB) $@
+	$(call BECHO,AR)
+	$(Q)$(AR) cr $@ $^
+	$(Q)$(RANLIB) $@
 
 $(BUILDDIR)/%.o: %.c
 ifneq ($(BUILDDIR),$(CURDIR))
-	mkdir -p $(dir $@)
+	$(Q)mkdir -p $(dir $@)
 endif
-	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep
-
-subdirs_%:
-	d=$(patsubst subdirs_%,%,$@); \
-	t=`echo $$d | sed s:.*_::` d=`echo $$d | sed s:_.*::`; \
-	$(MAKE) BUILDDIR=$(BUILDDIR)/$$d -C $$d $$t
+	$(call BECHO,CC)
+	$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep
 
 .SUFFIXES:
 
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index 9b01d32..0000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Makefile for libmtd
-#
-
-SUBDIRS =
-
-# CFLAGS += -Werror
-CPPFLAGS += -I../include
-LIBS = libmtd
-TARGETS = libmtd.a
-
-include ../common.mk
-
-$(BUILDDIR)/libmtd.a: $(addprefix $(BUILDDIR)/,\
-       libmtd.o libmtd_legacy.o libcrc32.o libfec.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-
-uninstall:
diff --git a/mkfs.ubifs/Makefile b/mkfs.ubifs/Makefile
deleted file mode 100644
index ba21a8c..0000000
--- a/mkfs.ubifs/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-
-CPPFLAGS += -I../include -I../ubi-utils/include
-CPPFLAGS += $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
-
-ALL_SOURCES=*.[ch] hashtable/*.[ch]
-
-TARGETS = mkfs.ubifs
-
-LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
-LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd
-LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-
-include ../common.mk
-
-$(BUILDDIR)/mkfs.ubifs: $(addprefix $(BUILDDIR)/,\
-	crc16.o lpt.o compr.o devtable.o \
-	hashtable/hashtable.o hashtable/hashtable_itr.o)
-
-clean::
-	rm -f $(BUILDDIR)/hashtable/*.o cscope.*
-
-cscope:
-	@echo $(ALL_SOURCES) > cscope.files
-	@cscope -bR
-	@rm cscope.files
-
-install:: ${TARGETS}
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
deleted file mode 100644
index df81cd9..0000000
--- a/ubi-utils/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Makefile for ubi-utils
-#
-
-KERNELHDR := ../include
-
-# CFLAGS += -Werror
-CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
-
-LIBS = libubi libubigen libiniparser libscan
-TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
-          ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
-
-VPATH = src
-LDLIBS = -L$(BUILDDIR)/../lib -lmtd
-
-include ../common.mk
-
-# And the below is the rule to get final executable from its .o and ubiutils-common.o
-$(TARGETS): $(addprefix $(BUILDDIR)/,\
-	libubi.a ubiutils-common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
-
-$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
-	ubicrc32.o)
-#	$(CC) $(CFLAGS) -o $@ $^
-
-$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
-	ubinize.o ubiutils-common.o libiniparser.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
-
-$(BUILDDIR)/mtdinfo: $(addprefix $(BUILDDIR)/,\
-	libubigen.a ubiutils-common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lubigen -o $@
-
-$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
-	ubiformat.o ubiutils-common.o libscan.a libubi.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
-
-$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
-
-$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
-
-$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
-	libiniparser.o dictionary.o)
-
-$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
-	libscan.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-
-uninstall:
-	for file in ${TARGETS}; do \
-		$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
-	done
diff --git a/ubi-utils/src/dictionary.c b/ubi-utils/dictionary.c
similarity index 100%
rename from ubi-utils/src/dictionary.c
rename to ubi-utils/dictionary.c
diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/dictionary.h
similarity index 100%
rename from ubi-utils/src/dictionary.h
rename to ubi-utils/dictionary.h
diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/libiniparser.c
similarity index 100%
rename from ubi-utils/src/libiniparser.c
rename to ubi-utils/libiniparser.c
diff --git a/ubi-utils/src/libscan.c b/ubi-utils/libscan.c
similarity index 100%
rename from ubi-utils/src/libscan.c
rename to ubi-utils/libscan.c
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/libubi.c
similarity index 100%
rename from ubi-utils/src/libubi.c
rename to ubi-utils/libubi.c
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/libubi_int.h
similarity index 100%
rename from ubi-utils/src/libubi_int.h
rename to ubi-utils/libubi_int.h
diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/libubigen.c
similarity index 100%
rename from ubi-utils/src/libubigen.c
rename to ubi-utils/libubigen.c
diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/mtdinfo.c
similarity index 100%
rename from ubi-utils/src/mtdinfo.c
rename to ubi-utils/mtdinfo.c
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/ubiattach.c
similarity index 100%
rename from ubi-utils/src/ubiattach.c
rename to ubi-utils/ubiattach.c
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/ubicrc32.c
similarity index 100%
rename from ubi-utils/src/ubicrc32.c
rename to ubi-utils/ubicrc32.c
diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/ubidetach.c
similarity index 100%
rename from ubi-utils/src/ubidetach.c
rename to ubi-utils/ubidetach.c
diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/ubiformat.c
similarity index 100%
rename from ubi-utils/src/ubiformat.c
rename to ubi-utils/ubiformat.c
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/ubimkvol.c
similarity index 100%
rename from ubi-utils/src/ubimkvol.c
rename to ubi-utils/ubimkvol.c
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/ubinfo.c
similarity index 100%
rename from ubi-utils/src/ubinfo.c
rename to ubi-utils/ubinfo.c
diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/ubinize.c
similarity index 100%
rename from ubi-utils/src/ubinize.c
rename to ubi-utils/ubinize.c
diff --git a/ubi-utils/src/ubirename.c b/ubi-utils/ubirename.c
similarity index 100%
rename from ubi-utils/src/ubirename.c
rename to ubi-utils/ubirename.c
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/ubirmvol.c
similarity index 100%
rename from ubi-utils/src/ubirmvol.c
rename to ubi-utils/ubirmvol.c
diff --git a/ubi-utils/src/ubirsvol.c b/ubi-utils/ubirsvol.c
similarity index 100%
rename from ubi-utils/src/ubirsvol.c
rename to ubi-utils/ubirsvol.c
diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/ubiupdatevol.c
similarity index 100%
rename from ubi-utils/src/ubiupdatevol.c
rename to ubi-utils/ubiupdatevol.c
diff --git a/ubi-utils/src/ubiutils-common.c b/ubi-utils/ubiutils-common.c
similarity index 100%
rename from ubi-utils/src/ubiutils-common.c
rename to ubi-utils/ubiutils-common.c
-- 
1.7.5.3



From dedekind1 at gmail.com  Sat Jun 25 02:55:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 09:55:41 +0300
Subject: mtd-utils-1.4.5 is out
Message-ID: <1308984943.23868.4.camel@koala>

Hi, I've just tagged mtd-utils-1.4.5 and uploaded a tarball to the usual
place.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Jun 25 03:03:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 10:03:40 +0300
Subject: [PATCH 0/6] complete nanddump feature-removals
In-Reply-To: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
References: <1308938594-20486-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1308985422.23868.5.camel@koala>

On Fri, 2011-06-24 at 11:03 -0700, Brian Norris wrote:
> Here's my patchset to complete the feature removals and change of
> defaults for nanddump (+ 1 bug fix for integck...). These should
> be pushed after the 1.4.5 release.

Pushed this series, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Jun 25 03:04:48 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 10:04:48 +0300
Subject: [PATCH] build: remove old SYMLINKS variable
In-Reply-To: <1308983401-27015-1-git-send-email-vapier@gentoo.org>
References: <1308983401-27015-1-git-send-email-vapier@gentoo.org>
Message-ID: <1308985492.23868.6.camel@koala>

On Sat, 2011-06-25 at 02:30 -0400, Mike Frysinger wrote:
> This is only used to create symlinks to out of tree files.  I doubt it
> has any relevance anymore now that jffs2 has been merged into mainline.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
>  Makefile |    6 ------
>  1 files changed, 0 insertions(+), 6 deletions(-)

Pushed to mtd-utils.git, thanks!
-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Sat Jun 25 03:13:48 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sat, 25 Jun 2011 10:13:48 +0300
Subject: [PATCH 1/2 v2] rewrite build system to avoid recursion
In-Reply-To: <1308984770-6594-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1308984770-6594-1-git-send-email-vapier@gentoo.org>
Message-ID: <1308986033.23868.8.camel@koala>

On Sat, 2011-06-25 at 02:52 -0400, Mike Frysinger wrote:
> The ubi-utils/src/ subdir is tossed as it just complicates things for no
> real gain.
> 
> The top level clean is replaced with a `find -delete` on objects, so it
> might prune more than necessary, but many projects now do this sort of
> thing and no one complained there.
> 
> A "mkdep" helper generates the actual rule, and the variables are used
> with "foreach" to expand these automatically.
> 
> While we're gutting things, also through in kbuild style output while
> building to make things more legible.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>
> ---
> v2
> 	- use -M when creating patch
> 	- add xprintf to autosize quiet output

Wow, looks great, however, I experience a build error:

[dedekind at koala mtd-utils (master)]$ make clean
[dedekind at koala mtd-utils (master)]$ git clean -f -d
[dedekind at koala mtd-utils (master)]$ make
  CC      ftl_format.o
  CC      lib/libmtd.o
  CC      lib/libmtd_legacy.o
  CC      lib/libcrc32.o
  CC      lib/libfec.o
  AR      lib/libmtd.a
  LD      ftl_format
  CC      flash_erase.o
  LD      flash_erase
  CC      nanddump.o
nanddump.c: In function ?process_options?:
nanddump.c:106:7: warning: variable ?bb_default? set but not used
[-Wunused-but-set-variable]
  LD      nanddump
  CC      doc_loadbios.o
  LD      doc_loadbios
  CC      ftl_check.o
  LD      ftl_check
  CC      mkfs.jffs2.o
  CC      compr_rtime.o
  CC      compr_zlib.o
  CC      compr_lzo.o
  CC      compr.o
  CC      rbtree.o
  LD      mkfs.jffs2
  CC      flash_lock.o
  LD      flash_lock
  CC      flash_unlock.o
  LD      flash_unlock
  CC      flash_info.o
  LD      flash_info
  CC      flash_otp_info.o
  LD      flash_otp_info
  CC      flash_otp_dump.o
  LD      flash_otp_dump
  CC      mtd_debug.o
  LD      mtd_debug
  CC      flashcp.o
flashcp.c: In function ?main?:
flashcp.c:255:2: warning: #warning "Check for smaller erase
regions" [-Wcpp]
  LD      flashcp
  CC      nandwrite.o
  LD      nandwrite
  CC      nandtest.o
  LD      nandtest
  CC      jffs2dump.o
  LD      jffs2dump
  CC      nftldump.o
  LD      nftldump
  CC      nftl_format.o
  LD      nftl_format
  CC      docfdisk.o
docfdisk.c: In function ?main?:
docfdisk.c:269:12: warning: ?ip? may be used uninitialized in this
function [-Wuninitialized]
  LD      docfdisk
  CC      rfddump.o
  LD      rfddump
  CC      rfdformat.o
  LD      rfdformat
  CC      serve_image.o
  LD      serve_image
  CC      recv_image.o
  LD      recv_image
  CC      sumtool.o
  LD      sumtool
  CC      mkfs.ubifs/mkfs.ubifs.o
mkfs.ubifs/mkfs.ubifs.c: In function ?main?:
mkfs.ubifs/ubifs.h:420:2: warning: ?child_cnt? may be used uninitialized
in this function [-Wuninitialized]
mkfs.ubifs/mkfs.ubifs.c:1775:6: note: ?child_cnt? was declared here
  CC      mkfs.ubifs/crc16.o
  CC      mkfs.ubifs/lpt.o
  CC      mkfs.ubifs/compr.o
  CC      mkfs.ubifs/devtable.o
  CC      mkfs.ubifs/hashtable/hashtable.o
  CC      mkfs.ubifs/hashtable/hashtable_itr.o
  CC      ubi-utils/libubi.o
  AR      ubi-utils/libubi.a
  LD      mkfs.ubifs/mkfs.ubifs
  CC      ubi-utils/ubiupdatevol.o
  CC      ubi-utils/ubiutils-common.o
  LD      ubi-utils/ubiupdatevol
  CC      ubi-utils/ubimkvol.o
  LD      ubi-utils/ubimkvol
  CC      ubi-utils/ubirmvol.o
  LD      ubi-utils/ubirmvol
  CC      ubi-utils/ubicrc32.o
  LD      ubi-utils/ubicrc32
  CC      ubi-utils/ubinfo.o
  LD      ubi-utils/ubinfo
  CC      ubi-utils/ubiattach.o
  LD      ubi-utils/ubiattach
  CC      ubi-utils/ubidetach.o
  LD      ubi-utils/ubidetach
  CC      ubi-utils/ubinize.o
In file included from ubi-utils/ubinize.c:38:0:
./ubi-utils/include/libiniparser.h:35:24: fatal error: dictionary.h: No
such file or directory
compilation terminated.
make: *** [/home/dedekind/git/mtd-utils/ubi-utils/ubinize.o] Error 1

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier at gentoo.org  Sat Jun 25 03:48:54 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 03:48:54 -0400
Subject: [PATCH 1/2 v2] rewrite build system to avoid recursion
In-Reply-To: <1308986033.23868.8.camel@koala>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1308984770-6594-1-git-send-email-vapier@gentoo.org>
	<1308986033.23868.8.camel@koala>
Message-ID: <BANLkTinJkfNpJ-13yTwpx9u-FaX1TKScuw@mail.gmail.com>

On Sat, Jun 25, 2011 at 03:13, Artem Bityutskiy wrote:
> ?CC ? ? ?ubi-utils/ubinize.o
> In file included from ubi-utils/ubinize.c:38:0:
> ./ubi-utils/include/libiniparser.h:35:24: fatal error: dictionary.h: No
> such file or directory
> compilation terminated.
> make: *** [/home/dedekind/git/mtd-utils/ubi-utils/ubinize.o] Error 1

weird ... i'm not seeing that.  i'll double check my system in the
morning to see what's going on.
-mike


From leiwen at marvell.com  Sat Jun 25 07:17:46 2011
From: leiwen at marvell.com (Lei Wen)
Date: Sat, 25 Jun 2011 04:17:46 -0700
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <4E031900.50108@compulab.co.il>
References: <4E031900.50108@compulab.co.il>
Message-ID: <1309000666-5242-1-git-send-email-leiwen@marvell.com>

Current pxa3xx_nand controller has two chip select which
both be workable. This patch enable this feature.

Update platform driver to support this feature.

Another notice should be taken that:
When you want to use this feature, you should not enable the
keep configuration feature, for two chip select could be
attached with different nand chip. The different page size
and timing requirement make the keep configuration impossible.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    5 +-
 arch/arm/mach-pxa/cm-x300.c                  |    5 +-
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
 arch/arm/mach-pxa/littleton.c                |    5 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
 arch/arm/mach-pxa/raumfeld.c                 |    5 +-
 arch/arm/mach-pxa/zylonite.c                 |    5 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  512 +++++++++++++++-----------
 9 files changed, 346 insertions(+), 224 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 06b5fa8..c4996f3 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -167,8 +167,9 @@ 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),
+	.num_cs = 1,
+	.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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b2248e7..969d252 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -423,8 +423,9 @@ 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),
+	.num_cs		= 1,
+	.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 3f9be41..2b8ca0d 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -139,8 +139,9 @@ 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),
+	.num_cs		= 1,
+	.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 e5e326d..f6d1f9d 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -325,8 +325,9 @@ 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),
+	.num_cs		= 1,
+	.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 b5a8fd3..90928d6 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,10 +389,11 @@ 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,
+	.num_cs		= 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 d130f77..c7ec847 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -349,8 +349,9 @@ 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),
+	.num_cs		= 1,
+	.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 5821185..64fdac9 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -366,8 +366,9 @@ 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),
+	.num_cs		= 1,
+	.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 442301f..4e17309 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
+/*
+ * Current pxa3xx_nand controller has two chip select which
+ * both be workable.
+ *
+ * Notice should be taken that:
+ * When you want to use this feature, you should not enable the
+ * keep configuration feature, for two chip select could be
+ * attached with different nand chip. The different page size
+ * and timing requirement make the keep configuration impossible.
+ */
+
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {
 
 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +65,10 @@ 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;
+	/* indicate how many chip selects will be used */
+	int	num_cs;
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];
 
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index b7db1b2..0825b7d 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -110,6 +110,7 @@ enum {
 
 enum {
 	STATE_IDLE = 0,
+	STATE_PREPARED,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
@@ -120,21 +121,40 @@ enum {
 	STATE_READY,
 };
 
-struct pxa3xx_nand_info {
-	struct nand_chip	nand_chip;
+struct pxa3xx_nand_host {
+	struct nand_chip	chip;
+	struct pxa3xx_nand_cmdset *cmdset;
+	struct mtd_info         *mtd;
+	void			*info_data;
 
+	/* page size of attached chip */
+	unsigned int		page_size;
+	int			cs;
+	int			use_ecc;
+
+	/* calculated from pxa3xx_nand_flash data */
+	unsigned int		col_addr_cycles;
+	unsigned int		row_addr_cycles;
+	size_t			read_id_bytes;
+
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+};
+
+struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
-	struct pxa3xx_nand_cmdset *cmdset;
 
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
+	struct completion	cmd_complete;
 
 	unsigned int 		buf_start;
 	unsigned int		buf_count;
 
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -142,44 +162,27 @@ struct pxa3xx_nand_info {
 	unsigned char		*data_buff;
 	unsigned char		*oob_buff;
 	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;
 
-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
-
+	struct pxa3xx_nand_host	*host[NUM_CHIP_SELECT];
 	/* relate to the command */
 	unsigned int		state;
 
+	int			cs;
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
 	int			is_ready;
 
-	unsigned int		page_size;	/* page size of attached chip */
 	unsigned int		data_size;	/* data size in FIFO */
+	unsigned int		oob_size;
 	int 			retcode;
-	struct completion 	cmd_complete;
 
 	/* generated NDCBx register values */
 	uint32_t		ndcb0;
 	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;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };
 
 static int use_dma = 1;
@@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
-const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+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)
@@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 
-static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
+static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 				   const struct pxa3xx_nand_timing *t)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	unsigned long nand_clk = clk_get_rate(info->clk);
 	uint32_t ndtr0, ndtr1;
 
@@ -258,23 +262,24 @@ 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;
+	host->ndtr0cs0 = ndtr0;
+	host->ndtr1cs0 = ndtr1;
 	nand_writel(info, NDTR0CS0, ndtr0);
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
 
-	info->data_size = info->page_size;
+	info->data_size = host->page_size;
 	if (!oob_enable) {
 		info->oob_size = 0;
 		return;
 	}
 
-	switch (info->page_size) {
+	switch (host->page_size) {
 	case 2048:
 		info->oob_size = (info->use_ecc) ? 40 : 64;
 		break;
@@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
  */
 static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr;
 
-	ndcr = info->reg_ndcr;
+	ndcr = host->reg_ndcr;
 	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
 	ndcr |= NDCR_ND_RUN;
@@ -359,8 +365,8 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
 					DIV_ROUND_UP(info->oob_size, 4));
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
-				info->state);
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
+			info->state);
 		BUG();
 	}
 }
@@ -385,7 +391,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
 				info->state);
 		BUG();
 	}
@@ -416,9 +422,17 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
 	unsigned int status, is_completed = 0;
+	unsigned int ready, cmd_done;
+
+	if (info->cs == 0) {
+		ready           = NDSR_FLASH_RDY;
+		cmd_done        = NDSR_CS0_CMDD;
+	} else {
+		ready           = NDSR_RDY;
+		cmd_done        = NDSR_CS1_CMDD;
+	}
 
 	status = nand_readl(info, NDSR);
-
 	if (status & NDSR_DBERR)
 		info->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
@@ -437,11 +451,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 			handle_data_pio(info);
 		}
 	}
-	if (status & NDSR_CS0_CMDD) {
+	if (status & cmd_done) {
 		info->state = STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY) {
+	if (status & ready) {
 		info->is_ready = 1;
 		info->state = STATE_READY;
 	}
@@ -463,12 +477,6 @@ 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--)
@@ -481,10 +489,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
-	int addr_cycle, exec_cmd, ndcb0;
-	struct mtd_info *mtd = info->mtd;
+	int addr_cycle, exec_cmd;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	struct mtd_info *mtd = host->mtd;
 
-	ndcb0 = 0;
 	addr_cycle = 0;
 	exec_cmd = 1;
 
@@ -495,6 +503,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	info->use_ecc		= 0;
 	info->is_ready		= 0;
 	info->retcode		= ERR_NONE;
+	if (info->cs != 0)
+		info->ndcb0 = NDCB0_CSEL;
+	else
+		info->ndcb0 = 0;
 
 	switch (command) {
 	case NAND_CMD_READ0:
@@ -512,20 +524,19 @@ 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);
+	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
+				    + host->col_addr_cycles);
 
 	switch (command) {
 	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		cmd = info->cmdset->read1;
+		cmd = host->cmdset->read1;
 		if (command == NAND_CMD_READOOB)
 			info->buf_start = mtd->writesize + column;
 		else
 			info->buf_start = column;
 
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
 			info->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
@@ -537,7 +548,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
 			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 
@@ -564,7 +575,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 			break;
 		}
 
-		cmd = info->cmdset->program;
+		cmd = host->cmdset->program;
 		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
@@ -574,8 +585,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		break;
 
 	case NAND_CMD_READID:
-		cmd = info->cmdset->read_id;
-		info->buf_count = info->read_id_bytes;
+		cmd = host->cmdset->read_id;
+		info->buf_count = host->read_id_bytes;
 		info->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
@@ -583,7 +594,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		info->data_size = 8;
 		break;
 	case NAND_CMD_STATUS:
-		cmd = info->cmdset->read_status;
+		cmd = host->cmdset->read_status;
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
@@ -593,7 +604,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		break;
 
 	case NAND_CMD_ERASE1:
-		cmd = info->cmdset->erase;
+		cmd = host->cmdset->erase;
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
@@ -604,7 +615,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 		break;
 	case NAND_CMD_RESET:
-		cmd = info->cmdset->reset;
+		cmd = host->cmdset->reset;
 		info->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;
 
@@ -616,7 +627,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	default:
 		exec_cmd = 0;
-		printk(KERN_ERR "pxa3xx-nand: non-supported"
+		dev_err(&info->pdev->dev, "pxa3xx-nand: non-supported"
 			" command %x\n", command);
 		break;
 	}
@@ -627,7 +638,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int ret, exec_cmd;
 
 	/*
@@ -635,9 +647,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 	 * "byte" address into a "word" address appropriate
 	 * for indexing a word-oriented device
 	 */
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
 		column /= 2;
 
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, host->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, host->ndtr1cs0);
+	}
+
+	info->state = STATE_PREPARED;
 	exec_cmd = prepare_command_pool(info, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&info->cmd_complete);
@@ -646,12 +670,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		ret = wait_for_completion_timeout(&info->cmd_complete,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
-			printk(KERN_ERR "Wait time out!!!\n");
+			dev_err(&info->pdev->dev, "Wait time out!!!\n");
 			/* Stop State Machine for next command cycle */
 			pxa3xx_nand_stop(info);
 		}
-		info->state = STATE_IDLE;
 	}
+	info->state = STATE_IDLE;
 }
 
 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
@@ -664,7 +688,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	chip->read_buf(mtd, buf, mtd->writesize);
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -695,7 +720,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	char retval = 0xFF;
 
 	if (info->buf_start < info->buf_count)
@@ -707,7 +733,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	u16 retval = 0xFFFF;
 
 	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
@@ -719,7 +746,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(buf, info->data_buff + info->buf_start, real_len);
@@ -729,7 +757,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(info->data_buff + info->buf_start, buf, real_len);
@@ -749,7 +778,8 @@ 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	/* pxa3xx_nand_send_command has waited for command complete */
 	if (this->state == FL_WRITING || this->state == FL_ERASING) {
@@ -772,54 +802,69 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512)
+	if (f->page_size != 2048 && f->page_size != 512) {
+		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
 		return -EINVAL;
+	}
 
-	if (f->flash_width != 16 && f->flash_width != 8)
+	if (f->flash_width != 16 && f->flash_width != 8) {
+		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
 		return -EINVAL;
+	}
 
 	/* calculate flash information */
-	info->cmdset = &default_cmdset;
-	info->page_size = f->page_size;
-	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+	host->cmdset = &default_cmdset;
+	host->page_size = f->page_size;
+	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
 	/* calculate addressing information */
-	info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
 
 	if (f->num_blocks * f->page_per_block > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
+		host->row_addr_cycles = 2;
 
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
 	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
 	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
 	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
 
-	ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
-	info->reg_ndcr = ndcr;
+	host->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(info, f->timing);
+	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
+	/*
+	 * We set 0 by hard coding here, for we don't support keep_config
+	 * when there is more than one chip attached to the controller
+	 */
+	struct pxa3xx_nand_host *host = info->host[0];
 	uint32_t ndcr = nand_readl(info, NDCR);
-	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* set info fields needed to read id */
-	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
-	info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
-	info->cmdset = &default_cmdset;
 
-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	if (ndcr & NDCR_PAGE_SZ) {
+		host->page_size = 2048;
+		host->read_id_bytes = 4;
+	} else {
+		host->page_size = 512;
+		host->read_id_bytes = 2;
+	}
+	host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+	host->cmdset = &default_cmdset;
+
+	host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+	host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
 	return 0;
 }
@@ -829,59 +874,41 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
  * data buffer and the DMA descriptor
  */
 #define MAX_BUFF_SIZE	PAGE_SIZE
-
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
-	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;
+	struct pxa3xx_nand_host *host;
+	struct mtd_info *mtd;
 
-	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;
-	}
+	if (!info->host[cs])
+		return;
 
-	return 0;
+	host = info->host[cs];
+	mtd = host->mtd;
+	kfree(mtd);
+	info->host[cs] = NULL;
 }
 
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct mtd_info *mtd = info->mtd;
-	struct nand_chip *chip = mtd->priv;
+	struct mtd_info *mtd = info->host[info->cs]->mtd;
+	int ret;
 
 	/* 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);
+	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	if (ret)
+		return ret;
+
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	if (info->is_ready)
-		return 1;
-	else
 		return 0;
+
+	return -ENODEV;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
@@ -891,26 +918,26 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret, num;
 
+	info->cs = host->cs;
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
 	ret = pxa3xx_nand_sensing(info);
-	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+	if (ret) {
+		free_cs_resource(info, info->cs);
+		dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n");
 
-		return -EINVAL;
+		return ret;
 	}
 
 	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);
+		dev_info(&info->pdev->dev, "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");
+		free_cs_resource(info, info->cs);
+		dev_warn(&info->pdev->dev, "Read out ID 0, "
+			 "potential timing set wrong!!\n");
 
 		return -EINVAL;
 	}
@@ -928,14 +955,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	}
 
 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+		free_cs_resource(info, info->cs);
+		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
 
 		return -EINVAL;
 	}
 
-	pxa3xx_nand_config_flash(info, f);
+	ret = pxa3xx_nand_config_flash(info, f);
+	if (ret) {
+		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
+		return ret;
+	}
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -950,66 +980,51 @@ KEEP_CONFIG:
 	if (nand_scan_ident(mtd, 1, def))
 		return -ENODEV;
 	/* calculate addressing information */
-	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	if (mtd->writesize >= 2048)
+		host->col_addr_cycles = 2;
+	else
+		host->col_addr_cycles = 1;
 	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
+		host->row_addr_cycles = 2;
+	mtd->name = mtd_names[info->cs];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = info->page_size;
+	chip->ecc.size = host->page_size;
 
-	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
+	chip->options = 0;
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
+		chip->options = NAND_BUSWIDTH_16;
 	chip->options |= NAND_NO_AUTOINCR;
 	chip->options |= NAND_NO_READRDY;
 
 	return nand_scan_tail(mtd);
 }
 
-static
-struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
+	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	struct pxa3xx_nand_host *host;
 	struct nand_chip *chip;
 	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) {
+	pdata = pdev->dev.platform_data;
+	info = kzalloc(sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
+	if (!info) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return NULL;
+		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->controller        = &info->controller;
-	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;
-
-	spin_lock_init(&chip->controller->lock);
-	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
 		ret = PTR_ERR(info->clk);
-		goto fail_free_mtd;
+		goto fail_alloc;
 	}
 	clk_enable(info->clk);
 
@@ -1058,10 +1073,6 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 	}
 	info->mmio_phys = r->start;
 
-	ret = pxa3xx_nand_init_buff(info);
-	if (ret)
-		goto fail_free_io;
-
 	/* initialize all interrupts to be disabled */
 	disable_int(info, NDSR_MASK);
 
@@ -1069,21 +1080,80 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 			  pdev->name, info);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
-		goto fail_free_buf;
+		ret = ENXIO;
+		goto fail_free_io;
 	}
 
 	platform_set_drvdata(pdev, info);
 
-	return info;
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		mtd = kzalloc(sizeof(struct mtd_info)
+				+ sizeof(struct pxa3xx_nand_host),
+				GFP_KERNEL);
+		if (!mtd) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			ret = -ENOMEM;
+			goto fail_free_irq;
+		}
+
+		host = (struct pxa3xx_nand_host *)(&mtd[1]);
+		host->info_data = info;
+		host->cs = cs;
+		host->mtd = mtd;
+		mtd->priv = host;
+		mtd->owner = THIS_MODULE;
+		info->host[cs] = host;
+
+		chip = (struct nand_chip *)(&mtd[1]);
+		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;
+	}
+
+	if (use_dma == 0) {
+		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (info->data_buff == NULL) {
+			ret = -ENOMEM;
+			goto fail_free_buf;
+		}
+		goto success_exit;
+	}
+
+	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, info);
+	if (info->data_dma_ch < 0) {
+		dev_err(&pdev->dev, "failed to request data dma\n");
+		ret = -ENXIO;
+		goto fail_free_dma_buf;
+	}
+success_exit:
+	return 0;
 
+fail_free_dma_buf:
+	dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
+			info->data_buff, info->data_buff_phys);
 fail_free_buf:
+	for (cs = 0; cs < pdata->num_cs; cs++)
+		free_cs_resource(info, cs);
+fail_free_irq:
 	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);
 fail_free_res:
@@ -1091,18 +1161,20 @@ fail_free_res:
 fail_put_clk:
 	clk_disable(info->clk);
 	clk_put(info->clk);
-fail_free_mtd:
-	kfree(mtd);
-	return NULL;
+fail_alloc:
+	kfree(info);
+	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_platform_data *pdata;
+	struct pxa3xx_nand_host *host;
 	struct resource *r;
-	int irq;
+	int irq, cs;
 
+	pdata = pdev->dev.platform_data;
 	platform_set_drvdata(pdev, NULL);
 
 	irq = platform_get_irq(pdev, 0);
@@ -1110,7 +1182,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 		free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, info->data_buff_size,
+		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
 				info->data_buff, info->data_buff_phys);
 	} else
 		kfree(info->data_buff);
@@ -1122,9 +1194,12 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	clk_disable(info->clk);
 	clk_put(info->clk);
 
-	if (mtd) {
-		nand_release(mtd);
-		kfree(mtd);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		host = info->host[cs];
+		if (!host)
+			continue;
+		nand_release(host->mtd);
+		free_cs_resource(info, cs);
 	}
 	return 0;
 }
@@ -1133,6 +1208,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	int cs, ret, probe_success = 0;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1140,18 +1216,38 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	info = alloc_nand_resource(pdev);
-	if (info == NULL)
-		return -ENOMEM;
+	if (pdata->keep_config && pdata->num_cs > 1) {
+		dev_warn(&pdev->dev, "keep_config is prohibited with multiple"
+			 " chip selects feature!\n");
+		pdata->keep_config = 0;
+	}
+
+	ret = alloc_nand_resource(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "alloc nand resource failed\n");
+		return ret;
+	}
+
+	info = platform_get_drvdata(pdev);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		ret = pxa3xx_nand_scan(info->host[cs]->mtd);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to scan nand\n");
+			continue;
+		}
+
+		ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
+			pdata->parts[cs], pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
+	}
 
-	if (pxa3xx_nand_scan(info->mtd)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
+	if (!probe_success) {
 		pxa3xx_nand_remove(pdev);
 		return -ENODEV;
 	}
 
-	return mtd_device_parse_register(info->mtd, NULL, 0,
-			pdata->parts, pdata->nr_parts);
+	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1171,8 +1267,12 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
 
-	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+	/*
+	 * Directly set the chip select to a invalid value,
+	 * then the driver would reset the timing according
+	 * to current chip select at the beginning of cmdfunc
+	 */
+	info->cs = 0xff;
 	clk_enable(info->clk);
 
 	return 0;
-- 
1.7.0.4



From gilles.ganault at free.fr  Sat Jun 25 07:34:41 2011
From: gilles.ganault at free.fr (Gilles)
Date: Sat, 25 Jun 2011 13:34:41 +0200
Subject: [Ubifs] Reboot -> "recovery needed"?
Message-ID: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>

Hello

	The root filesystem lives in a partition on a NAND, and I noticed
that after running "reboot", at the next boot, I get this message:

===============
...
UBIFS: recovery needed
UBIFS: recovery completed
UBIFS: mounted UBI device 0, volume 0, name "rootfs"
UBIFS: file system size:   251596800 bytes (245700 KiB, 239 MiB, 1950
LEBs)
UBIFS: journal size:       9033728 bytes (8822 KiB, 8 MiB, 71 LEBs)
UBIFS: media format:       w4/r0 (latest is w4/r0)
UBIFS: default compressor: lzo
UBIFS: reserved for root:  0 bytes (0 KiB)
VFS: Mounted root (ubifs filesystem) on device 0:10.
===============

Is this the way Ubifs works, or should I run a command prior to
"reboot"?

Thank you.



From zonque at gmail.com  Sat Jun 25 07:48:56 2011
From: zonque at gmail.com (Daniel Mack)
Date: Sat, 25 Jun 2011 13:48:56 +0200
Subject: [PATCH 2/2] MTD: pxa3xx_nand: Fix blank page ECC mismatch
In-Reply-To: <BANLkTin_Z8ndAjp9vw6QcNb5bT82uoR9ng@mail.gmail.com>
References: <1307440867-18993-1-git-send-email-leiwen@marvell.com>
	<1307440867-18993-2-git-send-email-leiwen@marvell.com>
	<1307445467.11104.80.camel@localhost>
	<BANLkTin_Z8ndAjp9vw6QcNb5bT82uoR9ng@mail.gmail.com>
Message-ID: <BANLkTi=7f2+LK32p6WG1doXzYWGf1wJQJQ@mail.gmail.com>

On Tue, Jun 7, 2011 at 2:28 PM, Lei Wen <adrian.wenl at gmail.com> wrote:
> On Tue, Jun 7, 2011 at 7:17 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
>> On Tue, 2011-06-07 at 03:01 -0700, Lei Wen wrote:
>>> From: Daniel Mack <zonque at gmail.com>
>>>
>>> This bug was introduced in f8155a40 ("mtd: pxa3xx_nand: rework irq
>>> logic") and causes the PXA3xx NAND controller fail to operate with NAND
>>> flash that has empty pages. According to the comment in this block, the
>>> hardware controller will report a double-bit error for empty pages,
>>> which can and must be ignored.
>>>
>>> This patch restores the original behaviour of the driver.
>>>
>>> Signed-off-by: Daniel Mack <zonque at gmail.com>
>>> Acked-by: Lei Wen <leiwen at marvell.com>
>>> Cc: Haojian Zhuang <haojian.zhuang at marvell.com>
>>> Cc: David Woodhouse <David.Woodhouse at intel.com>
>>> Cc: stable at kernel.org
>>
>> This was introduced in 2.6.38, so let's make it:
>>
>> Cc: stable at kernel.org [2.6.38+]
>>
> Thanks for correcting this.

Has anyone queued this for 3.0 yet? This fixes a serious regression,
so we need this merged, along with Lei's other patch titled "MTD:
pxa3xx_nand: fix nand detection issue".


Thanks,
Daniel


From zonque at gmail.com  Sat Jun 25 08:32:17 2011
From: zonque at gmail.com (Daniel Mack)
Date: Sat, 25 Jun 2011 14:32:17 +0200
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309000666-5242-1-git-send-email-leiwen@marvell.com>
References: <4E031900.50108@compulab.co.il>
	<1309000666-5242-1-git-send-email-leiwen@marvell.com>
Message-ID: <BANLkTimY2+qV_A7gSWOjAk0f54zKRC2wCg@mail.gmail.com>

On Sat, Jun 25, 2011 at 1:17 PM, Lei Wen <leiwen at marvell.com> wrote:
> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
>
> Update platform driver to support this feature.
>
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>

I tested this on a PXA303 platform with one chipselect only, at at
least I can say that this patch doesn't seem to cause any regression
here. But I couldn't test the new feature it adds.

So, FWIW:

Tested-by: Daniel Mack <zonque at gmail.com>


Thanks!
Daniel


> ---
> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 19 +-
> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?512 +++++++++++++++-----------
> ?9 files changed, 346 insertions(+), 224 deletions(-)
>
> diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
> index 06b5fa8..c4996f3 100644
> --- a/arch/arm/mach-mmp/aspenite.c
> +++ b/arch/arm/mach-mmp/aspenite.c
> @@ -167,8 +167,9 @@ 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),
> + ? ? ? .num_cs = 1,
> + ? ? ? .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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
> index b2248e7..969d252 100644
> --- a/arch/arm/mach-pxa/cm-x300.c
> +++ b/arch/arm/mach-pxa/cm-x300.c
> @@ -423,8 +423,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 3f9be41..2b8ca0d 100644
> --- a/arch/arm/mach-pxa/colibri-pxa3xx.c
> +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
> @@ -139,8 +139,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 e5e326d..f6d1f9d 100644
> --- a/arch/arm/mach-pxa/littleton.c
> +++ b/arch/arm/mach-pxa/littleton.c
> @@ -325,8 +325,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 b5a8fd3..90928d6 100644
> --- a/arch/arm/mach-pxa/mxm8x10.c
> +++ b/arch/arm/mach-pxa/mxm8x10.c
> @@ -389,10 +389,11 @@ 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,
> + ? ? ? .num_cs ? ? ? ? = 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 d130f77..c7ec847 100644
> --- a/arch/arm/mach-pxa/raumfeld.c
> +++ b/arch/arm/mach-pxa/raumfeld.c
> @@ -349,8 +349,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 5821185..64fdac9 100644
> --- a/arch/arm/mach-pxa/zylonite.c
> +++ b/arch/arm/mach-pxa/zylonite.c
> @@ -366,8 +366,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 442301f..4e17309 100644
> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> @@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
> ? ? ? ?struct pxa3xx_nand_timing *timing; ? ? ?/* NAND Flash timing */
> ?};
>
> +/*
> + * Current pxa3xx_nand controller has two chip select which
> + * both be workable.
> + *
> + * Notice should be taken that:
> + * When you want to use this feature, you should not enable the
> + * keep configuration feature, for two chip select could be
> + * attached with different nand chip. The different page size
> + * and timing requirement make the keep configuration impossible.
> + */
> +
> +/* The max num of chip select current support */
> +#define NUM_CHIP_SELECT ? ? ? ? ? ? ? ?(2)
> ?struct pxa3xx_nand_platform_data {
>
> ? ? ? ?/* the data flash bus is shared between the Static Memory
> @@ -52,8 +65,10 @@ 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;
> + ? ? ? /* indicate how many chip selects will be used */
> + ? ? ? int ? ? num_cs;
> + ? ? ? const struct mtd_partition ? ? ? ? ? ? ?*parts[NUM_CHIP_SELECT];
> + ? ? ? unsigned int ? ? ? ? ? ? ? ? ? ? ? ? ? ?nr_parts[NUM_CHIP_SELECT];
>
> ? ? ? ?const struct pxa3xx_nand_flash * ? ? ? ?flash;
> ? ? ? ?size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash;
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index b7db1b2..0825b7d 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -110,6 +110,7 @@ enum {
>
> ?enum {
> ? ? ? ?STATE_IDLE = 0,
> + ? ? ? STATE_PREPARED,
> ? ? ? ?STATE_CMD_HANDLE,
> ? ? ? ?STATE_DMA_READING,
> ? ? ? ?STATE_DMA_WRITING,
> @@ -120,21 +121,40 @@ enum {
> ? ? ? ?STATE_READY,
> ?};
>
> -struct pxa3xx_nand_info {
> - ? ? ? struct nand_chip ? ? ? ?nand_chip;
> +struct pxa3xx_nand_host {
> + ? ? ? struct nand_chip ? ? ? ?chip;
> + ? ? ? struct pxa3xx_nand_cmdset *cmdset;
> + ? ? ? struct mtd_info ? ? ? ? *mtd;
> + ? ? ? void ? ? ? ? ? ? ? ? ? ?*info_data;
>
> + ? ? ? /* page size of attached chip */
> + ? ? ? unsigned int ? ? ? ? ? ?page_size;
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? cs;
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? use_ecc;
> +
> + ? ? ? /* calculated from pxa3xx_nand_flash data */
> + ? ? ? unsigned int ? ? ? ? ? ?col_addr_cycles;
> + ? ? ? unsigned int ? ? ? ? ? ?row_addr_cycles;
> + ? ? ? size_t ? ? ? ? ? ? ? ? ?read_id_bytes;
> +
> + ? ? ? /* cached register value */
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr0cs0;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr1cs0;
> +};
> +
> +struct pxa3xx_nand_info {
> ? ? ? ?struct nand_hw_control ?controller;
> ? ? ? ?struct platform_device ? *pdev;
> - ? ? ? struct pxa3xx_nand_cmdset *cmdset;
>
> ? ? ? ?struct clk ? ? ? ? ? ? ?*clk;
> ? ? ? ?void __iomem ? ? ? ? ? ?*mmio_base;
> ? ? ? ?unsigned long ? ? ? ? ? mmio_phys;
> + ? ? ? struct completion ? ? ? cmd_complete;
>
> ? ? ? ?unsigned int ? ? ? ? ? ?buf_start;
> ? ? ? ?unsigned int ? ? ? ? ? ?buf_count;
>
> - ? ? ? struct mtd_info ? ? ? ? *mtd;
> ? ? ? ?/* DMA information */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_dat;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_cmd;
> @@ -142,44 +162,27 @@ struct pxa3xx_nand_info {
> ? ? ? ?unsigned char ? ? ? ? ? *data_buff;
> ? ? ? ?unsigned char ? ? ? ? ? *oob_buff;
> ? ? ? ?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;
>
> - ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
> -
> - ? ? ? /* saved column/page_addr during CMD_SEQIN */
> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_column;
> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_page_addr;
> -
> + ? ? ? struct pxa3xx_nand_host *host[NUM_CHIP_SELECT];
> ? ? ? ?/* relate to the command */
> ? ? ? ?unsigned int ? ? ? ? ? ?state;
>
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? cs;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_ecc; ? ? ? ?/* use HW ECC ? */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_dma; ? ? ? ?/* use DMA ? */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? is_ready;
>
> - ? ? ? unsigned int ? ? ? ? ? ?page_size; ? ? ?/* page size of attached chip */
> ? ? ? ?unsigned int ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
> + ? ? ? unsigned int ? ? ? ? ? ?oob_size;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? retcode;
> - ? ? ? struct completion ? ? ? cmd_complete;
>
> ? ? ? ?/* generated NDCBx register values */
> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?ndcb0;
> ? ? ? ?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;
> -
> - ? ? ? unsigned int ? ?col_addr_cycles;
> - ? ? ? unsigned int ? ?row_addr_cycles;
> ?};
>
> ?static int use_dma = 1;
> @@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
> ?/* Define a default flash type setting serve as flash detecting only */
> ?#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
>
> -const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> +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)
> @@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> ?/* convert nano-seconds to nand flash controller clock cycles */
> ?#define ns2cycle(ns, clk) ? ? ?(int)((ns) * (clk / 1000000) / 1000)
>
> -static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
> +static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const struct pxa3xx_nand_timing *t)
> ?{
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?unsigned long nand_clk = clk_get_rate(info->clk);
> ? ? ? ?uint32_t ndtr0, ndtr1;
>
> @@ -258,23 +262,24 @@ 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;
> + ? ? ? host->ndtr0cs0 = ndtr0;
> + ? ? ? host->ndtr1cs0 = ndtr1;
> ? ? ? ?nand_writel(info, NDTR0CS0, ndtr0);
> ? ? ? ?nand_writel(info, NDTR1CS0, ndtr1);
> ?}
>
> ?static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> + ? ? ? int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
>
> - ? ? ? info->data_size = info->page_size;
> + ? ? ? info->data_size = host->page_size;
> ? ? ? ?if (!oob_enable) {
> ? ? ? ? ? ? ? ?info->oob_size = 0;
> ? ? ? ? ? ? ? ?return;
> ? ? ? ?}
>
> - ? ? ? switch (info->page_size) {
> + ? ? ? switch (host->page_size) {
> ? ? ? ?case 2048:
> ? ? ? ? ? ? ? ?info->oob_size = (info->use_ecc) ? 40 : 64;
> ? ? ? ? ? ? ? ?break;
> @@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
> ?*/
> ?static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
> ?{
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> ? ? ? ?uint32_t ndcr;
>
> - ? ? ? ndcr = info->reg_ndcr;
> + ? ? ? ndcr = host->reg_ndcr;
> ? ? ? ?ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
> ? ? ? ?ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
> ? ? ? ?ndcr |= NDCR_ND_RUN;
> @@ -359,8 +365,8 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->oob_size, 4));
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> - ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
> + ? ? ? ? ? ? ? ? ? ? ? info->state);
> ? ? ? ? ? ? ? ?BUG();
> ? ? ? ?}
> ?}
> @@ -385,7 +391,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
> ? ? ? ? ? ? ? ?desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> - ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->state);
> ? ? ? ? ? ? ? ?BUG();
> ? ? ? ?}
> @@ -416,9 +422,17 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = devid;
> ? ? ? ?unsigned int status, is_completed = 0;
> + ? ? ? unsigned int ready, cmd_done;
> +
> + ? ? ? if (info->cs == 0) {
> + ? ? ? ? ? ? ? ready ? ? ? ? ? = NDSR_FLASH_RDY;
> + ? ? ? ? ? ? ? cmd_done ? ? ? ?= NDSR_CS0_CMDD;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? ready ? ? ? ? ? = NDSR_RDY;
> + ? ? ? ? ? ? ? cmd_done ? ? ? ?= NDSR_CS1_CMDD;
> + ? ? ? }
>
> ? ? ? ?status = nand_readl(info, NDSR);
> -
> ? ? ? ?if (status & NDSR_DBERR)
> ? ? ? ? ? ? ? ?info->retcode = ERR_DBERR;
> ? ? ? ?if (status & NDSR_SBERR)
> @@ -437,11 +451,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
> ? ? ? ? ? ? ? ? ? ? ? ?handle_data_pio(info);
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}
> - ? ? ? if (status & NDSR_CS0_CMDD) {
> + ? ? ? if (status & cmd_done) {
> ? ? ? ? ? ? ? ?info->state = STATE_CMD_DONE;
> ? ? ? ? ? ? ? ?is_completed = 1;
> ? ? ? ?}
> - ? ? ? if (status & NDSR_FLASH_RDY) {
> + ? ? ? if (status & ready) {
> ? ? ? ? ? ? ? ?info->is_ready = 1;
> ? ? ? ? ? ? ? ?info->state = STATE_READY;
> ? ? ? ?}
> @@ -463,12 +477,6 @@ 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--)
> @@ -481,10 +489,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?uint16_t column, int page_addr)
> ?{
> ? ? ? ?uint16_t cmd;
> - ? ? ? int addr_cycle, exec_cmd, ndcb0;
> - ? ? ? struct mtd_info *mtd = info->mtd;
> + ? ? ? int addr_cycle, exec_cmd;
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> + ? ? ? struct mtd_info *mtd = host->mtd;
>
> - ? ? ? ndcb0 = 0;
> ? ? ? ?addr_cycle = 0;
> ? ? ? ?exec_cmd = 1;
>
> @@ -495,6 +503,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ?info->use_ecc ? ? ? ? ? = 0;
> ? ? ? ?info->is_ready ? ? ? ? ?= 0;
> ? ? ? ?info->retcode ? ? ? ? ? = ERR_NONE;
> + ? ? ? if (info->cs != 0)
> + ? ? ? ? ? ? ? info->ndcb0 = NDCB0_CSEL;
> + ? ? ? else
> + ? ? ? ? ? ? ? info->ndcb0 = 0;
>
> ? ? ? ?switch (command) {
> ? ? ? ?case NAND_CMD_READ0:
> @@ -512,20 +524,19 @@ 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);
> + ? ? ? addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + host->col_addr_cycles);
>
> ? ? ? ?switch (command) {
> ? ? ? ?case NAND_CMD_READOOB:
> ? ? ? ?case NAND_CMD_READ0:
> - ? ? ? ? ? ? ? cmd = info->cmdset->read1;
> + ? ? ? ? ? ? ? cmd = host->cmdset->read1;
> ? ? ? ? ? ? ? ?if (command == NAND_CMD_READOOB)
> ? ? ? ? ? ? ? ? ? ? ? ?info->buf_start = mtd->writesize + column;
> ? ? ? ? ? ? ? ?else
> ? ? ? ? ? ? ? ? ? ? ? ?info->buf_start = column;
>
> - ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
> + ? ? ? ? ? ? ? if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
> ? ? ? ? ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(0)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| addr_cycle
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (cmd & NDCB0_CMD1_MASK);
> @@ -537,7 +548,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ?case NAND_CMD_SEQIN:
> ? ? ? ? ? ? ? ?/* small page addr setting */
> - ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
> + ? ? ? ? ? ? ? if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
> ? ? ? ? ? ? ? ? ? ? ? ?info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (column & 0xFF);
>
> @@ -564,7 +575,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
>
> - ? ? ? ? ? ? ? cmd = info->cmdset->program;
> + ? ? ? ? ? ? ? cmd = host->cmdset->program;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ST_ROW_EN
> @@ -574,8 +585,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_READID:
> - ? ? ? ? ? ? ? cmd = info->cmdset->read_id;
> - ? ? ? ? ? ? ? info->buf_count = info->read_id_bytes;
> + ? ? ? ? ? ? ? cmd = host->cmdset->read_id;
> + ? ? ? ? ? ? ? info->buf_count = host->read_id_bytes;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(3)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
> @@ -583,7 +594,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?info->data_size = 8;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_STATUS:
> - ? ? ? ? ? ? ? cmd = info->cmdset->read_status;
> + ? ? ? ? ? ? ? cmd = host->cmdset->read_status;
> ? ? ? ? ? ? ? ?info->buf_count = 1;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(4)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
> @@ -593,7 +604,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_ERASE1:
> - ? ? ? ? ? ? ? cmd = info->cmdset->erase;
> + ? ? ? ? ? ? ? cmd = host->cmdset->erase;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(2)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(3)
> @@ -604,7 +615,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_RESET:
> - ? ? ? ? ? ? ? cmd = info->cmdset->reset;
> + ? ? ? ? ? ? ? cmd = host->cmdset->reset;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(5)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>
> @@ -616,7 +627,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?exec_cmd = 0;
> - ? ? ? ? ? ? ? printk(KERN_ERR "pxa3xx-nand: non-supported"
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "pxa3xx-nand: non-supported"
> ? ? ? ? ? ? ? ? ? ? ? ?" command %x\n", command);
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
> @@ -627,7 +638,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ?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_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?int ret, exec_cmd;
>
> ? ? ? ?/*
> @@ -635,9 +647,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> ? ? ? ? * "byte" address into a "word" address appropriate
> ? ? ? ? * for indexing a word-oriented device
> ? ? ? ? */
> - ? ? ? if (info->reg_ndcr & NDCR_DWIDTH_M)
> + ? ? ? if (host->reg_ndcr & NDCR_DWIDTH_M)
> ? ? ? ? ? ? ? ?column /= 2;
>
> + ? ? ? /*
> + ? ? ? ?* There may be different NAND chip hooked to
> + ? ? ? ?* different chip select, so check whether
> + ? ? ? ?* chip select has been changed, if yes, reset the timing
> + ? ? ? ?*/
> + ? ? ? if (info->cs != host->cs) {
> + ? ? ? ? ? ? ? info->cs = host->cs;
> + ? ? ? ? ? ? ? nand_writel(info, NDTR0CS0, host->ndtr0cs0);
> + ? ? ? ? ? ? ? nand_writel(info, NDTR1CS0, host->ndtr1cs0);
> + ? ? ? }
> +
> + ? ? ? info->state = STATE_PREPARED;
> ? ? ? ?exec_cmd = prepare_command_pool(info, command, column, page_addr);
> ? ? ? ?if (exec_cmd) {
> ? ? ? ? ? ? ? ?init_completion(&info->cmd_complete);
> @@ -646,12 +670,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> ? ? ? ? ? ? ? ?ret = wait_for_completion_timeout(&info->cmd_complete,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CHIP_DELAY_TIMEOUT);
> ? ? ? ? ? ? ? ?if (!ret) {
> - ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "Wait time out!!!\n");
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "Wait time out!!!\n");
> ? ? ? ? ? ? ? ? ? ? ? ?/* Stop State Machine for next command cycle */
> ? ? ? ? ? ? ? ? ? ? ? ?pxa3xx_nand_stop(info);
> ? ? ? ? ? ? ? ?}
> - ? ? ? ? ? ? ? info->state = STATE_IDLE;
> ? ? ? ?}
> + ? ? ? info->state = STATE_IDLE;
> ?}
>
> ?static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> @@ -664,7 +688,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> ?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_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
>
> ? ? ? ?chip->read_buf(mtd, buf, mtd->writesize);
> ? ? ? ?chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
> @@ -695,7 +720,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>
> ?static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?char retval = 0xFF;
>
> ? ? ? ?if (info->buf_start < info->buf_count)
> @@ -707,7 +733,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>
> ?static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?u16 retval = 0xFFFF;
>
> ? ? ? ?if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
> @@ -719,7 +746,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>
> ?static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>
> ? ? ? ?memcpy(buf, info->data_buff + info->buf_start, real_len);
> @@ -729,7 +757,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> ?static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
> ? ? ? ? ? ? ? ?const uint8_t *buf, int len)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>
> ? ? ? ?memcpy(info->data_buff + info->buf_start, buf, real_len);
> @@ -749,7 +778,8 @@ 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_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
>
> ? ? ? ?/* pxa3xx_nand_send_command has waited for command complete */
> ? ? ? ?if (this->state == FL_WRITING || this->state == FL_ERASING) {
> @@ -772,54 +802,69 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
> ?{
> ? ? ? ?struct platform_device *pdev = info->pdev;
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> ? ? ? ?uint32_t ndcr = 0x0; /* enable all interrupts */
>
> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
> + ? ? ? if (f->page_size != 2048 && f->page_size != 512) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
> ? ? ? ? ? ? ? ?return -EINVAL;
> + ? ? ? }
>
> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
> + ? ? ? if (f->flash_width != 16 && f->flash_width != 8) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
> ? ? ? ? ? ? ? ?return -EINVAL;
> + ? ? ? }
>
> ? ? ? ?/* calculate flash information */
> - ? ? ? info->cmdset = &default_cmdset;
> - ? ? ? info->page_size = f->page_size;
> - ? ? ? info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
> + ? ? ? host->cmdset = &default_cmdset;
> + ? ? ? host->page_size = f->page_size;
> + ? ? ? host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
>
> ? ? ? ?/* calculate addressing information */
> - ? ? ? info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
> + ? ? ? host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
>
> ? ? ? ?if (f->num_blocks * f->page_per_block > 65536)
> - ? ? ? ? ? ? ? info->row_addr_cycles = 3;
> + ? ? ? ? ? ? ? host->row_addr_cycles = 3;
> ? ? ? ?else
> - ? ? ? ? ? ? ? info->row_addr_cycles = 2;
> + ? ? ? ? ? ? ? host->row_addr_cycles = 2;
>
> ? ? ? ?ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
> - ? ? ? ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
> + ? ? ? ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
> ? ? ? ?ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
> ? ? ? ?ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
> ? ? ? ?ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
> ? ? ? ?ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
>
> - ? ? ? ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
> + ? ? ? ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
> ? ? ? ?ndcr |= NDCR_SPARE_EN; /* enable spare by default */
>
> - ? ? ? info->reg_ndcr = ndcr;
> + ? ? ? host->reg_ndcr = ndcr;
>
> - ? ? ? pxa3xx_nand_set_timing(info, f->timing);
> + ? ? ? pxa3xx_nand_set_timing(host, f->timing);
> ? ? ? ?return 0;
> ?}
>
> ?static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ?{
> + ? ? ? /*
> + ? ? ? ?* We set 0 by hard coding here, for we don't support keep_config
> + ? ? ? ?* when there is more than one chip attached to the controller
> + ? ? ? ?*/
> + ? ? ? struct pxa3xx_nand_host *host = info->host[0];
> ? ? ? ?uint32_t ndcr = nand_readl(info, NDCR);
> - ? ? ? info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
> - ? ? ? /* set info fields needed to read id */
> - ? ? ? info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
> - ? ? ? info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
> - ? ? ? info->cmdset = &default_cmdset;
>
> - ? ? ? info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> - ? ? ? info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
> + ? ? ? if (ndcr & NDCR_PAGE_SZ) {
> + ? ? ? ? ? ? ? host->page_size = 2048;
> + ? ? ? ? ? ? ? host->read_id_bytes = 4;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? host->page_size = 512;
> + ? ? ? ? ? ? ? host->read_id_bytes = 2;
> + ? ? ? }
> + ? ? ? host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
> + ? ? ? host->cmdset = &default_cmdset;
> +
> + ? ? ? host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> + ? ? ? host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
>
> ? ? ? ?return 0;
> ?}
> @@ -829,59 +874,41 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ?* data buffer and the DMA descriptor
> ?*/
> ?#define MAX_BUFF_SIZE ?PAGE_SIZE
> -
> -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
> +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
> ?{
> - ? ? ? 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;
> + ? ? ? struct pxa3xx_nand_host *host;
> + ? ? ? struct mtd_info *mtd;
>
> - ? ? ? 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;
> - ? ? ? }
> + ? ? ? if (!info->host[cs])
> + ? ? ? ? ? ? ? return;
>
> - ? ? ? return 0;
> + ? ? ? host = info->host[cs];
> + ? ? ? mtd = host->mtd;
> + ? ? ? kfree(mtd);
> + ? ? ? info->host[cs] = NULL;
> ?}
>
> ?static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? struct mtd_info *mtd = info->mtd;
> - ? ? ? struct nand_chip *chip = mtd->priv;
> + ? ? ? struct mtd_info *mtd = info->host[info->cs]->mtd;
> + ? ? ? int ret;
>
> ? ? ? ?/* 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);
> + ? ? ? ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
> + ? ? ? if (ret)
> + ? ? ? ? ? ? ? return ret;
> +
> + ? ? ? pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
> ? ? ? ?if (info->is_ready)
> - ? ? ? ? ? ? ? return 1;
> - ? ? ? else
> ? ? ? ? ? ? ? ?return 0;
> +
> + ? ? ? return -ENODEV;
> ?}
>
> ?static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?struct platform_device *pdev = info->pdev;
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> ? ? ? ?struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
> @@ -891,26 +918,26 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?uint64_t chipsize;
> ? ? ? ?int i, ret, num;
>
> + ? ? ? info->cs = host->cs;
> ? ? ? ?if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
> ? ? ? ? ? ? ? ?goto KEEP_CONFIG;
>
> ? ? ? ?ret = pxa3xx_nand_sensing(info);
> - ? ? ? if (!ret) {
> - ? ? ? ? ? ? ? kfree(mtd);
> - ? ? ? ? ? ? ? info->mtd = NULL;
> - ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n");
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? free_cs_resource(info, info->cs);
> + ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n");
>
> - ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? ? ? ? ? return ret;
> ? ? ? ?}
>
> ? ? ? ?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);
> + ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "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");
> + ? ? ? ? ? ? ? free_cs_resource(info, info->cs);
> + ? ? ? ? ? ? ? dev_warn(&info->pdev->dev, "Read out ID 0, "
> + ? ? ? ? ? ? ? ? ? ? ? ?"potential timing set wrong!!\n");
>
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
> @@ -928,14 +955,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?}
>
> ? ? ? ?if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
> - ? ? ? ? ? ? ? kfree(mtd);
> - ? ? ? ? ? ? ? info->mtd = NULL;
> - ? ? ? ? ? ? ? printk(KERN_ERR "ERROR!! flash not defined!!!\n");
> + ? ? ? ? ? ? ? free_cs_resource(info, info->cs);
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
>
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
>
> - ? ? ? pxa3xx_nand_config_flash(info, f);
> + ? ? ? ret = pxa3xx_nand_config_flash(info, f);
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
> + ? ? ? ? ? ? ? return ret;
> + ? ? ? }
> ? ? ? ?pxa3xx_flash_ids[0].name = f->name;
> ? ? ? ?pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
> ? ? ? ?pxa3xx_flash_ids[0].pagesize = f->page_size;
> @@ -950,66 +980,51 @@ KEEP_CONFIG:
> ? ? ? ?if (nand_scan_ident(mtd, 1, def))
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?/* calculate addressing information */
> - ? ? ? info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
> + ? ? ? if (mtd->writesize >= 2048)
> + ? ? ? ? ? ? ? host->col_addr_cycles = 2;
> + ? ? ? else
> + ? ? ? ? ? ? ? host->col_addr_cycles = 1;
> ? ? ? ?info->oob_buff = info->data_buff + mtd->writesize;
> ? ? ? ?if ((mtd->size >> chip->page_shift) > 65536)
> - ? ? ? ? ? ? ? info->row_addr_cycles = 3;
> + ? ? ? ? ? ? ? host->row_addr_cycles = 3;
> ? ? ? ?else
> - ? ? ? ? ? ? ? info->row_addr_cycles = 2;
> - ? ? ? mtd->name = mtd_names[0];
> + ? ? ? ? ? ? ? host->row_addr_cycles = 2;
> + ? ? ? mtd->name = mtd_names[info->cs];
> ? ? ? ?chip->ecc.mode = NAND_ECC_HW;
> - ? ? ? chip->ecc.size = info->page_size;
> + ? ? ? chip->ecc.size = host->page_size;
>
> - ? ? ? chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
> + ? ? ? chip->options = 0;
> + ? ? ? if (host->reg_ndcr & NDCR_DWIDTH_M)
> + ? ? ? ? ? ? ? chip->options = NAND_BUSWIDTH_16;
> ? ? ? ?chip->options |= NAND_NO_AUTOINCR;
> ? ? ? ?chip->options |= NAND_NO_READRDY;
>
> ? ? ? ?return nand_scan_tail(mtd);
> ?}
>
> -static
> -struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> +static int alloc_nand_resource(struct platform_device *pdev)
> ?{
> + ? ? ? struct pxa3xx_nand_platform_data *pdata;
> ? ? ? ?struct pxa3xx_nand_info *info;
> + ? ? ? struct pxa3xx_nand_host *host;
> ? ? ? ?struct nand_chip *chip;
> ? ? ? ?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) {
> + ? ? ? pdata = pdev->dev.platform_data;
> + ? ? ? info = kzalloc(sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
> + ? ? ? if (!info) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to allocate memory\n");
> - ? ? ? ? ? ? ? return NULL;
> + ? ? ? ? ? ? ? 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->controller ? ? ? ?= &info->controller;
> - ? ? ? 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;
> -
> - ? ? ? spin_lock_init(&chip->controller->lock);
> - ? ? ? init_waitqueue_head(&chip->controller->wq);
> ? ? ? ?info->clk = clk_get(&pdev->dev, NULL);
> ? ? ? ?if (IS_ERR(info->clk)) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to get nand clock\n");
> ? ? ? ? ? ? ? ?ret = PTR_ERR(info->clk);
> - ? ? ? ? ? ? ? goto fail_free_mtd;
> + ? ? ? ? ? ? ? goto fail_alloc;
> ? ? ? ?}
> ? ? ? ?clk_enable(info->clk);
>
> @@ -1058,10 +1073,6 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> ? ? ? ?}
> ? ? ? ?info->mmio_phys = r->start;
>
> - ? ? ? ret = pxa3xx_nand_init_buff(info);
> - ? ? ? if (ret)
> - ? ? ? ? ? ? ? goto fail_free_io;
> -
> ? ? ? ?/* initialize all interrupts to be disabled */
> ? ? ? ?disable_int(info, NDSR_MASK);
>
> @@ -1069,21 +1080,80 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> ? ? ? ? ? ? ? ? ? ? ? ? ?pdev->name, info);
> ? ? ? ?if (ret < 0) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to request IRQ\n");
> - ? ? ? ? ? ? ? goto fail_free_buf;
> + ? ? ? ? ? ? ? ret = ENXIO;
> + ? ? ? ? ? ? ? goto fail_free_io;
> ? ? ? ?}
>
> ? ? ? ?platform_set_drvdata(pdev, info);
>
> - ? ? ? return info;
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++) {
> + ? ? ? ? ? ? ? mtd = kzalloc(sizeof(struct mtd_info)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + sizeof(struct pxa3xx_nand_host),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GFP_KERNEL);
> + ? ? ? ? ? ? ? if (!mtd) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to allocate memory\n");
> + ? ? ? ? ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? ? ? ? ? goto fail_free_irq;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? host = (struct pxa3xx_nand_host *)(&mtd[1]);
> + ? ? ? ? ? ? ? host->info_data = info;
> + ? ? ? ? ? ? ? host->cs = cs;
> + ? ? ? ? ? ? ? host->mtd = mtd;
> + ? ? ? ? ? ? ? mtd->priv = host;
> + ? ? ? ? ? ? ? mtd->owner = THIS_MODULE;
> + ? ? ? ? ? ? ? info->host[cs] = host;
> +
> + ? ? ? ? ? ? ? chip = (struct nand_chip *)(&mtd[1]);
> + ? ? ? ? ? ? ? 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;
> + ? ? ? }
> +
> + ? ? ? if (use_dma == 0) {
> + ? ? ? ? ? ? ? info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
> + ? ? ? ? ? ? ? if (info->data_buff == NULL) {
> + ? ? ? ? ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? ? ? ? ? goto fail_free_buf;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? goto success_exit;
> + ? ? ? }
> +
> + ? ? ? 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, info);
> + ? ? ? if (info->data_dma_ch < 0) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to request data dma\n");
> + ? ? ? ? ? ? ? ret = -ENXIO;
> + ? ? ? ? ? ? ? goto fail_free_dma_buf;
> + ? ? ? }
> +success_exit:
> + ? ? ? return 0;
>
> +fail_free_dma_buf:
> + ? ? ? dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
> + ? ? ? ? ? ? ? ? ? ? ? info->data_buff, info->data_buff_phys);
> ?fail_free_buf:
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++)
> + ? ? ? ? ? ? ? free_cs_resource(info, cs);
> +fail_free_irq:
> ? ? ? ?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);
> ?fail_free_res:
> @@ -1091,18 +1161,20 @@ fail_free_res:
> ?fail_put_clk:
> ? ? ? ?clk_disable(info->clk);
> ? ? ? ?clk_put(info->clk);
> -fail_free_mtd:
> - ? ? ? kfree(mtd);
> - ? ? ? return NULL;
> +fail_alloc:
> + ? ? ? kfree(info);
> + ? ? ? 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_platform_data *pdata;
> + ? ? ? struct pxa3xx_nand_host *host;
> ? ? ? ?struct resource *r;
> - ? ? ? int irq;
> + ? ? ? int irq, cs;
>
> + ? ? ? pdata = pdev->dev.platform_data;
> ? ? ? ?platform_set_drvdata(pdev, NULL);
>
> ? ? ? ?irq = platform_get_irq(pdev, 0);
> @@ -1110,7 +1182,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
> ? ? ? ? ? ? ? ?free_irq(irq, info);
> ? ? ? ?if (use_dma) {
> ? ? ? ? ? ? ? ?pxa_free_dma(info->data_dma_ch);
> - ? ? ? ? ? ? ? dma_free_writecombine(&pdev->dev, info->data_buff_size,
> + ? ? ? ? ? ? ? dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->data_buff, info->data_buff_phys);
> ? ? ? ?} else
> ? ? ? ? ? ? ? ?kfree(info->data_buff);
> @@ -1122,9 +1194,12 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
> ? ? ? ?clk_disable(info->clk);
> ? ? ? ?clk_put(info->clk);
>
> - ? ? ? if (mtd) {
> - ? ? ? ? ? ? ? nand_release(mtd);
> - ? ? ? ? ? ? ? kfree(mtd);
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++) {
> + ? ? ? ? ? ? ? host = info->host[cs];
> + ? ? ? ? ? ? ? if (!host)
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? nand_release(host->mtd);
> + ? ? ? ? ? ? ? free_cs_resource(info, cs);
> ? ? ? ?}
> ? ? ? ?return 0;
> ?}
> @@ -1133,6 +1208,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
> ?{
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata;
> ? ? ? ?struct pxa3xx_nand_info *info;
> + ? ? ? int cs, ret, probe_success = 0;
>
> ? ? ? ?pdata = pdev->dev.platform_data;
> ? ? ? ?if (!pdata) {
> @@ -1140,18 +1216,38 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?}
>
> - ? ? ? info = alloc_nand_resource(pdev);
> - ? ? ? if (info == NULL)
> - ? ? ? ? ? ? ? return -ENOMEM;
> + ? ? ? if (pdata->keep_config && pdata->num_cs > 1) {
> + ? ? ? ? ? ? ? dev_warn(&pdev->dev, "keep_config is prohibited with multiple"
> + ? ? ? ? ? ? ? ? ? ? ? ?" chip selects feature!\n");
> + ? ? ? ? ? ? ? pdata->keep_config = 0;
> + ? ? ? }
> +
> + ? ? ? ret = alloc_nand_resource(pdev);
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "alloc nand resource failed\n");
> + ? ? ? ? ? ? ? return ret;
> + ? ? ? }
> +
> + ? ? ? info = platform_get_drvdata(pdev);
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++) {
> + ? ? ? ? ? ? ? ret = pxa3xx_nand_scan(info->host[cs]->mtd);
> + ? ? ? ? ? ? ? if (ret) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
> + ? ? ? ? ? ? ? ? ? ? ? pdata->parts[cs], pdata->nr_parts[cs]);
> + ? ? ? ? ? ? ? if (!ret)
> + ? ? ? ? ? ? ? ? ? ? ? probe_success = 1;
> + ? ? ? }
>
> - ? ? ? if (pxa3xx_nand_scan(info->mtd)) {
> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
> + ? ? ? if (!probe_success) {
> ? ? ? ? ? ? ? ?pxa3xx_nand_remove(pdev);
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?}
>
> - ? ? ? return mtd_device_parse_register(info->mtd, NULL, 0,
> - ? ? ? ? ? ? ? ? ? ? ? pdata->parts, pdata->nr_parts);
> + ? ? ? return 0;
> ?}
>
> ?#ifdef CONFIG_PM
> @@ -1171,8 +1267,12 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
>
> - ? ? ? nand_writel(info, NDTR0CS0, info->ndtr0cs0);
> - ? ? ? nand_writel(info, NDTR1CS0, info->ndtr1cs0);
> + ? ? ? /*
> + ? ? ? ?* Directly set the chip select to a invalid value,
> + ? ? ? ?* then the driver would reset the timing according
> + ? ? ? ?* to current chip select at the beginning of cmdfunc
> + ? ? ? ?*/
> + ? ? ? info->cs = 0xff;
> ? ? ? ?clk_enable(info->clk);
>
> ? ? ? ?return 0;
> --
> 1.7.0.4
>
>


From adrian.wenl at gmail.com  Sat Jun 25 08:51:35 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Sat, 25 Jun 2011 20:51:35 +0800
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <BANLkTimY2+qV_A7gSWOjAk0f54zKRC2wCg@mail.gmail.com>
References: <4E031900.50108@compulab.co.il>
	<1309000666-5242-1-git-send-email-leiwen@marvell.com>
	<BANLkTimY2+qV_A7gSWOjAk0f54zKRC2wCg@mail.gmail.com>
Message-ID: <BANLkTinyjRFdzBzmhnREOTN+B4cCQMyqXg@mail.gmail.com>

Hi Daniel,

On Sat, Jun 25, 2011 at 8:32 PM, Daniel Mack <zonque at gmail.com> wrote:
> On Sat, Jun 25, 2011 at 1:17 PM, Lei Wen <leiwen at marvell.com> wrote:
>> Current pxa3xx_nand controller has two chip select which
>> both be workable. This patch enable this feature.
>>
>> Update platform driver to support this feature.
>>
>> Another notice should be taken that:
>> When you want to use this feature, you should not enable the
>> keep configuration feature, for two chip select could be
>> attached with different nand chip. The different page size
>> and timing requirement make the keep configuration impossible.
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>
> I tested this on a PXA303 platform with one chipselect only, at at
> least I can say that this patch doesn't seem to cause any regression
> here. But I couldn't test the new feature it adds.
>
> So, FWIW:
>
> Tested-by: Daniel Mack <zonque at gmail.com>

Thanks for testing!

Best regards,
Lei


From vapier at gentoo.org  Sat Jun 25 13:08:10 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 13:08:10 -0400
Subject: [PATCH 1/2 v2] rewrite build system to avoid recursion
In-Reply-To: <BANLkTinJkfNpJ-13yTwpx9u-FaX1TKScuw@mail.gmail.com>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1308984770-6594-1-git-send-email-vapier@gentoo.org>
	<1308986033.23868.8.camel@koala>
	<BANLkTinJkfNpJ-13yTwpx9u-FaX1TKScuw@mail.gmail.com>
Message-ID: <BANLkTin+Or+320Uz5bSj26yFJE2BZgO2dA@mail.gmail.com>

On Sat, Jun 25, 2011 at 03:48, Mike Frysinger wrote:
> On Sat, Jun 25, 2011 at 03:13, Artem Bityutskiy wrote:
>> ?CC ? ? ?ubi-utils/ubinize.o
>> In file included from ubi-utils/ubinize.c:38:0:
>> ./ubi-utils/include/libiniparser.h:35:24: fatal error: dictionary.h: No
>> such file or directory
>> compilation terminated.
>> make: *** [/home/dedekind/git/mtd-utils/ubi-utils/ubinize.o] Error 1
>
> weird ... i'm not seeing that. ?i'll double check my system in the
> morning to see what's going on.

i had /usr/include/dictionary.h which provided the same thing

so how to solve ... i dont quite understand the file layout in
ubi-utils.  why isnt dictionary.h in the include/ subdir ?  after all,
that's where the include is coming from:
ubi-utils/include/libiniparser.h.
-mike


From vapier at gentoo.org  Sat Jun 25 13:20:38 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 13:20:38 -0400
Subject: [PATCH 2/2 v2] autogenerate version.h from build system
In-Reply-To: <1309022438-10093-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1309022438-10093-1-git-send-email-vapier@gentoo.org>
Message-ID: <1309022438-10093-2-git-send-email-vapier@gentoo.org>

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v2
	- only add the version.h dep to *.o in the toplevel Makefile
	  so tests/ subdirs can work without it

 .gitignore       |    1 +
 Makefile         |   10 ++++++++++
 common.mk        |    2 +-
 flash_erase.c    |    1 -
 include/common.h |    1 +
 nanddump.c       |    1 -
 nandwrite.c      |    1 -
 7 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/.gitignore b/.gitignore
index 849265d..86aee63 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,6 +50,7 @@
 #
 # Generated include files
 #
+/include/version.h
 
 # stgit generated dirs
 patches-*
diff --git a/Makefile b/Makefile
index bd5ada3..8f871c6 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,8 @@
 
 # -*- sh -*-
 
+VERSION = 1.4.5
+
 CPPFLAGS += -I./include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
 
 ifeq ($(WITHOUT_XATTR), 1)
@@ -36,6 +38,8 @@ TARGETS = $(BINS)
 TARGETS += lib/libmtd.a
 TARGETS += ubi-utils/libubi.a
 
+OBJDEPS = $(BUILDDIR)/include/version.h
+
 include common.mk
 
 clean::
@@ -49,6 +53,7 @@ endif
 	find $(BUILDDIR)/ -xdev \
 		'(' -name '*.[ao]' -o -name '.*.c.dep' ')' \
 		-exec rm -f {} +
+	rm -f $(BUILDDIR)/include/version.h
 	$(MAKE) -C $(TESTS) clean
 
 install:: ${BINS} ${SCRIPTS}
@@ -63,6 +68,11 @@ tests::
 cscope:
 	cscope -bR
 
+$(BUILDDIR)/include/version.h: $(BUILDDIR)/include/version.h.tmp
+	$(Q)cmp -s $@ $@.tmp && rm -f $@.tmp || mv $@.tmp $@
+$(BUILDDIR)/include/version.h.tmp:
+	$(Q)echo '#define VERSION "$(VERSION)"' > $@
+
 #
 # Utils in top level
 #
diff --git a/common.mk b/common.mk
index d0e207d..ba87377 100644
--- a/common.mk
+++ b/common.mk
@@ -75,7 +75,7 @@ $(BUILDDIR)/%.a:
 	$(Q)$(AR) cr $@ $^
 	$(Q)$(RANLIB) $@
 
-$(BUILDDIR)/%.o: %.c
+$(BUILDDIR)/%.o: %.c $(OBJDEPS)
 ifneq ($(BUILDDIR),$(CURDIR))
 	$(Q)mkdir -p $(dir $@)
 endif
diff --git a/flash_erase.c b/flash_erase.c
index e0d2d4c..220f85a 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -19,7 +19,6 @@
  */
 
 #define PROGRAM_NAME "flash_erase"
-#define VERSION "2.1.0"
 
 #include <inttypes.h>
 #include <stdio.h>
diff --git a/include/common.h b/include/common.h
index 7ea282c..65ec086 100644
--- a/include/common.h
+++ b/include/common.h
@@ -25,6 +25,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <errno.h>
+#include "version.h"
 
 #ifndef PROGRAM_NAME
 # error "You must define PROGRAM_NAME before including this header"
diff --git a/nanddump.c b/nanddump.c
index 54198ae..27b0f7a 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -14,7 +14,6 @@
  */
 
 #define PROGRAM_NAME "nanddump"
-#define VERSION "1.31"
 
 #define _GNU_SOURCE
 #include <ctype.h>
diff --git a/nandwrite.c b/nandwrite.c
index 6e986c5..1700d61 100644
--- a/nandwrite.c
+++ b/nandwrite.c
@@ -20,7 +20,6 @@
  */
 
 #define PROGRAM_NAME "nandwrite"
-#define VERSION "$Revision: 1.32 $"
 
 #define _GNU_SOURCE
 #include <ctype.h>
-- 
1.7.5.3



From vapier at gentoo.org  Sat Jun 25 13:20:37 2011
From: vapier at gentoo.org (Mike Frysinger)
Date: Sat, 25 Jun 2011 13:20:37 -0400
Subject: [PATCH 1/2 v3] rewrite build system to avoid recursion
In-Reply-To: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
Message-ID: <1309022438-10093-1-git-send-email-vapier@gentoo.org>

The ubi-utils/src/ subdir is tossed as it just complicates things for no
real gain.  The dictionary.h header is relocated to the ubi-utils/include/
since other headers in there need it.

The top level clean is replaced with a `find -delete` on objects, so it
might prune more than necessary, but many projects now do this sort of
thing and no one complained there.

A "mkdep" helper generates the actual rule, and the variables are used
with "foreach" to expand these automatically.

The tests subdir is updated only to reflect the ubi-utils source move.
Otherwise, it is left untouched as making that non-recursive isn't really
worth the effort.

While we're gutting things, also through in kbuild style output while
building to make things more legible.

Signed-off-by: Mike Frysinger <vapier at gentoo.org>
---
v3
	- fix build failure with dictionary.h by moving it into the include dir
	- update some tests/ dirs to reflect ubi-utils file moving

 Makefile                                |   81 ++++++++++++++++++++++--------
 common.mk                               |   48 ++++++++++++-------
 lib/Makefile                            |   22 --------
 mkfs.ubifs/Makefile                     |   29 -----------
 tests/fs-tests/integrity/Makefile       |    7 +--
 tests/ubi-tests/Makefile                |   10 ++--
 ubi-utils/Makefile                      |   60 -----------------------
 ubi-utils/{src => }/dictionary.c        |    0
 ubi-utils/{src => include}/dictionary.h |    0
 ubi-utils/{src => }/libiniparser.c      |    0
 ubi-utils/{src => }/libscan.c           |    0
 ubi-utils/{src => }/libubi.c            |    0
 ubi-utils/{src => }/libubi_int.h        |    0
 ubi-utils/{src => }/libubigen.c         |    0
 ubi-utils/{src => }/mtdinfo.c           |    0
 ubi-utils/{src => }/ubiattach.c         |    0
 ubi-utils/{src => }/ubicrc32.c          |    0
 ubi-utils/{src => }/ubidetach.c         |    0
 ubi-utils/{src => }/ubiformat.c         |    0
 ubi-utils/{src => }/ubimkvol.c          |    0
 ubi-utils/{src => }/ubinfo.c            |    0
 ubi-utils/{src => }/ubinize.c           |    0
 ubi-utils/{src => }/ubirename.c         |    0
 ubi-utils/{src => }/ubirmvol.c          |    0
 ubi-utils/{src => }/ubirsvol.c          |    0
 ubi-utils/{src => }/ubiupdatevol.c      |    0
 ubi-utils/{src => }/ubiutils-common.c   |    0
 27 files changed, 97 insertions(+), 160 deletions(-)
 delete mode 100644 lib/Makefile
 delete mode 100644 mkfs.ubifs/Makefile
 delete mode 100644 ubi-utils/Makefile
 rename ubi-utils/{src => }/dictionary.c (100%)
 rename ubi-utils/{src => include}/dictionary.h (100%)
 rename ubi-utils/{src => }/libiniparser.c (100%)
 rename ubi-utils/{src => }/libscan.c (100%)
 rename ubi-utils/{src => }/libubi.c (100%)
 rename ubi-utils/{src => }/libubi_int.h (100%)
 rename ubi-utils/{src => }/libubigen.c (100%)
 rename ubi-utils/{src => }/mtdinfo.c (100%)
 rename ubi-utils/{src => }/ubiattach.c (100%)
 rename ubi-utils/{src => }/ubicrc32.c (100%)
 rename ubi-utils/{src => }/ubidetach.c (100%)
 rename ubi-utils/{src => }/ubiformat.c (100%)
 rename ubi-utils/{src => }/ubimkvol.c (100%)
 rename ubi-utils/{src => }/ubinfo.c (100%)
 rename ubi-utils/{src => }/ubinize.c (100%)
 rename ubi-utils/{src => }/ubirename.c (100%)
 rename ubi-utils/{src => }/ubirmvol.c (100%)
 rename ubi-utils/{src => }/ubirsvol.c (100%)
 rename ubi-utils/{src => }/ubiupdatevol.c (100%)
 rename ubi-utils/{src => }/ubiutils-common.c (100%)

diff --git a/Makefile b/Makefile
index d69206a..bd5ada3 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 
 # -*- sh -*-
 
-CPPFLAGS += -I./include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
+CPPFLAGS += -I./include -I./ubi-utils/include $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
 
 ifeq ($(WITHOUT_XATTR), 1)
   CPPFLAGS += -DWITHOUT_XATTR
@@ -12,10 +12,10 @@ else
   LZOLDLIBS = -llzo2
 endif
 
-SUBDIRS = lib ubi-utils mkfs.ubifs
 TESTS = tests
 
-TARGETS = ftl_format flash_erase nanddump doc_loadbios \
+MTD_BINS = \
+	ftl_format flash_erase nanddump doc_loadbios \
 	ftl_check mkfs.jffs2 flash_lock flash_unlock flash_info \
 	flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \
 	jffs2dump \
@@ -23,16 +23,21 @@ TARGETS = ftl_format flash_erase nanddump doc_loadbios \
 	rfddump rfdformat \
 	serve_image recv_image \
 	sumtool #jffs2reader
+UBI_BINS = \
+	ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
+	ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
+
+BINS = $(MTD_BINS)
+BINS += mkfs.ubifs/mkfs.ubifs
+BINS += $(addprefix ubi-utils/,$(UBI_BINS))
 SCRIPTS = flash_eraseall
 
-LDLIBS = -L$(BUILDDIR)/lib -lmtd
-LDDEPS = $(BUILDDIR)/lib/libmtd.a
+TARGETS = $(BINS)
+TARGETS += lib/libmtd.a
+TARGETS += ubi-utils/libubi.a
 
 include common.mk
 
-# mkfs.ubifs needs -lubi which is in ubi-utils/
-subdirs_mkfs.ubifs_all: subdirs_ubi-utils_all
-
 clean::
 ifneq ($(BUILDDIR)/.git,)
 ifneq ($(BUILDDIR),.)
@@ -41,23 +46,14 @@ ifneq ($(BUILDDIR),$(CURDIR))
 endif
 endif
 endif
+	find $(BUILDDIR)/ -xdev \
+		'(' -name '*.[ao]' -o -name '.*.c.dep' ')' \
+		-exec rm -f {} +
 	$(MAKE) -C $(TESTS) clean
 
-$(BUILDDIR)/mkfs.jffs2: $(addprefix $(BUILDDIR)/,\
-	compr_rtime.o mkfs.jffs2.o compr_zlib.o compr_lzo.o \
-	compr.o rbtree.o)
-LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
-
-$(BUILDDIR)/jffs2reader: $(BUILDDIR)/jffs2reader.o
-LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
-
-$(BUILDDIR)/lib/libmtd.a: subdirs_lib_all ;
-
-install:: ${TARGETS} ${SCRIPTS}
+install:: ${BINS} ${SCRIPTS}
 	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
+	install -m 0755 ${BINS} ${SCRIPTS} ${DESTDIR}/${SBINDIR}/
 	mkdir -p ${DESTDIR}/${MANDIR}/man1
 	gzip -9c mkfs.jffs2.1 > ${DESTDIR}/${MANDIR}/man1/mkfs.jffs2.1.gz
 
@@ -66,3 +62,44 @@ tests::
 
 cscope:
 	cscope -bR
+
+#
+# Utils in top level
+#
+obj-mkfs.jffs2 = compr_rtime.o compr_zlib.o compr_lzo.o compr.o rbtree.o
+LDFLAGS_mkfs.jffs2 = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_mkfs.jffs2  = -lz $(LZOLDLIBS)
+
+LDFLAGS_jffs2reader = $(ZLIBLDFLAGS) $(LZOLDFLAGS)
+LDLIBS_jffs2reader  = -lz $(LZOLDLIBS)
+
+$(foreach v,$(MTD_BINS),$(eval $(call mkdep,,$(v))))
+
+#
+# Common libmtd
+#
+obj-libmtd.a = libmtd.o libmtd_legacy.o libcrc32.o libfec.o
+$(call _mkdep,lib/,libmtd.a)
+
+#
+# Utils in mkfs.ubifs subdir
+#
+obj-mkfs.ubifs = crc16.o lpt.o compr.o devtable.o \
+	hashtable/hashtable.o hashtable/hashtable_itr.o
+LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid
+$(call mkdep,mkfs.ubifs/,mkfs.ubifs,,ubi-utils/libubi.a)
+
+#
+# Utils in ubi-utils/ subdir
+#
+obj-libiniparser.a = libiniparser.o dictionary.o
+obj-libscan.a      = libscan.o
+obj-libubi.a       = libubi.o
+obj-libubigen.a    = libubigen.o
+
+obj-mtdinfo   = libubigen.a
+obj-ubinize   = libubigen.a libiniparser.a
+obj-ubiformat = libubigen.a libscan.a
+
+$(foreach v,libubi.a libubigen.a libiniparser.a libscan.a,$(eval $(call _mkdep,ubi-utils/,$(v))))
+$(foreach v,$(UBI_BINS),$(eval $(call mkdep,ubi-utils/,$(v),libubi.a ubiutils-common.o)))
diff --git a/common.mk b/common.mk
index 0f3d447..d0e207d 100644
--- a/common.mk
+++ b/common.mk
@@ -39,34 +39,48 @@ override BUILDDIR := $(patsubst %/,%,$(BUILDDIR))
 
 override TARGETS := $(addprefix $(BUILDDIR)/,$(TARGETS))
 
-SUBDIRS_ALL = $(patsubst %,subdirs_%_all,$(SUBDIRS))
-SUBDIRS_CLEAN = $(patsubst %,subdirs_%_clean,$(SUBDIRS))
-SUBDIRS_INSTALL = $(patsubst %,subdirs_%_install,$(SUBDIRS))
+ifeq ($(V),1)
+XECHO = @:
+XPRINTF = @:
+Q =
+else
+XECHO = @echo
+XPRINTF = @printf
+Q = @
+endif
+define BECHO
+$(XPRINTF) '  %-7s %s\n' "$1" "$(subst $(BUILDDIR)/,,$@)"
+endef
 
-all:: $(TARGETS) $(SUBDIRS_ALL)
+all:: $(TARGETS)
 
-clean:: $(SUBDIRS_CLEAN)
+clean::
 	rm -f $(BUILDDIR)/*.o $(TARGETS) $(BUILDDIR)/.*.c.dep
 
-install:: $(TARGETS) $(SUBDIRS_INSTALL)
+install:: $(TARGETS)
 
-%: %.o $(LDDEPS) $(LDDEPS_$(notdir $@))
-	$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))
+define _mkdep
+$(BUILDDIR)/$1$2: $(addprefix $(BUILDDIR)/$1,$(obj-$2) $3) $(addprefix $(BUILDDIR)/,$4)
+endef
+define mkdep
+$(call _mkdep,$1,$2,$3 $2.o,$4 lib/libmtd.a)
+endef
+
+%: %.o $(LDDEPS)
+	$(call BECHO,LD)
+	$(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(LDFLAGS_$(notdir $@)) -g -o $@ $^ $(LDLIBS) $(LDLIBS_$(notdir $@))
 
 $(BUILDDIR)/%.a:
-	$(AR) crv $@ $^
-	$(RANLIB) $@
+	$(call BECHO,AR)
+	$(Q)$(AR) cr $@ $^
+	$(Q)$(RANLIB) $@
 
 $(BUILDDIR)/%.o: %.c
 ifneq ($(BUILDDIR),$(CURDIR))
-	mkdir -p $(dir $@)
+	$(Q)mkdir -p $(dir $@)
 endif
-	$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep
-
-subdirs_%:
-	d=$(patsubst subdirs_%,%,$@); \
-	t=`echo $$d | sed s:.*_::` d=`echo $$d | sed s:_.*::`; \
-	$(MAKE) BUILDDIR=$(BUILDDIR)/$$d -C $$d $$t
+	$(call BECHO,CC)
+	$(Q)$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $< -g -Wp,-MD,$(BUILDDIR)/.$(<F).dep
 
 .SUFFIXES:
 
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index 9b01d32..0000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-#
-# Makefile for libmtd
-#
-
-SUBDIRS =
-
-# CFLAGS += -Werror
-CPPFLAGS += -I../include
-LIBS = libmtd
-TARGETS = libmtd.a
-
-include ../common.mk
-
-$(BUILDDIR)/libmtd.a: $(addprefix $(BUILDDIR)/,\
-       libmtd.o libmtd_legacy.o libcrc32.o libfec.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-
-uninstall:
diff --git a/mkfs.ubifs/Makefile b/mkfs.ubifs/Makefile
deleted file mode 100644
index ba21a8c..0000000
--- a/mkfs.ubifs/Makefile
+++ /dev/null
@@ -1,29 +0,0 @@
-
-CPPFLAGS += -I../include -I../ubi-utils/include
-CPPFLAGS += $(ZLIBCPPFLAGS) $(LZOCPPFLAGS)
-
-ALL_SOURCES=*.[ch] hashtable/*.[ch]
-
-TARGETS = mkfs.ubifs
-
-LDLIBS_mkfs.ubifs = -lz -llzo2 -lm -luuid -L$(BUILDDIR)/../ubi-utils/ -lubi
-LDLIBS_mkfs.ubifs += -L$(BUILDDIR)/../lib -lmtd
-LDLIBS_mkfs.ubifs += $(ZLIBLDFLAGS) $(LZOLDFLAGS)
-
-include ../common.mk
-
-$(BUILDDIR)/mkfs.ubifs: $(addprefix $(BUILDDIR)/,\
-	crc16.o lpt.o compr.o devtable.o \
-	hashtable/hashtable.o hashtable/hashtable_itr.o)
-
-clean::
-	rm -f $(BUILDDIR)/hashtable/*.o cscope.*
-
-cscope:
-	@echo $(ALL_SOURCES) > cscope.files
-	@cscope -bR
-	@rm cscope.files
-
-install:: ${TARGETS}
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
diff --git a/tests/fs-tests/integrity/Makefile b/tests/fs-tests/integrity/Makefile
index 509a94e..4d6fc7d 100644
--- a/tests/fs-tests/integrity/Makefile
+++ b/tests/fs-tests/integrity/Makefile
@@ -4,9 +4,8 @@ CC = gcc
 endif
 
 COMMON_HEADERS_DIR := ../../../include
-LIBUBI_PATH=../../../ubi-utils/
-LIBUBI_SRC_PATH=../../../ubi-utils/src/
-LIBUBI_HEADER_PATH=../../../ubi-utils/include
+LIBUBI_PATH = ../../../ubi-utils/
+LIBUBI_HEADER_PATH = $(LIBUBI_PATH)/include
 
 CFLAGS := $(CFLAGS) -Wall -g -O2 -I$(COMMON_HEADERS_DIR) -I$(LIBUBI_HEADER_PATH)
 
@@ -18,7 +17,7 @@ all: $(TARGETS)
 
 # Compile ubilib
 libubi.a:
-	$(CC) $(CFLAGS) -I $(LIBUBI_SRC_PATH) -c $(LIBUBI_SRC_PATH)/libubi.c -o libubi.o
+	$(CC) $(CFLAGS) -c $(LIBUBI_PATH)/libubi.c -o libubi.o
 	ar cr libubi.a libubi.o
 
 $(TARGETS): libubi.a
diff --git a/tests/ubi-tests/Makefile b/tests/ubi-tests/Makefile
index 741a5c2..2c47a9f 100644
--- a/tests/ubi-tests/Makefile
+++ b/tests/ubi-tests/Makefile
@@ -1,9 +1,7 @@
-LIBUBI_PATH=../../ubi-utils/
-LIBUBI_SRC_PATH=../../ubi-utils/src/
-LIBUBI_HEADER_PATH=../../ubi-utils/include
+LIBUBI_PATH = ../../ubi-utils/
+LIBUBI_HEADER_PATH = $(LIBUBI_PATH)/include
 UBIUTILS_PATH=../../ubi-utils/
 
-LIBUBI_PATH=../../ubi-utils/
 KERNELHDR := ../../include
 
 LIBS = libubi
@@ -15,8 +13,8 @@ CFLAGS += -I$(LIBUBI_HEADER_PATH) -I $(KERNELHDR) -lpthread
 include ../../common.mk
 
 # Compile ubilib with the udevsettle hack
-libubi.a: $(LIBUBI_SRC_PATH)/libubi.c  $(LIBUBI_HEADER_PATH)/libubi.h  $(LIBUBI_SRC_PATH)/libubi_int.h
-	$(CC) $(CFLAGS) -I $(LIBUBI_SRC_PATH) -I../../include -DUDEV_SETTLE_HACK -c $(LIBUBI_SRC_PATH)/libubi.c -o libubi.o
+libubi.a: $(LIBUBI_PATH)/libubi.c  $(LIBUBI_HEADER_PATH)/libubi.h  $(LIBUBI_PATH)/libubi_int.h
+	$(CC) $(CFLAGS) -I $(LIBUBI_PATH) -I../../include -DUDEV_SETTLE_HACK -c $(LIBUBI_PATH)/libubi.c -o libubi.o
 	ar cr libubi.a libubi.o
 
 $(TARGETS): $(addprefix $(BUILDDIR)/, common.o) libubi.a
diff --git a/ubi-utils/Makefile b/ubi-utils/Makefile
deleted file mode 100644
index df81cd9..0000000
--- a/ubi-utils/Makefile
+++ /dev/null
@@ -1,60 +0,0 @@
-#
-# Makefile for ubi-utils
-#
-
-KERNELHDR := ../include
-
-# CFLAGS += -Werror
-CPPFLAGS += -Iinclude -Isrc -I$(KERNELHDR)
-
-LIBS = libubi libubigen libiniparser libscan
-TARGETS = ubiupdatevol ubimkvol ubirmvol ubicrc32 ubinfo ubiattach \
-          ubidetach ubinize ubiformat ubirename mtdinfo ubirsvol
-
-VPATH = src
-LDLIBS = -L$(BUILDDIR)/../lib -lmtd
-
-include ../common.mk
-
-# And the below is the rule to get final executable from its .o and ubiutils-common.o
-$(TARGETS): $(addprefix $(BUILDDIR)/,\
-	libubi.a ubiutils-common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lubi -o $@
-
-$(BUILDDIR)/ubicrc32: $(addprefix $(BUILDDIR)/,\
-	ubicrc32.o)
-#	$(CC) $(CFLAGS) -o $@ $^
-
-$(BUILDDIR)/ubinize: $(addprefix $(BUILDDIR)/,\
-	ubinize.o ubiutils-common.o libiniparser.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -liniparser -lubigen -o $@
-
-$(BUILDDIR)/mtdinfo: $(addprefix $(BUILDDIR)/,\
-	libubigen.a ubiutils-common.o)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lubigen -o $@
-
-$(BUILDDIR)/ubiformat: $(addprefix $(BUILDDIR)/,\
-	ubiformat.o ubiutils-common.o libscan.a libubi.a libubigen.a)
-#	$(CC) $(CFLAGS) $(filter %.o, $^) -L. -lmtd -lscan -lubi -lubigen -o $@
-
-$(BUILDDIR)/libubi.a: $(BUILDDIR)/libubi.o
-
-$(BUILDDIR)/libubigen.a: $(BUILDDIR)/libubigen.o
-
-$(BUILDDIR)/libiniparser.a: $(addprefix $(BUILDDIR)/,\
-	libiniparser.o dictionary.o)
-
-$(BUILDDIR)/libscan.a: $(addprefix $(BUILDDIR)/,\
-	libscan.o)
-
-clean::
-	rm -f $(addsuffix .a, $(LIBS))
-
-install::
-	mkdir -p ${DESTDIR}/${SBINDIR}
-	install -m 0755 ${TARGETS} ${DESTDIR}/${SBINDIR}/
-
-uninstall:
-	for file in ${TARGETS}; do \
-		$(RM) ${DESTDIR}/${SBINDIR}/$$file; \
-	done
diff --git a/ubi-utils/src/dictionary.c b/ubi-utils/dictionary.c
similarity index 100%
rename from ubi-utils/src/dictionary.c
rename to ubi-utils/dictionary.c
diff --git a/ubi-utils/src/dictionary.h b/ubi-utils/include/dictionary.h
similarity index 100%
rename from ubi-utils/src/dictionary.h
rename to ubi-utils/include/dictionary.h
diff --git a/ubi-utils/src/libiniparser.c b/ubi-utils/libiniparser.c
similarity index 100%
rename from ubi-utils/src/libiniparser.c
rename to ubi-utils/libiniparser.c
diff --git a/ubi-utils/src/libscan.c b/ubi-utils/libscan.c
similarity index 100%
rename from ubi-utils/src/libscan.c
rename to ubi-utils/libscan.c
diff --git a/ubi-utils/src/libubi.c b/ubi-utils/libubi.c
similarity index 100%
rename from ubi-utils/src/libubi.c
rename to ubi-utils/libubi.c
diff --git a/ubi-utils/src/libubi_int.h b/ubi-utils/libubi_int.h
similarity index 100%
rename from ubi-utils/src/libubi_int.h
rename to ubi-utils/libubi_int.h
diff --git a/ubi-utils/src/libubigen.c b/ubi-utils/libubigen.c
similarity index 100%
rename from ubi-utils/src/libubigen.c
rename to ubi-utils/libubigen.c
diff --git a/ubi-utils/src/mtdinfo.c b/ubi-utils/mtdinfo.c
similarity index 100%
rename from ubi-utils/src/mtdinfo.c
rename to ubi-utils/mtdinfo.c
diff --git a/ubi-utils/src/ubiattach.c b/ubi-utils/ubiattach.c
similarity index 100%
rename from ubi-utils/src/ubiattach.c
rename to ubi-utils/ubiattach.c
diff --git a/ubi-utils/src/ubicrc32.c b/ubi-utils/ubicrc32.c
similarity index 100%
rename from ubi-utils/src/ubicrc32.c
rename to ubi-utils/ubicrc32.c
diff --git a/ubi-utils/src/ubidetach.c b/ubi-utils/ubidetach.c
similarity index 100%
rename from ubi-utils/src/ubidetach.c
rename to ubi-utils/ubidetach.c
diff --git a/ubi-utils/src/ubiformat.c b/ubi-utils/ubiformat.c
similarity index 100%
rename from ubi-utils/src/ubiformat.c
rename to ubi-utils/ubiformat.c
diff --git a/ubi-utils/src/ubimkvol.c b/ubi-utils/ubimkvol.c
similarity index 100%
rename from ubi-utils/src/ubimkvol.c
rename to ubi-utils/ubimkvol.c
diff --git a/ubi-utils/src/ubinfo.c b/ubi-utils/ubinfo.c
similarity index 100%
rename from ubi-utils/src/ubinfo.c
rename to ubi-utils/ubinfo.c
diff --git a/ubi-utils/src/ubinize.c b/ubi-utils/ubinize.c
similarity index 100%
rename from ubi-utils/src/ubinize.c
rename to ubi-utils/ubinize.c
diff --git a/ubi-utils/src/ubirename.c b/ubi-utils/ubirename.c
similarity index 100%
rename from ubi-utils/src/ubirename.c
rename to ubi-utils/ubirename.c
diff --git a/ubi-utils/src/ubirmvol.c b/ubi-utils/ubirmvol.c
similarity index 100%
rename from ubi-utils/src/ubirmvol.c
rename to ubi-utils/ubirmvol.c
diff --git a/ubi-utils/src/ubirsvol.c b/ubi-utils/ubirsvol.c
similarity index 100%
rename from ubi-utils/src/ubirsvol.c
rename to ubi-utils/ubirsvol.c
diff --git a/ubi-utils/src/ubiupdatevol.c b/ubi-utils/ubiupdatevol.c
similarity index 100%
rename from ubi-utils/src/ubiupdatevol.c
rename to ubi-utils/ubiupdatevol.c
diff --git a/ubi-utils/src/ubiutils-common.c b/ubi-utils/ubiutils-common.c
similarity index 100%
rename from ubi-utils/src/ubiutils-common.c
rename to ubi-utils/ubiutils-common.c
-- 
1.7.5.3



From randy.dunlap at oracle.com  Sat Jun 25 18:20:09 2011
From: randy.dunlap at oracle.com (Randy Dunlap)
Date: Sat, 25 Jun 2011 15:20:09 -0700
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <1308983721.23868.2.camel@koala>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
	<1308947172.13493.37.camel@koala> <4E04F5D0.9090900@oracle.com>
	<1308983721.23868.2.camel@koala>
Message-ID: <20110625152009.f264be78.randy.dunlap@oracle.com>

On Sat, 25 Jun 2011 09:35:13 +0300 Artem Bityutskiy wrote:

> On Fri, 2011-06-24 at 13:38 -0700, Randy Dunlap wrote:
> > On 06/24/11 13:26, Artem Bityutskiy wrote:
> > > On Fri, 2011-06-24 at 09:04 -0700, Randy Dunlap wrote:
> > >> On Fri, 24 Jun 2011 15:58:22 +1000 Stephen Rothwell wrote:
> > >>
> > >>> Hi all,
> > >>>
> > >>> Changes since 20110623:
> > >>>
> > >>> My fixes tree includes:
> > >>> 	(as an experiment) the early part of mmotm-2011-06-22-13-05
> > >>> 	STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
> > >>
> > >>
> > >> When CONFIG_MTD=m, CONFIG_MTD_OF_PARTS=y:
> > >>
> > >> drivers/mtd/ofpart.o: In function `init_module':
> > >> ofpart.c:(.init.text+0x0): multiple definition of `init_module'
> > >> drivers/mtd/mtdcore.o:(.init.text+0x43): first defined here
> > > 
> > > I guess this is some old issue? I do not think ofpart can be compiled-in
> > > if the mtd core is a module...
> > 
> > [adding driver author, Vitaly]
> > 
> > No, it's a current issue.
> 
> I meant that the subject suggests this is about linux-next, but this
> problem should be in upstream.

Sorry I misunderstood your comment.

3.0-rc4 does not have this build error when I use the .config file with it...
however, I think that 3.0-rc4 also does not build ofpart.ko as it should.

Looks to me like changes in drivers/mtd/{Kconfig && Makefile} caused this
build error.


---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***


From grant.likely at secretlab.ca  Sun Jun 26 02:11:40 2011
From: grant.likely at secretlab.ca (Grant Likely)
Date: Sun, 26 Jun 2011 00:11:40 -0600
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <20110625152009.f264be78.randy.dunlap@oracle.com>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
	<1308947172.13493.37.camel@koala> <4E04F5D0.9090900@oracle.com>
	<1308983721.23868.2.camel@koala>
	<20110625152009.f264be78.randy.dunlap@oracle.com>
Message-ID: <BANLkTi=Q-7bCHaH+-z6gnbwvexpGLYH6pA@mail.gmail.com>

On Sat, Jun 25, 2011 at 4:20 PM, Randy Dunlap <randy.dunlap at oracle.com> wrote:
> On Sat, 25 Jun 2011 09:35:13 +0300 Artem Bityutskiy wrote:
>
>> On Fri, 2011-06-24 at 13:38 -0700, Randy Dunlap wrote:
>> > On 06/24/11 13:26, Artem Bityutskiy wrote:
>> > > On Fri, 2011-06-24 at 09:04 -0700, Randy Dunlap wrote:
>> > >> On Fri, 24 Jun 2011 15:58:22 +1000 Stephen Rothwell wrote:
>> > >>
>> > >>> Hi all,
>> > >>>
>> > >>> Changes since 20110623:
>> > >>>
>> > >>> My fixes tree includes:
>> > >>> ? ? ? ? (as an experiment) the early part of mmotm-2011-06-22-13-05
>> > >>> ? ? ? ? STAGING: Comedi: Build only on arches providing PAGE_KERNEL_NOCACHE
>> > >>
>> > >>
>> > >> When CONFIG_MTD=m, CONFIG_MTD_OF_PARTS=y:
>> > >>
>> > >> drivers/mtd/ofpart.o: In function `init_module':
>> > >> ofpart.c:(.init.text+0x0): multiple definition of `init_module'
>> > >> drivers/mtd/mtdcore.o:(.init.text+0x43): first defined here
>> > >
>> > > I guess this is some old issue? I do not think ofpart can be compiled-in
>> > > if the mtd core is a module...
>> >
>> > [adding driver author, Vitaly]
>> >
>> > No, it's a current issue.
>>
>> I meant that the subject suggests this is about linux-next, but this
>> problem should be in upstream.
>
> Sorry I misunderstood your comment.
>
> 3.0-rc4 does not have this build error when I use the .config file with it...
> however, I think that 3.0-rc4 also does not build ofpart.ko as it should.
>
> Looks to me like changes in drivers/mtd/{Kconfig && Makefile} caused this
> build error.

The following commit in linux-next appears to be the culprit:

commit 1a6bc893044b961caae1c5a9c6c2065e608da427
Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
Date:   Sun May 29 21:32:33 2011 +0400

    mtd: prepare to convert of_mtd_parse_partitions to partition parser

    Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
    1) Register ofpart parser
    2) Internally don't use passed device for error printing
    3) Add device_node to mtd_part_parser_data struct
    4) Move of_mtd_parse_partitions from __devinit to common text section
    5) add ofpart to the default list of partition parsers

    Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
    Signed-off-by: Artem Bityutskiy <dedekind1 at gmail.com>

It adds a module_init() call to ofpart.c which does not work the way
that ofpart.c is linked to mtdcore.o.  Seems like that commit series
still needs work.

g.


From jacmet at sunsite.dk  Sun Jun 26 03:13:38 2011
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Sun, 26 Jun 2011 09:13:38 +0200
Subject: mtd-utils-1.4.5 is out
In-Reply-To: <1308984943.23868.4.camel@koala> (Artem Bityutskiy's message of
	"Sat, 25 Jun 2011 09:55:41 +0300")
References: <1308984943.23868.4.camel@koala>
Message-ID: <87vcvt6p5p.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

 Artem> Hi, I've just tagged mtd-utils-1.4.5 and uploaded a tarball to
 Artem> the usual place.

Thanks. I've added it to buildroot and done a few test builds without
problems.

-- 
Bye, Peter Korsgaard


From jacmet at sunsite.dk  Sun Jun 26 03:15:35 2011
From: jacmet at sunsite.dk (Peter Korsgaard)
Date: Sun, 26 Jun 2011 09:15:35 +0200
Subject: [PATCH v3 0/7] prepare new nanddump options, defaults
In-Reply-To: <1308946822.13493.36.camel@koala> (Artem Bityutskiy's message of
	"Fri, 24 Jun 2011 23:20:17 +0300")
References: <BANLkTi=-25MExYfuB-ANK4ceh3gWy+BqCg@mail.gmail.com>
	<1308761363-16512-1-git-send-email-computersforpeace@gmail.com>
	<1308841377.23597.10.camel@sauron> <1308841503.23597.12.camel@sauron>
	<BANLkTimTu1ORjEvtJ7XSCCqwzDbid957Aw@mail.gmail.com>
	<BANLkTi=cUqQcQzeinQaqh_VBFtfnfkVinw@mail.gmail.com>
	<BANLkTimJN8yOXCqsNscax6bmkTWTzvHphA@mail.gmail.com>
	<1308946822.13493.36.camel@koala>
Message-ID: <87r56h6p2g.fsf@macbook.be.48ers.dk>

>>>>> "Artem" == Artem Bityutskiy <dedekind1 at gmail.com> writes:

Hi,

 >> i dont think anyone has scripts parsing these things.  i say let's
 >> just lock them all to the mtd release and forget about it.

 Artem> Let's ask CC Peter who is packaging mtd-utils just in
 Artem> case. Peter, will you suffer if mtd-utils' version all suddenly
 Artem> become 1.4.6? Also, will you suffer if we switch to 2.0 or 3.0 -
 Artem> 2 numbers instead of 3?

No, the version number doesn't matter as long as it increases and
release tarballs are made.

Thanks.

-- 
Bye, Peter Korsgaard


From dedekind1 at gmail.com  Sun Jun 26 05:43:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Sun, 26 Jun 2011 12:43:41 +0300
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <BANLkTi=Q-7bCHaH+-z6gnbwvexpGLYH6pA@mail.gmail.com>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
	<1308947172.13493.37.camel@koala> <4E04F5D0.9090900@oracle.com>
	<1308983721.23868.2.camel@koala>
	<20110625152009.f264be78.randy.dunlap@oracle.com>
	<BANLkTi=Q-7bCHaH+-z6gnbwvexpGLYH6pA@mail.gmail.com>
Message-ID: <1309081426.6618.0.camel@koala>

On Sun, 2011-06-26 at 00:11 -0600, Grant Likely wrote:
> > 3.0-rc4 does not have this build error when I use the .config file with it...
> > however, I think that 3.0-rc4 also does not build ofpart.ko as it should.
> >
> > Looks to me like changes in drivers/mtd/{Kconfig && Makefile} caused this
> > build error.
> 
> The following commit in linux-next appears to be the culprit:
> 
> commit 1a6bc893044b961caae1c5a9c6c2065e608da427
> Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> Date:   Sun May 29 21:32:33 2011 +0400
> 
>     mtd: prepare to convert of_mtd_parse_partitions to partition parser
> 
>     Prepare to convert of_mtd_parse_partitions() to usual partitions parser:
>     1) Register ofpart parser
>     2) Internally don't use passed device for error printing
>     3) Add device_node to mtd_part_parser_data struct
>     4) Move of_mtd_parse_partitions from __devinit to common text section
>     5) add ofpart to the default list of partition parsers
> 
>     Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>     Signed-off-by: Artem Bityutskiy <dedekind1 at gmail.com>
> 
> It adds a module_init() call to ofpart.c which does not work the way
> that ofpart.c is linked to mtdcore.o.  Seems like that commit series
> still needs work.

OK, let's ask Dmitry to take a look at this.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From linux_vpn at yahoo.com  Sun Jun 26 09:21:44 2011
From: linux_vpn at yahoo.com (Zhiwei Yu)
Date: Sun, 26 Jun 2011 06:21:44 -0700 (PDT)
Subject: No subject
Message-ID: <579375.58487.qm@web161915.mail.bf1.yahoo.com>

http://www.peterhans-schibli.ch/best2011.php


From matthieu.castet at parrot.com  Sun Jun 26 12:26:51 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Sun, 26 Jun 2011 18:26:51 +0200
Subject: [PATCH 1/6] nand_wait_ready timeout fix
Message-ID: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>

nand_wait_ready timeout should not assume HZ=1000.
Make it independent of HZ value.

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
---
 drivers/mtd/nand/nand_base.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a46e9bb..a3c7fd3 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -512,7 +512,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
 void nand_wait_ready(struct mtd_info *mtd)
 {
 	struct nand_chip *chip = mtd->priv;
-	unsigned long timeo = jiffies + 2;
+	unsigned long timeo = jiffies + (2 * HZ) / 1000;
 
 	/* 400ms timeout */
 	if (in_interrupt() || oops_in_progress)
-- 
1.7.5.4



From matthieu.castet at parrot.com  Sun Jun 26 12:26:52 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Sun, 26 Jun 2011 18:26:52 +0200
Subject: [PATCH 2/6] nand_wait : warn if the nand is busy on exit
In-Reply-To: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>

This patch allow to detect buggy driver/hardware with
bad RnB (dev_ready) management.
This check cost nothing and could help to detect bugs.

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
---
 drivers/mtd/nand/nand_base.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a3c7fd3..095dfea 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -885,6 +885,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 	led_trigger_event(nand_led_trigger, LED_OFF);
 
 	status = (int)chip->read_byte(mtd);
+	/* This can happen if in case of timeout or buggy dev_ready */
+	WARN_ON(!(status & NAND_STATUS_READY));
 	return status;
 }
 
-- 
1.7.5.4



From matthieu.castet at parrot.com  Sun Jun 26 12:26:55 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Sun, 26 Jun 2011 18:26:55 +0200
Subject: [PATCH 5/6] nand_flash_detect_onfi propagate busw info
In-Reply-To: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309105616-3609-5-git-send-email-matthieu.castet@parrot.com>

there is a bug in nand_flash_detect_onfi, busw need to be passed
by pointer to return it.

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
---
 drivers/mtd/nand/nand_base.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 5f0a0de..e7c8bdd 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2850,7 +2850,7 @@ static u16 onfi_crc16(u16 crc, u8 const *p, size_t len)
  * Check if the NAND chip is ONFI compliant, returns 1 if it is, 0 otherwise
  */
 static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
-					int busw)
+					int *busw)
 {
 	struct nand_onfi_params *p = &chip->onfi_params;
 	int i;
@@ -2905,9 +2905,9 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip,
 	mtd->erasesize = le32_to_cpu(p->pages_per_block) * mtd->writesize;
 	mtd->oobsize = le16_to_cpu(p->spare_bytes_per_page);
 	chip->chipsize = (uint64_t)le32_to_cpu(p->blocks_per_lun) * mtd->erasesize;
-	busw = 0;
+	*busw = 0;
 	if (le16_to_cpu(p->features) & 1)
-		busw = NAND_BUSWIDTH_16;
+		*busw = NAND_BUSWIDTH_16;
 
 	chip->options &= ~NAND_CHIPOPTIONS_MSK;
 	chip->options |= (NAND_NO_READRDY |
@@ -2973,7 +2973,7 @@ static struct nand_flash_dev *nand_get_flash_type(struct mtd_info *mtd,
 	chip->onfi_version = 0;
 	if (!type->name || !type->pagesize) {
 		/* Check is chip is ONFI compliant */
-		ret = nand_flash_detect_onfi(mtd, chip, busw);
+		ret = nand_flash_detect_onfi(mtd, chip, &busw);
 		if (ret)
 			goto ident_done;
 	}
-- 
1.7.5.4



From matthieu.castet at parrot.com  Sun Jun 26 12:26:56 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Sun, 26 Jun 2011 18:26:56 +0200
Subject: [PATCH 6/6] add NAND_BUSWIDTH_AUTO
In-Reply-To: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309105616-3609-6-git-send-email-matthieu.castet@parrot.com>

Nand read id and Read Parameter (onfi) return data on low 8 bits.
So if the driver start in 8 bit mode, it is possible to detect nand
buswidth, and configure the controller to the correct buswidth
after nand_scan_ident.

This is a new flag, so only driver that know what there are doing
will use it.

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
---
 drivers/mtd/nand/nand_base.c |    7 ++++++-
 include/linux/mtd/nand.h     |    5 +++++
 2 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index e7c8bdd..34f441e 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3096,11 +3096,16 @@ ident_done:
 			break;
 	}
 
+	if (chip->options & NAND_BUSWIDTH_AUTO) {
+		BUG_ON(chip->options & NAND_BUSWIDTH_16);
+		chip->options |= busw;
+		nand_set_defaults(chip, busw);
+	}
 	/*
 	 * Check, if buswidth is correct. Hardware drivers should set
 	 * chip correct !
 	 */
-	if (busw != (chip->options & NAND_BUSWIDTH_16)) {
+	else if (busw != (chip->options & NAND_BUSWIDTH_16)) {
 		printk(KERN_INFO "NAND device: Manufacturer ID:"
 		       " 0x%02x, Chip ID: 0x%02x (%s %s)\n", *maf_id,
 		       *dev_id, nand_manuf_ids[maf_idx].name, mtd->name);
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c2b9ac4..cdda28a 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -240,6 +240,11 @@ typedef enum {
 #define NAND_USE_FLASH_BBT_NO_OOB	0x00800000
 /* Create an empty BBT with no vendor information if the BBT is available */
 #define NAND_CREATE_EMPTY_BBT		0x01000000
+/* autodetect nand buswidth with readid. This suppose the driver will
+ * configure the hardware has 8 bit in nand_scan_ident, and update
+ * configuration before calling nand_scan_tail
+ */
+#define NAND_BUSWIDTH_AUTO			0x02000000
 
 /* Options set by nand scan */
 /* Nand scan has allocated controller struct */
-- 
1.7.5.4



From matthieu.castet at parrot.com  Sun Jun 26 12:26:54 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Sun, 26 Jun 2011 18:26:54 +0200
Subject: [PATCH 4/6] nand_wait_read : add code to wait on status for LP
In-Reply-To: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309105616-3609-4-git-send-email-matthieu.castet@parrot.com>

Use read status instead of waiting a fixed time.

For reading data after read status a command 0x0 should be issued (on large page) [1].
Only apply it for driver that use nand_command_lp, because other cmdfunc won't expect
NAND_CMD_READ0 without address.

[1]
While monitoring the read status to determine when the tR (transfer from Flash array to page
register) is complete, the host shall re-issue a command value of 00h to start reading data.
Issuing a command value of 00h will cause data to be returned starting at the selected column
address.

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
---
 drivers/mtd/nand/nand_base.c |   13 ++++++++++++-
 1 files changed, 12 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 70af1c0..5f0a0de 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -703,6 +703,8 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 		return;
 
 	case NAND_CMD_READ0:
+		if (column == -1 && page_addr == -1)
+			return;
 		chip->cmd_ctrl(mtd, NAND_CMD_READSTART,
 			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
 		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
@@ -889,11 +891,20 @@ static void nand_wait_reset(struct mtd_info *mtd, struct nand_chip *chip)
   */
 static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip)
 {
+	if (!chip->dev_ready && chip->cmdfunc == nand_command_lp) {
+		int status;
+		/* same timeout than nand_wait_ready */
+		unsigned long timeo = jiffies + (2 * HZ) / 1000;
+		status = nand_wait_timeout(mtd, chip, timeo);
+		WARN_ON(!(status & NAND_STATUS_READY));
+		/* start reading data */
+		chip->cmdfunc(mtd, NAND_CMD_READ0, -1, -1);
+	}
 	/*
 	 * If we don't have access to the busy pin, we apply the given
 	 * command delay
 	 */
-	if (!chip->dev_ready) {
+	else if (!chip->dev_ready) {
 		udelay(chip->chip_delay);
 	}
 	else {
-- 
1.7.5.4



From matthieu.castet at parrot.com  Sun Jun 26 12:26:53 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Sun, 26 Jun 2011 18:26:53 +0200
Subject: [PATCH 3/6] refactor mtd wait code
In-Reply-To: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309105616-3609-3-git-send-email-matthieu.castet@parrot.com>

This patch move the common wait code for read and reset in the function
nand_wait_reset and nand_wait_read.

The only fonctionnal change are :
- there is a 5s timeout for nand reset (there was no timeout before)
- For AUTOINC nand, we wait 100ns before pooling RnB (to be similar of
what we do after a read command).

Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
---
 drivers/mtd/nand/nand_base.c |  148 ++++++++++++++++++++++--------------------
 1 files changed, 78 insertions(+), 70 deletions(-)

diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 095dfea..70af1c0 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -99,6 +99,9 @@ static int nand_get_device(struct nand_chip *chip, struct mtd_info *mtd,
 static int nand_do_write_oob(struct mtd_info *mtd, loff_t to,
 			     struct mtd_oob_ops *ops);
 
+static void nand_wait_reset(struct mtd_info *mtd, struct nand_chip *chip);
+static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip);
+
 /*
  * For devices which display every fart in the system on a separate LED. Is
  * compiled away when LED support is disabled.
@@ -603,33 +606,11 @@ static void nand_command(struct mtd_info *mtd, unsigned int command,
 		return;
 
 	case NAND_CMD_RESET:
-		if (chip->dev_ready)
-			break;
-		udelay(chip->chip_delay);
-		chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
-			       NAND_CTRL_CLE | NAND_CTRL_CHANGE);
-		chip->cmd_ctrl(mtd,
-			       NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
-		while (!(chip->read_byte(mtd) & NAND_STATUS_READY))
-				;
+		nand_wait_reset(mtd, chip);
 		return;
-
-		/* This applies to read commands */
-	default:
-		/*
-		 * If we don't have access to the busy pin, we apply the given
-		 * command delay
-		 */
-		if (!chip->dev_ready) {
-			udelay(chip->chip_delay);
-			return;
-		}
 	}
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
-	ndelay(100);
-
-	nand_wait_ready(mtd);
+	/* This applies to read commands */
+	nand_wait_read(mtd, chip);
 }
 
 /**
@@ -710,15 +691,7 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 		return;
 
 	case NAND_CMD_RESET:
-		if (chip->dev_ready)
-			break;
-		udelay(chip->chip_delay);
-		chip->cmd_ctrl(mtd, NAND_CMD_STATUS,
-			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
-		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
-			       NAND_NCE | NAND_CTRL_CHANGE);
-		while (!(chip->read_byte(mtd) & NAND_STATUS_READY))
-				;
+		nand_wait_reset(mtd, chip);
 		return;
 
 	case NAND_CMD_RNDOUT:
@@ -734,24 +707,9 @@ static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
 			       NAND_NCE | NAND_CLE | NAND_CTRL_CHANGE);
 		chip->cmd_ctrl(mtd, NAND_CMD_NONE,
 			       NAND_NCE | NAND_CTRL_CHANGE);
-
-		/* This applies to read commands */
-	default:
-		/*
-		 * If we don't have access to the busy pin, we apply the given
-		 * command delay
-		 */
-		if (!chip->dev_ready) {
-			udelay(chip->chip_delay);
-			return;
-		}
 	}
-
-	/* Apply this short delay always to ensure that we do wait tWB in
-	 * any case on any machine. */
-	ndelay(100);
-
-	nand_wait_ready(mtd);
+	/* This applies to read commands */
+	nand_wait_read(mtd, chip);
 }
 
 /**
@@ -838,25 +796,19 @@ static void panic_nand_wait(struct mtd_info *mtd, struct nand_chip *chip,
 }
 
 /**
- * nand_wait - [DEFAULT]  wait until the command is done
+ * nand_wait_timeout - wait until the command is done
  * @mtd:	MTD device structure
  * @chip:	NAND chip structure
+ * @timeout : timeout (in jiffies) to wait
  *
- * Wait for command done. This applies to erase and program only
- * Erase can take up to 400ms and program up to 20ms according to
- * general NAND and SmartMedia specs
+ * Wait for command done. This applies to erase, program and reset
  */
-static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
+static int nand_wait_timeout(struct mtd_info *mtd, struct nand_chip *chip,
+					unsigned long timeo)
 {
 
-	unsigned long timeo = jiffies;
 	int status, state = chip->state;
 
-	if (state == FL_ERASING)
-		timeo += (HZ * 400) / 1000;
-	else
-		timeo += (HZ * 20) / 1000;
-
 	led_trigger_event(nand_led_trigger, LED_FULL);
 
 	/* Apply this short delay always to ensure that we do wait tWB in
@@ -891,6 +843,68 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
 }
 
 /**
+ * nand_wait - [DEFAULT]  wait until the command is done
+ * @mtd:	MTD device structure
+ * @chip:	NAND chip structure
+ *
+ * Wait for command done. This applies to erase and program only
+ * Erase can take up to 400ms and program up to 20ms according to
+ * general NAND and SmartMedia specs
+ */
+static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	unsigned long timeo = jiffies;
+	int state = chip->state;
+
+	if (state == FL_ERASING)
+		timeo += (HZ * 400) / 1000;
+	else
+		timeo += (HZ * 20) / 1000;
+
+	return nand_wait_timeout(mtd, chip, timeo);
+}
+
+/**
+ * nand_wait_reset - wait until the reset is done
+ * @mtd:	MTD device structure
+ * @chip:	NAND chip structure
+ *
+ * Wait for command done. This applies to erase and program only
+ */
+static void nand_wait_reset(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	/* 5s timeout */
+	unsigned long timeo = jiffies + (HZ * 5000) / 1000;
+	nand_wait_timeout(mtd, chip, timeo);
+
+	return;
+}
+
+/**
+  * This is call after sending a read command, or for autoincrement
+  * chip that need it (!NAND_NO_READRDY).
+  *
+  * We can't call NAND_CMD_STATUS here, because the read command
+  * is not finished
+  */
+static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip)
+{
+	/*
+	 * If we don't have access to the busy pin, we apply the given
+	 * command delay
+	 */
+	if (!chip->dev_ready) {
+		udelay(chip->chip_delay);
+	}
+	else {
+		/* Apply this short delay always to ensure that we do wait tWB in
+		 * any case on any machine. */
+		ndelay(100);
+		nand_wait_ready(mtd);
+	}
+}
+
+/**
  * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
  *
  * @mtd: mtd info
@@ -1526,10 +1540,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
 				 * increment is marked as NOAUTOINCR by the
 				 * board driver.
 				 */
-				if (!chip->dev_ready)
-					udelay(chip->chip_delay);
-				else
-					nand_wait_ready(mtd);
+				nand_wait_read(mtd, chip);
 			}
 		} else {
 			memcpy(buf, chip->buffers->databuf + col, bytes);
@@ -1811,10 +1822,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 			 * chip which does auto increment is marked as
 			 * NOAUTOINCR by the board driver.
 			 */
-			if (!chip->dev_ready)
-				udelay(chip->chip_delay);
-			else
-				nand_wait_ready(mtd);
+			nand_wait_read(mtd, chip);
 		}
 
 		readlen -= len;
-- 
1.7.5.4



From dbaryshkov at gmail.com  Sun Jun 26 16:09:16 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 00:09:16 +0400
Subject: linux-next: Tree for June 24 (mtd + of)
In-Reply-To: <1309081426.6618.0.camel@koala>
References: <20110624155822.cb8cf6eb.sfr@canb.auug.org.au>
	<20110624090456.191f1fda.randy.dunlap@oracle.com>
	<1308947172.13493.37.camel@koala> <4E04F5D0.9090900@oracle.com>
	<1308983721.23868.2.camel@koala>
	<20110625152009.f264be78.randy.dunlap@oracle.com>
	<BANLkTi=Q-7bCHaH+-z6gnbwvexpGLYH6pA@mail.gmail.com>
	<1309081426.6618.0.camel@koala>
Message-ID: <BANLkTikUbL0d49mhrYYLy2ZvOF9Wa0b+mw@mail.gmail.com>

On 6/26/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Sun, 2011-06-26 at 00:11 -0600, Grant Likely wrote:
>> > 3.0-rc4 does not have this build error when I use the .config file with
>> > it...
>> > however, I think that 3.0-rc4 also does not build ofpart.ko as it
>> > should.
>> >
>> > Looks to me like changes in drivers/mtd/{Kconfig && Makefile} caused
>> > this
>> > build error.
>>
>> The following commit in linux-next appears to be the culprit:
>>
>> commit 1a6bc893044b961caae1c5a9c6c2065e608da427
>> Author: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>> Date:   Sun May 29 21:32:33 2011 +0400
>>
>>     mtd: prepare to convert of_mtd_parse_partitions to partition parser
>>
>>     Prepare to convert of_mtd_parse_partitions() to usual partitions
>> parser:
>>     1) Register ofpart parser
>>     2) Internally don't use passed device for error printing
>>     3) Add device_node to mtd_part_parser_data struct
>>     4) Move of_mtd_parse_partitions from __devinit to common text section
>>     5) add ofpart to the default list of partition parsers
>>
>>     Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>>     Signed-off-by: Artem Bityutskiy <dedekind1 at gmail.com>
>>
>> It adds a module_init() call to ofpart.c which does not work the way
>> that ofpart.c is linked to mtdcore.o.  Seems like that commit series
>> still needs work.
>
> OK, let's ask Dmitry to take a look at this.

Yes, I've forgot about this... ofpart can be made a simple module now.
I'll send two patches in five minutes or so.

-- 
With best wishes
Dmitry


From dbaryshkov at gmail.com  Sun Jun 26 17:02:59 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 01:02:59 +0400
Subject: [PATCH 1/2] mtd: make ofpart buildable as a separate module
In-Reply-To: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1309122180-12838-2-git-send-email-dbaryshkov@gmail.com>

As ofpart now uses a standard mtd partitions parser interface, make it
buildable as a separate module. Also provide MODULE_DESCRIPTION and
MODULE_AUTHOR for this module.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/Kconfig  |    3 ++-
 drivers/mtd/Makefile |    2 +-
 drivers/mtd/ofpart.c |    2 ++
 3 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
index 4be8373..cc02e21 100644
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -137,7 +137,8 @@ config MTD_AFS_PARTS
 	  'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
 
 config MTD_OF_PARTS
-	def_bool y
+	tristate "OpenFirmware partitioning information support"
+	default Y
 	depends on OF
 	help
 	  This provides a partition parsing function which derives
diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
index 39664c4..9aaac3a 100644
--- a/drivers/mtd/Makefile
+++ b/drivers/mtd/Makefile
@@ -5,8 +5,8 @@
 # Core functionality.
 obj-$(CONFIG_MTD)		+= mtd.o
 mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
-mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 
+obj-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index 41c4518..aa33b8a 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -174,3 +174,5 @@ out:
 module_init(ofpart_parser_init);
 
 MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
+MODULE_AUTHOR("Vitaly Wool, David Gibson");
-- 
1.7.5.4



From dbaryshkov at gmail.com  Sun Jun 26 17:03:00 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 01:03:00 +0400
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>

ofpart.ko also provides ofoldpart MTD parser. Add respective
MODULE_ALIAS("ofoldpart"); declaration.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/ofpart.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index aa33b8a..c4b8d17 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -176,3 +176,4 @@ module_init(ofpart_parser_init);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
 MODULE_AUTHOR("Vitaly Wool, David Gibson");
+MODULE_ALIAS("ofoldpart");
-- 
1.7.5.4



From dbaryshkov at gmail.com  Sun Jun 26 17:02:58 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 01:02:58 +0400
Subject: [PATCH 0/2] finish modularization of ofpart parser
Message-ID: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>

To fix building of kernel if MTD is selected as a module and OF_PARTS
is selected, finish modularization of ofpart MTD partition parser.

The following changes since commit 81e49819e7d6c11c91702d6b4d9fc71255614488:

  mtd: spelling, capitalization, uniformity (2011-06-24 22:58:01 +0300)

are available in the git repository at:
  git://git.infradead.org/users/dbaryshkov/mtd-cleanup.git mtd-big-cleanup

Dmitry Eremin-Solenikov (2):
      mtd: make ofpart buildable as a separate module
      mtd/ofpart: add ofoldpart alias

 drivers/mtd/Kconfig  |    3 ++-
 drivers/mtd/Makefile |    2 +-
 drivers/mtd/ofpart.c |    3 +++
 3 files changed, 6 insertions(+), 2 deletions(-)



From randy.dunlap at oracle.com  Sun Jun 26 19:29:08 2011
From: randy.dunlap at oracle.com (Randy Dunlap)
Date: Sun, 26 Jun 2011 16:29:08 -0700
Subject: [PATCH 1/2] mtd: make ofpart buildable as a separate module
In-Reply-To: <1309122180-12838-2-git-send-email-dbaryshkov@gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
	<1309122180-12838-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <20110626162908.2f783471.randy.dunlap@oracle.com>

On Mon, 27 Jun 2011 01:02:59 +0400 Dmitry Eremin-Solenikov wrote:

> As ofpart now uses a standard mtd partitions parser interface, make it
> buildable as a separate module. Also provide MODULE_DESCRIPTION and
> MODULE_AUTHOR for this module.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Acked-by: Randy Dunlap <randy.dunlap at oracle.com>

Thanks.

> ---
>  drivers/mtd/Kconfig  |    3 ++-
>  drivers/mtd/Makefile |    2 +-
>  drivers/mtd/ofpart.c |    2 ++
>  3 files changed, 5 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/mtd/Kconfig b/drivers/mtd/Kconfig
> index 4be8373..cc02e21 100644
> --- a/drivers/mtd/Kconfig
> +++ b/drivers/mtd/Kconfig
> @@ -137,7 +137,8 @@ config MTD_AFS_PARTS
>  	  'physmap' map driver (CONFIG_MTD_PHYSMAP) does this, for example.
>  
>  config MTD_OF_PARTS
> -	def_bool y
> +	tristate "OpenFirmware partitioning information support"
> +	default Y
>  	depends on OF
>  	help
>  	  This provides a partition parsing function which derives
> diff --git a/drivers/mtd/Makefile b/drivers/mtd/Makefile
> index 39664c4..9aaac3a 100644
> --- a/drivers/mtd/Makefile
> +++ b/drivers/mtd/Makefile
> @@ -5,8 +5,8 @@
>  # Core functionality.
>  obj-$(CONFIG_MTD)		+= mtd.o
>  mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o mtdpart.o
> -mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
>  
> +obj-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
>  obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
>  obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
>  obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
> diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
> index 41c4518..aa33b8a 100644
> --- a/drivers/mtd/ofpart.c
> +++ b/drivers/mtd/ofpart.c
> @@ -174,3 +174,5 @@ out:
>  module_init(ofpart_parser_init);
>  
>  MODULE_LICENSE("GPL");
> +MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
> +MODULE_AUTHOR("Vitaly Wool, David Gibson");
> -- 

---
~Randy
*** Remember to use Documentation/SubmitChecklist when testing your code ***


From grant.likely at secretlab.ca  Sun Jun 26 19:35:35 2011
From: grant.likely at secretlab.ca (Grant Likely)
Date: Sun, 26 Jun 2011 17:35:35 -0600
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
	<1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>
Message-ID: <BANLkTi=G30BB66a6cbTWbmfd0Zokm2Kz3A@mail.gmail.com>

On Sun, Jun 26, 2011 at 3:03 PM, Dmitry Eremin-Solenikov
<dbaryshkov at gmail.com> wrote:
> ofpart.ko also provides ofoldpart MTD parser. Add respective
> MODULE_ALIAS("ofoldpart"); declaration.
>
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Is MODULE_ALIAS actually necessary for what is essentially a library
module?  I though MODULE_ALIAS was only needed to trigger loading a
module for specific hardware.  In this case, the module should be
autoloaded when another module needs it.  I may be misinformed though,
my module-foo is a little rusty.

g.

> ---
> ?drivers/mtd/ofpart.c | ? ?1 +
> ?1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
> index aa33b8a..c4b8d17 100644
> --- a/drivers/mtd/ofpart.c
> +++ b/drivers/mtd/ofpart.c
> @@ -176,3 +176,4 @@ module_init(ofpart_parser_init);
> ?MODULE_LICENSE("GPL");
> ?MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
> ?MODULE_AUTHOR("Vitaly Wool, David Gibson");
> +MODULE_ALIAS("ofoldpart");
> --
> 1.7.5.4
>
>



-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.


From dedekind1 at gmail.com  Mon Jun 27 01:45:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 08:45:40 +0300
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
	<1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1309153545.23597.13.camel@sauron>

On Mon, 2011-06-27 at 01:03 +0400, Dmitry Eremin-Solenikov wrote:
> ofpart.ko also provides ofoldpart MTD parser. Add respective
> MODULE_ALIAS("ofoldpart"); declaration.
> 

Why we need the alias?

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Mon Jun 27 01:49:23 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 08:49:23 +0300
Subject: [PATCH 1/2] mtd: make ofpart buildable as a separate module
In-Reply-To: <1309122180-12838-2-git-send-email-dbaryshkov@gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
	<1309122180-12838-2-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1309153769.23597.15.camel@sauron>

On Mon, 2011-06-27 at 01:02 +0400, Dmitry Eremin-Solenikov wrote:
> As ofpart now uses a standard mtd partitions parser interface, make it
> buildable as a separate module. Also provide MODULE_DESCRIPTION and
> MODULE_AUTHOR for this module.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>

Pushed this one to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Mon Jun 27 01:51:24 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 09:51:24 +0400
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309153545.23597.13.camel@sauron>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
	<1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>
	<1309153545.23597.13.camel@sauron>
Message-ID: <BANLkTikmCY8UjJWRKTkM_QW2_Bxw4yqPfQ@mail.gmail.com>

On 6/27/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Mon, 2011-06-27 at 01:03 +0400, Dmitry Eremin-Solenikov wrote:
>> ofpart.ko also provides ofoldpart MTD parser. Add respective
>> MODULE_ALIAS("ofoldpart"); declaration.
>>
>
> Why we need the alias?

Please check the parse_mtd_partitions code. If requested parser
isn't registered, it tries to load corresponding module. So, this alias
is necessary in the semi-bogus case when one will have the list
of parsers containing ofoldpart, but not ofpart partition parser.

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Mon Jun 27 02:03:26 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 09:03:26 +0300
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <BANLkTikmCY8UjJWRKTkM_QW2_Bxw4yqPfQ@mail.gmail.com>
References: <1309122180-12838-1-git-send-email-dbaryshkov@gmail.com>
	<1309122180-12838-3-git-send-email-dbaryshkov@gmail.com>
	<1309153545.23597.13.camel@sauron>
	<BANLkTikmCY8UjJWRKTkM_QW2_Bxw4yqPfQ@mail.gmail.com>
Message-ID: <1309154611.23597.18.camel@sauron>

On Mon, 2011-06-27 at 09:51 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/27/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> > On Mon, 2011-06-27 at 01:03 +0400, Dmitry Eremin-Solenikov wrote:
> >> ofpart.ko also provides ofoldpart MTD parser. Add respective
> >> MODULE_ALIAS("ofoldpart"); declaration.
> >>
> >
> > Why we need the alias?
> 
> Please check the parse_mtd_partitions code. If requested parser
> isn't registered, it tries to load corresponding module. So, this alias
> is necessary in the semi-bogus case when one will have the list
> of parsers containing ofoldpart, but not ofpart partition parser.

Fair enough, but would you please prepend MODULE_ALIAS with a comment
like this which explains why we need the alias?

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Mon Jun 27 02:11:24 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 09:11:24 +0300
Subject: [PATCH 1/2 v3] rewrite build system to avoid recursion
In-Reply-To: <1309022438-10093-1-git-send-email-vapier@gentoo.org>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1309022438-10093-1-git-send-email-vapier@gentoo.org>
Message-ID: <1309155088.23597.20.camel@sauron>

On Sat, 2011-06-25 at 13:20 -0400, Mike Frysinger wrote:
> The ubi-utils/src/ subdir is tossed as it just complicates things for no
> real gain.  The dictionary.h header is relocated to the ubi-utils/include/
> since other headers in there need it.
> 
> The top level clean is replaced with a `find -delete` on objects, so it
> might prune more than necessary, but many projects now do this sort of
> thing and no one complained there.
> 
> A "mkdep" helper generates the actual rule, and the variables are used
> with "foreach" to expand these automatically.
> 
> The tests subdir is updated only to reflect the ubi-utils source move.
> Otherwise, it is left untouched as making that non-recursive isn't really
> worth the effort.
> 
> While we're gutting things, also through in kbuild style output while
> building to make things more legible.
> 
> Signed-off-by: Mike Frysinger <vapier at gentoo.org>

Pushed both, thanks, this makes a lot of difference!

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Mon Jun 27 08:34:46 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 16:34:46 +0400
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309154611.23597.18.camel@sauron>
References: <1309154611.23597.18.camel@sauron>
Message-ID: <1309178086-10604-1-git-send-email-dbaryshkov@gmail.com>

ofpart.ko also provides ofoldpart MTD parser. Add respective
MODULE_ALIAS("ofoldpart"); declaration.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/ofpart.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index aa33b8a..77f0640 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -176,3 +176,6 @@ module_init(ofpart_parser_init);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
 MODULE_AUTHOR("Vitaly Wool, David Gibson");
+/* Required so that this module will be picked up ofoldpart
+ * MTD partition information parser */
+MODULE_ALIAS("ofoldpart");
-- 
1.7.5.4



From dbaryshkov at gmail.com  Mon Jun 27 08:58:01 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Mon, 27 Jun 2011 16:58:01 +0400
Subject: [PATCH] mtd: tmio_nand should call mtd_device_parse_register
Message-ID: <1309179481-30957-1-git-send-email-dbaryshkov@gmail.com>

While patching tmio_nand for mtd_device_parse_register(), I've changed
it to correctly pass arguments, but didn't change the function call
itself, so correct that mistake.

Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
---
 drivers/mtd/nand/tmio_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index d476857..beebd95 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -456,7 +456,7 @@ static int tmio_probe(struct platform_device *dev)
 		goto err_scan;
 	}
 	/* Register the partitions */
-	retval = mtd_device_register(mtd, NULL, 0,
+	retval = mtd_device_parse_register(mtd, NULL, 0,
 			data ? data->partition : NULL,
 			data ? data->num_partitions : 0);
 	if (!retval)
-- 
1.7.5.4



From grinberg at compulab.co.il  Mon Jun 27 09:22:05 2011
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Mon, 27 Jun 2011 16:22:05 +0300
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309000666-5242-1-git-send-email-leiwen@marvell.com>
References: <4E031900.50108@compulab.co.il>
	<1309000666-5242-1-git-send-email-leiwen@marvell.com>
Message-ID: <4E0883FD.3080707@compulab.co.il>

On 06/25/11 14:17, Lei Wen wrote:

> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
>
> Update platform driver to support this feature.
>
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
>  arch/arm/mach-mmp/aspenite.c                 |    5 +-
>  arch/arm/mach-pxa/cm-x300.c                  |    5 +-
>  arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
>  arch/arm/mach-pxa/littleton.c                |    5 +-
>  arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
>  arch/arm/mach-pxa/raumfeld.c                 |    5 +-
>  arch/arm/mach-pxa/zylonite.c                 |    5 +-
>  arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
>  drivers/mtd/nand/pxa3xx_nand.c               |  512 +++++++++++++++-----------
>  9 files changed, 346 insertions(+), 224 deletions(-)

~100 lines less - nice!

[...]

> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index b7db1b2..0825b7d 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c

[...]

> @@ -616,7 +627,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>  
>  	default:
>  		exec_cmd = 0;
> -		printk(KERN_ERR "pxa3xx-nand: non-supported"
> +		dev_err(&info->pdev->dev, "pxa3xx-nand: non-supported"

If you use dev_err(), why do you still need pxa3xx-nand in the message?


-- 
Regards,
Igor.



From peter.barada at gmail.com  Mon Jun 27 10:31:29 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Mon, 27 Jun 2011 10:31:29 -0400
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <1308943581.13493.15.camel@koala>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>	
	<4E020A36.6070708@gmail.com> <1308943581.13493.15.camel@koala>
Message-ID: <4E089441.3010809@gmail.com>

On 06/24/2011 03:26 PM, Artem Bityutskiy wrote:
> On Wed, 2011-06-22 at 11:28 -0400, Peter Barada wrote:
>> Thoughts?
> Sorry, could you please define the problem you are trying to solve?
> Sorry if you did define it in your long post, but I could not easily
> find it.
The problem I'm trying to solve is that the Micron NAND  I'm using has 
an internal 4-bit ECC engine and uses four 8-byte ECCs that provide 
4-bit protection per 512 data bytes + four OOB bytes.  The ecclayout I'm 
using is:

ecclayout = {
         eccbytes = 32,
         eccpos = { 8, 9, 10, 11, 12, 13, 14, 15, /* ECC data bytes 
0-511 + OOB bytes 4-7 */
                 24, 25, 26, 27, 28, 19, 30, 31, /* ECC data bytes 
512-1023 + OOB bytes 20-23 */
                 40, 41, 42, 43, 44, 45, 46, 47,  /* ECC data bytes 
1024-1535 + OOB bytes 36-39 */
                 56, 57, 58, 59, 60, 61, 62, 63},  /* ECC data bytes 
1536-2047 + OOB bytes 52-55 */
         .oobfree = {
                 { .offset = 4,
                   .length = 4},
                 { .offset = 20,
                   .length = 4},
                 { .offset = 36,
                   .length = 4},
                 { .offset = 52,
                   .length = 4},
         },
};

After the JFFS2 cleanmarker is written into bytes 4-7 and 16-23 of the 
OOB, nanddump shows:

   OOB Data: ff ff ff ff 85 19 03 20 5a e3 da 69 01 40 f1 36
   OOB Data: ff ff ff ff 08 00 00 00 91 99 3c 05 01 d0 5d b3
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
   OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

Note that the ECC bytes 8-15 and 24-31 are no longer FF due to bytes 4-7 
and bytes 20-23 being written with non-zero data.

When data is later written to this same page (w/o an intervening erase 
of its block) reading the page causes an uncorrectable ECC error.

There are eight additional bytes of OOB space available for writing, but 
they are not ECC'd.

The issue I'm trying to solve is how to communicate from MTD to JFFS2 
that some bytes of the oobfree array perturb the data ECC and can not be 
used to write the cleanmarker.

-- 
Peter Barada
peter.barada at gmail.com



From computersforpeace at gmail.com  Mon Jun 27 12:53:23 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 09:53:23 -0700
Subject: [PATCH 1/2 v3] rewrite build system to avoid recursion
In-Reply-To: <1309155088.23597.20.camel@sauron>
References: <1308983405-27064-1-git-send-email-vapier@gentoo.org>
	<1309022438-10093-1-git-send-email-vapier@gentoo.org>
	<1309155088.23597.20.camel@sauron>
Message-ID: <BANLkTikkhZOrevWrx=gZ-X7JZ6+J9ra_xw@mail.gmail.com>

On Sun, Jun 26, 2011 at 11:11 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> Pushed both, thanks, this makes a lot of difference!

I'll second the thanks! I really appreciate the cleaner build.


From computersforpeace at gmail.com  Mon Jun 27 14:27:17 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:17 -0700
Subject: [PATCH 00/10] more mtd-utils cleanup
Message-ID: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>

This series fixes several mtd-utils issues and takes care of a few things
on the feature-removal schedule.

I think patch 9 ("mtdinfo: kill -m option") could use some review, as I
am not the one who formed the original feature removal request.

Thanks,
Brian

Brian Norris (10):
  mtd-tests: checkfs: fix size_t related warning
  mtd-tests: io_paral: build error, "variable length strings"
  mtd-utils: remove whitespace at end of lines
  mtd-utils: update .gitignore files
  mkfs.ubifs: use common.h
  mtd-utils: add common version printing function
  mtd-utils: switch more utils to unified versioning
  mtd-utils: kill flash_info
  mtdinfo: kill -m option
  nanddump: remove unused variable

 .gitignore                               |    5 ++
 Makefile                                 |    2 +-
 device_table.txt                         |    6 +-
 feature-removal-schedule.txt             |   14 ------
 flash_info.c                             |   67 ------------------------------
 include/common.h                         |    6 +++
 include/linux/jffs2.h                    |    2 +-
 jffs2dump.c                              |    2 +-
 lib/libfec.c                             |   14 +++---
 mcast_image.h                            |    4 +-
 mkfs.jffs2.1                             |    6 +-
 mkfs.jffs2.c                             |    6 +-
 mkfs.ubifs/hashtable/hashtable.c         |   14 +++---
 mkfs.ubifs/hashtable/hashtable.h         |   30 +++++++-------
 mkfs.ubifs/hashtable/hashtable_itr.c     |   12 +++---
 mkfs.ubifs/hashtable/hashtable_itr.h     |   12 +++---
 mkfs.ubifs/hashtable/hashtable_private.h |   12 +++---
 mkfs.ubifs/mkfs.ubifs.c                  |   12 ++----
 nanddump.c                               |    3 +-
 nandtest.c                               |   16 ++++----
 rbtree.c                                 |    6 +-
 rbtree.h                                 |    4 +-
 recv_image.c                             |   24 +++++-----
 serve_image.c                            |   30 +++++++-------
 tests/checkfs/.gitignore                 |    2 +
 tests/checkfs/README                     |   26 ++++++------
 tests/checkfs/checkfs.c                  |    2 +-
 tests/fs-tests/integrity/.gitignore      |    1 +
 tests/fs-tests/simple/.gitignore         |    5 ++
 tests/fs-tests/stress/atoms/.gitignore   |   10 ++++
 tests/fs-tests/utils/.gitignore          |    2 +
 tests/jittertest/.gitignore              |    2 +
 tests/jittertest/README                  |   18 ++++----
 tests/jittertest/filljffs2.sh            |    2 +-
 tests/ubi-tests/io_paral.c               |    2 +-
 ubi-utils/dictionary.c                   |    6 +-
 ubi-utils/libiniparser.c                 |    8 ++--
 ubi-utils/mtdinfo.c                      |   30 ++++----------
 ubi-utils/ubiattach.c                    |    5 +-
 ubi-utils/ubicrc32.c                     |    5 +-
 ubi-utils/ubidetach.c                    |    5 +-
 ubi-utils/ubiformat.c                    |    5 +-
 ubi-utils/ubimkvol.c                     |    5 +-
 ubi-utils/ubinfo.c                       |    5 +-
 ubi-utils/ubinize.c                      |    5 +-
 ubi-utils/ubirename.c                    |    1 -
 ubi-utils/ubirmvol.c                     |    5 +-
 ubi-utils/ubirsvol.c                     |    5 +-
 ubi-utils/ubiupdatevol.c                 |    5 +-
 49 files changed, 199 insertions(+), 277 deletions(-)
 delete mode 100644 flash_info.c
 create mode 100644 tests/checkfs/.gitignore
 create mode 100644 tests/fs-tests/integrity/.gitignore
 create mode 100644 tests/fs-tests/simple/.gitignore
 create mode 100644 tests/fs-tests/stress/atoms/.gitignore
 create mode 100644 tests/fs-tests/utils/.gitignore
 create mode 100644 tests/jittertest/.gitignore




From computersforpeace at gmail.com  Mon Jun 27 14:27:18 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:18 -0700
Subject: [PATCH 01/10] mtd-tests: checkfs: fix size_t related warning
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-2-git-send-email-computersforpeace@gmail.com>

Depending on your compiler, size_t may or may not be long unsigned int.
Use printf's %zu format to clarify.

Warning message:

   checkfs.c:524:28: warning: format '%lu' expects type
   'long unsigned int', but argument 2 has type 'unsigned int'

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 tests/checkfs/checkfs.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/tests/checkfs/checkfs.c b/tests/checkfs/checkfs.c
index 8e74da8..0e67626 100644
--- a/tests/checkfs/checkfs.c
+++ b/tests/checkfs/checkfs.c
@@ -520,7 +520,7 @@ void processCmdLine(int argc, char **argv)
                 FileSizeMax = (float)atoi(argv[++cnt]);
                 if(FileSizeMax > (MAX_INTS_ALLOW*sizeof(int)))
                 {
-                    printf("Max file size allowed is %lu.\n",
+                    printf("Max file size allowed is %zu.\n",
                            MAX_INTS_ALLOW*sizeof(int));
                     exit(0);
                 }
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:19 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:19 -0700
Subject: [PATCH 02/10] mtd-tests: io_paral: build error,
	"variable length strings"
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-3-git-send-email-computersforpeace@gmail.com>

Some compilers will complain about use of strlen() within a static array
size declaration. For this type of string, "sizeof() - 1" is equivalent
and prevents the build error.

Error:

   io_paral.c:48:13: error: variably modified 'vol_nodes' at file scope

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 tests/ubi-tests/io_paral.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/tests/ubi-tests/io_paral.c b/tests/ubi-tests/io_paral.c
index 9754a0d..1d9a97c 100644
--- a/tests/ubi-tests/io_paral.c
+++ b/tests/ubi-tests/io_paral.c
@@ -45,7 +45,7 @@ static int vol_size;
 
 static struct ubi_mkvol_request reqests[THREADS_NUM + 1];
 static char vol_name[THREADS_NUM + 1][100];
-static char vol_nodes[THREADS_NUM + 1][strlen(UBI_VOLUME_PATTERN) + 100];
+static char vol_nodes[THREADS_NUM + 1][sizeof(UBI_VOLUME_PATTERN) + 99];
 static unsigned char *wbufs[THREADS_NUM + 1];
 static unsigned char *rbufs[THREADS_NUM + 1];
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:20 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:20 -0700
Subject: [PATCH 03/10] mtd-utils: remove whitespace at end of lines
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-4-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 device_table.txt                         |    6 +++---
 include/linux/jffs2.h                    |    2 +-
 lib/libfec.c                             |   14 +++++++-------
 mcast_image.h                            |    4 ++--
 mkfs.jffs2.1                             |    6 +++---
 mkfs.jffs2.c                             |    6 +++---
 mkfs.ubifs/hashtable/hashtable.c         |   14 +++++++-------
 mkfs.ubifs/hashtable/hashtable.h         |   30 +++++++++++++++---------------
 mkfs.ubifs/hashtable/hashtable_itr.c     |   12 ++++++------
 mkfs.ubifs/hashtable/hashtable_itr.h     |   12 ++++++------
 mkfs.ubifs/hashtable/hashtable_private.h |   12 ++++++------
 nandtest.c                               |   16 ++++++++--------
 rbtree.c                                 |    6 +++---
 rbtree.h                                 |    4 ++--
 recv_image.c                             |   24 ++++++++++++------------
 serve_image.c                            |   30 +++++++++++++++---------------
 tests/checkfs/README                     |   26 +++++++++++++-------------
 tests/jittertest/README                  |   18 +++++++++---------
 tests/jittertest/filljffs2.sh            |    2 +-
 ubi-utils/dictionary.c                   |    6 +++---
 ubi-utils/libiniparser.c                 |    8 ++++----
 21 files changed, 129 insertions(+), 129 deletions(-)

diff --git a/device_table.txt b/device_table.txt
index 74fdc56..194fed6 100644
--- a/device_table.txt
+++ b/device_table.txt
@@ -5,10 +5,10 @@
 #   /sbin/foobar	f	2755	0	0	-	-	-	-	-
 # and (assuming the file /sbin/foobar exists) it will be made setuid
 # root (regardless of what its permissions are on the host filesystem.
-# 
+#
 # Device table entries take the form of:
 # <name>		<type>	<mode>	<uid>	<gid>	<major>	<minor>	<start>	<inc>	<count>
-# where name is the file name,  type can be one of: 
+# where name is the file name,  type can be one of:
 #	f	A regular file
 #	d	Directory
 #	c	Character special device file
@@ -19,7 +19,7 @@
 # file.
 
 # When building a target filesystem, it is desirable to not have to
-# become root and then run 'mknod' a thousand times.  Using a device 
+# become root and then run 'mknod' a thousand times.  Using a device
 # table you can create device nodes and directories "on the fly".
 # Furthermore, you can use a single table entry to create a many device
 # minors.  For example, if I wanted to create /dev/hda and /dev/hda[0-15]
diff --git a/include/linux/jffs2.h b/include/linux/jffs2.h
index c2f684a..7306f86 100644
--- a/include/linux/jffs2.h
+++ b/include/linux/jffs2.h
@@ -15,7 +15,7 @@
 #ifndef __LINUX_JFFS2_H__
 #define __LINUX_JFFS2_H__
 
-/* You must include something which defines the C99 uintXX_t types. 
+/* You must include something which defines the C99 uintXX_t types.
    We don't do it from here because this file is used in too many
    different environments. */
 
diff --git a/lib/libfec.c b/lib/libfec.c
index c89a180..ff5a127 100644
--- a/lib/libfec.c
+++ b/lib/libfec.c
@@ -79,7 +79,7 @@ typedef unsigned short u_short ;
 	  if (t1 < t) t = 256000000 + t1 - t ; \
 	  else t = t1 - t ; \
 	  if (t == 0) t = 1 ;}
-	
+
 u_long ticks[10];	/* vars for timekeeping */
 #else
 #define DEB(x)
@@ -200,7 +200,7 @@ static inline gf
 gf_mul(x,y)
 {
     if ( (x) == 0 || (y)==0 ) return 0;
-     
+
     return gf_exp[gf_log[x] + gf_log[y] ] ;
 }
 #define init_mul_table()
@@ -315,7 +315,7 @@ generate_gf(void)
  * unrolled 16 times, a good value for 486 and pentium-class machines.
  * The case c=0 is also optimized, whereas c=1 is not. These
  * calls are unfrequent in my typical apps so I did not bother.
- * 
+ *
  * Note that gcc on
  */
 #define addmul(dst, src, c, sz) \
@@ -452,7 +452,7 @@ invert_mat(gf *src, int k)
 			}
 		    } else if (ipiv[ix] > 1) {
 			fprintf(stderr, "singular matrix\n");
-			goto fail ; 
+			goto fail ;
 		    }
 		}
 	    }
@@ -562,7 +562,7 @@ invert_vdm(gf *src, int k)
     b = NEW_GF_MATRIX(1, k);
 
     p = NEW_GF_MATRIX(1, k);
-   
+
     for ( j=1, i = 0 ; i < k ; i++, j+=k ) {
 	c[i] = 0 ;
 	p[i] = src[j] ;    /* p[i] */
@@ -807,7 +807,7 @@ build_decode_matrix(struct fec_parms *code, int index[])
 	} else
 #endif
 	if (index[i] < code->n )
-	    memcpy(p,  &(code->enc_matrix[index[i]*k]), k*sizeof(gf) ); 
+	    memcpy(p,  &(code->enc_matrix[index[i]*k]), k*sizeof(gf) );
 	else {
 	    fprintf(stderr, "decode: invalid index %d (max %d)\n",
 		index[i], code->n - 1 );
@@ -838,7 +838,7 @@ build_decode_matrix(struct fec_parms *code, int index[])
 int
 fec_decode(struct fec_parms *code, gf *pkt[], int index[], int sz)
 {
-    gf *m_dec ; 
+    gf *m_dec ;
     gf **new_pkt ;
     int row, col , k = code->k ;
 
diff --git a/mcast_image.h b/mcast_image.h
index 07b6e31..8e94ffa 100644
--- a/mcast_image.h
+++ b/mcast_image.h
@@ -24,7 +24,7 @@ struct image_pkt {
 struct fec_parms;
 
 /* k - number of actual data packets
- * n - total number of packets including data and redundant packets 
+ * n - total number of packets including data and redundant packets
  *   (actual packet size isn't relevant here) */
 struct fec_parms *fec_new(int k, int n);
 void fec_free(struct fec_parms *p);
@@ -45,7 +45,7 @@ void fec_encode_linear(struct fec_parms *code, unsigned char *src,
 /* data  - array of (k) pointers to data packets, in arbitrary order (see i)
  * i     - indices of (data) packets
  * sz    - data packet size
- * 
+ *
  * Will never fail as long as you give it (k) individual data packets.
  * Will re-order the (data) pointers but not the indices -- data packets
  * are ordered on return.
diff --git a/mkfs.jffs2.1 b/mkfs.jffs2.1
index 1eefeda..9b0acc3 100644
--- a/mkfs.jffs2.1
+++ b/mkfs.jffs2.1
@@ -104,7 +104,7 @@ or the present directory, if the
 .B -r
 option is not specified.
 
-Each block of the files to be placed into the file system image 
+Each block of the files to be placed into the file system image
 are compressed using one of the avaiable compressors depending
 on the selected compression mode.
 
@@ -196,8 +196,8 @@ Enables xattr, stuff only SELinux Labels into jffs2 image file.
 Enable xattr, stuff only POSIX ACL entries into jffs2 image file.
 .TP
 .B -m, --compression-mode=MODE
-Set the default compression mode. The default mode is 
-.B priority 
+Set the default compression mode. The default mode is
+.B priority
 which tries the compressors in a predefinied order and chooses the first
 successful one. The alternatives are:
 .B none
diff --git a/mkfs.jffs2.c b/mkfs.jffs2.c
index 7abaf50..ad88ac6 100644
--- a/mkfs.jffs2.c
+++ b/mkfs.jffs2.c
@@ -123,11 +123,11 @@ uint32_t find_hardlink(struct filesystem_entry *e)
 		f = rb_entry(parent, struct filesystem_entry, hardlink_rb);
 
 		if ((f->sb.st_dev < e->sb.st_dev) ||
-		    (f->sb.st_dev == e->sb.st_dev && 
+		    (f->sb.st_dev == e->sb.st_dev &&
 		     f->sb.st_ino < e->sb.st_ino))
 			n = &parent->rb_left;
 		else if ((f->sb.st_dev > e->sb.st_dev) ||
-			 (f->sb.st_dev == e->sb.st_dev && 
+			 (f->sb.st_dev == e->sb.st_dev &&
 			  f->sb.st_ino > e->sb.st_ino)) {
 			n = &parent->rb_right;
 		} else
@@ -264,7 +264,7 @@ static struct filesystem_entry *add_host_filesystem_entry(const char *name,
 	tmp = xstrdup(name);
 	entry->path = xstrdup(dirname(tmp));
 	free(tmp);
-	
+
 	entry->sb.st_ino = sb.st_ino;
 	entry->sb.st_dev = sb.st_dev;
 	entry->sb.st_nlink = sb.st_nlink;
diff --git a/mkfs.ubifs/hashtable/hashtable.c b/mkfs.ubifs/hashtable/hashtable.c
index 8aa273c..c1f99ed 100644
--- a/mkfs.ubifs/hashtable/hashtable.c
+++ b/mkfs.ubifs/hashtable/hashtable.c
@@ -100,7 +100,7 @@ hashtable_expand(struct hashtable *h)
         h->table = newtable;
     }
     /* Plan B: realloc instead */
-    else 
+    else
     {
         newtable = (struct entry **)
                    realloc(h->table, newsize * sizeof(struct entry *));
@@ -246,23 +246,23 @@ hashtable_destroy(struct hashtable *h, int free_values)
 /*
  * Copyright (c) 2002, Christopher Clark
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/mkfs.ubifs/hashtable/hashtable.h b/mkfs.ubifs/hashtable/hashtable.h
index b90781a..c0b0acd 100644
--- a/mkfs.ubifs/hashtable/hashtable.h
+++ b/mkfs.ubifs/hashtable/hashtable.h
@@ -19,7 +19,7 @@ struct hashtable;
  *      v = (struct some_value *)   malloc(sizeof(struct some_value));
  *
  *      (initialise k and v to suitable values)
- * 
+ *
  *      if (! hashtable_insert(h,k,v) )
  *      {     exit(-1);               }
  *
@@ -33,7 +33,7 @@ struct hashtable;
 
 /* Macros may be used to define type-safe(r) hashtable access functions, with
  * methods specialized to take known key and value types as parameters.
- * 
+ *
  * Example:
  *
  * Insert this at the start of your file:
@@ -63,7 +63,7 @@ struct hashtable;
 
 /*****************************************************************************
  * create_hashtable
-   
+
  * @name                    create_hashtable
  * @param   minsize         minimum initial size of hashtable
  * @param   hashfunction    function for hashing keys
@@ -78,7 +78,7 @@ create_hashtable(unsigned int minsize,
 
 /*****************************************************************************
  * hashtable_insert
-   
+
  * @name        hashtable_insert
  * @param   h   the hashtable to insert into
  * @param   k   the key - hashtable claims ownership and will free on removal
@@ -95,7 +95,7 @@ create_hashtable(unsigned int minsize,
  * If in doubt, remove before insert.
  */
 
-int 
+int
 hashtable_insert(struct hashtable *h, void *k, void *v);
 
 #define DEFINE_HASHTABLE_INSERT(fnname, keytype, valuetype) \
@@ -106,7 +106,7 @@ int fnname (struct hashtable *h, keytype *k, valuetype *v) \
 
 /*****************************************************************************
  * hashtable_search
-   
+
  * @name        hashtable_search
  * @param   h   the hashtable to search
  * @param   k   the key to search for  - does not claim ownership
@@ -124,7 +124,7 @@ valuetype * fnname (struct hashtable *h, keytype *k) \
 
 /*****************************************************************************
  * hashtable_remove
-   
+
  * @name        hashtable_remove
  * @param   h   the hashtable to remove the item from
  * @param   k   the key to search for  - does not claim ownership
@@ -143,7 +143,7 @@ valuetype * fnname (struct hashtable *h, keytype *k) \
 
 /*****************************************************************************
  * hashtable_count
-   
+
  * @name        hashtable_count
  * @param   h   the hashtable
  * @return      the number of items stored in the hashtable
@@ -154,7 +154,7 @@ hashtable_count(struct hashtable *h);
 
 /*****************************************************************************
  * hashtable_destroy
-   
+
  * @name        hashtable_destroy
  * @param   h   the hashtable
  * @param       free_values     whether to call 'free' on the remaining values
@@ -168,23 +168,23 @@ hashtable_destroy(struct hashtable *h, int free_values);
 /*
  * Copyright (c) 2002, Christopher Clark
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/mkfs.ubifs/hashtable/hashtable_itr.c b/mkfs.ubifs/hashtable/hashtable_itr.c
index 5dced84..24f4dde 100644
--- a/mkfs.ubifs/hashtable/hashtable_itr.c
+++ b/mkfs.ubifs/hashtable/hashtable_itr.c
@@ -157,23 +157,23 @@ hashtable_iterator_search(struct hashtable_itr *itr,
 /*
  * Copyright (c) 2002, 2004, Christopher Clark
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/mkfs.ubifs/hashtable/hashtable_itr.h b/mkfs.ubifs/hashtable/hashtable_itr.h
index eea699a..87a97eb 100644
--- a/mkfs.ubifs/hashtable/hashtable_itr.h
+++ b/mkfs.ubifs/hashtable/hashtable_itr.h
@@ -81,23 +81,23 @@ int fnname (struct hashtable_itr *i, struct hashtable *h, keytype *k) \
 /*
  * Copyright (c) 2002, 2004, Christopher Clark
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/mkfs.ubifs/hashtable/hashtable_private.h b/mkfs.ubifs/hashtable/hashtable_private.h
index 3e95f60..3a558e6 100644
--- a/mkfs.ubifs/hashtable/hashtable_private.h
+++ b/mkfs.ubifs/hashtable/hashtable_private.h
@@ -54,23 +54,23 @@ indexFor(unsigned int tablelength, unsigned int hashvalue)
 /*
  * Copyright (c) 2002, Christopher Clark
  * All rights reserved.
- * 
+ *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * are met:
- * 
+ *
  * * Redistributions of source code must retain the above copyright
  * notice, this list of conditions and the following disclaimer.
- * 
+ *
  * * Redistributions in binary form must reproduce the above copyright
  * notice, this list of conditions and the following disclaimer in the
  * documentation and/or other materials provided with the distribution.
- * 
+ *
  * * Neither the name of the original author; nor the names of any contributors
  * may be used to endorse or promote products derived from this software
  * without specific prior written permission.
- * 
- * 
+ *
+ *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/nandtest.c b/nandtest.c
index 93f01ca..d03dc11 100644
--- a/nandtest.c
+++ b/nandtest.c
@@ -79,7 +79,7 @@ int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf)
 
 	printf("\r%08x: reading...", (unsigned)ofs);
 	fflush(stdout);
-	
+
 	len = pread(fd, rbuf, meminfo.erasesize, ofs);
 	if (len < meminfo.erasesize) {
 		printf("\n");
@@ -89,7 +89,7 @@ int erase_and_write(loff_t ofs, unsigned char *data, unsigned char *rbuf)
 			perror("read");
 		exit(1);
 	}
-		
+
 	if (ioctl(fd, ECCGETSTATS, &newstats)) {
 		printf("\n");
 		perror("ECCGETSTATS");
@@ -184,7 +184,7 @@ int main(int argc, char **argv)
 		case 'l':
 			length = strtol(optarg, NULL, 0);
 			break;
-			
+
 		}
 	}
 	if (argc - optind != 1)
@@ -195,7 +195,7 @@ int main(int argc, char **argv)
 		perror("open");
 		exit(1);
 	}
-	
+
 	if (ioctl(fd, MEMGETINFO, &meminfo)) {
 		perror("MEMGETINFO");
 		close(fd);
@@ -206,20 +206,20 @@ 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 %x 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 %x 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 %x + offset %x exceeds device size %x\n",
 			length, offset, meminfo.size);
 		exit(1);
-	}		
+	}
 
 	wbuf = malloc(meminfo.erasesize * 3);
 	if (!wbuf) {
diff --git a/rbtree.c b/rbtree.c
index dd50134..329e098 100644
--- a/rbtree.c
+++ b/rbtree.c
@@ -2,7 +2,7 @@
   Red Black Trees
   (C) 1999  Andrea Arcangeli <andrea at suse.de>
   (C) 2002  David Woodhouse <dwmw2 at infradead.org>
-  
+
   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
@@ -324,7 +324,7 @@ struct rb_node *rb_next(struct rb_node *node)
 	/* If we have a right-hand child, go down and then left as far
 	   as we can. */
 	if (node->rb_right) {
-		node = node->rb_right; 
+		node = node->rb_right;
 		while (node->rb_left)
 			node=node->rb_left;
 		return node;
@@ -352,7 +352,7 @@ struct rb_node *rb_prev(struct rb_node *node)
 	/* If we have a left-hand child, go down and then right as far
 	   as we can. */
 	if (node->rb_left) {
-		node = node->rb_left; 
+		node = node->rb_left;
 		while (node->rb_right)
 			node=node->rb_right;
 		return node;
diff --git a/rbtree.h b/rbtree.h
index e64dc9a..0d77b65 100644
--- a/rbtree.h
+++ b/rbtree.h
@@ -1,7 +1,7 @@
 /*
   Red Black Trees
   (C) 1999  Andrea Arcangeli <andrea at suse.de>
-  
+
   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
@@ -156,7 +156,7 @@ extern struct rb_node *rb_first(struct rb_root *);
 extern struct rb_node *rb_last(struct rb_root *);
 
 /* Fast replacement of a single node without remove/rebalance/add/rebalance */
-extern void rb_replace_node(struct rb_node *victim, struct rb_node *new, 
+extern void rb_replace_node(struct rb_node *victim, struct rb_node *new,
 			    struct rb_root *root);
 
 static inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
diff --git a/recv_image.c b/recv_image.c
index a3c3fd5..26a8361 100644
--- a/recv_image.c
+++ b/recv_image.c
@@ -111,7 +111,7 @@ int main(int argc, char **argv)
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_flags = AI_ADDRCONFIG;
 	hints.ai_socktype = SOCK_DGRAM;
-	
+
 	ret = getaddrinfo(argv[1], argv[2], &hints, &ai);
 	if (ret) {
 		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
@@ -131,18 +131,18 @@ int main(int argc, char **argv)
 			rq.imr_multiaddr = ((struct sockaddr_in *)runp->ai_addr)->sin_addr;
 			rq.imr_interface.s_addr = INADDR_ANY;
 			if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &rq, sizeof(rq))) {
-				perror("IP_ADD_MEMBERSHIP"); 
+				perror("IP_ADD_MEMBERSHIP");
 				close(sock);
 				continue;
 			}
-			
+
 		} else if (runp->ai_family == AF_INET6 &&
 			   ((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr.s6_addr[0] == 0xff) {
 			struct ipv6_mreq rq;
 			rq.ipv6mr_multiaddr =  ((struct sockaddr_in6 *)runp->ai_addr)->sin6_addr;
 			rq.ipv6mr_interface = 0;
 			if (setsockopt(sock, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &rq, sizeof(rq))) {
-				perror("IPV6_ADD_MEMBERSHIP"); 
+				perror("IPV6_ADD_MEMBERSHIP");
 				close(sock);
 				continue;
 			}
@@ -254,7 +254,7 @@ int main(int argc, char **argv)
 			continue;
 		}
 	pkt_again:
-		eraseblocks[block_nr].pkt_indices[eraseblocks[block_nr].nr_pkts++] = 
+		eraseblocks[block_nr].pkt_indices[eraseblocks[block_nr].nr_pkts++] =
 			ntohs(thispkt.hdr.pkt_nr);
 		total_pkts++;
 		if (!(total_pkts % 50) || total_pkts == pkts_per_block * nr_blocks) {
@@ -290,7 +290,7 @@ int main(int argc, char **argv)
 			       thispkt.data, fits);
 			wrotelen = pwrite(flfd, eraseblocks[block_nr].wbuf, WBUF_SIZE,
 					  eraseblocks[block_nr].flash_offset);
-			
+
 			if (wrotelen < WBUF_SIZE || (block_nr == 5 && eraseblocks[block_nr].nr_pkts == 5 && !faked)) {
 				faked = 1;
 				if (wrotelen < 0)
@@ -308,7 +308,7 @@ int main(int argc, char **argv)
 						~(meminfo.erasesize - 1);
 					erase.length = meminfo.erasesize;
 
-					printf("Will erase at %08x len %08x (bad write was at %08x)\n", 
+					printf("Will erase at %08x len %08x (bad write was at %08x)\n",
 					       erase.start, erase.length, eraseblocks[block_nr].flash_offset);
 					if (ioctl(flfd, MEMERASE, &erase)) {
 						perror("MEMERASE");
@@ -342,7 +342,7 @@ int main(int argc, char **argv)
 			memcpy(eraseblocks[block_nr].wbuf, &thispkt.data[fits], PKT_SIZE - fits);
 			eraseblocks[block_nr].wbuf_ofs = PKT_SIZE - fits;
 		}
-		
+
 		if (eraseblocks[block_nr].nr_pkts == pkts_per_block) {
 			eraseblocks[block_nr].crc = ntohl(thispkt.hdr.block_crc);
 
@@ -388,7 +388,7 @@ int main(int argc, char **argv)
 		gettimeofday(&now, NULL);
 		fec_time += (now.tv_usec - start.tv_usec) / 1000;
 		fec_time += (now.tv_sec - start.tv_sec) * 1000;
-		
+
 		for (i=0; i < pkts_per_block; i++)
 			memcpy(&decode_buf[i*PKT_SIZE], src_pkts[i], PKT_SIZE);
 
@@ -396,7 +396,7 @@ int main(int argc, char **argv)
 		gettimeofday(&start, NULL);
 		if (mtd_crc32(-1, decode_buf, meminfo.erasesize) != eraseblocks[block_nr].crc) {
 			printf("\nCRC mismatch for block #%d: want %08x got %08x\n",
-			       block_nr, eraseblocks[block_nr].crc, 
+			       block_nr, eraseblocks[block_nr].crc,
 			       mtd_crc32(-1, decode_buf, meminfo.erasesize));
 			exit(1);
 		}
@@ -410,7 +410,7 @@ int main(int argc, char **argv)
 
 			erase.start = eraseblocks[block_nr].flash_offset;
 			erase.length = meminfo.erasesize;
-			
+
 			printf("\rErasing block at %08x...", erase.start);
 
 			if (ioctl(flfd, MEMERASE, &erase)) {
@@ -430,7 +430,7 @@ int main(int argc, char **argv)
 		if (rwlen < meminfo.erasesize) {
 			if (rwlen < 0) {
 				perror("\ndecoded data write");
-			} else 
+			} else
 				fprintf(stderr, "\nshort write of decoded data\n");
 
 			if (!file_mode) {
diff --git a/serve_image.c b/serve_image.c
index f7f6315..38549a1 100644
--- a/serve_image.c
+++ b/serve_image.c
@@ -2,13 +2,13 @@
 #define _POSIX_C_SOURCE 199309
 
 #include <time.h>
-#include <errno.h>  	
-#include <error.h> 	
-#include <netdb.h> 	
-#include <stdio.h> 	
-#include <stdlib.h> 	
+#include <errno.h>
+#include <error.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
-#include <unistd.h> 	
+#include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -83,7 +83,7 @@ int main(int argc, char **argv)
 		fprintf(stderr, "Failed to allocate last-block buffer\n");
 		exit(1);
 	}
-	
+
 	fec = fec_new(pkts_per_block, total_pkts_per_block);
 	if (!fec) {
 		fprintf(stderr, "Error initialising FEC\n");
@@ -93,7 +93,7 @@ int main(int argc, char **argv)
 	memset(&hints, 0, sizeof(hints));
 	hints.ai_flags = AI_ADDRCONFIG;
 	hints.ai_socktype = SOCK_DGRAM;
-	
+
 	ret = getaddrinfo(argv[1], argv[2], &hints, &ai);
 	if (ret) {
 		fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(ret));
@@ -167,9 +167,9 @@ int main(int argc, char **argv)
 		fflush(stdout);
 		block_crcs[block_nr] = mtd_crc32(-1, image + (block_nr * erasesize), erasesize);
 	}
-		
+
 	printf("\nImage size %ld KiB (0x%08lx). %d blocks at %d pkts/block\n"
-	       "Estimated transmit time per cycle: %ds\n", 
+	       "Estimated transmit time per cycle: %ds\n",
 	       (long)st.st_size / 1024, (long) st.st_size,
 	       nr_blocks, pkts_per_block,
 	       nr_blocks * pkts_per_block * pkt_delay / 1000000);
@@ -202,11 +202,11 @@ int main(int argc, char **argv)
 			   the first $pkts_per_block are cheap enough though
 			   because they're just copies. So alternate between
 			   simple and complex stuff, so that we don't start
-			   to choke and fail to keep up with the expected 
+			   to choke and fail to keep up with the expected
 			   bitrate in the second half of the sequence */
 			if (block_nr & 1)
 				actualpkt = pkt_nr;
-			else 
+			else
 				actualpkt = total_pkts_per_block - 1 - pkt_nr;
 
 			blockptr = image + (erasesize * block_nr);
@@ -246,7 +246,7 @@ int main(int argc, char **argv)
 #endif
 			gettimeofday(&now, NULL);
 #if 1
-			tosleep = nextpkt.tv_usec - now.tv_usec + 
+			tosleep = nextpkt.tv_usec - now.tv_usec +
 				(1000000 * (nextpkt.tv_sec - now.tv_sec));
 
 			/* We need hrtimers for this to actually work */
@@ -276,7 +276,7 @@ int main(int argc, char **argv)
 			   Adjust our expected timings accordingly. If
 			   we're only a little way behind, don't slip yet */
 			if (now.tv_usec > (now.tv_usec + (5 * pkt_delay) +
-					   1000000 * (nextpkt.tv_sec - now.tv_sec))) { 
+					1000000 * (nextpkt.tv_sec - now.tv_sec))) {
 				nextpkt = now;
 			}
 
@@ -291,7 +291,7 @@ int main(int argc, char **argv)
 				writeerrors = 0;
 
 
-			
+
 		}
 	}
 	munmap(image, st.st_size);
diff --git a/tests/checkfs/README b/tests/checkfs/README
index d9966a5..6b72487 100644
--- a/tests/checkfs/README
+++ b/tests/checkfs/README
@@ -11,11 +11,11 @@ This is the README file for the "checkfs" power fail test program.
 By: Vipin Malik
 
 NOTE: This program requires an external "power cycling box"
-connected to one of the com ports of the system under test. 
-This power cycling box should wait for a random amount of time 
-after it receives a "ok to power me down" message over the 
+connected to one of the com ports of the system under test.
+This power cycling box should wait for a random amount of time
+after it receives a "ok to power me down" message over the
 serial port, and then yank power to the system under test.
-(The box that I rigged up tested with waits anywhere from 
+(The box that I rigged up tested with waits anywhere from
 0 to ~40 seconds).
 
 
@@ -75,7 +75,7 @@ some "sister" files on the root fs even though "checkfs" would
 run fine through all its own check files.
 
 (I found this out when one of the clobbered sister file happened
-to be /bin/bash. The system refused to run rc.local thus 
+to be /bin/bash. The system refused to run rc.local thus
 preventing my "checkfs" program from being launched :)
 
 "checkfs":
@@ -98,8 +98,8 @@ Each file has a random number of bytes in it (set by using the
 first "int" in it (note: 0 length files are not allowed). Each file
 is then filled with random data and a 16 bit CRC appended at the end.
 
-When "checkfs" is run, it runs through all files (with predetermined 
-file names)- one at a time- and checks for the number of "int's" 
+When "checkfs" is run, it runs through all files (with predetermined
+file names)- one at a time- and checks for the number of "int's"
 in it as well as the ending CRC.
 
 The program exits if the numbers of files that are corrupt are greater
@@ -116,10 +116,10 @@ the data reliability of "other" files present of the fs, use -e 1.
 "other" files are defined as sister files on the fs, not being written to
 by the "checkfs" test program.
 
-As mentioned, in this case you would set -e 1, or allow at most 1 file 
-to be corrupt each time after a power fail. This would be the file 
-that was probably being written to when power failed (and CRC was not 
-updated to reflect the  new data being written). You would check file 
+As mentioned, in this case you would set -e 1, or allow at most 1 file
+to be corrupt each time after a power fail. This would be the file
+that was probably being written to when power failed (and CRC was not
+updated to reflect the  new data being written). You would check file
 systems like ext2 etc. with such a configuration.
 (As you have no hope that these file systems provide for either your
 new data or old data to be present in the file if power failed during
@@ -137,13 +137,13 @@ In other words, JFFS2 will partially update a file on FLASH even before
 the write() command has completed, thus leaving part old data part new
 data in your file if power failed in the middle of a write().
 
-This is bad functionality if you are updating a binary structure or a 
+This is bad functionality if you are updating a binary structure or a
 CRC protected file (as in our case).
 
 
 If All Files Check Out OK:
 
-On the startup scan, if there are less errors than specified by the "-e flag" 
+On the startup scan, if there are less errors than specified by the "-e flag"
 a "ok to power me down message" is sent via the specified com port.
 
 The actual format of this message will depend on the format expected
diff --git a/tests/jittertest/README b/tests/jittertest/README
index f411a2c..b97a8b7 100644
--- a/tests/jittertest/README
+++ b/tests/jittertest/README
@@ -11,7 +11,7 @@ a real time task under Linux with background
 JFFS file system activity.
 
 The jitter is measured in milli seconds (ms) from
-the expected time of arrival of a signal from a 
+the expected time of arrival of a signal from a
 periodic timer (set by the task) to when the
 task actually gets the signal.
 
@@ -20,7 +20,7 @@ This jitter is then stored in a file specified
 
 The data  may also be sent out to the console by
 writing to /dev/console (See help options. This is
-highly desirable specially if you have redirected 
+highly desirable specially if you have redirected
 your console to the serial port and are storing it
 as a minicom log on another computer for later analysis
 using some tools provided here).
@@ -82,7 +82,7 @@ supports it).
   In this test you would generate some background
 write/erase type activity that would generate
 chip erases. Since this program is reading from
-the same file system, you contrast the latencies 
+the same file system, you contrast the latencies
 with those obtained with writes going to the same
 fs.
 
@@ -90,7 +90,7 @@ fs.
 file system:
 
   Here you would test for latencies experienced by
-a program if it were writing (and optionally also 
+a program if it were writing (and optionally also
 reading) from a JFFS fs.
 
 
@@ -99,7 +99,7 @@ reading) from a JFFS fs.
 Grabing a kernel profile:
 
 This program can also conditionally grab a kernel profile.
-Specify --grab_kprofile on the cmd line as well as 
+Specify --grab_kprofile on the cmd line as well as
 a "threshold" parameter (see help options by -?).
 
 Any jitter greater than this "threshold" will cause the
@@ -119,10 +119,10 @@ when you boot the kernel if you want to use this functionality.
 
 Signalling the JFFS[2] GC task:
 
-You can also force this program to send a SIGSTOP/SIGCONT to the 
+You can also force this program to send a SIGSTOP/SIGCONT to the
 JFFS (or JFFS2) gc task by specifing --siggc <pid> on the cmd line.
 
-This will let you investigate the effect of forcing the gc task to 
+This will let you investigate the effect of forcing the gc task to
 wake up and do its thing when you are not writing to the fs and to
 force it to sleep when you want to write to the fs.
 
@@ -130,7 +130,7 @@ These are just various tools to investigate the possibility of
 achieving minimal read/write latency when using JFFS[2].
 
 You need to manually do a "ps aux" and look up the PID of the gc
-thread and provide it to the program. 
+thread and provide it to the program.
 
 
 
@@ -156,7 +156,7 @@ console log or printk data).
 
 You can then run this saved console log through this program and it
 will output a very nice text file with the %fill in one col and
-corrosponding jitter values in the second. gnuplot then does a 
+corrosponding jitter values in the second. gnuplot then does a
 beautifull plot of this resulting file showing you graphically the
 jitters encountered at different fill % of your JFFS[2] fs.
 
diff --git a/tests/jittertest/filljffs2.sh b/tests/jittertest/filljffs2.sh
index 10651f4..d8c2a83 100644
--- a/tests/jittertest/filljffs2.sh
+++ b/tests/jittertest/filljffs2.sh
@@ -8,7 +8,7 @@
 while [ $(( 1 )) -gt $(( 0 )) ]
 do
    cp $1 $2
-   rm $2 
+   rm $2
    df |grep mtd > /dev/console
    echo "sleeping $3"
    sleep $3
diff --git a/ubi-utils/dictionary.c b/ubi-utils/dictionary.c
index b7c9ebf..f4b7468 100644
--- a/ubi-utils/dictionary.c
+++ b/ubi-utils/dictionary.c
@@ -44,7 +44,7 @@
 static void * mem_double(void * ptr, int size)
 {
     void * newptr ;
- 
+
     newptr = calloc(2*size, 1);
     if (newptr==NULL) {
         return NULL ;
@@ -230,7 +230,7 @@ int dictionary_set(dictionary * d, char * key, char * val)
 	unsigned	hash ;
 
 	if (d==NULL || key==NULL) return -1 ;
-	
+
 	/* Compute hash for this key */
 	hash = dictionary_hash(key) ;
 	/* Find if value is already in dictionary */
@@ -374,7 +374,7 @@ int main(int argc, char *argv[])
 	/* Allocate dictionary */
 	printf("allocating...\n");
 	d = dictionary_new(0);
-	
+
 	/* Set values in dictionary */
 	printf("setting %d values...\n", NVALS);
 	for (i=0 ; i<NVALS ; i++) {
diff --git a/ubi-utils/libiniparser.c b/ubi-utils/libiniparser.c
index 3bea51e..898f57f 100644
--- a/ubi-utils/libiniparser.c
+++ b/ubi-utils/libiniparser.c
@@ -82,9 +82,9 @@ static char * strstrip(char * s)
 {
     static char l[ASCIILINESZ+1];
 	char * last ;
-	
+
     if (s==NULL) return NULL ;
-    
+
 	while (isspace((int)*s) && *s) s++;
 	memset(l, 0, ASCIILINESZ+1);
 	strcpy(l, s);
@@ -457,7 +457,7 @@ static line_status iniparser_line(
     char * section,
     char * key,
     char * value)
-{   
+{
     line_status sta ;
     char        line[ASCIILINESZ+1];
     int         len ;
@@ -471,7 +471,7 @@ static line_status iniparser_line(
         sta = LINE_EMPTY ;
     } else if (line[0]=='#') {
         /* Comment line */
-        sta = LINE_COMMENT ; 
+        sta = LINE_COMMENT ;
     } else if (line[0]=='[' && line[len-1]==']') {
         /* Section name */
         sscanf(line, "[%[^]]", section);
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:23 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:23 -0700
Subject: [PATCH 06/10] mtd-utils: add common version printing function
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-7-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 include/common.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/common.h b/include/common.h
index 65ec086..b285bc0 100644
--- a/include/common.h
+++ b/include/common.h
@@ -129,6 +129,12 @@ simple_strtoX(strtoll, long long int)
 simple_strtoX(strtoul, unsigned long int)
 simple_strtoX(strtoull, unsigned long long int)
 
+/* Simple version-printing for utils */
+#define common_print_version() \
+do { \
+	fprintf(stderr, PROGRAM_NAME " " VERSION "\n"); \
+} while (0)
+
 #include "xalloc.h"
 
 #ifdef __cplusplus
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:24 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:24 -0700
Subject: [PATCH 07/10] mtd-utils: switch more utils to unified
 versioning
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-8-git-send-email-computersforpeace@gmail.com>

More utilities now use the common VERSION system.

For utils that printed a very simple message, we use the new
common_print_version() "function."

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 jffs2dump.c              |    2 +-
 mkfs.ubifs/mkfs.ubifs.c  |    4 +---
 ubi-utils/mtdinfo.c      |    5 ++---
 ubi-utils/ubiattach.c    |    5 ++---
 ubi-utils/ubicrc32.c     |    5 ++---
 ubi-utils/ubidetach.c    |    5 ++---
 ubi-utils/ubiformat.c    |    5 ++---
 ubi-utils/ubimkvol.c     |    5 ++---
 ubi-utils/ubinfo.c       |    5 ++---
 ubi-utils/ubinize.c      |    5 ++---
 ubi-utils/ubirename.c    |    1 -
 ubi-utils/ubirmvol.c     |    5 ++---
 ubi-utils/ubirsvol.c     |    5 ++---
 ubi-utils/ubiupdatevol.c |    5 ++---
 14 files changed, 24 insertions(+), 38 deletions(-)

diff --git a/jffs2dump.c b/jffs2dump.c
index d093afc..9e13e98 100644
--- a/jffs2dump.c
+++ b/jffs2dump.c
@@ -15,7 +15,6 @@
  */
 
 #define PROGRAM_NAME "jffs2dump"
-#define VERSION "$Revision: 1.10 $"
 
 #include <errno.h>
 #include <stdint.h>
@@ -36,6 +35,7 @@
 #include <getopt.h>
 #include <crc32.h>
 #include "summary.h"
+#include "common.h"
 
 #define PAD(x) (((x)+3)&~3)
 
diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index c718818..733a3bb 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -26,8 +26,6 @@
 #include <crc32.h>
 #include "common.h"
 
-#define PROGRAM_VERSION "1.5"
-
 /* Size (prime number) of hash table for link counting */
 #define HASH_TABLE_SIZE 10099
 
@@ -606,7 +604,7 @@ static int get_options(int argc, char**argv)
 			verbose = 1;
 			break;
 		case 'V':
-			printf("Version " PROGRAM_VERSION "\n");
+			common_print_version();
 			exit(0);
 		case 'g':
 			debug_level = strtol(optarg, &endp, 0);
diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
index bfd7e6d..ab00ce0 100644
--- a/ubi-utils/mtdinfo.c
+++ b/ubi-utils/mtdinfo.c
@@ -21,7 +21,6 @@
  * Author: Artem Bityutskiy
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "mtdinfo"
 
 #include <stdint.h>
@@ -53,7 +52,7 @@ static struct args args = {
 	.node = NULL,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to print MTD information.";
 
 static const char optionsstr[] =
@@ -125,7 +124,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			printf("%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubiattach.c b/ubi-utils/ubiattach.c
index 4f18e99..27e7c09 100644
--- a/ubi-utils/ubiattach.c
+++ b/ubi-utils/ubiattach.c
@@ -21,7 +21,6 @@
  * Author: Artem Bityutskiy
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "ubiattach"
 
 #include <stdio.h>
@@ -53,7 +52,7 @@ static struct args args = {
 	.dev = NULL,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to attach MTD device to UBI.";
 
 static const char optionsstr[] =
@@ -129,7 +128,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubicrc32.c b/ubi-utils/ubicrc32.c
index 73ec595..0ea255d 100644
--- a/ubi-utils/ubicrc32.c
+++ b/ubi-utils/ubicrc32.c
@@ -22,7 +22,6 @@
  * Author: Oliver Lohmann
  */
 
-#define PROGRAM_VERSION "1.0"
 #define PROGRAM_NAME    "ubicrc32"
 
 #include <stdio.h>
@@ -37,7 +36,7 @@
 
 #define BUFSIZE 4096
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to calculate CRC32 with UBI start value (0xFFFFFFFF)";
 
 static const char optionsstr[] =
@@ -70,7 +69,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubidetach.c b/ubi-utils/ubidetach.c
index 668f1bd..64b748e 100644
--- a/ubi-utils/ubidetach.c
+++ b/ubi-utils/ubidetach.c
@@ -21,7 +21,6 @@
  * Author: Artem Bityutskiy
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "ubidetach"
 
 #include <stdio.h>
@@ -50,7 +49,7 @@ static struct args args = {
 	.dev = NULL,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 " - tool to remove UBI devices (detach MTD devices from UBI)";
 
 static const char optionsstr[] =
@@ -113,7 +112,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubiformat.c b/ubi-utils/ubiformat.c
index c4b944a..bfa1730 100644
--- a/ubi-utils/ubiformat.c
+++ b/ubi-utils/ubiformat.c
@@ -29,7 +29,6 @@
  */
 #define MAX_CONSECUTIVE_BAD_BLOCKS 4
 
-#define PROGRAM_VERSION "1.5"
 #define PROGRAM_NAME    "ubiformat"
 
 #include <sys/stat.h>
@@ -72,7 +71,7 @@ static struct args args =
 	.ubi_ver   = 1,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 		" - a tool to format MTD devices and flash UBI images";
 
 static const char optionsstr[] =
@@ -206,7 +205,7 @@ static int parse_opt(int argc, char * const argv[])
 			break;
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case 'h':
diff --git a/ubi-utils/ubimkvol.c b/ubi-utils/ubimkvol.c
index 25065e3..7c2a234 100644
--- a/ubi-utils/ubimkvol.c
+++ b/ubi-utils/ubimkvol.c
@@ -23,7 +23,6 @@
  *          Frank Haverkamp <haver at vnet.ibm.com>
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "ubimkvol"
 
 #include <stdio.h>
@@ -56,7 +55,7 @@ static struct args args = {
 	.vol_id = UBI_VOL_NUM_AUTO,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to create UBI volumes.";
 
 static const char optionsstr[] =
@@ -173,7 +172,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case 'm':
diff --git a/ubi-utils/ubinfo.c b/ubi-utils/ubinfo.c
index 8e14e6e..7aa4aa4 100644
--- a/ubi-utils/ubinfo.c
+++ b/ubi-utils/ubinfo.c
@@ -21,7 +21,6 @@
  * Author: Artem Bityutskiy
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "ubinfo"
 
 #include <stdint.h>
@@ -51,7 +50,7 @@ static struct args args = {
 	.vol_name = NULL,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to print UBI information.";
 
 static const char optionsstr[] =
@@ -124,7 +123,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubinize.c b/ubi-utils/ubinize.c
index 3085b66..453494d 100644
--- a/ubi-utils/ubinize.c
+++ b/ubi-utils/ubinize.c
@@ -24,7 +24,6 @@
  *          Oliver Lohmann
  */
 
-#define PROGRAM_VERSION "1.2"
 #define PROGRAM_NAME    "ubinize"
 
 #include <sys/stat.h>
@@ -39,7 +38,7 @@
 #include "common.h"
 #include "ubiutils-common.h"
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 " - a tool to generate UBI images. An UBI image may contain one or more UBI "
 "volumes which have to be defined in the input configuration ini-file. The "
 "ini file defines all the UBI volumes - their characteristics and the and the "
@@ -234,7 +233,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		default:
diff --git a/ubi-utils/ubirename.c b/ubi-utils/ubirename.c
index 070e32e..288475b 100644
--- a/ubi-utils/ubirename.c
+++ b/ubi-utils/ubirename.c
@@ -21,7 +21,6 @@
  * Author: Richard Titmuss
  */
 
-#define PROGRAM_VERSION "1.0"
 #define PROGRAM_NAME    "ubirename"
 
 #include <stdio.h>
diff --git a/ubi-utils/ubirmvol.c b/ubi-utils/ubirmvol.c
index 5725d90..464f05d 100644
--- a/ubi-utils/ubirmvol.c
+++ b/ubi-utils/ubirmvol.c
@@ -23,7 +23,6 @@
  *          Frank Haverkamp <haver at vnet.ibm.com>
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "ubirmvol"
 
 #include <stdio.h>
@@ -46,7 +45,7 @@ static struct args args = {
 	.vol_id = -1,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 				 " - a tool to remove UBI volumes.";
 
 static const char optionsstr[] =
@@ -117,7 +116,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubirsvol.c b/ubi-utils/ubirsvol.c
index 65f579c..c469060 100644
--- a/ubi-utils/ubirsvol.c
+++ b/ubi-utils/ubirsvol.c
@@ -23,7 +23,6 @@
  *          Frank Haverkamp <haver at vnet.ibm.com>
  */
 
-#define PROGRAM_VERSION "1.1"
 #define PROGRAM_NAME    "ubirsvol"
 
 #include <stdio.h>
@@ -51,7 +50,7 @@ static struct args args = {
 	.lebs = -1,
 };
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 				 " - a tool to resize UBI volumes.";
 
 static const char optionsstr[] =
@@ -146,7 +145,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
diff --git a/ubi-utils/ubiupdatevol.c b/ubi-utils/ubiupdatevol.c
index 24f38fe..7fedb3c 100644
--- a/ubi-utils/ubiupdatevol.c
+++ b/ubi-utils/ubiupdatevol.c
@@ -24,7 +24,6 @@
  *          Artem Bityutskiy
  */
 
-#define PROGRAM_VERSION "1.2"
 #define PROGRAM_NAME    "ubiupdatevol"
 
 #include <fcntl.h>
@@ -52,7 +51,7 @@ struct args {
 
 static struct args args;
 
-static const char doc[] = PROGRAM_NAME " version " PROGRAM_VERSION
+static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to write data to UBI volumes.";
 
 static const char optionsstr[] =
@@ -103,7 +102,7 @@ static int parse_opt(int argc, char * const argv[])
 			exit(EXIT_SUCCESS);
 
 		case 'V':
-			fprintf(stderr, "%s\n", PROGRAM_VERSION);
+			common_print_version();
 			exit(EXIT_SUCCESS);
 
 		case ':':
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:22 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:22 -0700
Subject: [PATCH 05/10] mkfs.ubifs: use common.h
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-6-git-send-email-computersforpeace@gmail.com>

To use more unified versioning and to re-use other existing code,
switch to common.h.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 mkfs.ubifs/mkfs.ubifs.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/mkfs.ubifs/mkfs.ubifs.c b/mkfs.ubifs/mkfs.ubifs.c
index ac3c8d3..c718818 100644
--- a/mkfs.ubifs/mkfs.ubifs.c
+++ b/mkfs.ubifs/mkfs.ubifs.c
@@ -20,8 +20,11 @@
  *          Zoltan Sogor
  */
 
+#define PROGRAM_NAME "mkfs.ubifs"
+
 #include "mkfs.ubifs.h"
 #include <crc32.h>
+#include "common.h"
 
 #define PROGRAM_VERSION "1.5"
 
@@ -390,11 +393,6 @@ static long long add_space_overhead(long long size)
         return size / divisor;
 }
 
-static inline int is_power_of_2(unsigned long long n)
-{
-                return (n != 0 && ((n & (n - 1)) == 0));
-}
-
 static int validate_options(void)
 {
 	int tmp;
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:21 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:21 -0700
Subject: [PATCH 04/10] mtd-utils: update .gitignore files
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-5-git-send-email-computersforpeace@gmail.com>

First, the top-level Makefile should not tell git to ignore sub-level
.gitignore files.

Second, add simple .gitignores to ignore the executables generated under
the various `tests' subdirectories.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 .gitignore                             |    5 +++++
 tests/checkfs/.gitignore               |    2 ++
 tests/fs-tests/integrity/.gitignore    |    1 +
 tests/fs-tests/simple/.gitignore       |    5 +++++
 tests/fs-tests/stress/atoms/.gitignore |   10 ++++++++++
 tests/fs-tests/utils/.gitignore        |    2 ++
 tests/jittertest/.gitignore            |    2 ++
 7 files changed, 27 insertions(+), 0 deletions(-)
 create mode 100644 tests/checkfs/.gitignore
 create mode 100644 tests/fs-tests/integrity/.gitignore
 create mode 100644 tests/fs-tests/simple/.gitignore
 create mode 100644 tests/fs-tests/stress/atoms/.gitignore
 create mode 100644 tests/fs-tests/utils/.gitignore
 create mode 100644 tests/jittertest/.gitignore

diff --git a/.gitignore b/.gitignore
index 86aee63..3a56d0d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -48,6 +48,11 @@
 #
 
 #
+# git files that we don't want to ignore even it they are dot-files
+#
+!.gitignore
+
+#
 # Generated include files
 #
 /include/version.h
diff --git a/tests/checkfs/.gitignore b/tests/checkfs/.gitignore
new file mode 100644
index 0000000..52e7b5d
--- /dev/null
+++ b/tests/checkfs/.gitignore
@@ -0,0 +1,2 @@
+/checkfs
+/makefiles
diff --git a/tests/fs-tests/integrity/.gitignore b/tests/fs-tests/integrity/.gitignore
new file mode 100644
index 0000000..2ea8e69
--- /dev/null
+++ b/tests/fs-tests/integrity/.gitignore
@@ -0,0 +1 @@
+/integck
diff --git a/tests/fs-tests/simple/.gitignore b/tests/fs-tests/simple/.gitignore
new file mode 100644
index 0000000..f3ccde4
--- /dev/null
+++ b/tests/fs-tests/simple/.gitignore
@@ -0,0 +1,5 @@
+/ftrunc
+/orph
+/perf
+/test_1
+/test_2
diff --git a/tests/fs-tests/stress/atoms/.gitignore b/tests/fs-tests/stress/atoms/.gitignore
new file mode 100644
index 0000000..67dede0
--- /dev/null
+++ b/tests/fs-tests/stress/atoms/.gitignore
@@ -0,0 +1,10 @@
+/fwrite00
+/gcd_hupper
+/pdfrun
+/rmdir00
+/rndrm00
+/rndrm99
+/rndwrite00
+/stress_1
+/stress_2
+/stress_3
diff --git a/tests/fs-tests/utils/.gitignore b/tests/fs-tests/utils/.gitignore
new file mode 100644
index 0000000..f3cdf5f
--- /dev/null
+++ b/tests/fs-tests/utils/.gitignore
@@ -0,0 +1,2 @@
+/free_space
+/fstest_monitor
diff --git a/tests/jittertest/.gitignore b/tests/jittertest/.gitignore
new file mode 100644
index 0000000..05d4e9e
--- /dev/null
+++ b/tests/jittertest/.gitignore
@@ -0,0 +1,2 @@
+/JitterTest
+/plotJittervsFill
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:25 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:25 -0700
Subject: [PATCH 08/10] mtd-utils: kill flash_info
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-9-git-send-email-computersforpeace@gmail.com>

According to "feature-removal-schedule," we kill flash_info in favor of
mtdinfo.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 Makefile                     |    2 +-
 feature-removal-schedule.txt |    6 ----
 flash_info.c                 |   67 ------------------------------------------
 3 files changed, 1 insertions(+), 74 deletions(-)
 delete mode 100644 flash_info.c

diff --git a/Makefile b/Makefile
index 8f871c6..afbe201 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,7 @@ TESTS = tests
 
 MTD_BINS = \
 	ftl_format flash_erase nanddump doc_loadbios \
-	ftl_check mkfs.jffs2 flash_lock flash_unlock flash_info \
+	ftl_check mkfs.jffs2 flash_lock flash_unlock \
 	flash_otp_info flash_otp_dump mtd_debug flashcp nandwrite nandtest \
 	jffs2dump \
 	nftldump nftl_format docfdisk \
diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index a5980f7..0920203 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -34,9 +34,3 @@ the -m option. For now, we just have a warning, but the option will be
 removed in release 1.4.6.
 
 ---------------------------
-3. flash_info utility
-
-This is duplicating behavior with the mtdinfo utility.  Now the util
-warns when people use it, but it'll be removed in release 1.4.6.
-
----------------------------
diff --git a/flash_info.c b/flash_info.c
deleted file mode 100644
index d9a4492..0000000
--- a/flash_info.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * flash_info.c -- print info about a MTD device
- */
-
-#define PROGRAM_NAME "flash_info"
-
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <fcntl.h>
-#include <time.h>
-#include <sys/ioctl.h>
-#include <sys/mount.h>
-
-#include "common.h"
-#include <mtd/mtd-user.h>
-
-static void usage(int status)
-{
-	fprintf(status ? stderr : stdout,
-		"Usage: %s <device> [devices]\n",
-		PROGRAM_NAME);
-	exit(status);
-}
-
-int main(int argc, char *argv[])
-{
-	int fd, i, regcount;
-
-	warnmsg("this utility is deprecated in favor of `mtdinfo` and will be removed in mtd-utils-1.4.6");
-
-	if (argc < 2)
-		usage(1);
-	if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help"))
-		usage(0);
-
-	for (i = 1; i < argc; ++i) {
-		const char *dev = argv[i];
-		int r;
-		region_info_t reginfo;
-
-		/* Open and size the device */
-		fd = open(dev, O_RDONLY);
-		if (fd < 0) {
-			sys_errmsg("could not open: %s", dev);
-			continue;
-		}
-
-		if (ioctl(fd, MEMGETREGIONCOUNT, &regcount))
-			continue;
-
-		printf("%s: %d erase regions\n", dev, regcount);
-		for (r = 0; r < regcount; ++r) {
-			reginfo.regionindex = r;
-			if (ioctl(fd, MEMGETREGIONINFO, &reginfo) == 0) {
-				printf("Region %d is at 0x%x with size 0x%x and "
-						"has 0x%x blocks\n", r, reginfo.offset,
-						reginfo.erasesize, reginfo.numblocks);
-			} else {
-				warnmsg("can not read region %d from a %d region device",
-					r, regcount);
-			}
-		}
-	}
-
-	return 0;
-}
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:26 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:26 -0700
Subject: [PATCH 09/10] mtdinfo: kill -m option
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-10-git-send-email-computersforpeace@gmail.com>

According to feature-removal-schedule, we shouldn't use `-m', since
it relies on a specific device-naming pattern.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 feature-removal-schedule.txt |    8 --------
 ubi-utils/mtdinfo.c          |   25 ++++++-------------------
 2 files changed, 6 insertions(+), 27 deletions(-)

diff --git a/feature-removal-schedule.txt b/feature-removal-schedule.txt
index 0920203..69a8155 100644
--- a/feature-removal-schedule.txt
+++ b/feature-removal-schedule.txt
@@ -26,11 +26,3 @@ to stop using them.
 The further step is to remove both of them.
 
 ---------------------------
-2. Kill -m parameter of mtdinfo
-
-We cannot assume that mtd device names follow the "/dev/mtd%d" pattern,
-because it is up to udev rules to name the devices. So we are removing
-the -m option. For now, we just have a warning, but the option will be
-removed in release 1.4.6.
-
----------------------------
diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
index ab00ce0..dd5da53 100644
--- a/ubi-utils/mtdinfo.c
+++ b/ubi-utils/mtdinfo.c
@@ -56,8 +56,6 @@ static const char doc[] = PROGRAM_NAME " version " VERSION
 			 " - a tool to print MTD information.";
 
 static const char optionsstr[] =
-"-m, --mtdn=<MTD device number>  MTD device number to get information about\n"
-"                                (deprecated option, will be removed, do not use)\n"
 "-u, --ubi-info                  print what would UBI layout be if it was put\n"
 "                                on this MTD device\n"
 "-M, --map                       print eraseblock map\n"
@@ -66,20 +64,16 @@ static const char optionsstr[] =
 "-V, --version                   print program version";
 
 static const char usage[] =
-"Usage 1: " PROGRAM_NAME " [-m <MTD device number>] [-u] [-M] [-h] [-V] [--mtdn <MTD device number>]\n"
-"\t\t[--ubi-info] [--help] [--version]\n"
-"Usage 2: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
+"Usage: " PROGRAM_NAME " <MTD device node file name> [-u] [-M] [-h] [-V] [--ubi-info] [--help]\n"
 "\t\t[--version]\n"
 "Example 1: " PROGRAM_NAME " - (no arguments) print general MTD information\n"
-"Example 2: " PROGRAM_NAME " -m 1 - print information about MTD device number 1\n"
-"Example 3: " PROGRAM_NAME " /dev/mtd0 - print information MTD device /dev/mtd0\n"
-"Example 4: " PROGRAM_NAME " /dev/mtd0 -u - print information MTD device /dev/mtd0\n"
+"Example 2: " PROGRAM_NAME " /dev/mtd0 - print information MTD device /dev/mtd0\n"
+"Example 3: " PROGRAM_NAME " /dev/mtd0 -u - print information MTD device /dev/mtd0\n"
 "\t\t\t\tand include UBI layout information\n"
-"Example 5: " PROGRAM_NAME " -a - print information about all MTD devices\n"
+"Example 4: " PROGRAM_NAME " -a - print information about all MTD devices\n"
 "\t\t\tand include UBI layout information\n";
 
 static const struct option long_options[] = {
-	{ .name = "mtdn",      .has_arg = 1, .flag = NULL, .val = 'm' },
 	{ .name = "ubi-info",  .has_arg = 0, .flag = NULL, .val = 'u' },
 	{ .name = "map",       .has_arg = 0, .flag = NULL, .val = 'M' },
 	{ .name = "all",       .has_arg = 0, .flag = NULL, .val = 'a' },
@@ -91,9 +85,9 @@ static const struct option long_options[] = {
 static int parse_opt(int argc, char * const argv[])
 {
 	while (1) {
-		int key, error = 0;
+		int key;
 
-		key = getopt_long(argc, argv, "am:uMhV", long_options, NULL);
+		key = getopt_long(argc, argv, "auMhV", long_options, NULL);
 		if (key == -1)
 			break;
 
@@ -106,13 +100,6 @@ static int parse_opt(int argc, char * const argv[])
 			args.ubinfo = 1;
 			break;
 
-		case 'm':
-			args.mtdn = simple_strtoul(optarg, &error);
-			if (error || args.mtdn < 0)
-				return errmsg("bad MTD device number: \"%s\"", optarg);
-			warnmsg("-m/--mtdn is depecated, will be removed in mtd-utils-1.4.6");
-			break;
-
 		case 'M':
 			args.map = 1;
 			break;
-- 
1.7.0.4




From computersforpeace at gmail.com  Mon Jun 27 14:27:27 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 11:27:27 -0700
Subject: [PATCH 10/10] nanddump: remove unused variable
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309199247-19248-11-git-send-email-computersforpeace@gmail.com>

The "bb_default" bool was temporarily being used to straighten out
potential issues with the changing --bb=METHOD options and to warn
users properly. Now, it's unnecessary.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 nanddump.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/nanddump.c b/nanddump.c
index 27b0f7a..0b931db 100644
--- a/nanddump.c
+++ b/nanddump.c
@@ -102,7 +102,7 @@ static enum {
 static void process_options(int argc, char * const argv[])
 {
 	int error = 0;
-	bool bb_default = true, oob_default = true;
+	bool oob_default = true;
 
 	for (;;) {
 		int option_index = 0;
@@ -149,7 +149,6 @@ static void process_options(int argc, char * const argv[])
 							bb_method = skipbad;
 						else
 							error++;
-						bb_default = false;
 						break;
 					case 3: /* --omitoob */
 						if (oob_default) {
-- 
1.7.0.4




From dedekind1 at gmail.com  Mon Jun 27 15:10:43 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 22:10:43 +0300
Subject: [PATCH] mtd: nand: handle ECC errors in OOB
In-Reply-To: <1308872724-6196-1-git-send-email-computersforpeace@gmail.com>
References: <1308872724-6196-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309201845.24805.0.camel@koala>

On Thu, 2011-06-23 at 16:45 -0700, Brian Norris wrote:
> While the standard NAND OOB functions do not do ECC on the spare area,
> it is possible for a driver to supply its own OOB ECC functions (e.g., HW
> ECC). nand_do_read_oob should act like nand_do_read_ops in checking the
> ECC stats and returning -EBADMSG or -EUCLEAN on uncorrectable errors or
> correctable bitflips, respectively. These error codes could be used in
> flash-based BBT code or in YAFFS, for example.
> 
> Doing this, however, messes with the behavior of mtd_do_readoob. Now,
> mtd_do_readoob should check whether we had -EUCLEAN or -EBADMSG errors
> and discard those as "non-fatal" so that the ioctls can still succeed
> with (possibly uncorrected) data.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  drivers/mtd/mtdchar.c        |   15 +++++++++++++++
>  drivers/mtd/nand/nand_base.c |    9 ++++++++-
>  2 files changed, 23 insertions(+), 1 deletions(-)

Looks good, pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Mon Jun 27 15:14:30 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 22:14:30 +0300
Subject: [RFC] ubiblk: read-only block layer on top of UBI
In-Reply-To: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
Message-ID: <1309202072.24805.4.camel@koala>

Hi,

thanks, for the driver.

On Fri, 2011-06-24 at 15:34 +0200, david.wagner at free-electrons.com
wrote:
> I'm submitting it for review, comments (on the concept as well as on the
> implementation) and advice.  It is my first kernel module - a lot of code was
> taken from mtd_blkdevs and some from gluebi.

If you borrow code from anywhere, you should preserve Copyrights.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From dedekind1 at gmail.com  Mon Jun 27 15:26:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Mon, 27 Jun 2011 22:26:08 +0300
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
	<1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>
Message-ID: <1309202771.24805.11.camel@koala>

On Fri, 2011-06-24 at 15:34 +0200, david.wagner at free-electrons.com
wrote:
> +	/* Stolen from mtd_blkdevs.c */
> +	/* Create processing thread */
> +	dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
> +				  "kubiblkd", dev->ubi_num, dev->vol_id);
> +	if (IS_ERR(dev->thread)) {
> +		ret = PTR_ERR(dev->thread);
> +		goto out_thread;
> +	}

Why we need a kernel thread? Could you please describe when exactly it
is needed and why we cannot avoid having it?

> +	ret = register_blkdev(0, "ubiblk");
> +	if (ret <= 0) {
> +		pr_err("UBIBLK: could not register_blkdev\n");
> +		return -ENODEV;
> +	}
> +	major = ret;
> +	pr_info("UBIBLK: device's major: %d\n", major);
> +
> +	mutex_init(&devtable_lock);
> +	ret = ubi_register_volume_notifier(&ubiblk_notifier, 0);
> +	if (ret < 0)
> +		return ret;

You should probably de-register the blkdev when you fail here.

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From vapier.adi at gmail.com  Mon Jun 27 15:51:44 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 27 Jun 2011 15:51:44 -0400
Subject: [PATCH 06/10] mtd-utils: add common version printing function
In-Reply-To: <1309199247-19248-7-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<1309199247-19248-7-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTimEsXdEcH2JJ0x4-iidSkAoK6jy_w@mail.gmail.com>

On Mon, Jun 27, 2011 at 14:27, Brian Norris wrote:
> +/* Simple version-printing for utils */
> +#define common_print_version() \
> +do { \
> + ? ? ? fprintf(stderr, PROGRAM_NAME " " VERSION "\n"); \
> +} while (0)

this shouldnt go to stderr

if the string is const, then it could just be puts().  but i wonder if
it shouldnt instead use printf("%s %s\n", PROGRAM_NAME, VERSION) so
that the string that represents PROGRAM_NAME isn't duplicated in the
.rodata section.
-mike


From vapier.adi at gmail.com  Mon Jun 27 15:52:31 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 27 Jun 2011 15:52:31 -0400
Subject: [PATCH 00/10] more mtd-utils cleanup
In-Reply-To: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTimMhBbAJENgDJ8+8abMn3Qgi0iLHw@mail.gmail.com>

except for the one i commented on, the rest look fine to me
Acked-by: Mike Frysinger <vapier at gentoo.org>
-mike


From computersforpeace at gmail.com  Mon Jun 27 16:15:23 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 13:15:23 -0700
Subject: [PATCH 06/10] mtd-utils: add common version printing function
In-Reply-To: <BANLkTimEsXdEcH2JJ0x4-iidSkAoK6jy_w@mail.gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<1309199247-19248-7-git-send-email-computersforpeace@gmail.com>
	<BANLkTimEsXdEcH2JJ0x4-iidSkAoK6jy_w@mail.gmail.com>
Message-ID: <BANLkTi=HJwuX1hy-YxGMXmk6LjAq_gMgfQ@mail.gmail.com>

On Mon, Jun 27, 2011 at 12:51 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> On Mon, Jun 27, 2011 at 14:27, Brian Norris wrote:
>> +/* Simple version-printing for utils */
>> +#define common_print_version() \
>> +do { \
>> + ? ? ? fprintf(stderr, PROGRAM_NAME " " VERSION "\n"); \
>> +} while (0)
>
> this shouldnt go to stderr

Yeah, I wasn't too sure on that one. There were several utils that
already used stderr, but that doesn't actually make much sense, I
guess.

> if the string is const, then it could just be puts(). ?but i wonder if
> it shouldnt instead use printf("%s %s\n", PROGRAM_NAME, VERSION) so
> that the string that represents PROGRAM_NAME isn't duplicated in the
> .rodata section.

I'm not sure I know what the exact technical difference would be
between the string concatenation version and the '%s' argument
version...

Brian


From vapier.adi at gmail.com  Mon Jun 27 16:20:09 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 27 Jun 2011 16:20:09 -0400
Subject: [PATCH 06/10] mtd-utils: add common version printing function
In-Reply-To: <BANLkTi=HJwuX1hy-YxGMXmk6LjAq_gMgfQ@mail.gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<1309199247-19248-7-git-send-email-computersforpeace@gmail.com>
	<BANLkTimEsXdEcH2JJ0x4-iidSkAoK6jy_w@mail.gmail.com>
	<BANLkTi=HJwuX1hy-YxGMXmk6LjAq_gMgfQ@mail.gmail.com>
Message-ID: <BANLkTi=V42maw_NtTTO86tggp5SjhH=zHQ@mail.gmail.com>

On Mon, Jun 27, 2011 at 16:15, Brian Norris wrote:
> On Mon, Jun 27, 2011 at 12:51 PM, Mike Frysinger wrote:
>> if the string is const, then it could just be puts(). ?but i wonder if
>> it shouldnt instead use printf("%s %s\n", PROGRAM_NAME, VERSION) so
>> that the string that represents PROGRAM_NAME isn't duplicated in the
>> .rodata section.
>
> I'm not sure I know what the exact technical difference would be
> between the string concatenation version and the '%s' argument
> version...

"%s %s\n" is one string in .rodata, and PROGRAM_NAME is another.  so
anytime the app uses PROGRAM_NAME (like in all the helpers in
common.h), they'll reuse that same PROGRAM_NAME string rather than
constantly duplicating it.

if however you use PROGRAM_NAME " " VERSION, you have a unique string
that is only used by the version code.

minor details, but all these duplicate const strings slowly add up ...
-mike


From khoroshilov at ispras.ru  Mon Jun 27 16:21:30 2011
From: khoroshilov at ispras.ru (Alexey Khoroshilov)
Date: Tue, 28 Jun 2011 00:21:30 +0400
Subject: [PATCH] jffs2: use mutex_is_locked() in __jffs2_flush_wbuf()
Message-ID: <1309206090-2805-1-git-send-email-khoroshilov@ispras.ru>

Use a helper to test if a mutex is held instead of a hack with
mutex_trylock().

Signed-off-by: Alexey Khoroshilov <khoroshilov at ispras.ru>
---
 fs/jffs2/wbuf.c |    3 +--
 1 files changed, 1 insertions(+), 2 deletions(-)

diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c
index 4515bea..a10fb24 100644
--- a/fs/jffs2/wbuf.c
+++ b/fs/jffs2/wbuf.c
@@ -578,8 +578,7 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad)
 	if (!jffs2_is_writebuffered(c))
 		return 0;
 
-	if (mutex_trylock(&c->alloc_sem)) {
-		mutex_unlock(&c->alloc_sem);
+	if (!mutex_is_locked(&c->alloc_sem)) {
 		printk(KERN_CRIT "jffs2_flush_wbuf() called with alloc_sem not locked!\n");
 		BUG();
 	}
-- 
1.7.4.1



From computersforpeace at gmail.com  Mon Jun 27 16:30:00 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 13:30:00 -0700
Subject: [PATCH 00/10] more mtd-utils cleanup
In-Reply-To: <BANLkTimMhBbAJENgDJ8+8abMn3Qgi0iLHw@mail.gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<BANLkTimMhBbAJENgDJ8+8abMn3Qgi0iLHw@mail.gmail.com>
Message-ID: <BANLkTimo+M1107M+6fcvL8DBXHwYnZzA6g@mail.gmail.com>

On Mon, Jun 27, 2011 at 12:52 PM, Mike Frysinger <vapier.adi at gmail.com> wrote:
> except for the one i commented on, the rest look fine to me
> Acked-by: Mike Frysinger <vapier at gentoo.org>
> -mike

Thanks. I'll send v2 soon if I don't get any more comments.

Brian


From computersforpeace at gmail.com  Mon Jun 27 20:00:28 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 17:00:28 -0700
Subject: [PATCH v2 00/10] more mtd-utils cleanup
Message-ID: <1309219229-5604-1-git-send-email-computersforpeace@gmail.com>

This series fixes several mtd-utils issues and takes care of a few things
on the feature-removal schedule.

v2: addressed comments about common_version_print() (patch 6)

I'm only bothering to send patch 6, since the other 9 should be identical.
I'll resend if you want...

Thanks,
Brian

Brian Norris (10):
  mtd-tests: checkfs: fix size_t related warning
  mtd-tests: io_paral: build error, "variable length strings"
  mtd-utils: remove whitespace at end of lines
  mtd-utils: update .gitignore files
  mkfs.ubifs: use common.h
  mtd-utils: add common version printing function
  mtd-utils: switch more utils to unified versioning
  mtd-utils: kill flash_info
  mtdinfo: kill -m option
  nanddump: remove unused variable

 .gitignore                               |    5 ++
 Makefile                                 |    2 +-
 device_table.txt                         |    6 +-
 feature-removal-schedule.txt             |   14 ------
 flash_info.c                             |   67 ------------------------------
 include/common.h                         |    6 +++
 include/linux/jffs2.h                    |    2 +-
 jffs2dump.c                              |    2 +-
 lib/libfec.c                             |   14 +++---
 mcast_image.h                            |    4 +-
 mkfs.jffs2.1                             |    6 +-
 mkfs.jffs2.c                             |    6 +-
 mkfs.ubifs/hashtable/hashtable.c         |   14 +++---
 mkfs.ubifs/hashtable/hashtable.h         |   30 +++++++-------
 mkfs.ubifs/hashtable/hashtable_itr.c     |   12 +++---
 mkfs.ubifs/hashtable/hashtable_itr.h     |   12 +++---
 mkfs.ubifs/hashtable/hashtable_private.h |   12 +++---
 mkfs.ubifs/mkfs.ubifs.c                  |   12 ++----
 nanddump.c                               |    3 +-
 nandtest.c                               |   16 ++++----
 rbtree.c                                 |    6 +-
 rbtree.h                                 |    4 +-
 recv_image.c                             |   24 +++++-----
 serve_image.c                            |   30 +++++++-------
 tests/checkfs/.gitignore                 |    2 +
 tests/checkfs/README                     |   26 ++++++------
 tests/checkfs/checkfs.c                  |    2 +-
 tests/fs-tests/integrity/.gitignore      |    1 +
 tests/fs-tests/simple/.gitignore         |    5 ++
 tests/fs-tests/stress/atoms/.gitignore   |   10 ++++
 tests/fs-tests/utils/.gitignore          |    2 +
 tests/jittertest/.gitignore              |    2 +
 tests/jittertest/README                  |   18 ++++----
 tests/jittertest/filljffs2.sh            |    2 +-
 tests/ubi-tests/io_paral.c               |    2 +-
 ubi-utils/dictionary.c                   |    6 +-
 ubi-utils/libiniparser.c                 |    8 ++--
 ubi-utils/mtdinfo.c                      |   30 ++++----------
 ubi-utils/ubiattach.c                    |    5 +-
 ubi-utils/ubicrc32.c                     |    5 +-
 ubi-utils/ubidetach.c                    |    5 +-
 ubi-utils/ubiformat.c                    |    5 +-
 ubi-utils/ubimkvol.c                     |    5 +-
 ubi-utils/ubinfo.c                       |    5 +-
 ubi-utils/ubinize.c                      |    5 +-
 ubi-utils/ubirename.c                    |    1 -
 ubi-utils/ubirmvol.c                     |    5 +-
 ubi-utils/ubirsvol.c                     |    5 +-
 ubi-utils/ubiupdatevol.c                 |    5 +-
 49 files changed, 199 insertions(+), 277 deletions(-)
 delete mode 100644 flash_info.c
 create mode 100644 tests/checkfs/.gitignore
 create mode 100644 tests/fs-tests/integrity/.gitignore
 create mode 100644 tests/fs-tests/simple/.gitignore
 create mode 100644 tests/fs-tests/stress/atoms/.gitignore
 create mode 100644 tests/fs-tests/utils/.gitignore
 create mode 100644 tests/jittertest/.gitignore




From computersforpeace at gmail.com  Mon Jun 27 20:00:29 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Mon, 27 Jun 2011 17:00:29 -0700
Subject: [PATCH v2 06/10] mtd-utils: add common version printing
 function
In-Reply-To: <1309219229-5604-1-git-send-email-computersforpeace@gmail.com>
References: <1309219229-5604-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309219229-5604-2-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 include/common.h |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/include/common.h b/include/common.h
index 65ec086..88b67e5 100644
--- a/include/common.h
+++ b/include/common.h
@@ -129,6 +129,12 @@ simple_strtoX(strtoll, long long int)
 simple_strtoX(strtoul, unsigned long int)
 simple_strtoX(strtoull, unsigned long long int)
 
+/* Simple version-printing for utils */
+#define common_print_version() \
+do { \
+	printf("%s %s\n", PROGRAM_NAME, VERSION); \
+} while (0)
+
 #include "xalloc.h"
 
 #ifdef __cplusplus
-- 
1.7.0.4




From vapier.adi at gmail.com  Mon Jun 27 20:10:09 2011
From: vapier.adi at gmail.com (Mike Frysinger)
Date: Mon, 27 Jun 2011 20:10:09 -0400
Subject: [PATCH v2 00/10] more mtd-utils cleanup
In-Reply-To: <1309219229-5604-1-git-send-email-computersforpeace@gmail.com>
References: <1309219229-5604-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTink1FKj=AMPBSOYc=yDFCvGpKqSrA@mail.gmail.com>

On Mon, Jun 27, 2011 at 20:00, Brian Norris wrote:
> This series fixes several mtd-utils issues and takes care of a few things
> on the feature-removal schedule.
>
> v2: addressed comments about common_version_print() (patch 6)
>
> I'm only bothering to send patch 6, since the other 9 should be identical.
> I'll resend if you want...

i dont think that's necessary
-mike


From hartleys at visionengravers.com  Mon Jun 27 21:14:52 2011
From: hartleys at visionengravers.com (H Hartley Sweeten)
Date: Mon, 27 Jun 2011 18:14:52 -0700
Subject: Q: jffs2 "Erase at 0x???????? failed immediately: errno -5"
Message-ID: <201106271814.52461.hartleys@visionengravers.com>

Hello all,

I have tried everything I can think of but my system still occasionally
spits out error messages like:

Erase at 0x01cc0000 failed immediately: errno -5

What do these messages actually mean?  Everything appears to be
working fine but the errors worry me a bit.

For the record, my filesystem is on a NOR device partitioned as follows:

# cat /proc/mtd
dev:    size   erasesize  name
mtd0: 00040000 00020000 "RedBoot"
mtd1: 00020000 00020000 "unallocated"
mtd2: 0001f000 00020000 "FIS directory"
mtd3: 00001000 00020000 "RedBoot config"
mtd4: 00200000 00020000 "kernel"
mtd5: 00c00000 00020000 "root"
mtd6: 03180000 00020000 "user"

And mounted like this:

# mount
rootfs on / type rootfs (rw)
/dev/root on / type jffs2 (rw,relatime)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
mdev on /dev type tmpfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,gid=5,mode=620)
/dev/mtdblock6 on /user type jffs2 (rw,relatime)

If I understand the error messages correctly, they all appear to be happening
in the /dev/mtdblock6 partition.  I do a:

# flash_erase -j /dev/mtd6 0 0

On this partition before using it.

Any ideas will be appreciated.

Thanks,
Hartley


From b35362 at freescale.com  Mon Jun 27 21:50:51 2011
From: b35362 at freescale.com (b35362 at freescale.com)
Date: Tue, 28 Jun 2011 09:50:51 +0800
Subject: [PATCH 1/2] mtd/nand : don't free the global data
	fsl_lbc_ctrl_dev->nand in fsl_elbc_chip_remove()
Message-ID: <1309225852-1664-1-git-send-email-b35362@freescale.com>

From: Liu Shuo <b35362 at freescale.com>

The global data fsl_lbc_ctrl_dev->nand don't have to be freed in
fsl_elbc_chip_remove(). The right place to do that is in fsl_elbc_nand_remove()
if elbc_fcm_ctrl->counter is zero.

Signed-off-by: Liu Shuo <b35362 at freescale.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index 0bb254c..a212116 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -829,7 +829,6 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
 
 	elbc_fcm_ctrl->chips[priv->bank] = NULL;
 	kfree(priv);
-	kfree(elbc_fcm_ctrl);
 	return 0;
 }
 
-- 
1.7.1




From b35362 at freescale.com  Mon Jun 27 21:50:52 2011
From: b35362 at freescale.com (b35362 at freescale.com)
Date: Tue, 28 Jun 2011 09:50:52 +0800
Subject: [PATCH 2/2] mtd/nand : workaround for Freescale FCM to support
	large-page Nand chip
In-Reply-To: <1309225852-1664-1-git-send-email-b35362@freescale.com>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
Message-ID: <1309225852-1664-2-git-send-email-b35362@freescale.com>

From: Liu Shuo <b35362 at freescale.com>

Freescale FCM controller has a 2K size limitation of buffer RAM. In order
to support the Nand flash chip whose page size is larger than 2K bytes,
we divide a page into multi-2K pages for MTD layer driver. In that case,
we force to set the page size to 2K bytes. We convert the page address of
MTD layer driver to a real page address in flash chips and a column index
in fsl_elbc driver. We can issue any column address by UA instruction of
elbc controller.

Signed-off-by: Liu Shuo <b35362 at freescale.com>
Signed-off-by: Li Yang <leoli at freescale.com>
---
 drivers/mtd/nand/fsl_elbc_nand.c |   61 +++++++++++++++++++++++++++++--------
 1 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
index a212116..eea7a22 100644
--- a/drivers/mtd/nand/fsl_elbc_nand.c
+++ b/drivers/mtd/nand/fsl_elbc_nand.c
@@ -76,6 +76,10 @@ struct fsl_elbc_fcm_ctrl {
 	unsigned int oob;        /* Non zero if operating on OOB data     */
 	unsigned int counter;	 /* counter for the initializations	  */
 	char *oob_poi;           /* Place to write ECC after read back    */
+
+	int subpage_shift;       /* If writesize > 2048, these two members*/
+	int subpage_mask;        /* are used to calculate the real page   */
+	                         /* address and real column address       */
 };
 
 /* These map to the positions used by the FCM hardware ECC generator */
@@ -164,18 +168,27 @@ static void set_addr(struct mtd_info *mtd, int column, int page_addr, int oob)
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	int buf_num;
+	u32 real_ca = column;
 
-	elbc_fcm_ctrl->page = page_addr;
+	if (priv->page_size && elbc_fcm_ctrl->subpage_shift) {
+		real_ca = (page_addr & elbc_fcm_ctrl->subpage_mask) * 2112;
+		page_addr >>= elbc_fcm_ctrl->subpage_shift;
+	}
 
-	out_be32(&lbc->fbar,
-	         page_addr >> (chip->phys_erase_shift - chip->page_shift));
+	elbc_fcm_ctrl->page = page_addr;
 
 	if (priv->page_size) {
+		real_ca += (oob ? 2048 : 0);
+		elbc_fcm_ctrl->use_mdr = 1;
+		elbc_fcm_ctrl->mdr = real_ca;
+
+		out_be32(&lbc->fbar, page_addr >> 6);
 		out_be32(&lbc->fpar,
 		         ((page_addr << FPAR_LP_PI_SHIFT) & FPAR_LP_PI) |
 		         (oob ? FPAR_LP_MS : 0) | column);
 		buf_num = (page_addr & 1) << 2;
 	} else {
+		out_be32(&lbc->fbar, page_addr >> 5);
 		out_be32(&lbc->fpar,
 		         ((page_addr << FPAR_SP_PI_SHIFT) & FPAR_SP_PI) |
 		         (oob ? FPAR_SP_MS : 0) | column);
@@ -256,10 +269,11 @@ static void fsl_elbc_do_read(struct nand_chip *chip, int oob)
 	if (priv->page_size) {
 		out_be32(&lbc->fir,
 		         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
-		         (FIR_OP_CA  << FIR_OP1_SHIFT) |
-		         (FIR_OP_PA  << FIR_OP2_SHIFT) |
-		         (FIR_OP_CM1 << FIR_OP3_SHIFT) |
-		         (FIR_OP_RBW << FIR_OP4_SHIFT));
+		         (FIR_OP_UA  << FIR_OP1_SHIFT) |
+		         (FIR_OP_UA  << FIR_OP2_SHIFT) |
+		         (FIR_OP_PA  << FIR_OP3_SHIFT) |
+		         (FIR_OP_CM1 << FIR_OP4_SHIFT) |
+		         (FIR_OP_RBW << FIR_OP5_SHIFT));
 
 		out_be32(&lbc->fcr, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) |
 		                    (NAND_CMD_READSTART << FCR_CMD1_SHIFT));
@@ -399,12 +413,13 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 		if (priv->page_size) {
 			out_be32(&lbc->fir,
 			         (FIR_OP_CM2 << FIR_OP0_SHIFT) |
-			         (FIR_OP_CA  << FIR_OP1_SHIFT) |
-			         (FIR_OP_PA  << FIR_OP2_SHIFT) |
-			         (FIR_OP_WB  << FIR_OP3_SHIFT) |
-			         (FIR_OP_CM3 << FIR_OP4_SHIFT) |
-			         (FIR_OP_CW1 << FIR_OP5_SHIFT) |
-			         (FIR_OP_RS  << FIR_OP6_SHIFT));
+			         (FIR_OP_UA  << FIR_OP1_SHIFT) |
+			         (FIR_OP_UA  << FIR_OP2_SHIFT) |
+			         (FIR_OP_PA  << FIR_OP3_SHIFT) |
+			         (FIR_OP_WB  << FIR_OP4_SHIFT) |
+			         (FIR_OP_CM3 << FIR_OP5_SHIFT) |
+			         (FIR_OP_CW1 << FIR_OP6_SHIFT) |
+			         (FIR_OP_RS  << FIR_OP7_SHIFT));
 		} else {
 			out_be32(&lbc->fir,
 			         (FIR_OP_CM0 << FIR_OP0_SHIFT) |
@@ -453,6 +468,9 @@ static void fsl_elbc_cmdfunc(struct mtd_info *mtd, unsigned int command,
 			full_page = 1;
 		}
 
+		if (priv->page_size)
+			elbc_fcm_ctrl->use_mdr = 1;
+
 		fsl_elbc_run_command(mtd);
 
 		/* Read back the page in order to fill in the ECC for the
@@ -654,9 +672,26 @@ static int fsl_elbc_chip_init_tail(struct mtd_info *mtd)
 	struct nand_chip *chip = mtd->priv;
 	struct fsl_elbc_mtd *priv = chip->priv;
 	struct fsl_lbc_ctrl *ctrl = priv->ctrl;
+	struct fsl_elbc_fcm_ctrl *elbc_fcm_ctrl = ctrl->nand;
 	struct fsl_lbc_regs __iomem *lbc = ctrl->regs;
 	unsigned int al;
 
+	/* Hack for supporting the flash chip whose writesize is
+	 * larger than 2K bytes.
+	 */
+	if (mtd->writesize > 2048) {
+		elbc_fcm_ctrl->subpage_shift = ffs(mtd->writesize >> 11) - 1;
+		elbc_fcm_ctrl->subpage_mask =
+			(1 << elbc_fcm_ctrl->subpage_shift) - 1;
+		/* Rewrite mtd->writesize, mtd->oobsize, chip->page_shift
+		 * and chip->pagemask.
+		 */
+		mtd->writesize = 2048;
+		mtd->oobsize = 64;
+		chip->page_shift = ffs(mtd->writesize) - 1;
+		chip->pagemask = (chip->chipsize >> chip->page_shift) - 1;
+	}
+
 	/* calculate FMR Address Length field */
 	al = 0;
 	if (chip->pagemask & 0xffff0000)
-- 
1.7.1




From dedekind1 at gmail.com  Tue Jun 28 03:32:36 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 10:32:36 +0300
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309000666-5242-1-git-send-email-leiwen@marvell.com>
References: <4E031900.50108@compulab.co.il>
	<1309000666-5242-1-git-send-email-leiwen@marvell.com>
Message-ID: <1309246361.23597.30.camel@sauron>

On Sat, 2011-06-25 at 04:17 -0700, Lei Wen wrote:
> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
> 
> Update platform driver to support this feature.
> 
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.
> 
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
>  arch/arm/mach-mmp/aspenite.c                 |    5 +-
>  arch/arm/mach-pxa/cm-x300.c                  |    5 +-
>  arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
>  arch/arm/mach-pxa/littleton.c                |    5 +-
>  arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
>  arch/arm/mach-pxa/raumfeld.c                 |    5 +-
>  arch/arm/mach-pxa/zylonite.c                 |    5 +-
>  arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
>  drivers/mtd/nand/pxa3xx_nand.c               |  512 +++++++++++++++-----------
>  9 files changed, 346 insertions(+), 224 deletions(-)

In general huge patches like this are not encouraged and it is better to
split them. At least the printk changes can be in a separate patch. Then
re-naming host to info probably could be another patch. Could you please
rather do a series of smaller patches? Also, if you use dev_info and the
like functions, you probably do not need the pxa3xx_nand prefix anymore.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 03:33:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 10:33:34 +0300
Subject: [Ubifs] Reboot -> "recovery needed"?
In-Reply-To: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
Message-ID: <1309246418.23597.31.camel@sauron>

On Sat, 2011-06-25 at 13:34 +0200, Gilles wrote:
> Hello
> 
> 	The root filesystem lives in a partition on a NAND, and I noticed
> that after running "reboot", at the next boot, I get this message:
> 
> ===============
> ...
> UBIFS: recovery needed
> UBIFS: recovery completed
> UBIFS: mounted UBI device 0, volume 0, name "rootfs"
> UBIFS: file system size:   251596800 bytes (245700 KiB, 239 MiB, 1950
> LEBs)
> UBIFS: journal size:       9033728 bytes (8822 KiB, 8 MiB, 71 LEBs)
> UBIFS: media format:       w4/r0 (latest is w4/r0)
> UBIFS: default compressor: lzo
> UBIFS: reserved for root:  0 bytes (0 KiB)
> VFS: Mounted root (ubifs filesystem) on device 0:10.
> ===============
> 
> Is this the way Ubifs works, or should I run a command prior to
> "reboot"?

Your reboot command does not unmount the file-system, so from UBIFS's
point of view you do unclean reboot, and UBIFS needs to do recovery.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 03:41:41 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 10:41:41 +0300
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309178086-10604-1-git-send-email-dbaryshkov@gmail.com>
References: <1309154611.23597.18.camel@sauron>
	<1309178086-10604-1-git-send-email-dbaryshkov@gmail.com>
Message-ID: <1309246907.23597.34.camel@sauron>

On Mon, 2011-06-27 at 16:34 +0400, Dmitry Eremin-Solenikov wrote:
> ofpart.ko also provides ofoldpart MTD parser. Add respective
> MODULE_ALIAS("ofoldpart"); declaration.
> 
> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
> ---
>  drivers/mtd/ofpart.c |    3 +++
>  1 files changed, 3 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
> index aa33b8a..77f0640 100644
> --- a/drivers/mtd/ofpart.c
> +++ b/drivers/mtd/ofpart.c
> @@ -176,3 +176,6 @@ module_init(ofpart_parser_init);
>  MODULE_LICENSE("GPL");
>  MODULE_DESCRIPTION("Parser for MTD partitioning information in device tree");
>  MODULE_AUTHOR("Vitaly Wool, David Gibson");
> +/* Required so that this module will be picked up ofoldpart
> + * MTD partition information parser */
> +MODULE_ALIAS("ofoldpart");

Well, the codyng style documents how multi-line comments should look
like... And this comment is less readable than your previous
explanation... But I've fixed this myself and pushed to my tree, thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 03:48:40 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 10:48:40 +0300
Subject: [PATCH 1/6] nand_wait_ready timeout fix
In-Reply-To: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309247324.23597.37.camel@sauron>

On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> nand_wait_ready timeout should not assume HZ=1000.
> Make it independent of HZ value.
> 
> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> ---
>  drivers/mtd/nand/nand_base.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index a46e9bb..a3c7fd3 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -512,7 +512,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
>  void nand_wait_ready(struct mtd_info *mtd)
>  {
>  	struct nand_chip *chip = mtd->priv;
> -	unsigned long timeo = jiffies + 2;
> +	unsigned long timeo = jiffies + (2 * HZ) / 1000;

I agree that the code is buggy, but your fix is strange: if HZ = 100, (2
* HZ) / 1000 will be zero?

I think you should instead know for how many msecs you want to wait, and
use msecs_to_jiffies().

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 03:57:12 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 10:57:12 +0300
Subject: [PATCH 2/6] nand_wait : warn if the nand is busy on exit
In-Reply-To: <1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309247836.23597.42.camel@sauron>

On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> This patch allow to detect buggy driver/hardware with
> bad RnB (dev_ready) management.
> This check cost nothing and could help to detect bugs.
> 
> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> ---
>  drivers/mtd/nand/nand_base.c |    2 ++
>  1 files changed, 2 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index a3c7fd3..095dfea 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -885,6 +885,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
>  	led_trigger_event(nand_led_trigger, LED_OFF);
>  
>  	status = (int)chip->read_byte(mtd);
> +	/* This can happen if in case of timeout or buggy dev_ready */
> +	WARN_ON(!(status & NAND_STATUS_READY));
>  	return status;

This seem to completely miss the chip->dev_ready != NULL case, e.g.,
piece of code above is like this

                while (time_before(jiffies, timeo)) {
                        if (chip->dev_ready) {
                                if (chip->dev_ready(mtd))
                                        break;
                        } else {
                                if (chip->read_byte(mtd) & NAND_STATUS_READY)
                                        break;
                        }
                        cond_resched();
                }

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 04:00:27 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 11:00:27 +0300
Subject: [PATCH 3/6] refactor mtd wait code
In-Reply-To: <1309105616-3609-3-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-3-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309248031.23597.45.camel@sauron>

On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> +/**
> +  * This is call after sending a read command, or for autoincrement
> +  * chip that need it (!NAND_NO_READRDY).
> +  *
> +  * We can't call NAND_CMD_STATUS here, because the read command
> +  * is not finished
> +  */
> +static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip)
> +{
> +	/*
> +	 * If we don't have access to the busy pin, we apply the given
> +	 * command delay
> +	 */
> +	if (!chip->dev_ready) {
> +		udelay(chip->chip_delay);
> +	}
> +	else {
> +		/* Apply this short delay always to ensure that we do wait tWB in
> +		 * any case on any machine. */
> +		ndelay(100);

Please, all these hard-coded numbers should be hidden in the specific
driver.

> +		nand_wait_ready(mtd);
> +	}
> +}
> +
> +/**
>   * __nand_unlock - [REPLACEABLE] unlocks specified locked blocks
>   *
>   * @mtd: mtd info
> @@ -1526,10 +1540,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
>  				 * increment is marked as NOAUTOINCR by the
>  				 * board driver.
>  				 */
> -				if (!chip->dev_ready)
> -					udelay(chip->chip_delay);
> -				else
> -					nand_wait_ready(mtd);
> +				nand_wait_read(mtd, chip);
>  			}
>  		} else {
>  			memcpy(buf, chip->buffers->databuf + col, bytes);
> @@ -1811,10 +1822,7 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
>  			 * chip which does auto increment is marked as
>  			 * NOAUTOINCR by the board driver.
>  			 */
> -			if (!chip->dev_ready)
> -				udelay(chip->chip_delay);
> -			else
> -				nand_wait_ready(mtd);
> +			nand_wait_read(mtd, chip);

I think one thing which you should do as part of this series is to get
rid of all the if (!chip->dev_ready) checks. Instead, you should
introduce something like default_chip_ready and make it do the job.
Also, make sure nand_wait_ready() works in that case.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 04:03:30 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 11:03:30 +0300
Subject: [PATCH 3/6] refactor mtd wait code
In-Reply-To: <1309248031.23597.45.camel@sauron>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-3-git-send-email-matthieu.castet@parrot.com>
	<1309248031.23597.45.camel@sauron>
Message-ID: <1309248214.23597.47.camel@sauron>

On Tue, 2011-06-28 at 11:00 +0300, Artem Bityutskiy wrote:
> On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> > +/**
> > +  * This is call after sending a read command, or for autoincrement
> > +  * chip that need it (!NAND_NO_READRDY).
> > +  *
> > +  * We can't call NAND_CMD_STATUS here, because the read command
> > +  * is not finished
> > +  */
> > +static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip)
> > +{
> > +	/*
> > +	 * If we don't have access to the busy pin, we apply the given
> > +	 * command delay
> > +	 */
> > +	if (!chip->dev_ready) {
> > +		udelay(chip->chip_delay);
> > +	}
> > +	else {
> > +		/* Apply this short delay always to ensure that we do wait tWB in
> > +		 * any case on any machine. */
> > +		ndelay(100);
> 
> Please, all these hard-coded numbers should be hidden in the specific
> driver.

Or could you please explain a bit better why this delay has to be part
of nand core? And why it is 100 and not 200?

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Tue Jun 28 04:09:50 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Tue, 28 Jun 2011 12:09:50 +0400
Subject: [PATCH 2/2] mtd/ofpart: add ofoldpart alias
In-Reply-To: <1309246907.23597.34.camel@sauron>
References: <1309154611.23597.18.camel@sauron>
	<1309178086-10604-1-git-send-email-dbaryshkov@gmail.com>
	<1309246907.23597.34.camel@sauron>
Message-ID: <BANLkTi=8G-aw8ZTJUVYdh7_2u442AonaRg@mail.gmail.com>

On 6/28/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Mon, 2011-06-27 at 16:34 +0400, Dmitry Eremin-Solenikov wrote:
>> ofpart.ko also provides ofoldpart MTD parser. Add respective
>> MODULE_ALIAS("ofoldpart"); declaration.
>>
>> Signed-off-by: Dmitry Eremin-Solenikov <dbaryshkov at gmail.com>
>> ---
>>  drivers/mtd/ofpart.c |    3 +++
>>  1 files changed, 3 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
>> index aa33b8a..77f0640 100644
>> --- a/drivers/mtd/ofpart.c
>> +++ b/drivers/mtd/ofpart.c
>> @@ -176,3 +176,6 @@ module_init(ofpart_parser_init);
>>  MODULE_LICENSE("GPL");
>>  MODULE_DESCRIPTION("Parser for MTD partitioning information in device
>> tree");
>>  MODULE_AUTHOR("Vitaly Wool, David Gibson");
>> +/* Required so that this module will be picked up ofoldpart
>> + * MTD partition information parser */
>> +MODULE_ALIAS("ofoldpart");
>
> Well, the codyng style documents how multi-line comments should look
> like... And this comment is less readable than your previous
> explanation... But I've fixed this myself and pushed to my tree, thanks!

It seems I've got "All work and no play makes Jack a dull boy" sindrom...

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Tue Jun 28 05:34:02 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 12:34:02 +0300
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <4E089441.3010809@gmail.com>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
	<4E020A36.6070708@gmail.com> <1308943581.13493.15.camel@koala>
	<4E089441.3010809@gmail.com>
Message-ID: <1309253646.23597.58.camel@sauron>

On Mon, 2011-06-27 at 10:31 -0400, Peter Barada wrote:
> On 06/24/2011 03:26 PM, Artem Bityutskiy wrote:
> > On Wed, 2011-06-22 at 11:28 -0400, Peter Barada wrote:
> >> Thoughts?
> > Sorry, could you please define the problem you are trying to solve?
> > Sorry if you did define it in your long post, but I could not easily
> > find it.
> The problem I'm trying to solve is that the Micron NAND  I'm using has 
> an internal 4-bit ECC engine and uses four 8-byte ECCs that provide 
> 4-bit protection per 512 data bytes + four OOB bytes.  The ecclayout I'm 
> using is:
> 
> ecclayout = {
>          eccbytes = 32,
>          eccpos = { 8, 9, 10, 11, 12, 13, 14, 15, /* ECC data bytes 
> 0-511 + OOB bytes 4-7 */
>                  24, 25, 26, 27, 28, 19, 30, 31, /* ECC data bytes 
> 512-1023 + OOB bytes 20-23 */
>                  40, 41, 42, 43, 44, 45, 46, 47,  /* ECC data bytes 
> 1024-1535 + OOB bytes 36-39 */
>                  56, 57, 58, 59, 60, 61, 62, 63},  /* ECC data bytes 
> 1536-2047 + OOB bytes 52-55 */
>          .oobfree = {
>                  { .offset = 4,
>                    .length = 4},
>                  { .offset = 20,
>                    .length = 4},
>                  { .offset = 36,
>                    .length = 4},
>                  { .offset = 52,
>                    .length = 4},
>          },
> };
> 
> After the JFFS2 cleanmarker is written into bytes 4-7 and 16-23 of the 
> OOB, nanddump shows:
> 
>    OOB Data: ff ff ff ff 85 19 03 20 5a e3 da 69 01 40 f1 36
>    OOB Data: ff ff ff ff 08 00 00 00 91 99 3c 05 01 d0 5d b3
>    OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>    OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> 
> Note that the ECC bytes 8-15 and 24-31 are no longer FF due to bytes 4-7 
> and bytes 20-23 being written with non-zero data.
> 
> When data is later written to this same page (w/o an intervening erase 
> of its block) reading the page causes an uncorrectable ECC error.
> 
> There are eight additional bytes of OOB space available for writing, but 
> they are not ECC'd.
> 
> The issue I'm trying to solve is how to communicate from MTD to JFFS2 
> that some bytes of the oobfree array perturb the data ECC and can not be 
> used to write the cleanmarker.

OK, thanks for explanation. I am not very good in this area as I do not
have much experience dealing with OOB, but here is what I thing.

1. Linux MTD code was _not_ designed for "ECC'ed OOB".
2. I do not really know what MTD_OOB_RAW is, and the comment in mtd.h
   is not very verbose.
3. But in my opinion MTD_OOB_AUTO makes most sense and should be used
   everywhere except for some tricky cases when you want to test things
   by writing incorrect ECC, or you have an image with ECC and you want
   to flash it as is.
4. In general, OOB should be considered as belonging to the driver, and
   modern software should not rely on OOB at all.
5. So MTD_OOB_AUTO make free bytes in OOB look like a contiguous buffer
   which the _user_ can freely and _independently_ use.
6. In your case only this assumption does not work and your ecclayout is
   incorrect because the OOB areas you expose are not independent.
7. So in your case your ecclayout should be changed and you should
   expose only independent ECC bytes.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Tue Jun 28 05:39:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 12:39:47 +0300
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <1309253646.23597.58.camel@sauron>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
	<4E020A36.6070708@gmail.com> <1308943581.13493.15.camel@koala>
	<4E089441.3010809@gmail.com> <1309253646.23597.58.camel@sauron>
Message-ID: <1309253992.23597.62.camel@sauron>

On Tue, 2011-06-28 at 12:34 +0300, Artem Bityutskiy wrote:
> OK, thanks for explanation. I am not very good in this area as I do not
> have much experience dealing with OOB, but here is what I thing.
> 
> 1. Linux MTD code was _not_ designed for "ECC'ed OOB".
> 2. I do not really know what MTD_OOB_RAW is, and the comment in mtd.h
>    is not very verbose.
> 3. But in my opinion MTD_OOB_AUTO makes most sense and should be used
>    everywhere except for some tricky cases when you want to test things
>    by writing incorrect ECC, or you have an image with ECC and you want
>    to flash it as is.
> 4. In general, OOB should be considered as belonging to the driver, and
>    modern software should not rely on OOB at all.
> 5. So MTD_OOB_AUTO make free bytes in OOB look like a contiguous buffer
>    which the _user_ can freely and _independently_ use.
> 6. In your case only this assumption does not work and your ecclayout is
>    incorrect because the OOB areas you expose are not independent.
> 7. So in your case your ecclayout should be changed and you should
>    expose only independent ECC bytes.

To put it differently, I current model does not distinguish (I think,
correct me if I am wrong) between ECC'd OOB bytes and ECC'less OOB
bytes. BTW, does your flash has the latter?

So MTD would need some work to make it distinguish between those 2 types
of OOB bytes - probably additional info could be added to the ooblayout
structure, and the interfaces could be improved. How exactly - dunno,
I'd first need to figure out what MTD_OOB_RAW is - may be Brian or Ivan
could comment.

-- 
Best Regards,
Artem Bityutskiy



From nicolas.ferre at atmel.com  Tue Jun 28 07:50:56 2011
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 28 Jun 2011 13:50:56 +0200
Subject: [RFC PATCH] MTD: atmel_nand: optimize read/write buffer functions
Message-ID: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>

For PIO NAND access functions, we use the features of the SMC:
- no need to take into account the NAND bus width: SMC will deal with this
- a word aligned memcpy on the NAND chip-select space is able to generate
  proper SMC behavior while optimizing AHB bus usage thanks to optimized memcpy
  implementation.

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
 drivers/mtd/nand/atmel_nand.c |   71 +++++++++++++++++-----------------------
 1 files changed, 30 insertions(+), 41 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index b300705..cb8a04b 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -160,37 +160,6 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
                 !!host->board->rdy_pin_active_low;
 }
 
-/*
- * Minimal-overhead PIO for data access.
- */
-static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
-}
-
-static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
-}
-
-static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_writesb(nand_chip->IO_ADDR_W, buf, len);
-}
-
-static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
-{
-	struct nand_chip	*nand_chip = mtd->priv;
-
-	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
-}
-
 static void dma_complete_func(void *completion)
 {
 	complete(completion);
@@ -265,33 +234,53 @@ err_buf:
 static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
-	struct atmel_nand_host *host = chip->priv;
+	u32 align;
+	u8 *pbuf;
 
 	if (use_dma && len > mtd->oobsize)
 		/* only use DMA for bigger than oob size: better performances */
 		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
 			return;
 
-	if (host->board->bus_width_16)
-		atmel_read_buf16(mtd, buf, len);
-	else
-		atmel_read_buf8(mtd, buf, len);
+	/* if no DMA operation possible, use PIO */
+	pbuf = buf;
+	align = 0x03 & ((unsigned)pbuf);
+
+	if (align) {
+		u32 align_len = 4 - align;
+
+		/* non aligned buffer: re-align to next word boundary */
+		ioread8_rep(chip->IO_ADDR_R, pbuf, align_len);
+		pbuf += align_len;
+		len -= align_len;
+	}
+	memcpy((void *)pbuf, chip->IO_ADDR_R, len);
 }
 
 static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
 {
 	struct nand_chip *chip = mtd->priv;
-	struct atmel_nand_host *host = chip->priv;
+	u32 align;
+	const u8 *pbuf;
 
 	if (use_dma && len > mtd->oobsize)
 		/* only use DMA for bigger than oob size: better performances */
 		if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
 			return;
 
-	if (host->board->bus_width_16)
-		atmel_write_buf16(mtd, buf, len);
-	else
-		atmel_write_buf8(mtd, buf, len);
+	/* if no DMA operation possible, use PIO */
+	pbuf = buf;
+	align = 0x03 & ((unsigned)pbuf);
+
+	if (align) {
+		u32 align_len = 4 - align;
+
+		/* non aligned buffer: re-align to next word boundary */
+		iowrite8_rep(chip->IO_ADDR_W, pbuf, align_len);
+		pbuf += align_len;
+		len -= align_len;
+	}
+	memcpy(chip->IO_ADDR_W, (void *)pbuf, len);
 }
 
 /*
-- 
1.7.3



From u.kleine-koenig at pengutronix.de  Tue Jun 28 07:10:43 2011
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Tue, 28 Jun 2011 13:10:43 +0200
Subject: [RFC PATCH] MTD: atmel_nand: optimize read/write buffer functions
In-Reply-To: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>
References: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <20110628111043.GH6588@pengutronix.de>

On Tue, Jun 28, 2011 at 01:50:56PM +0200, Nicolas Ferre wrote:
> For PIO NAND access functions, we use the features of the SMC:
> - no need to take into account the NAND bus width: SMC will deal with this
> - a word aligned memcpy on the NAND chip-select space is able to generate
>   proper SMC behavior while optimizing AHB bus usage thanks to optimized memcpy
>   implementation.
> 
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
> ---
>  drivers/mtd/nand/atmel_nand.c |   71 +++++++++++++++++-----------------------
>  1 files changed, 30 insertions(+), 41 deletions(-)
> 
> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
> index b300705..cb8a04b 100644
> --- a/drivers/mtd/nand/atmel_nand.c
> +++ b/drivers/mtd/nand/atmel_nand.c
> @@ -160,37 +160,6 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
>                  !!host->board->rdy_pin_active_low;
>  }
>  
> -/*
> - * Minimal-overhead PIO for data access.
> - */
> -static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
> -{
> -	struct nand_chip	*nand_chip = mtd->priv;
> -
> -	__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
> -}
> -
> -static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
> -{
> -	struct nand_chip	*nand_chip = mtd->priv;
> -
> -	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
> -}
> -
> -static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
> -{
> -	struct nand_chip	*nand_chip = mtd->priv;
> -
> -	__raw_writesb(nand_chip->IO_ADDR_W, buf, len);
> -}
> -
> -static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
> -{
> -	struct nand_chip	*nand_chip = mtd->priv;
> -
> -	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
> -}
> -
>  static void dma_complete_func(void *completion)
>  {
>  	complete(completion);
> @@ -265,33 +234,53 @@ err_buf:
>  static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>  {
>  	struct nand_chip *chip = mtd->priv;
> -	struct atmel_nand_host *host = chip->priv;
> +	u32 align;
> +	u8 *pbuf;
>  
>  	if (use_dma && len > mtd->oobsize)
>  		/* only use DMA for bigger than oob size: better performances */
>  		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
>  			return;
>  
> -	if (host->board->bus_width_16)
> -		atmel_read_buf16(mtd, buf, len);
> -	else
> -		atmel_read_buf8(mtd, buf, len);
> +	/* if no DMA operation possible, use PIO */
> +	pbuf = buf;
> +	align = 0x03 & ((unsigned)pbuf);
> +
> +	if (align) {
> +		u32 align_len = 4 - align;
> +
> +		/* non aligned buffer: re-align to next word boundary */
> +		ioread8_rep(chip->IO_ADDR_R, pbuf, align_len);
> +		pbuf += align_len;
> +		len -= align_len;
> +	}
> +	memcpy((void *)pbuf, chip->IO_ADDR_R, len);
I think you don't need to cast to (void *). I think you need to cast the
2nd parameter instead because sparse don't like you passing an void
__iomem *.
Is it correct to read from chip->IO_ADDR_R, don't you need
chip->IO_ADDR_R + align_len? Taking this into account, does it really
help to align pbuf?

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From gilles.ganault at free.fr  Tue Jun 28 07:19:40 2011
From: gilles.ganault at free.fr (Gilles)
Date: Tue, 28 Jun 2011 13:19:40 +0200
Subject: [Ubifs] Reboot -> "recovery needed"?
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
Message-ID: <45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>

On Tue, 28 Jun 2011 10:33:34 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>Your reboot command does not unmount the file-system, so from UBIFS's
>point of view you do unclean reboot, and UBIFS needs to do recovery.

Thanks for the info. I'll see if I can edit the source code to
"reboot" to unmount the root filesystem, or replace "reboot" with
another application or script.



From dedekind1 at gmail.com  Tue Jun 28 07:22:38 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 14:22:38 +0300
Subject: [Ubifs] Reboot -> "recovery needed"?
In-Reply-To: <45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
Message-ID: <1309260162.23597.66.camel@sauron>

On Tue, 2011-06-28 at 13:19 +0200, Gilles wrote:
> On Tue, 28 Jun 2011 10:33:34 +0300, Artem Bityutskiy
> <dedekind1 at gmail.com> wrote:
> >Your reboot command does not unmount the file-system, so from UBIFS's
> >point of view you do unclean reboot, and UBIFS needs to do recovery.
> 
> Thanks for the info. I'll see if I can edit the source code to
> "reboot" to unmount the root filesystem, or replace "reboot" with
> another application or script.

I think it may be enough to re-mount read-only, and probably it is
impossible to unmount in many cases. But I am not 100% sure.

-- 
Best Regards,
Artem Bityutskiy



From gilles.ganault at free.fr  Tue Jun 28 07:25:33 2011
From: gilles.ganault at free.fr (Gilles)
Date: Tue, 28 Jun 2011 13:25:33 +0200
Subject: [Ubifs] Reboot -> "recovery needed"?
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
Message-ID: <gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>

On Tue, 28 Jun 2011 14:22:38 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>> Thanks for the info. I'll see if I can edit the source code to
>> "reboot" to unmount the root filesystem, or replace "reboot" with
>> another application or script.
>
>I think it may be enough to re-mount read-only, and probably it is
>impossible to unmount in many cases. But I am not 100% sure.

So I could rename "reboot" something else, then write a shell script
named "reboot" that will first remount the Ubifs partition ro, and
then call the real "reboot"?



From david.wagner at free-electrons.com  Tue Jun 28 07:35:37 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Tue, 28 Jun 2011 13:35:37 +0200
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <1309202771.24805.11.camel@koala>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>	<1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>
	<1309202771.24805.11.camel@koala>
Message-ID: <4E09BC89.40306@free-electrons.com>

Hi,

On 06/27/2011 09:26 PM, Artem Bityutskiy wrote:
> On Fri, 2011-06-24 at 15:34 +0200, david.wagner at free-electrons.com
> wrote:
>> +	/* Stolen from mtd_blkdevs.c */
>> +	/* Create processing thread */
>> +	dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
>> +				  "kubiblkd", dev->ubi_num, dev->vol_id);
>> +	if (IS_ERR(dev->thread)) {
>> +		ret = PTR_ERR(dev->thread);
>> +		goto out_thread;
>> +	}
> 
> Why we need a kernel thread? Could you please describe when exactly it
> is needed and why we cannot avoid having it?

Do you mean that there could be another/better way ?
I read that workqueues could be used for that but since they seem to
internally use kthreads, I don't see the advantage yet. Simpler API ?

I also tried without a kthread altogether (and call do_ubiblk_request
directly within the callback registered with blk_init_queue) but got
lost in locks/context debugging ...

It seems that do_ubiblk_request needs to be in process context because
there are thousands causes for blocking (locking, page fault, for
instance, are the one I encountered). And on the other hand,
blk_run_queue must not block ; So we need to wake the thread up and
return (what ubi_ubiblk_request does).
So, would this be a sufficient justification ?


It's probably possible, however, to have only one thread for the whole
module instead of having one for each volume ; but that seemed good
enough on first approach.


I fixed the read errors issue with filesystems != SquashFS, so they
should all work, now.
I'll send the next iteration, probably later today.

-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From dedekind1 at gmail.com  Tue Jun 28 07:38:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 14:38:04 +0300
Subject: [Ubifs] Reboot -> "recovery needed"?
In-Reply-To: <gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
	<gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
Message-ID: <1309261088.23597.68.camel@sauron>

On Tue, 2011-06-28 at 13:25 +0200, Gilles wrote:
> On Tue, 28 Jun 2011 14:22:38 +0300, Artem Bityutskiy
> <dedekind1 at gmail.com> wrote:
> >> Thanks for the info. I'll see if I can edit the source code to
> >> "reboot" to unmount the root filesystem, or replace "reboot" with
> >> another application or script.
> >
> >I think it may be enough to re-mount read-only, and probably it is
> >impossible to unmount in many cases. But I am not 100% sure.
> 
> So I could rename "reboot" something else, then write a shell script
> named "reboot" that will first remount the Ubifs partition ro, and
> then call the real "reboot"?

I think it is not that simple - if there is any file open for writing -
remount will fail with EBUSY. So you'd first need to shut down apps,
then do that. You should probably refer standard boot scripts to see
what they do.

On the other hand, as long as your reboot command runs sync, it is
harmless to not unmount UBIFS.

-- 
Best Regards,
Artem Bityutskiy



From gilles.ganault at free.fr  Tue Jun 28 07:50:55 2011
From: gilles.ganault at free.fr (Gilles)
Date: Tue, 28 Jun 2011 13:50:55 +0200
Subject: [Ubifs] Reboot -> "recovery needed"?
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
	<gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
	<1309261088.23597.68.camel@sauron>
Message-ID: <enfj071fg5ebr0n2u15t2nogem32afb5kh@4ax.com>

On Tue, 28 Jun 2011 14:38:04 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>I think it is not that simple - if there is any file open for writing -
>remount will fail with EBUSY. So you'd first need to shut down apps,
>then do that. You should probably refer standard boot scripts to see
>what they do.
>
>On the other hand, as long as your reboot command runs sync, it is
>harmless to not unmount UBIFS.

It looks like it does:

There a several files returned when searching with "reboot*", but it
looks like /usr/src/uClinux-dist-2010R1-RC5/user/sysutils/reboot.c is
the one:

http://blackfin.uclinux.org/gf/project/uclinux-dist/scmsvn/?action=browse&path=%2Ftrunk%2Fuser%2Fsysutils%2Freboot.c&view=markup



From dedekind1 at gmail.com  Tue Jun 28 08:14:27 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 15:14:27 +0300
Subject: [Ubifs] Reboot -> "recovery needed"?
In-Reply-To: <enfj071fg5ebr0n2u15t2nogem32afb5kh@4ax.com>
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
	<gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
	<1309261088.23597.68.camel@sauron>
	<enfj071fg5ebr0n2u15t2nogem32afb5kh@4ax.com>
Message-ID: <1309263271.23597.70.camel@sauron>

On Tue, 2011-06-28 at 13:50 +0200, Gilles wrote:
> On Tue, 28 Jun 2011 14:38:04 +0300, Artem Bityutskiy
> <dedekind1 at gmail.com> wrote:
> >I think it is not that simple - if there is any file open for writing -
> >remount will fail with EBUSY. So you'd first need to shut down apps,
> >then do that. You should probably refer standard boot scripts to see
> >what they do.
> >
> >On the other hand, as long as your reboot command runs sync, it is
> >harmless to not unmount UBIFS.
> 
> It looks like it does:
> 
> There a several files returned when searching with "reboot*", but it
> looks like /usr/src/uClinux-dist-2010R1-RC5/user/sysutils/reboot.c is
> the one:
> 
> http://blackfin.uclinux.org/gf/project/uclinux-dist/scmsvn/?action=browse&path=%2Ftrunk%2Fuser%2Fsysutils%2Freboot.c&view=markup

Then you do not have to worry about UBIFS recovery - it will be quick
and will do almost nothing - just check that everything is all-right and
mark the master node as clean.

-- 
Best Regards,
Artem Bityutskiy



From gilles.ganault at free.fr  Tue Jun 28 08:33:24 2011
From: gilles.ganault at free.fr (Gilles)
Date: Tue, 28 Jun 2011 14:33:24 +0200
Subject: [Ubifs] Reboot -> "recovery needed"?
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
	<gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
	<1309261088.23597.68.camel@sauron>
	<enfj071fg5ebr0n2u15t2nogem32afb5kh@4ax.com>
	<1309263271.23597.70.camel@sauron>
Message-ID: <1bij07h511u24jct1qrpvo4622jogipiuj@4ax.com>

On Tue, 28 Jun 2011 15:14:27 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>Then you do not have to worry about UBIFS recovery - it will be quick
>and will do almost nothing - just check that everything is all-right and
>mark the master node as clean.

What is the command for this? Google says that it's part of the Ubifs
source code:

www.spinics.net/lists/stable-commits/msg11702.html



From dedekind1 at gmail.com  Tue Jun 28 08:43:33 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 15:43:33 +0300
Subject: [Ubifs] Reboot -> "recovery needed"?
In-Reply-To: <1bij07h511u24jct1qrpvo4622jogipiuj@4ax.com>
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
	<gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
	<1309261088.23597.68.camel@sauron>
	<enfj071fg5ebr0n2u15t2nogem32afb5kh@4ax.com>
	<1309263271.23597.70.camel@sauron>
	<1bij07h511u24jct1qrpvo4622jogipiuj@4ax.com>
Message-ID: <1309265018.23597.74.camel@sauron>

On Tue, 2011-06-28 at 14:33 +0200, Gilles wrote:
> On Tue, 28 Jun 2011 15:14:27 +0300, Artem Bityutskiy
> <dedekind1 at gmail.com> wrote:
> >Then you do not have to worry about UBIFS recovery - it will be quick
> >and will do almost nothing - just check that everything is all-right and
> >mark the master node as clean.
> 
> What is the command for this? Google says that it's part of the Ubifs
> source code:
> 
> www.spinics.net/lists/stable-commits/msg11702.html

This all is done automatically by UBIFS, you do not have to worry. Just
make sure you sync before reboot.

-- 
Best Regards,
Artem Bityutskiy



From gilles.ganault at free.fr  Tue Jun 28 08:45:07 2011
From: gilles.ganault at free.fr (Gilles)
Date: Tue, 28 Jun 2011 14:45:07 +0200
Subject: [Ubifs] Reboot -> "recovery needed"?
References: <1rhb079etc7nr1tasfal6eag1d6lmfhd73@4ax.com>
	<1309246418.23597.31.camel@sauron>
	<45ej07pjslh20fb66illqsmn9r0au0fejb@4ax.com>
	<1309260162.23597.66.camel@sauron>
	<gfej07dg451r0l2co91fuvn4k2ujktk1ta@4ax.com>
	<1309261088.23597.68.camel@sauron>
	<enfj071fg5ebr0n2u15t2nogem32afb5kh@4ax.com>
	<1309263271.23597.70.camel@sauron>
	<1bij07h511u24jct1qrpvo4622jogipiuj@4ax.com>
	<1309265018.23597.74.camel@sauron>
Message-ID: <46jj07dq6egqupjbbgvttn01sn8344s876@4ax.com>

On Tue, 28 Jun 2011 15:43:33 +0300, Artem Bityutskiy
<dedekind1 at gmail.com> wrote:
>This all is done automatically by UBIFS, you do not have to worry. Just
>make sure you sync before reboot.

Ok, problem solved then. Thank you for your help.



From nicolas.ferre at atmel.com  Tue Jun 28 09:58:01 2011
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Tue, 28 Jun 2011 15:58:01 +0200
Subject: [RFC PATCH] MTD: atmel_nand: optimize read/write buffer functions
In-Reply-To: <20110628111043.GH6588@pengutronix.de>
References: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>
	<20110628111043.GH6588@pengutronix.de>
Message-ID: <4E09DDE9.2070900@atmel.com>

Le 28/06/2011 13:10, Uwe Kleine-K?nig :
> On Tue, Jun 28, 2011 at 01:50:56PM +0200, Nicolas Ferre wrote:
>> For PIO NAND access functions, we use the features of the SMC:
>> - no need to take into account the NAND bus width: SMC will deal with this
>> - a word aligned memcpy on the NAND chip-select space is able to generate
>>   proper SMC behavior while optimizing AHB bus usage thanks to optimized memcpy
>>   implementation.
>>
>> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
>> ---
>>  drivers/mtd/nand/atmel_nand.c |   71 +++++++++++++++++-----------------------
>>  1 files changed, 30 insertions(+), 41 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
>> index b300705..cb8a04b 100644
>> --- a/drivers/mtd/nand/atmel_nand.c
>> +++ b/drivers/mtd/nand/atmel_nand.c
>> @@ -160,37 +160,6 @@ static int atmel_nand_device_ready(struct mtd_info *mtd)
>>                  !!host->board->rdy_pin_active_low;
>>  }
>>  
>> -/*
>> - * Minimal-overhead PIO for data access.
>> - */
>> -static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
>> -{
>> -	struct nand_chip	*nand_chip = mtd->priv;
>> -
>> -	__raw_readsb(nand_chip->IO_ADDR_R, buf, len);
>> -}
>> -
>> -static void atmel_read_buf16(struct mtd_info *mtd, u8 *buf, int len)
>> -{
>> -	struct nand_chip	*nand_chip = mtd->priv;
>> -
>> -	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
>> -}
>> -
>> -static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
>> -{
>> -	struct nand_chip	*nand_chip = mtd->priv;
>> -
>> -	__raw_writesb(nand_chip->IO_ADDR_W, buf, len);
>> -}
>> -
>> -static void atmel_write_buf16(struct mtd_info *mtd, const u8 *buf, int len)
>> -{
>> -	struct nand_chip	*nand_chip = mtd->priv;
>> -
>> -	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
>> -}
>> -
>>  static void dma_complete_func(void *completion)
>>  {
>>  	complete(completion);
>> @@ -265,33 +234,53 @@ err_buf:
>>  static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>>  {
>>  	struct nand_chip *chip = mtd->priv;
>> -	struct atmel_nand_host *host = chip->priv;
>> +	u32 align;
>> +	u8 *pbuf;
>>  
>>  	if (use_dma && len > mtd->oobsize)
>>  		/* only use DMA for bigger than oob size: better performances */
>>  		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
>>  			return;
>>  
>> -	if (host->board->bus_width_16)
>> -		atmel_read_buf16(mtd, buf, len);
>> -	else
>> -		atmel_read_buf8(mtd, buf, len);
>> +	/* if no DMA operation possible, use PIO */
>> +	pbuf = buf;
>> +	align = 0x03 & ((unsigned)pbuf);
>> +
>> +	if (align) {
>> +		u32 align_len = 4 - align;
>> +
>> +		/* non aligned buffer: re-align to next word boundary */
>> +		ioread8_rep(chip->IO_ADDR_R, pbuf, align_len);
>> +		pbuf += align_len;
>> +		len -= align_len;
>> +	}
>> +	memcpy((void *)pbuf, chip->IO_ADDR_R, len);
> I think you don't need to cast to (void *). I think you need to cast the
> 2nd parameter instead because sparse don't like you passing an void
> __iomem *.

Yes but if I try to cast it, sparse will notice it anyway. So yes, it
seems that I am doing something _bad_ and that the use of memcpy() here
is not the preferred way to deal with hardware FIFO.
On the other hand, the memcpy_fromio() function is far from being as
optimized as the ARM memcpy() implementation... I am wandering what is
the best solution?

> Is it correct to read from chip->IO_ADDR_R, don't you need
> chip->IO_ADDR_R + align_len?

No, it is a FIFO, so each reading from it will give the next data.

> Taking this into account, does it really help to align pbuf?

Aligning to next 32bit word address avoid having to deal with memcpy()
alignment management that reads twice to rearrange data (loosing datas
in the case of a FIFO ;-)). So yes, aligning really helps.

So, all this leads me to append RFC to this patch title...

Best regards,
-- 
Nicolas Ferre



From matthieu.castet at parrot.com  Tue Jun 28 10:50:58 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Tue, 28 Jun 2011 16:50:58 +0200
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <1309202771.24805.11.camel@koala>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>	<1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>
	<1309202771.24805.11.camel@koala>
Message-ID: <4E09EA52.8090006@parrot.com>

Hi,

Artem Bityutskiy a ?crit :
> On Fri, 2011-06-24 at 15:34 +0200, david.wagner at free-electrons.com
> wrote:
>> +	/* Stolen from mtd_blkdevs.c */
>> +	/* Create processing thread */
>> +	dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
>> +				  "kubiblkd", dev->ubi_num, dev->vol_id);
>> +	if (IS_ERR(dev->thread)) {
>> +		ret = PTR_ERR(dev->thread);
>> +		goto out_thread;
>> +	}
> 
> Why we need a kernel thread? Could you please describe when exactly it
> is needed and why we cannot avoid having it?
Also what are the advantage against gluebi + mtdblock_ro ?


From matthieu.castet at parrot.com  Tue Jun 28 11:00:07 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Tue, 28 Jun 2011 17:00:07 +0200
Subject: [PATCH 3/6] refactor mtd wait code
In-Reply-To: <1309248214.23597.47.camel@sauron>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>	
	<1309105616-3609-3-git-send-email-matthieu.castet@parrot.com>	
	<1309248031.23597.45.camel@sauron>
	<1309248214.23597.47.camel@sauron>
Message-ID: <4E09EC77.10501@parrot.com>

Artem Bityutskiy a ?crit :
> On Tue, 2011-06-28 at 11:00 +0300, Artem Bityutskiy wrote:
>> On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
>>> +/**
>>> +  * This is call after sending a read command, or for autoincrement
>>> +  * chip that need it (!NAND_NO_READRDY).
>>> +  *
>>> +  * We can't call NAND_CMD_STATUS here, because the read command
>>> +  * is not finished
>>> +  */
>>> +static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip)
>>> +{
>>> +	/*
>>> +	 * If we don't have access to the busy pin, we apply the given
>>> +	 * command delay
>>> +	 */
>>> +	if (!chip->dev_ready) {
>>> +		udelay(chip->chip_delay);
>>> +	}
>>> +	else {
>>> +		/* Apply this short delay always to ensure that we do wait tWB in
>>> +		 * any case on any machine. */
>>> +		ndelay(100);
>> Please, all these hard-coded numbers should be hidden in the specific
>> driver.
> 
> Or could you please explain a bit better why this delay has to be part
> of nand core? And why it is 100 and not 200?
> 
This delay is already in the nand core. I only put it in a common function :

> -	/* Apply this short delay always to ensure that we do wait tWB in
> -	 * any case on any machine. */
> -	ndelay(100);
> -
> -	nand_wait_ready(mtd);
> +	/* This applies to read commands */
> +	nand_wait_read(mtd, chip);
>  }

> -
> -	/* Apply this short delay always to ensure that we do wait tWB in
> -	 * any case on any machine. */
> -	ndelay(100);
> -
> -	nand_wait_ready(mtd);
> +	/* This applies to read commands */
> +	nand_wait_read(mtd, chip);
>  }


And I think it is 100 ns, because it is the worst case for tWB.


Matthieu


From linux at arm.linux.org.uk  Tue Jun 28 10:59:37 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Tue, 28 Jun 2011 15:59:37 +0100
Subject: [RFC PATCH] MTD: atmel_nand: optimize read/write buffer functions
In-Reply-To: <20110628111043.GH6588@pengutronix.de>
References: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>
	<20110628111043.GH6588@pengutronix.de>
Message-ID: <20110628145937.GG21898@n2100.arm.linux.org.uk>

On Tue, Jun 28, 2011 at 01:10:43PM +0200, Uwe Kleine-K?nig wrote:
> > @@ -265,33 +234,53 @@ err_buf:
> >  static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
> >  {
> >  	struct nand_chip *chip = mtd->priv;
> > -	struct atmel_nand_host *host = chip->priv;
> > +	u32 align;
> > +	u8 *pbuf;
> >  
> >  	if (use_dma && len > mtd->oobsize)
> >  		/* only use DMA for bigger than oob size: better performances */
> >  		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
> >  			return;
> >  
> > -	if (host->board->bus_width_16)
> > -		atmel_read_buf16(mtd, buf, len);
> > -	else
> > -		atmel_read_buf8(mtd, buf, len);
> > +	/* if no DMA operation possible, use PIO */
> > +	pbuf = buf;
> > +	align = 0x03 & ((unsigned)pbuf);
> > +
> > +	if (align) {
> > +		u32 align_len = 4 - align;
> > +
> > +		/* non aligned buffer: re-align to next word boundary */
> > +		ioread8_rep(chip->IO_ADDR_R, pbuf, align_len);
> > +		pbuf += align_len;
> > +		len -= align_len;
> > +	}
> > +	memcpy((void *)pbuf, chip->IO_ADDR_R, len);
> I think you don't need to cast to (void *). I think you need to cast the
> 2nd parameter instead because sparse don't like you passing an void
> __iomem *.
> Is it correct to read from chip->IO_ADDR_R, don't you need
> chip->IO_ADDR_R + align_len? Taking this into account, does it really
> help to align pbuf?

I think you need to read Documentation/bus-virt-phys-mapping.txt,
particularly the part after "NOTE NOTE NOTE".

Dereferencing ioremap'd memory is not permitted.  That includes passing
it to memcpy.  Even with a cast.


From matthieu.castet at parrot.com  Tue Jun 28 11:03:50 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Tue, 28 Jun 2011 17:03:50 +0200
Subject: [PATCH 2/6] nand_wait : warn if the nand is busy on exit
In-Reply-To: <1309247836.23597.42.camel@sauron>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>	
	<1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>
	<1309247836.23597.42.camel@sauron>
Message-ID: <4E09ED56.2070704@parrot.com>

Artem Bityutskiy a ?crit :
> On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
>> This patch allow to detect buggy driver/hardware with
>> bad RnB (dev_ready) management.
>> This check cost nothing and could help to detect bugs.
>>
>> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
>> ---
>>  drivers/mtd/nand/nand_base.c |    2 ++
>>  1 files changed, 2 insertions(+), 0 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
>> index a3c7fd3..095dfea 100644
>> --- a/drivers/mtd/nand/nand_base.c
>> +++ b/drivers/mtd/nand/nand_base.c
>> @@ -885,6 +885,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
>>  	led_trigger_event(nand_led_trigger, LED_OFF);
>>  
>>  	status = (int)chip->read_byte(mtd);
>> +	/* This can happen if in case of timeout or buggy dev_ready */
>> +	WARN_ON(!(status & NAND_STATUS_READY));
>>  	return status;
> 
> This seem to completely miss the chip->dev_ready != NULL case, e.g.,
> piece of code above is like this
> 
>                 while (time_before(jiffies, timeo)) {
>                         if (chip->dev_ready) {
>                                 if (chip->dev_ready(mtd))
>                                         break;
>                         } else {
>                                 if (chip->read_byte(mtd) & NAND_STATUS_READY)
>                                         break;
>                         }
>                         cond_resched();
>                 }
> 
Sorry, I don't understand what you mean.

We don't care what's done in the loop (chip->dev_ready != NULL or, not). We only
check when the loop exit, that READY bit is set in the status.


Matthieu


From matthieu.castet at parrot.com  Tue Jun 28 11:09:29 2011
From: matthieu.castet at parrot.com (Matthieu CASTET)
Date: Tue, 28 Jun 2011 17:09:29 +0200
Subject: [PATCH 1/6] nand_wait_ready timeout fix
In-Reply-To: <1309247324.23597.37.camel@sauron>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309247324.23597.37.camel@sauron>
Message-ID: <4E09EEA9.2040307@parrot.com>

Artem Bityutskiy a ?crit :
> On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
>> nand_wait_ready timeout should not assume HZ=1000.
>> Make it independent of HZ value.
>>
>> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
>> ---
>>  drivers/mtd/nand/nand_base.c |    2 +-
>>  1 files changed, 1 insertions(+), 1 deletions(-)
>>
>> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
>> index a46e9bb..a3c7fd3 100644
>> --- a/drivers/mtd/nand/nand_base.c
>> +++ b/drivers/mtd/nand/nand_base.c
>> @@ -512,7 +512,7 @@ static void panic_nand_wait_ready(struct mtd_info *mtd, unsigned long timeo)
>>  void nand_wait_ready(struct mtd_info *mtd)
>>  {
>>  	struct nand_chip *chip = mtd->priv;
>> -	unsigned long timeo = jiffies + 2;
>> +	unsigned long timeo = jiffies + (2 * HZ) / 1000;
> 
> I agree that the code is buggy, but your fix is strange: if HZ = 100, (2
> * HZ) / 1000 will be zero?
> 
> I think you should instead know for how many msecs you want to wait, and
> use msecs_to_jiffies().
> 
Your right, I assume the code was written for HZ=100, and the code should wait
for 20 ms :
unsigned long timeo = jiffies + (20 * HZ) / 1000;

this will match with the
static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
{

    unsigned long timeo = jiffies;
    int status, state = chip->state;

    if (state == FL_ERASING)
        timeo += (HZ * 400) / 1000;
    else
        timeo += (HZ * 20) / 1000;
[...]
}

Matthieu


From adrian.wenl at gmail.com  Tue Jun 28 11:12:38 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Tue, 28 Jun 2011 23:12:38 +0800
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <4E031900.50108@compulab.co.il>
	<1309000666-5242-1-git-send-email-leiwen@marvell.com>
	<1309246361.23597.30.camel@sauron>
Message-ID: <BANLkTik6gSqYk1FsnCGS7WgfupgA6jdY0A@mail.gmail.com>

On Tue, Jun 28, 2011 at 3:32 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Sat, 2011-06-25 at 04:17 -0700, Lei Wen wrote:
>> Current pxa3xx_nand controller has two chip select which
>> both be workable. This patch enable this feature.
>>
>> Update platform driver to support this feature.
>>
>> Another notice should be taken that:
>> When you want to use this feature, you should not enable the
>> keep configuration feature, for two chip select could be
>> attached with different nand chip. The different page size
>> and timing requirement make the keep configuration impossible.
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> ---
>> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
>> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
>> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
>> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 19 +-
>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?512 +++++++++++++++-----------
>> ?9 files changed, 346 insertions(+), 224 deletions(-)
>
> In general huge patches like this are not encouraged and it is better to
> split them. At least the printk changes can be in a separate patch. Then
> re-naming host to info probably could be another patch. Could you please
> rather do a series of smaller patches? Also, if you use dev_info and the
> like functions, you probably do not need the pxa3xx_nand prefix anymore.
>

Hi Artem & Igor,

Thanks for your suggestion, I would seperate this patch and push back later.

Best regards,
Lei


From david.wagner at free-electrons.com  Tue Jun 28 11:24:51 2011
From: david.wagner at free-electrons.com (david.wagner at free-electrons.com)
Date: Tue, 28 Jun 2011 17:24:51 +0200
Subject: [RFC PATCHv2] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
Message-ID: <1309274691-4898-1-git-send-email-david.wagner@free-electrons.com>

From: David Wagner <david.wagner at free-electrons.com>

	Hi,

This is next iteration ; the read errors issue with FS that do large requests
has been fixed (it means that all block filesystems should now work) ; the
'resized' callback is implemented.

The reuse of code from mtd_blkdevs and gluebi is now mentionned is the file
header.
The use of a kernel thread is also justified (line 353).
The Kconfig has also been fixed.

I also tested compiling ubiblk statically into the kernel ; it worked and I was
able to mount a squashfs ubiblk device as root with, for instance:
"ubi.mtd=1 root=/dev/ubiblk0_0"

Performances still haven't been tested, though.


Thanks to those for review it !
David.

PS: I included the commit message+diff in the same mail as the introduction for
convenience ; tell me if it annoys you - I'll split the next iterations as I did
for the first one.


ubiblk is a read-only block layer on top of UBI.  It presents UBI volumes as
read-only block devices.

It is used by putting a block filesystem image on a UBI volume and then mounting
the corresponding device.

It uses the UBI API to register to UBI notifications (to dynamically create and
delete devices as volumes are added or removed) and to read from the volumes.

Known issues:
 * the modules keeps a table of the devices which length is the maximum number
   of UBI volumes.  It should make use of a linked list.

Some code is taken from mtd_blkdevs and gluebi

Signed-off-by: David Wagner <david.wagner at free-electrons.com>
---
 drivers/mtd/ubi/Kconfig  |   12 +
 drivers/mtd/ubi/Makefile |    1 +
 drivers/mtd/ubi/ubiblk.c |  554 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 567 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/ubi/ubiblk.c

diff --git a/drivers/mtd/ubi/Kconfig b/drivers/mtd/ubi/Kconfig
index 4dcc752..d19508b 100644
--- a/drivers/mtd/ubi/Kconfig
+++ b/drivers/mtd/ubi/Kconfig
@@ -60,4 +60,16 @@ config MTD_UBI_DEBUG
 	help
 	  This option enables UBI debugging.
 
+config MTD_UBI_UBIBLK
+	tristate "Read-only block transition layer on top of UBI"
+	help
+	   Read-only block interface on top of UBI.
+
+	   This option adds ubiblk, which creates a read-ony block device for
+	   each UBI volume.  It makes it possible to use block filesystems on
+	   top of UBI (and thus, on top of MTDs while avoiding bad blocks).
+
+	   The devices are named ubiblkX_Y where X is the UBI number and Y is
+	   the Volume ID.
+
 endif # MTD_UBI
diff --git a/drivers/mtd/ubi/Makefile b/drivers/mtd/ubi/Makefile
index c9302a5..354b2df 100644
--- a/drivers/mtd/ubi/Makefile
+++ b/drivers/mtd/ubi/Makefile
@@ -5,3 +5,4 @@ ubi-y += misc.o
 
 ubi-$(CONFIG_MTD_UBI_DEBUG) += debug.o
 obj-$(CONFIG_MTD_UBI_GLUEBI) += gluebi.o
+obj-$(CONFIG_MTD_UBI_UBIBLK) += ubiblk.o
diff --git a/drivers/mtd/ubi/ubiblk.c b/drivers/mtd/ubi/ubiblk.c
new file mode 100644
index 0000000..53e6d4e
--- /dev/null
+++ b/drivers/mtd/ubi/ubiblk.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) Free Electrons, 2011
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: David Wagner
+ * Some code taken from gluebi.c (Artem Bityutskiy (???????????????? ??????????),
+ *                                Joern Engel)
+ * Some code taken from mtd_blkdevs.c (David Woodhouse)
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+#include <linux/mtd/ubi.h>
+#include <linux/blkdev.h>
+#include <linux/kthread.h>
+#include <linux/mutex.h>
+#include "ubi.h"
+
+#define BLK_SIZE 512
+
+#define UBIBLK_MAX_DEVS (UBI_MAX_DEVICES * UBI_MAX_VOLUMES)
+
+/*
+ * Structure representing a ubiblk device, proxying a UBI volume
+ */
+struct ubiblk_dev {
+	struct ubi_volume_desc *vol_desc;
+	struct ubi_volume_info *vol_info;
+	int ubi_num;
+	int vol_id;
+
+	/* Block stuff */
+	struct gendisk *gd;
+	struct request_queue *rq;
+	struct task_struct *thread;
+
+	/* Protects the access to the UBI volume */
+	struct mutex lock;
+
+	/* Avoids concurrent accesses to the request queue */
+	spinlock_t queue_lock;
+};
+
+/*
+ * Contains the pointers to all ubiblk_dev instances
+ * TODO: use a linked list
+ */
+static struct ubiblk_dev *ubiblk_devs[UBIBLK_MAX_DEVS];
+static struct mutex devtable_lock;
+
+int major;
+static const struct block_device_operations ubiblk_ops;
+
+static struct ubiblk_dev *ubiblk_find_dev(struct ubi_volume_info *vol_info)
+{
+	int i;
+	struct ubiblk_dev *dev;
+
+	mutex_lock(&devtable_lock);
+	for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+		dev = ubiblk_devs[i];
+		if (dev && dev->ubi_num == vol_info->ubi_num &&
+		    dev->vol_id == vol_info->vol_id)
+			break;
+	}
+	mutex_unlock(&devtable_lock);
+	if (i == UBIBLK_MAX_DEVS)
+		return NULL;
+	return dev;
+}
+
+/*
+ * Read a LEB and fill the request buffer with the requested sector
+ */
+static int do_ubiblk_request(struct request *req, struct ubiblk_dev *dev)
+{
+	unsigned long start, len, read_bytes;
+	int offset;
+	int leb;
+	int ret;
+
+	start = blk_rq_pos(req) << 9;
+	len = blk_rq_cur_bytes(req);
+	read_bytes = 0;
+
+	/* We are always reading. No need to handle writing for now */
+
+	leb = start / dev->vol_info->usable_leb_size;
+	offset = start % dev->vol_info->usable_leb_size;
+
+	do {
+		int overlap = 0;
+
+		if (offset + len > dev->vol_info->usable_leb_size) {
+			len = dev->vol_info->usable_leb_size - offset;
+			overlap = 1;
+		}
+
+		if (blk_rq_pos(req) + blk_rq_cur_sectors(req) >
+		    get_capacity(req->rq_disk)) {
+			pr_err("UBIBLK: attempting to read too far\n");
+			return -EIO;
+		}
+
+		pr_debug("%s(%s) of sector %llu (LEB %d). offset=%d, len=%lu\n",
+			 __func__, rq_data_dir(req) ? "Write" : "Read",
+			 blk_rq_pos(req), leb, offset, len);
+
+		/* Read (len) bytes of LEB (leb) from (offset) and put the
+		 * result in the buffer given by the request ; if the request
+		 * is overlapping on several lebs, (read) will be > 0 and the
+		 * data will be put in the buffer at offset (read) */
+		ret = ubi_read(dev->vol_desc, leb, req->buffer + read_bytes,
+			       offset, len);
+
+		if (ret) {
+			pr_err("ubi_read error\n");
+			return ret;
+		}
+
+		read_bytes += len;
+		len = blk_rq_cur_bytes(req) - read_bytes;
+
+		/* If we needed to cap the length of ubi_read, the next
+		 * ubi_read will be done on the beginning of the next LEB */
+		if (overlap) {
+			leb++;
+			offset = 0;
+			overlap = 0;
+		}
+	} while (read_bytes < blk_rq_cur_bytes(req));
+
+	pr_debug("ubi_read done.\n");
+
+	return 0;
+}
+
+static void ubi_ubiblk_request(struct request_queue *rq)
+{
+	struct ubiblk_dev *dev;
+	struct request *req = NULL;
+
+	dev = rq->queuedata;
+
+	if (!dev)
+		while ((req = blk_fetch_request(rq)) != NULL)
+			__blk_end_request_all(req, -ENODEV);
+	else
+		wake_up_process(dev->thread);
+}
+
+/*
+ * Open a UBI volume (get the volume descriptor)
+ */
+static int ubiblk_open(struct block_device *bdev, fmode_t mode)
+{
+	struct ubiblk_dev *dev = bdev->bd_disk->private_data;
+	pr_debug("%s() disk_name=%s, mode=%d\n", __func__,
+		 bdev->bd_disk->disk_name, mode);
+
+	dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+					UBI_READONLY);
+	if (!dev->vol_desc) {
+		pr_err("open_volume failed");
+		return -EINVAL;
+	}
+
+	dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+	if (!dev->vol_info) {
+		ubi_close_volume(dev->vol_desc);
+		dev->vol_desc = NULL;
+		return -ENOMEM;
+	}
+	ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+	return 0;
+}
+
+/*
+ * Close a UBI volume (close the volume descriptor)
+ */
+static int ubiblk_release(struct gendisk *gd, fmode_t mode)
+{
+	struct ubiblk_dev *dev = gd->private_data;
+	pr_debug("%s() disk_name=%s, mode=%d\n", __func__, gd->disk_name, mode);
+
+	kfree(dev->vol_info);
+	dev->vol_info = NULL;
+	if (dev->vol_desc) {
+		ubi_close_volume(dev->vol_desc);
+		dev->vol_desc = NULL;
+	}
+
+	return 0;
+}
+
+/*
+ * Loop on the block request queue and wait for new requests ; run them with
+ * do_ubiblk_request()
+ *
+ * Mostly stolen from mtd_blkdevs.c
+ */
+static int ubi_ubiblk_thread(void *arg)
+{
+	struct ubiblk_dev *dev = arg;
+	struct request_queue *rq = dev->rq;
+	struct request *req = NULL;
+
+	spin_lock_irq(rq->queue_lock);
+
+	while (!kthread_should_stop()) {
+		int res;
+
+		if (!req && !(req = blk_fetch_request(rq))) {
+			set_current_state(TASK_INTERRUPTIBLE);
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
+
+			spin_unlock_irq(rq->queue_lock);
+			schedule();
+			spin_lock_irq(rq->queue_lock);
+			continue;
+		}
+
+		spin_unlock_irq(rq->queue_lock);
+
+		mutex_lock(&dev->lock);
+		res = do_ubiblk_request(req, dev);
+		pr_debug("return from request: %d\n", res);
+		mutex_unlock(&dev->lock);
+
+		spin_lock_irq(rq->queue_lock);
+
+		if (!__blk_end_request_cur(req, res))
+			req = NULL;
+	}
+
+	if (req)
+		__blk_end_request_all(req, -EIO);
+
+	spin_unlock_irq(rq->queue_lock);
+
+	return 0;
+}
+
+/*
+ * An UBI volume has been created ; create a corresponding ubiblk device:
+ * Initialize the locks, the structure, the block layer infos and start a
+ * thread.
+ */
+static int ubiblk_create(struct ubi_device_info *dev_info,
+			 struct ubi_volume_info *vol_info)
+{
+	struct ubiblk_dev *dev;
+	struct gendisk *gd;
+	int i;
+	int ret = 0;
+
+	mutex_lock(&devtable_lock);
+	for (i = 0; i < UBIBLK_MAX_DEVS; i++)
+		if (!ubiblk_devs[i])
+			break;
+
+	if (i == UBIBLK_MAX_DEVS) {
+		/* Shouldn't happen: UBI can't make more volumes than that */
+		pr_err("no slot left for a new ubiblk device.\n");
+		mutex_unlock(&devtable_lock);
+		return -ENOMEM;
+	}
+
+	dev = kzalloc(sizeof(struct ubiblk_dev), GFP_KERNEL);
+	if (!dev) {
+		pr_err("UBIBLK: ENOMEM when trying to create a new"
+		       "ubiblk dev\n");
+		mutex_unlock(&devtable_lock);
+		return -ENOMEM;
+	}
+	ubiblk_devs[i] = dev;
+	mutex_unlock(&devtable_lock);
+
+	mutex_init(&dev->lock);
+	mutex_lock(&dev->lock);
+
+	dev->ubi_num = vol_info->ubi_num;
+	dev->vol_id = vol_info->vol_id;
+
+	dev->vol_desc = ubi_open_volume(dev->ubi_num, dev->vol_id,
+					UBI_READONLY);
+	if (IS_ERR(dev->vol_desc)) {
+		pr_err("open_volume failed\n");
+		ret = PTR_ERR(dev->vol_desc);
+		goto out_vol;
+	}
+
+	dev->vol_info = kzalloc(sizeof(struct ubi_volume_info), GFP_KERNEL);
+	if (!dev->vol_info) {
+		ret = -ENOMEM;
+		goto out_info;
+	}
+	ubi_get_volume_info(dev->vol_desc, dev->vol_info);
+
+	pr_info("Got volume %s: device %d/volume %d of size %d\n",
+		dev->vol_info->name, dev->ubi_num, dev->vol_id,
+		dev->vol_info->size);
+
+	/* Initialize the gendisk of this ubiblk device */
+	gd = alloc_disk(1);
+	if (!gd) {
+		pr_err("alloc_disk failed\n");
+		ret = -ENODEV;
+		goto out_disk;
+	}
+
+	gd->fops = &ubiblk_ops;
+	gd->major = major;
+	gd->first_minor = dev->ubi_num * UBI_MAX_VOLUMES + dev->vol_id;
+	gd->private_data = dev;
+	sprintf(gd->disk_name, "ubiblk%d_%d", dev->ubi_num, dev->vol_id);
+	pr_debug("creating a gd '%s'\n", gd->disk_name);
+	set_capacity(gd,
+		     (dev->vol_info->size *
+		      dev->vol_info->usable_leb_size) >> 9);
+	set_disk_ro(gd, 1);
+	dev->gd = gd;
+
+	spin_lock_init(&dev->queue_lock);
+	dev->rq = blk_init_queue(ubi_ubiblk_request, &dev->queue_lock);
+	if (!dev->rq) {
+		pr_err("init_queue failed\n");
+		ret = -ENODEV;
+		goto out_queue;
+	}
+	dev->rq->queuedata = dev;
+	blk_queue_logical_block_size(dev->rq, BLK_SIZE);
+	dev->gd->queue = dev->rq;
+
+	/* Stolen from mtd_blkdevs.c */
+	/* Create processing thread
+	 *
+	 * The processing of the request has to be done in process context (it
+	 * might sleep) but blk_run_queue can't block ; so we need to separate
+	 * the event of a request being added to the queue (which triggers the
+	 * callback ubi_ubiblk_request - that is set with blk_init_queue())
+	 * and the processing of that request.
+	 *
+	 * Thus, the sole purpose of ubi_ubiblk_reuqest is to wake the kthread
+	 * up so that it will process the request queue
+	 */
+	dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
+				  "kubiblk", dev->ubi_num, dev->vol_id);
+	if (IS_ERR(dev->thread)) {
+		ret = PTR_ERR(dev->thread);
+		goto out_thread;
+	}
+
+	add_disk(dev->gd);
+	kfree(dev->vol_info);
+	dev->vol_info = NULL;
+	ubi_close_volume(dev->vol_desc);
+	dev->vol_desc = NULL;
+	mutex_unlock(&dev->lock);
+
+	return 0;
+
+out_thread:
+	blk_cleanup_queue(dev->rq);
+out_queue:
+	put_disk(dev->gd);
+out_disk:
+	kfree(dev->vol_info);
+	dev->vol_info = NULL;
+out_info:
+	ubi_close_volume(dev->vol_desc);
+	dev->vol_desc = NULL;
+out_vol:
+	mutex_unlock(&dev->lock);
+
+	return ret;
+}
+
+/*
+ * A UBI has been removed ; destroy the corresponding ubiblk device
+ */
+static int ubiblk_remove(struct ubi_volume_info *vol_info)
+{
+	struct ubiblk_dev *dev;
+
+	dev = ubiblk_find_dev(vol_info);
+
+	if (!dev) {
+		pr_warn("Trying to remove %s, which is unknown from ubiblk\n",
+			vol_info->name);
+		return -ENODEV;
+	}
+
+	pr_info("Removing %s\n", vol_info->name);
+
+	if (dev->vol_desc)
+		ubi_close_volume(dev->vol_desc);
+
+	del_gendisk(dev->gd);
+	blk_cleanup_queue(dev->rq);
+	kthread_stop(dev->thread);
+	put_disk(dev->gd);
+
+	kfree(dev->vol_info);
+
+	mutex_lock(&devtable_lock);
+	kfree(dev);
+	dev = NULL;
+	mutex_unlock(&devtable_lock);
+
+	return 0;
+}
+
+static int ubiblk_resized(struct ubi_volume_info *vol_info)
+{
+	struct ubiblk_dev *dev;
+
+	dev = ubiblk_find_dev(vol_info);
+	if (!dev) {
+		pr_warn("Trying to resize %s, which is unknown from ubiblk\n",
+			vol_info->name);
+		return -ENODEV;
+	}
+
+	mutex_lock(&dev->lock);
+	set_capacity(dev->gd,
+		     (vol_info->size * vol_info->usable_leb_size) >> 9);
+	mutex_unlock(&dev->lock);
+	pr_debug("Resized ubiblk%d_%d to %d LEBs\n", vol_info->ubi_num,
+		 vol_info->vol_id, vol_info->size);
+	return 0;
+}
+
+/*
+ * Dispatches the UBI notifications
+ * copied from gluebi.c
+ */
+static int ubiblk_notify(struct notifier_block *nb,
+			 unsigned long notification_type, void *ns_ptr)
+{
+	struct ubi_notification *nt = ns_ptr;
+
+	switch (notification_type) {
+	case UBI_VOLUME_ADDED:
+		ubiblk_create(&nt->di, &nt->vi);
+		break;
+	case UBI_VOLUME_REMOVED:
+		ubiblk_remove(&nt->vi);
+		break;
+	case UBI_VOLUME_RESIZED:
+		ubiblk_resized(&nt->vi);
+		break;
+	case UBI_VOLUME_UPDATED:
+		break;
+	case UBI_VOLUME_RENAMED:
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+static const struct block_device_operations ubiblk_ops = {
+	.owner = THIS_MODULE,
+	.open = ubiblk_open,
+	.release = ubiblk_release,
+};
+
+static struct notifier_block ubiblk_notifier = {
+	.notifier_call = ubiblk_notify,
+};
+
+/*
+ * Initialize the module
+ * (Get a major number and register to UBI notifications)
+ */
+static int __init ubi_ubiblk_init(void)
+{
+	int ret = 0;
+
+	pr_info("UBIBLK starting\n");
+
+	ret = register_blkdev(0, "ubiblk");
+	if (ret <= 0) {
+		pr_err("UBIBLK: could not register_blkdev\n");
+		return -ENODEV;
+	}
+	major = ret;
+	pr_info("UBIBLK: device's major: %d\n", major);
+
+	mutex_init(&devtable_lock);
+	ret = ubi_register_volume_notifier(&ubiblk_notifier, 0);
+	if (ret < 0)
+		unregister_blkdev(major, "ubiblk");
+
+	return ret;
+}
+
+/*
+ * End of life
+ * unregister the block device major, unregister from UBI notifications,
+ * stop the threads and free the memory.
+ */
+static void __exit ubi_ubiblk_exit(void)
+{
+	int i;
+
+	pr_info("UBIBLK: going to exit\n");
+
+	ubi_unregister_volume_notifier(&ubiblk_notifier);
+
+	for (i = 0; i < UBIBLK_MAX_DEVS; i++) {
+		struct ubiblk_dev *dev = ubiblk_devs[i];
+		if (!dev)
+			continue;
+
+		if (dev->vol_desc)
+			ubi_close_volume(dev->vol_desc);
+
+		del_gendisk(dev->gd);
+		blk_cleanup_queue(dev->rq);
+		kthread_stop(dev->thread);
+		put_disk(dev->gd);
+
+		kfree(dev->vol_info);
+		kfree(dev);
+	}
+
+	unregister_blkdev(major, "ubiblk");
+	pr_info("UBIBLK: The End\n");
+}
+
+module_init(ubi_ubiblk_init);
+module_exit(ubi_ubiblk_exit);
+MODULE_DESCRIPTION("Read-only block transition layer on top of UBI");
+MODULE_AUTHOR("David Wagner");
+MODULE_LICENSE("GPL");
-- 
1.7.0.4



From david.wagner at free-electrons.com  Tue Jun 28 11:32:01 2011
From: david.wagner at free-electrons.com (David Wagner)
Date: Tue, 28 Jun 2011 17:32:01 +0200
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <4E09EA52.8090006@parrot.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>	<1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>	<1309202771.24805.11.camel@koala>
	<4E09EA52.8090006@parrot.com>
Message-ID: <4E09F3F1.7080109@free-electrons.com>

On 06/28/2011 04:50 PM, Matthieu CASTET wrote:
> Hi,
>
[...]
> Also what are the advantage against gluebi + mtdblock_ro ?

The main advantage is a reduced number of layers ; I must say I cannot
see much more for now.  I could add that the Kconfig help of gluebi
advises not to use it except when needed by legacy software.

-- 
David Wagner, Free Electrons
Kernel, drivers, real-time and embedded Linux
development, consulting, training and support.
http://free-electrons.com


From mhench at elutions.com  Tue Jun 28 11:35:12 2011
From: mhench at elutions.com (Mike Hench)
Date: Tue, 28 Jun 2011 11:35:12 -0400
Subject: [PATCH 2/2] mtd/nand : workaround for Freescale FCM to
	supportlarge-page Nand chip
In-Reply-To: <1309225852-1664-2-git-send-email-b35362@freescale.com>
Message-ID: <F87D23B7E1F84E4AB52E4FA4A55F85DC0262C53D@tpamail.elutions.com>


Any boot ideas ?
Will the FCM load 2k and run it?

Thanks for any insight you might have.


From scottwood at freescale.com  Tue Jun 28 12:30:33 2011
From: scottwood at freescale.com (Scott Wood)
Date: Tue, 28 Jun 2011 11:30:33 -0500
Subject: [PATCH 2/2] mtd/nand : workaround for Freescale FCM to
	supportlarge-page Nand chip
In-Reply-To: <F87D23B7E1F84E4AB52E4FA4A55F85DC0262C53D@tpamail.elutions.com>
References: <1309225852-1664-2-git-send-email-b35362@freescale.com>
	<F87D23B7E1F84E4AB52E4FA4A55F85DC0262C53D@tpamail.elutions.com>
Message-ID: <20110628113033.5e71a8ed@schlenkerla.am.freescale.net>

On Tue, 28 Jun 2011 11:35:12 -0400
Mike Hench <mhench at elutions.com> wrote:

> 
> Any boot ideas ?
> Will the FCM load 2k and run it?

The 4K boot region will have to be split over pages 0 and 2 (2k view) or
the first half of pages 0 and 1 (4k view).

-Scott



From peter.barada at gmail.com  Tue Jun 28 14:56:19 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Tue, 28 Jun 2011 14:56:19 -0400
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <1309253646.23597.58.camel@sauron>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>		
	<4E020A36.6070708@gmail.com> <1308943581.13493.15.camel@koala>	
	<4E089441.3010809@gmail.com> <1309253646.23597.58.camel@sauron>
Message-ID: <4E0A23D3.8060303@gmail.com>

On 06/28/2011 05:34 AM, Artem Bityutskiy wrote:
> On Mon, 2011-06-27 at 10:31 -0400, Peter Barada wrote:
>> On 06/24/2011 03:26 PM, Artem Bityutskiy wrote:
>>> On Wed, 2011-06-22 at 11:28 -0400, Peter Barada wrote:
>>>> Thoughts?
>>> Sorry, could you please define the problem you are trying to solve?
>>> Sorry if you did define it in your long post, but I could not easily
>>> find it.
>> The problem I'm trying to solve is that the Micron NAND  I'm using has
>> an internal 4-bit ECC engine and uses four 8-byte ECCs that provide
>> 4-bit protection per 512 data bytes + four OOB bytes.  The ecclayout I'm
>> using is:
>>
>> ecclayout = {
>>           eccbytes = 32,
>>           eccpos = { 8, 9, 10, 11, 12, 13, 14, 15, /* ECC data bytes
>> 0-511 + OOB bytes 4-7 */
>>                   24, 25, 26, 27, 28, 19, 30, 31, /* ECC data bytes
>> 512-1023 + OOB bytes 20-23 */
>>                   40, 41, 42, 43, 44, 45, 46, 47,  /* ECC data bytes
>> 1024-1535 + OOB bytes 36-39 */
>>                   56, 57, 58, 59, 60, 61, 62, 63},  /* ECC data bytes
>> 1536-2047 + OOB bytes 52-55 */
>>           .oobfree = {
>>                   { .offset = 4,
>>                     .length = 4},
>>                   { .offset = 20,
>>                     .length = 4},
>>                   { .offset = 36,
>>                     .length = 4},
>>                   { .offset = 52,
>>                     .length = 4},
>>           },
>> };
>>
>> After the JFFS2 cleanmarker is written into bytes 4-7 and 16-23 of the
>> OOB, nanddump shows:
>>
>>     OOB Data: ff ff ff ff 85 19 03 20 5a e3 da 69 01 40 f1 36
>>     OOB Data: ff ff ff ff 08 00 00 00 91 99 3c 05 01 d0 5d b3
>>     OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>>     OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>>
>> Note that the ECC bytes 8-15 and 24-31 are no longer FF due to bytes 4-7
>> and bytes 20-23 being written with non-zero data.
>>
>> When data is later written to this same page (w/o an intervening erase
>> of its block) reading the page causes an uncorrectable ECC error.
>>
>> There are eight additional bytes of OOB space available for writing, but
>> they are not ECC'd.
>>
>> The issue I'm trying to solve is how to communicate from MTD to JFFS2
>> that some bytes of the oobfree array perturb the data ECC and can not be
>> used to write the cleanmarker.
> OK, thanks for explanation. I am not very good in this area as I do not
> have much experience dealing with OOB, but here is what I thing.
>
> 1. Linux MTD code was _not_ designed for "ECC'ed OOB".
> 2. I do not really know what MTD_OOB_RAW is, and the comment in mtd.h
>     is not very verbose.
> 3. But in my opinion MTD_OOB_AUTO makes most sense and should be used
>     everywhere except for some tricky cases when you want to test things
>     by writing incorrect ECC, or you have an image with ECC and you want
>     to flash it as is.
> 4. In general, OOB should be considered as belonging to the driver, and
>     modern software should not rely on OOB at all.
> 5. So MTD_OOB_AUTO make free bytes in OOB look like a contiguous buffer
>     which the _user_ can freely and _independently_ use.
> 6. In your case only this assumption does not work and your ecclayout is
>     incorrect because the OOB areas you expose are not independent.
> 7. So in your case your ecclayout should be changed and you should
>     expose only independent ECC bytes.
The independent ECC bytes available only total to eight, which makes it 
impossible to use YAFFS (which needs at least 16 bytes to stor e its 
metadata in).  I can add the independent bytes at the end of the layout 
(and tweak YAFFS to ignore them since it needs only 16 bytes if the 
metadata is ECC'ed), but I still need to create a fix in JFFS2 (and 
u-boot and utilities) to skip the first 16 bytes of oobfree area.  
That's why I think another ioctl call (GETOOBLAYOUT?) would be useful to 
describe the oobfree list, as well as lists(or bitfields) that indicates 
which bytes in oobfree are either ECC'ed as part of the data ECC, or 
ECC'ed independently.

Another issue this exposes is that JFFS2 reads/compares the cleanmarker 
w/o any ECC in the marker data to verify its validity - if a bitflip in 
an unECC'd cleanmarker is read back, then I think JFFS2 will fail to use 
that block.

Also, from what I can find, MTD does not provide a method of programming 
OOB NAND data using MTD_OOB_AUTO as mtd_do_writeoob (called in mtdchar.c 
from the MTDWRITEOOB ioctl) uses only MTD_OOB_PLACE.

-- 
Peter Barada
peter.barada at gmail.com



From dedekind1 at gmail.com  Tue Jun 28 15:05:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Tue, 28 Jun 2011 22:05:14 +0300
Subject: [PATCH 2/6] nand_wait : warn if the nand is busy on exit
In-Reply-To: <4E09ED56.2070704@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>
	<1309247836.23597.42.camel@sauron> <4E09ED56.2070704@parrot.com>
Message-ID: <1309287916.7411.9.camel@koala>

On Tue, 2011-06-28 at 17:03 +0200, Matthieu CASTET wrote:
> Artem Bityutskiy a ?crit :
> > On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> >> This patch allow to detect buggy driver/hardware with
> >> bad RnB (dev_ready) management.
> >> This check cost nothing and could help to detect bugs.
> >>
> >> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> >> ---
> >>  drivers/mtd/nand/nand_base.c |    2 ++
> >>  1 files changed, 2 insertions(+), 0 deletions(-)
> >>
> >> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> >> index a3c7fd3..095dfea 100644
> >> --- a/drivers/mtd/nand/nand_base.c
> >> +++ b/drivers/mtd/nand/nand_base.c
> >> @@ -885,6 +885,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
> >>  	led_trigger_event(nand_led_trigger, LED_OFF);
> >>  
> >>  	status = (int)chip->read_byte(mtd);
> >> +	/* This can happen if in case of timeout or buggy dev_ready */
> >> +	WARN_ON(!(status & NAND_STATUS_READY));
> >>  	return status;
> > 
> > This seem to completely miss the chip->dev_ready != NULL case, e.g.,
> > piece of code above is like this
> > 
> >                 while (time_before(jiffies, timeo)) {
> >                         if (chip->dev_ready) {
> >                                 if (chip->dev_ready(mtd))
> >                                         break;
> >                         } else {
> >                                 if (chip->read_byte(mtd) & NAND_STATUS_READY)
> >                                         break;
> >                         }
> >                         cond_resched();
> >                 }
> > 
> Sorry, I don't understand what you mean.
> 
> We don't care what's done in the loop (chip->dev_ready != NULL or, not). We only
> check when the loop exit, that READY bit is set in the status.

Well, the logic is suspicious.

1. For NAND with chip->dev_ready != NULL, why NAND_STATUS_READY should
be set? We do not check for this in the loop.

2. For NAND with chip->dev_ready != NULL, if NAND_STATUS_READY has to be
set at the end, why wouldn't we drop this chip_ready part completely? We
could just loop while NAND_STATUS_READY is not set.

Isn't this strange?

-- 
Best Regards,
Artem Bityutskiy (???????? ?????)



From zhubr at mail.ru  Tue Jun 28 18:26:57 2011
From: zhubr at mail.ru (Nikolai Zhubr)
Date: Wed, 29 Jun 2011 02:26:57 +0400
Subject: JFFS2 oops
Message-ID: <4E0A5531.7020304@mail.ru>

Hello people,

I'm getting an oops in (or related to) JFFS2 filesystem in stock kernel 
2.6.36.4 on ARM with a real MTD memory and I've found that it also 
happens on x86_64 opensuse 11.3 kernel 2.6.34-12-desktop with mtdram 
simulator if 256K erase-block size is specified.

The oops is fully reproducible and happens immediately on mount attempt. 
I think, the data was not even subject to sudden power failure or any 
such event. Just upon normal reboot it failed to mount.
Some logs are attached below.

The image (300Kb) causing this oops can be found here:
http://n-a-zhubr.narod.ru/openwrt/jffs2oops.img.gz
(hopefully the link works for all, otherwise I can email it personally 
to whoever is interested)
The size of erase block is set to 256K because my device of interest 
does have it this way.

Please CC me, I'm not subscribed.
Thank you.
Nikolai ZHUBR
===================================================================
JFFS2 error: (233) jffs2_link_node_ref: Adding new ref c59eaeec at 
(0x00000000-0x00000034) not immediately after previous 
(0x00000000-0x00000000)
kernel BUG at fs/jffs2/nodelist.c:644!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = c59ec000
[00000000] *pgd=059e8031, *pte=00000000, *ppte=00000000
Internal error: Oops: 817 [#1]
last sysfs file: /sys/kernel/uevent_seqnum
Modules linked in:
CPU: 0    Not tainted  (2.6.36.4 #50)
===================================================================
2.6.34-12-desktop:
kernel:[ 1192.811506] ------------[ cut here ]------------
kernel:[ 1192.811512] invalid opcode: 0000 [#1] PREEMPT SMP
kernel:[ 1192.811515] last sysfs file: /sys/devices/virtual/bdi/31:0/uevent
kernel:[ 1192.811628] Stack:
kernel:[ 1192.811640] Call Trace:
kernel:[ 1192.811805] Code: 8b b6 b0 02 00 00 41 83 e0 fc 46 8d 0c 01 48 
89 d9 83 e2 fc 01 d0 89 14 24 48 c7 c2 50 4f aa a0 89 44 24 08 31 c0 e8 
9e d7 a0 e0 <0f> 0b 0f 0b 66 66 66 66 2e 0f 1f 84 00 00 00 00 00 48 83 
ec 08


From computersforpeace at gmail.com  Tue Jun 28 19:28:57 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 28 Jun 2011 16:28:57 -0700
Subject: [PATCH 0/3] fixups for OOB ECC problems
Message-ID: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>

Hello,

Now that we have added the possibility that mtd->read_oob returns
-EUCLEAN or -EBADMSG for corrected bitflips and for uncorrectable errors,
respectively, there are more pieces of code that need to take this into
account. These patches should address some of these by ignoring bitflips
when bit accuracy is not needed or by ignoring corrected errors when
scrubbing would be unnecessary.

There are still other cases to address, for example, some flash-based BBT
code.

This applies on top of l2-mtd-2.6.git. Patch 3 is an amendment to commit
abf386c475beab813dc9b3366e592e00255e987a, ("mtd: nand: handle ECC errors
in OOB"), so it can be squashed in if you want. Let me know if you want
me to do this and do a resend.

Brian

Brian Norris (3):
  mtd: nand: ignore ECC errors for simple BBM scans
  mtd: tests: ignore corrected bitflips in OOB on mtd_readtest
  mtd: edit NAND-related comment

 drivers/mtd/mtdchar.c            |    5 +++--
 drivers/mtd/nand/nand_bbt.c      |   13 ++++++++++---
 drivers/mtd/tests/mtd_readtest.c |    3 ++-
 3 files changed, 15 insertions(+), 6 deletions(-)




From computersforpeace at gmail.com  Tue Jun 28 19:28:58 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 28 Jun 2011 16:28:58 -0700
Subject: [PATCH 1/3] mtd: nand: ignore ECC errors for simple BBM scans
In-Reply-To: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
References: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309303740-9936-2-git-send-email-computersforpeace@gmail.com>

Now that nand_do_readoob() may return -EUCLEAN or -EBADMSG on ECC errors,
we need to handle the return value specially in some cases.

When scanning for simple bad block markers, reacting to an ECC error is
not very useful, as we assume that the relevant markers are still
non-0xFF for true bad blocks.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/nand_bbt.c |   13 ++++++++++---
 1 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index f30807c..a4fcbf1 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -312,14 +312,20 @@ static int scan_read_raw_oob(struct mtd_info *mtd, uint8_t *buf, loff_t offs,
 			ops.oobbuf = buf + len;
 			ops.datbuf = buf;
 			ops.len = len;
-			return mtd->read_oob(mtd, offs, &ops);
+			res = mtd->read_oob(mtd, offs, &ops);
+
+			/* Ignore ECC errors when checking for BBM */
+			if (res != -EUCLEAN && res != -EBADMSG)
+				return res;
+			return 0;
 		} else {
 			ops.oobbuf = buf + mtd->writesize;
 			ops.datbuf = buf;
 			ops.len = mtd->writesize;
 			res = mtd->read_oob(mtd, offs, &ops);
 
-			if (res)
+			/* Ignore ECC errors when checking for BBM */
+			if (res && res != -EUCLEAN && res != -EBADMSG)
 				return res;
 		}
 
@@ -435,7 +441,8 @@ static int scan_block_fast(struct mtd_info *mtd, struct nand_bbt_descr *bd,
 		 * byte reads for 16 bit buswidth.
 		 */
 		ret = mtd->read_oob(mtd, offs, &ops);
-		if (ret)
+		/* Ignore ECC errors when checking for BBM */
+		if (ret && ret != -EUCLEAN && ret != -EBADMSG)
 			return ret;
 
 		if (check_short_pattern(buf, bd))
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 28 19:28:59 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 28 Jun 2011 16:28:59 -0700
Subject: [PATCH 2/3] mtd: tests: ignore corrected bitflips in OOB on
	mtd_readtest
In-Reply-To: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
References: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309303740-9936-3-git-send-email-computersforpeace@gmail.com>

read_oob may now return ECC error codes. If the code is -EUCLEAN, then
we can safely ignore the error as a corrected bitflip.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/tests/mtd_readtest.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/tests/mtd_readtest.c b/drivers/mtd/tests/mtd_readtest.c
index afe71aa..de23e8e 100644
--- a/drivers/mtd/tests/mtd_readtest.c
+++ b/drivers/mtd/tests/mtd_readtest.c
@@ -75,7 +75,8 @@ static int read_eraseblock_by_page(int ebnum)
 			ops.datbuf    = NULL;
 			ops.oobbuf    = oobbuf;
 			ret = mtd->read_oob(mtd, addr, &ops);
-			if (ret || ops.oobretlen != mtd->oobsize) {
+			if (ret && ret != -EUCLEAN ||
+					ops.oobretlen != mtd->oobsize) {
 				printk(PRINT_PREF "error: read oob failed at "
 						  "%#llx\n", (long long)addr);
 				if (!err)
-- 
1.7.0.4




From computersforpeace at gmail.com  Tue Jun 28 19:29:00 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Tue, 28 Jun 2011 16:29:00 -0700
Subject: [PATCH 3/3] mtd: edit NAND-related comment
In-Reply-To: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
References: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309303740-9936-4-git-send-email-computersforpeace@gmail.com>

This comment was unclear regarding which NAND functions do and do not
support ECC on the spare area. This update should reflect the current
status of the NAND system but can be updated if changes are made in
the standard functions.

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/mtdchar.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index 0995e8e..978e084 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -482,8 +482,9 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start,
 	 * to signal the caller that a bitflip has occured and has
 	 * been corrected by the ECC algorithm.
 	 *
-	 * Note: most NAND ECC algorithms do not calculate ECC
-	 * for the OOB area.
+	 * Note: currently the standard NAND function, nand_read_oob_std,
+	 * does not calculate ECC for the OOB area, so do not rely on
+	 * this behavior unless you have replaced it with your own.
 	 */
 	if (ret == -EUCLEAN || ret == -EBADMSG)
 		return 0;
-- 
1.7.0.4




From leiwen at marvell.com  Tue Jun 28 23:51:25 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:25 -0700
Subject: [PATCH V3 0/9] pxa3xx_nand: add two chip select support
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-1-git-send-email-leiwen@marvell.com>

V2:
Choose to at most keep original pxa3xx_nand_info structure to reduce
patch size

V3:
Seperate original one patch into a patch set

Lei Wen (9):
  MTD: pxa3xx_nand: convert all printk into dev_*
  MTD: pxa3xx_nand: enable multiple chip select support
  ARM: aspenite: fix nand platform data
  ARM: cm-x300: fix nand platform data
  ARM: colibri-pxa3xx: fix nand platform data
  ARM: littleton: fix nand platform data
  ARM: mxm8x10: fix nand platform data
  ARM: raumfeld: fix nand platform data
  ARM: zylonite: fix nand platform data

 arch/arm/mach-mmp/aspenite.c                 |    5 +-
 arch/arm/mach-pxa/cm-x300.c                  |    5 +-
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
 arch/arm/mach-pxa/littleton.c                |    5 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
 arch/arm/mach-pxa/raumfeld.c                 |    5 +-
 arch/arm/mach-pxa/zylonite.c                 |    5 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  512 +++++++++++++++-----------
 9 files changed, 346 insertions(+), 224 deletions(-)



From leiwen at marvell.com  Tue Jun 28 23:51:26 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:26 -0700
Subject: [PATCH 1/9] MTD: pxa3xx_nand: convert all printk into dev_*
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-2-git-send-email-leiwen@marvell.com>

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 drivers/mtd/nand/pxa3xx_nand.c |   19 ++++++++++---------
 1 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index b7db1b2..44fb210 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -359,7 +359,7 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
 					DIV_ROUND_UP(info->oob_size, 4));
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
 				info->state);
 		BUG();
 	}
@@ -385,7 +385,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
 				info->state);
 		BUG();
 	}
@@ -616,8 +616,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	default:
 		exec_cmd = 0;
-		printk(KERN_ERR "pxa3xx-nand: non-supported"
-			" command %x\n", command);
+		dev_err(&info->pdev->dev, "non-supported command %x\n",
+				command);
 		break;
 	}
 
@@ -646,7 +646,7 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		ret = wait_for_completion_timeout(&info->cmd_complete,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
-			printk(KERN_ERR "Wait time out!!!\n");
+			dev_err(&info->pdev->dev, "Wait time out!!!\n");
 			/* Stop State Machine for next command cycle */
 			pxa3xx_nand_stop(info);
 		}
@@ -898,7 +898,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	if (!ret) {
 		kfree(mtd);
 		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+		dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n");
 
 		return -EINVAL;
 	}
@@ -906,11 +906,12 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	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);
+		dev_info(&info->pdev->dev, "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");
+		dev_warn(&info->pdev->dev, "Read out ID 0, "
+				"potential timing set wrong!!\n");
 
 		return -EINVAL;
 	}
@@ -930,7 +931,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
 		kfree(mtd);
 		info->mtd = NULL;
-		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
 
 		return -EINVAL;
 	}
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:28 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:28 -0700
Subject: [PATCH 3/9] ARM: aspenite: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-4-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 06b5fa8..c4996f3 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -167,8 +167,9 @@ 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),
+	.num_cs = 1,
+	.parts[0]	= aspenite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(aspenite_nand_partitions),
 };
 
 static struct i2c_board_info aspenite_i2c_info[] __initdata = {
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:29 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:29 -0700
Subject: [PATCH 4/9] ARM: cm-x300: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-5-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-pxa/cm-x300.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b2248e7..969d252 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -423,8 +423,9 @@ 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),
+	.num_cs		= 1,
+	.parts[0]	= cm_x300_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(cm_x300_nand_partitions),
 };
 
 static void __init cm_x300_init_nand(void)
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:30 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:30 -0700
Subject: [PATCH 5/9] ARM: colibri-pxa3xx: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-6-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-pxa/colibri-pxa3xx.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c
index 3f9be41..2b8ca0d 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -139,8 +139,9 @@ 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),
+	.num_cs		= 1,
+	.parts[0]	= colibri_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(colibri_nand_partitions),
 };
 
 void __init colibri_pxa3xx_init_nand(void)
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:31 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:31 -0700
Subject: [PATCH 6/9] ARM: littleton: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-7-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-pxa/littleton.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index e5e326d..f6d1f9d 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -325,8 +325,9 @@ 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),
+	.num_cs		= 1,
+	.parts[0]	= littleton_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(littleton_nand_partitions),
 };
 
 static void __init littleton_init_nand(void)
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:32 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:32 -0700
Subject: [PATCH 7/9] ARM: mxm8x10: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-8-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-pxa/mxm8x10.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/arch/arm/mach-pxa/mxm8x10.c b/arch/arm/mach-pxa/mxm8x10.c
index b5a8fd3..90928d6 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,10 +389,11 @@ 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,
+	.num_cs		= 1,
+	.parts[0]	= mxm_8x10_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(mxm_8x10_nand_partitions)
 };
 
 static void __init mxm_8x10_nand_init(void)
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:33 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:33 -0700
Subject: [PATCH 8/9] ARM: raumfeld: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-9-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-pxa/raumfeld.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index d130f77..c7ec847 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -349,8 +349,9 @@ 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),
+	.num_cs		= 1,
+	.parts[0]	= raumfeld_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(raumfeld_nand_partitions),
 };
 
 /**
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:34 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:34 -0700
Subject: [PATCH 9/9] ARM: zylonite: fix nand platform data
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-10-git-send-email-leiwen@marvell.com>

Since two chip select is supported, the original defined nand platform
data need to be fixed accordingly.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-pxa/zylonite.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 5821185..64fdac9 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -366,8 +366,9 @@ 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),
+	.num_cs		= 1,
+	.parts[0]	= zylonite_nand_partitions,
+	.nr_parts[0]	= ARRAY_SIZE(zylonite_nand_partitions),
 };
 
 static void __init zylonite_init_nand(void)
-- 
1.7.0.4



From leiwen at marvell.com  Tue Jun 28 23:51:27 2011
From: leiwen at marvell.com (Lei Wen)
Date: Tue, 28 Jun 2011 20:51:27 -0700
Subject: [PATCH 2/9] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309246361.23597.30.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
Message-ID: <1309319494-17951-3-git-send-email-leiwen@marvell.com>

Current pxa3xx_nand controller has two chip select which
both be workable. This patch enable this feature.

Update platform driver to support this feature.

Another notice should be taken that:
When you want to use this feature, you should not enable the
keep configuration feature, for two chip select could be
attached with different nand chip. The different page size
and timing requirement make the keep configuration impossible.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  493 +++++++++++++++----------
 2 files changed, 313 insertions(+), 199 deletions(-)

diff --git a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
index 442301f..4e17309 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
+/*
+ * Current pxa3xx_nand controller has two chip select which
+ * both be workable.
+ *
+ * Notice should be taken that:
+ * When you want to use this feature, you should not enable the
+ * keep configuration feature, for two chip select could be
+ * attached with different nand chip. The different page size
+ * and timing requirement make the keep configuration impossible.
+ */
+
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {
 
 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +65,10 @@ 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;
+	/* indicate how many chip selects will be used */
+	int	num_cs;
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];
 
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index 44fb210..3ffa6e0 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -110,6 +110,7 @@ enum {
 
 enum {
 	STATE_IDLE = 0,
+	STATE_PREPARED,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
@@ -120,21 +121,40 @@ enum {
 	STATE_READY,
 };
 
-struct pxa3xx_nand_info {
-	struct nand_chip	nand_chip;
+struct pxa3xx_nand_host {
+	struct nand_chip	chip;
+	struct pxa3xx_nand_cmdset *cmdset;
+	struct mtd_info         *mtd;
+	void			*info_data;
+
+	/* page size of attached chip */
+	unsigned int		page_size;
+	int			cs;
+	int			use_ecc;
+
+	/* calculated from pxa3xx_nand_flash data */
+	unsigned int		col_addr_cycles;
+	unsigned int		row_addr_cycles;
+	size_t			read_id_bytes;
+
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+};
 
+struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
-	struct pxa3xx_nand_cmdset *cmdset;
 
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
+	struct completion	cmd_complete;
 
 	unsigned int 		buf_start;
 	unsigned int		buf_count;
 
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -142,44 +162,27 @@ struct pxa3xx_nand_info {
 	unsigned char		*data_buff;
 	unsigned char		*oob_buff;
 	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;
 
-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
-
+	struct pxa3xx_nand_host	*host[NUM_CHIP_SELECT];
 	/* relate to the command */
 	unsigned int		state;
 
+	int			cs;
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
 	int			is_ready;
 
-	unsigned int		page_size;	/* page size of attached chip */
 	unsigned int		data_size;	/* data size in FIFO */
+	unsigned int		oob_size;
 	int 			retcode;
-	struct completion 	cmd_complete;
 
 	/* generated NDCBx register values */
 	uint32_t		ndcb0;
 	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;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };
 
 static int use_dma = 1;
@@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
-const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+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)
@@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 
-static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
+static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 				   const struct pxa3xx_nand_timing *t)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	unsigned long nand_clk = clk_get_rate(info->clk);
 	uint32_t ndtr0, ndtr1;
 
@@ -258,23 +262,24 @@ 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;
+	host->ndtr0cs0 = ndtr0;
+	host->ndtr1cs0 = ndtr1;
 	nand_writel(info, NDTR0CS0, ndtr0);
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
 
-	info->data_size = info->page_size;
+	info->data_size = host->page_size;
 	if (!oob_enable) {
 		info->oob_size = 0;
 		return;
 	}
 
-	switch (info->page_size) {
+	switch (host->page_size) {
 	case 2048:
 		info->oob_size = (info->use_ecc) ? 40 : 64;
 		break;
@@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
  */
 static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr;
 
-	ndcr = info->reg_ndcr;
+	ndcr = host->reg_ndcr;
 	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
 	ndcr |= NDCR_ND_RUN;
@@ -416,9 +422,17 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
 	unsigned int status, is_completed = 0;
+	unsigned int ready, cmd_done;
+
+	if (info->cs == 0) {
+		ready           = NDSR_FLASH_RDY;
+		cmd_done        = NDSR_CS0_CMDD;
+	} else {
+		ready           = NDSR_RDY;
+		cmd_done        = NDSR_CS1_CMDD;
+	}
 
 	status = nand_readl(info, NDSR);
-
 	if (status & NDSR_DBERR)
 		info->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
@@ -437,11 +451,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 			handle_data_pio(info);
 		}
 	}
-	if (status & NDSR_CS0_CMDD) {
+	if (status & cmd_done) {
 		info->state = STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY) {
+	if (status & ready) {
 		info->is_ready = 1;
 		info->state = STATE_READY;
 	}
@@ -463,12 +477,6 @@ 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--)
@@ -481,10 +489,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
-	int addr_cycle, exec_cmd, ndcb0;
-	struct mtd_info *mtd = info->mtd;
+	int addr_cycle, exec_cmd;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	struct mtd_info *mtd = host->mtd;
 
-	ndcb0 = 0;
 	addr_cycle = 0;
 	exec_cmd = 1;
 
@@ -495,6 +503,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	info->use_ecc		= 0;
 	info->is_ready		= 0;
 	info->retcode		= ERR_NONE;
+	if (info->cs != 0)
+		info->ndcb0 = NDCB0_CSEL;
+	else
+		info->ndcb0 = 0;
 
 	switch (command) {
 	case NAND_CMD_READ0:
@@ -512,20 +524,19 @@ 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);
+	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
+				    + host->col_addr_cycles);
 
 	switch (command) {
 	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		cmd = info->cmdset->read1;
+		cmd = host->cmdset->read1;
 		if (command == NAND_CMD_READOOB)
 			info->buf_start = mtd->writesize + column;
 		else
 			info->buf_start = column;
 
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
 			info->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
@@ -537,7 +548,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
 			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 
@@ -564,7 +575,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 			break;
 		}
 
-		cmd = info->cmdset->program;
+		cmd = host->cmdset->program;
 		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
@@ -574,8 +585,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		break;
 
 	case NAND_CMD_READID:
-		cmd = info->cmdset->read_id;
-		info->buf_count = info->read_id_bytes;
+		cmd = host->cmdset->read_id;
+		info->buf_count = host->read_id_bytes;
 		info->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
@@ -583,7 +594,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		info->data_size = 8;
 		break;
 	case NAND_CMD_STATUS:
-		cmd = info->cmdset->read_status;
+		cmd = host->cmdset->read_status;
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
@@ -593,7 +604,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		break;
 
 	case NAND_CMD_ERASE1:
-		cmd = info->cmdset->erase;
+		cmd = host->cmdset->erase;
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
@@ -604,7 +615,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 		break;
 	case NAND_CMD_RESET:
-		cmd = info->cmdset->reset;
+		cmd = host->cmdset->reset;
 		info->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;
 
@@ -627,7 +638,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int ret, exec_cmd;
 
 	/*
@@ -635,9 +647,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 	 * "byte" address into a "word" address appropriate
 	 * for indexing a word-oriented device
 	 */
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
 		column /= 2;
 
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, host->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, host->ndtr1cs0);
+	}
+
+	info->state = STATE_PREPARED;
 	exec_cmd = prepare_command_pool(info, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&info->cmd_complete);
@@ -650,8 +674,8 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 			/* Stop State Machine for next command cycle */
 			pxa3xx_nand_stop(info);
 		}
-		info->state = STATE_IDLE;
 	}
+	info->state = STATE_IDLE;
 }
 
 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
@@ -664,7 +688,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	chip->read_buf(mtd, buf, mtd->writesize);
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -695,7 +720,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	char retval = 0xFF;
 
 	if (info->buf_start < info->buf_count)
@@ -707,7 +733,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	u16 retval = 0xFFFF;
 
 	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
@@ -719,7 +746,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(buf, info->data_buff + info->buf_start, real_len);
@@ -729,7 +757,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(info->data_buff + info->buf_start, buf, real_len);
@@ -749,7 +778,8 @@ 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	/* pxa3xx_nand_send_command has waited for command complete */
 	if (this->state == FL_WRITING || this->state == FL_ERASING) {
@@ -772,54 +802,69 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512)
+	if (f->page_size != 2048 && f->page_size != 512) {
+		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
 		return -EINVAL;
+	}
 
-	if (f->flash_width != 16 && f->flash_width != 8)
+	if (f->flash_width != 16 && f->flash_width != 8) {
+		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
 		return -EINVAL;
+	}
 
 	/* calculate flash information */
-	info->cmdset = &default_cmdset;
-	info->page_size = f->page_size;
-	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+	host->cmdset = &default_cmdset;
+	host->page_size = f->page_size;
+	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
 	/* calculate addressing information */
-	info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
 
 	if (f->num_blocks * f->page_per_block > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
+		host->row_addr_cycles = 2;
 
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
 	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
 	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
 	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
 
-	ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
-	info->reg_ndcr = ndcr;
+	host->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(info, f->timing);
+	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
+	/*
+	 * We set 0 by hard coding here, for we don't support keep_config
+	 * when there is more than one chip attached to the controller
+	 */
+	struct pxa3xx_nand_host *host = info->host[0];
 	uint32_t ndcr = nand_readl(info, NDCR);
-	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* set info fields needed to read id */
-	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
-	info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
-	info->cmdset = &default_cmdset;
 
-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	if (ndcr & NDCR_PAGE_SZ) {
+		host->page_size = 2048;
+		host->read_id_bytes = 4;
+	} else {
+		host->page_size = 512;
+		host->read_id_bytes = 2;
+	}
+	host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+	host->cmdset = &default_cmdset;
+
+	host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+	host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
 	return 0;
 }
@@ -829,59 +874,41 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
  * data buffer and the DMA descriptor
  */
 #define MAX_BUFF_SIZE	PAGE_SIZE
-
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
-	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;
+	struct pxa3xx_nand_host *host;
+	struct mtd_info *mtd;
 
-	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;
-	}
+	if (!info->host[cs])
+		return;
 
-	return 0;
+	host = info->host[cs];
+	mtd = host->mtd;
+	kfree(mtd);
+	info->host[cs] = NULL;
 }
 
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct mtd_info *mtd = info->mtd;
-	struct nand_chip *chip = mtd->priv;
+	struct mtd_info *mtd = info->host[info->cs]->mtd;
+	int ret;
 
 	/* 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);
+	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	if (ret)
+		return ret;
+
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	if (info->is_ready)
-		return 1;
-	else
 		return 0;
+
+	return -ENODEV;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
@@ -891,16 +918,16 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret, num;
 
+	info->cs = host->cs;
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
 	ret = pxa3xx_nand_sensing(info);
-	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
+	if (ret) {
+		free_cs_resource(info, info->cs);
 		dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n");
 
-		return -EINVAL;
+		return ret;
 	}
 
 	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
@@ -908,8 +935,7 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	if (id != 0)
 		dev_info(&info->pdev->dev, "Detect a flash id %x\n", id);
 	else {
-		kfree(mtd);
-		info->mtd = NULL;
+		free_cs_resource(info, info->cs);
 		dev_warn(&info->pdev->dev, "Read out ID 0, "
 				"potential timing set wrong!!\n");
 
@@ -929,14 +955,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	}
 
 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
+		free_cs_resource(info, info->cs);
 		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
 
 		return -EINVAL;
 	}
 
-	pxa3xx_nand_config_flash(info, f);
+	ret = pxa3xx_nand_config_flash(info, f);
+	if (ret) {
+		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
+		return ret;
+	}
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -951,66 +980,51 @@ KEEP_CONFIG:
 	if (nand_scan_ident(mtd, 1, def))
 		return -ENODEV;
 	/* calculate addressing information */
-	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	if (mtd->writesize >= 2048)
+		host->col_addr_cycles = 2;
+	else
+		host->col_addr_cycles = 1;
 	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
+		host->row_addr_cycles = 2;
+	mtd->name = mtd_names[info->cs];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = info->page_size;
+	chip->ecc.size = host->page_size;
 
-	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
+	chip->options = 0;
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
+		chip->options = NAND_BUSWIDTH_16;
 	chip->options |= NAND_NO_AUTOINCR;
 	chip->options |= NAND_NO_READRDY;
 
 	return nand_scan_tail(mtd);
 }
 
-static
-struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
+	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	struct pxa3xx_nand_host *host;
 	struct nand_chip *chip;
 	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) {
+	pdata = pdev->dev.platform_data;
+	info = kzalloc(sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
+	if (!info) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return NULL;
+		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->controller        = &info->controller;
-	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;
-
-	spin_lock_init(&chip->controller->lock);
-	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
 		ret = PTR_ERR(info->clk);
-		goto fail_free_mtd;
+		goto fail_alloc;
 	}
 	clk_enable(info->clk);
 
@@ -1059,10 +1073,6 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 	}
 	info->mmio_phys = r->start;
 
-	ret = pxa3xx_nand_init_buff(info);
-	if (ret)
-		goto fail_free_io;
-
 	/* initialize all interrupts to be disabled */
 	disable_int(info, NDSR_MASK);
 
@@ -1070,21 +1080,80 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 			  pdev->name, info);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
-		goto fail_free_buf;
+		ret = ENXIO;
+		goto fail_free_io;
 	}
 
 	platform_set_drvdata(pdev, info);
 
-	return info;
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		mtd = kzalloc(sizeof(struct mtd_info)
+				+ sizeof(struct pxa3xx_nand_host),
+				GFP_KERNEL);
+		if (!mtd) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			ret = -ENOMEM;
+			goto fail_free_irq;
+		}
+
+		host = (struct pxa3xx_nand_host *)(&mtd[1]);
+		host->info_data = info;
+		host->cs = cs;
+		host->mtd = mtd;
+		mtd->priv = host;
+		mtd->owner = THIS_MODULE;
+		info->host[cs] = host;
+
+		chip = (struct nand_chip *)(&mtd[1]);
+		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;
+	}
+
+	if (use_dma == 0) {
+		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (info->data_buff == NULL) {
+			ret = -ENOMEM;
+			goto fail_free_buf;
+		}
+		goto success_exit;
+	}
+
+	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, info);
+	if (info->data_dma_ch < 0) {
+		dev_err(&pdev->dev, "failed to request data dma\n");
+		ret = -ENXIO;
+		goto fail_free_dma_buf;
+	}
+success_exit:
+	return 0;
 
+fail_free_dma_buf:
+	dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
+			info->data_buff, info->data_buff_phys);
 fail_free_buf:
+	for (cs = 0; cs < pdata->num_cs; cs++)
+		free_cs_resource(info, cs);
+fail_free_irq:
 	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);
 fail_free_res:
@@ -1092,18 +1161,20 @@ fail_free_res:
 fail_put_clk:
 	clk_disable(info->clk);
 	clk_put(info->clk);
-fail_free_mtd:
-	kfree(mtd);
-	return NULL;
+fail_alloc:
+	kfree(info);
+	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_platform_data *pdata;
+	struct pxa3xx_nand_host *host;
 	struct resource *r;
-	int irq;
+	int irq, cs;
 
+	pdata = pdev->dev.platform_data;
 	platform_set_drvdata(pdev, NULL);
 
 	irq = platform_get_irq(pdev, 0);
@@ -1111,7 +1182,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 		free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, info->data_buff_size,
+		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
 				info->data_buff, info->data_buff_phys);
 	} else
 		kfree(info->data_buff);
@@ -1123,9 +1194,12 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	clk_disable(info->clk);
 	clk_put(info->clk);
 
-	if (mtd) {
-		nand_release(mtd);
-		kfree(mtd);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		host = info->host[cs];
+		if (!host)
+			continue;
+		nand_release(host->mtd);
+		free_cs_resource(info, cs);
 	}
 	return 0;
 }
@@ -1134,6 +1208,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	int cs, ret, probe_success = 0;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1141,18 +1216,38 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	info = alloc_nand_resource(pdev);
-	if (info == NULL)
-		return -ENOMEM;
+	if (pdata->keep_config && pdata->num_cs > 1) {
+		dev_warn(&pdev->dev, "keep_config is prohibited with multiple"
+			 " chip selects feature!\n");
+		pdata->keep_config = 0;
+	}
+
+	ret = alloc_nand_resource(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "alloc nand resource failed\n");
+		return ret;
+	}
+
+	info = platform_get_drvdata(pdev);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		ret = pxa3xx_nand_scan(info->host[cs]->mtd);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to scan nand\n");
+			continue;
+		}
+
+		ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
+			pdata->parts[cs], pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
+	}
 
-	if (pxa3xx_nand_scan(info->mtd)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
+	if (!probe_success) {
 		pxa3xx_nand_remove(pdev);
 		return -ENODEV;
 	}
 
-	return mtd_device_parse_register(info->mtd, NULL, 0,
-			pdata->parts, pdata->nr_parts);
+	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1172,8 +1267,12 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
 
-	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+	/*
+	 * Directly set the chip select to a invalid value,
+	 * then the driver would reset the timing according
+	 * to current chip select at the beginning of cmdfunc
+	 */
+	info->cs = 0xff;
 	clk_enable(info->clk);
 
 	return 0;
-- 
1.7.0.4



From dedekind1 at gmail.com  Wed Jun 29 02:02:25 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:02:25 +0300
Subject: [PATCH 09/10] mtdinfo: kill -m option
In-Reply-To: <1309199247-19248-10-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<1309199247-19248-10-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309327350.23597.96.camel@sauron>

On Mon, 2011-06-27 at 11:27 -0700, Brian Norris wrote:
> According to feature-removal-schedule, we shouldn't use `-m', since
> it relies on a specific device-naming pattern.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  feature-removal-schedule.txt |    8 --------
>  ubi-utils/mtdinfo.c          |   25 ++++++-------------------
>  2 files changed, 6 insertions(+), 27 deletions(-)

Pushed the series, thanks! I would also like to add the following patch
on top of your series, is ok with you?

From: Artem Bityutskiy <dedekind1 at gmail.com>
Date: Wed, 29 Jun 2011 08:56:39 +0300
Subject: [PATCH] mtdinfo: remove -m leftovers

We have removed the -m option, but did not remove args.mtdn which represents
the -m parameters. Kill args.mtdn as well.

Signed-off-by: Artem Bityutskiy <dedekind1 at gmail.com>
---
 ubi-utils/mtdinfo.c |   22 +++++++++-------------
 1 files changed, 9 insertions(+), 13 deletions(-)

diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
index dd5da53..4631f37 100644
--- a/ubi-utils/mtdinfo.c
+++ b/ubi-utils/mtdinfo.c
@@ -128,10 +128,8 @@ static int parse_opt(int argc, char * const argv[])
 	else if (optind < argc)
 		return errmsg("more then one MTD device specified (use -h for help)");
 
-	if (args.all && (args.node || args.mtdn != -1)) {
-		args.mtdn = -1;
+	if (args.all && args.node)
 		args.node = NULL;
-	}
 
 	if (args.map && !args.node)
 		return errmsg("-M requires MTD device node name");
@@ -153,8 +151,7 @@ static int translate_dev(libmtd_t libmtd, const char *node)
 				  "device \"%s\"", node);
 	}
 
-	args.mtdn = mtd.mtd_num;
-	return 0;
+	return mtd.mtd_num;
 }
 
 static void print_ubi_info(const struct mtd_info *mtd_info,
@@ -406,20 +403,19 @@ int main(int argc, char * const argv[])
 		return sys_errmsg("cannot get MTD information");
 	}
 
-	if (args.node) {
+	if (!args.all) {
+		int mtdn;
+
 		/*
 		 * A character device was specified, translate this to MTD
 		 * device number.
 		 */
-		err = translate_dev(libmtd, args.node);
-		if (err)
+		mtdn = translate_dev(libmtd, args.node);
+		if (mtdn < 0)
 			goto out_libmtd;
-	}
-
-	if (args.mtdn == -1)
+		err = print_dev_info(libmtd, &mtd_info, mtdn);
+	} else
 		err = print_general_info(libmtd, &mtd_info, args.all);
-	else
-		err = print_dev_info(libmtd, &mtd_info, args.mtdn);
 	if (err)
 		goto out_libmtd;
 
-- 
1.7.5.4


-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:05:34 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:05:34 +0300
Subject: [PATCH] jffs2: use mutex_is_locked() in __jffs2_flush_wbuf()
In-Reply-To: <1309206090-2805-1-git-send-email-khoroshilov@ispras.ru>
References: <1309206090-2805-1-git-send-email-khoroshilov@ispras.ru>
Message-ID: <1309327538.23597.97.camel@sauron>

On Tue, 2011-06-28 at 00:21 +0400, Alexey Khoroshilov wrote:
> Use a helper to test if a mutex is held instead of a hack with
> mutex_trylock().
> 
> Signed-off-by: Alexey Khoroshilov <khoroshilov at ispras.ru>

Pushed to l2-mtd-2.6.git, thanks.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:08:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:08:08 +0300
Subject: [PATCH 1/6] nand_wait_ready timeout fix
In-Reply-To: <4E09EEA9.2040307@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309247324.23597.37.camel@sauron> <4E09EEA9.2040307@parrot.com>
Message-ID: <1309327692.23597.99.camel@sauron>

On Tue, 2011-06-28 at 17:09 +0200, Matthieu CASTET wrote:
> >>  	struct nand_chip *chip = mtd->priv;
> >> -	unsigned long timeo = jiffies + 2;
> >> +	unsigned long timeo = jiffies + (2 * HZ) / 1000;
> > 
> > I agree that the code is buggy, but your fix is strange: if HZ = 100, (2
> > * HZ) / 1000 will be zero?
> > 
> > I think you should instead know for how many msecs you want to wait, and
> > use msecs_to_jiffies().
> > 
> Your right, I assume the code was written for HZ=100, and the code should wait
> for 20 ms :
> unsigned long timeo = jiffies + (20 * HZ) / 1000;
> 
> this will match with the
> static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
> {
> 
>     unsigned long timeo = jiffies;
>     int status, state = chip->state;
> 
>     if (state == FL_ERASING)
>         timeo += (HZ * 400) / 1000;
>     else
>         timeo += (HZ * 20) / 1000;
> [...]
> }

I think we should use msecs_to_jiffies() in nand_wait() as well. Why
relying on weird calculations with HZ?

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:09:24 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:09:24 +0300
Subject: [PATCH 3/6] refactor mtd wait code
In-Reply-To: <4E09EC77.10501@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-3-git-send-email-matthieu.castet@parrot.com>
	<1309248031.23597.45.camel@sauron> <1309248214.23597.47.camel@sauron>
	<4E09EC77.10501@parrot.com>
Message-ID: <1309327769.23597.101.camel@sauron>

On Tue, 2011-06-28 at 17:00 +0200, Matthieu CASTET wrote:
> Artem Bityutskiy a ?crit :
> > On Tue, 2011-06-28 at 11:00 +0300, Artem Bityutskiy wrote:
> >> On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> >>> +/**
> >>> +  * This is call after sending a read command, or for autoincrement
> >>> +  * chip that need it (!NAND_NO_READRDY).
> >>> +  *
> >>> +  * We can't call NAND_CMD_STATUS here, because the read command
> >>> +  * is not finished
> >>> +  */
> >>> +static void nand_wait_read(struct mtd_info *mtd, struct nand_chip *chip)
> >>> +{
> >>> +	/*
> >>> +	 * If we don't have access to the busy pin, we apply the given
> >>> +	 * command delay
> >>> +	 */
> >>> +	if (!chip->dev_ready) {
> >>> +		udelay(chip->chip_delay);
> >>> +	}
> >>> +	else {
> >>> +		/* Apply this short delay always to ensure that we do wait tWB in
> >>> +		 * any case on any machine. */
> >>> +		ndelay(100);
> >> Please, all these hard-coded numbers should be hidden in the specific
> >> driver.
> > 
> > Or could you please explain a bit better why this delay has to be part
> > of nand core? And why it is 100 and not 200?
> > 
> This delay is already in the nand core. I only put it in a common function :

OK, sorry, but would it be possible to take a look at how this patch
could be split on smaller ones to make review a bit simpler?

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:20:25 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:20:25 +0300
Subject: [PATCH 1/2] mtd/nand : don't free the global data
	fsl_lbc_ctrl_dev->nand in fsl_elbc_chip_remove()
In-Reply-To: <1309225852-1664-1-git-send-email-b35362@freescale.com>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
Message-ID: <1309328435.23597.104.camel@sauron>

On Tue, 2011-06-28 at 09:50 +0800, b35362 at freescale.com wrote:
> From: Liu Shuo <b35362 at freescale.com>
> 
> The global data fsl_lbc_ctrl_dev->nand don't have to be freed in
> fsl_elbc_chip_remove(). The right place to do that is in fsl_elbc_nand_remove()
> if elbc_fcm_ctrl->counter is zero.
> 
> Signed-off-by: Liu Shuo <b35362 at freescale.com>
> ---
>  drivers/mtd/nand/fsl_elbc_nand.c |    1 -
>  1 files changed, 0 insertions(+), 1 deletions(-)
> 
> diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> index 0bb254c..a212116 100644
> --- a/drivers/mtd/nand/fsl_elbc_nand.c
> +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> @@ -829,7 +829,6 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
>  
>  	elbc_fcm_ctrl->chips[priv->bank] = NULL;
>  	kfree(priv);
> -	kfree(elbc_fcm_ctrl);
>  	return 0;
>  }

Do we have to assign fsl_lbc_ctrl_dev->nand to NULL in
fsl_elbc_nand_remove() then? I think that assignment can be killed then.

        if (!elbc_fcm_ctrl->counter) {
                fsl_lbc_ctrl_dev->nand = NULL;
                kfree(elbc_fcm_ctrl);
        }

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:22:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:22:04 +0300
Subject: [PATCH 2/2] mtd/nand : workaround for Freescale FCM to support
	large-page Nand chip
In-Reply-To: <1309225852-1664-2-git-send-email-b35362@freescale.com>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
	<1309225852-1664-2-git-send-email-b35362@freescale.com>
Message-ID: <1309328529.23597.106.camel@sauron>

On Tue, 2011-06-28 at 09:50 +0800, b35362 at freescale.com wrote:
> +	/* Hack for supporting the flash chip whose writesize is
> +	 * larger than 2K bytes.
> +	 */

Please, use proper kernel multi-line comments. Please, make sure
checkpatch.pl does not generate 13 errors with this patch.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:25:47 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:25:47 +0300
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <4E09F3F1.7080109@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
	<1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>
	<1309202771.24805.11.camel@koala> <4E09EA52.8090006@parrot.com>
	<4E09F3F1.7080109@free-electrons.com>
Message-ID: <1309328751.23597.109.camel@sauron>

On Tue, 2011-06-28 at 17:32 +0200, David Wagner wrote:
> On 06/28/2011 04:50 PM, Matthieu CASTET wrote:
> > Hi,
> >
> [...]
> > Also what are the advantage against gluebi + mtdblock_ro ?
> 
> The main advantage is a reduced number of layers ; I must say I cannot
> see much more for now.  I could add that the Kconfig help of gluebi
> advises not to use it except when needed by legacy software.

Well, I think Matthieu has a valid poit, you should try to come up with
a set of advantages, otherwise why would this drivers be needed? Why
would people spend time reviewing it? May be less memcpy's? Do we do an
extra memcpy in gluebi? If yes, can we avoid doing this. Anyway, please,
try to sell this driver a bit better.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:33:39 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:33:39 +0300
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <4E0A23D3.8060303@gmail.com>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>
	<4E020A36.6070708@gmail.com> <1308943581.13493.15.camel@koala>
	<4E089441.3010809@gmail.com> <1309253646.23597.58.camel@sauron>
	<4E0A23D3.8060303@gmail.com>
Message-ID: <1309329223.23597.116.camel@sauron>

On Tue, 2011-06-28 at 14:56 -0400, Peter Barada wrote:
> On 06/28/2011 05:34 AM, Artem Bityutskiy wrote:
> > On Mon, 2011-06-27 at 10:31 -0400, Peter Barada wrote:
> >> On 06/24/2011 03:26 PM, Artem Bityutskiy wrote:
> >>> On Wed, 2011-06-22 at 11:28 -0400, Peter Barada wrote:
> >>>> Thoughts?
> >>> Sorry, could you please define the problem you are trying to solve?
> >>> Sorry if you did define it in your long post, but I could not easily
> >>> find it.
> >> The problem I'm trying to solve is that the Micron NAND  I'm using has
> >> an internal 4-bit ECC engine and uses four 8-byte ECCs that provide
> >> 4-bit protection per 512 data bytes + four OOB bytes.  The ecclayout I'm
> >> using is:
> >>
> >> ecclayout = {
> >>           eccbytes = 32,
> >>           eccpos = { 8, 9, 10, 11, 12, 13, 14, 15, /* ECC data bytes
> >> 0-511 + OOB bytes 4-7 */
> >>                   24, 25, 26, 27, 28, 19, 30, 31, /* ECC data bytes
> >> 512-1023 + OOB bytes 20-23 */
> >>                   40, 41, 42, 43, 44, 45, 46, 47,  /* ECC data bytes
> >> 1024-1535 + OOB bytes 36-39 */
> >>                   56, 57, 58, 59, 60, 61, 62, 63},  /* ECC data bytes
> >> 1536-2047 + OOB bytes 52-55 */
> >>           .oobfree = {
> >>                   { .offset = 4,
> >>                     .length = 4},
> >>                   { .offset = 20,
> >>                     .length = 4},
> >>                   { .offset = 36,
> >>                     .length = 4},
> >>                   { .offset = 52,
> >>                     .length = 4},
> >>           },
> >> };
> >>
> >> After the JFFS2 cleanmarker is written into bytes 4-7 and 16-23 of the
> >> OOB, nanddump shows:
> >>
> >>     OOB Data: ff ff ff ff 85 19 03 20 5a e3 da 69 01 40 f1 36
> >>     OOB Data: ff ff ff ff 08 00 00 00 91 99 3c 05 01 d0 5d b3
> >>     OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> >>     OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
> >>
> >> Note that the ECC bytes 8-15 and 24-31 are no longer FF due to bytes 4-7
> >> and bytes 20-23 being written with non-zero data.
> >>
> >> When data is later written to this same page (w/o an intervening erase
> >> of its block) reading the page causes an uncorrectable ECC error.
> >>
> >> There are eight additional bytes of OOB space available for writing, but
> >> they are not ECC'd.
> >>
> >> The issue I'm trying to solve is how to communicate from MTD to JFFS2
> >> that some bytes of the oobfree array perturb the data ECC and can not be
> >> used to write the cleanmarker.
> > OK, thanks for explanation. I am not very good in this area as I do not
> > have much experience dealing with OOB, but here is what I thing.
> >
> > 1. Linux MTD code was _not_ designed for "ECC'ed OOB".
> > 2. I do not really know what MTD_OOB_RAW is, and the comment in mtd.h
> >     is not very verbose.
> > 3. But in my opinion MTD_OOB_AUTO makes most sense and should be used
> >     everywhere except for some tricky cases when you want to test things
> >     by writing incorrect ECC, or you have an image with ECC and you want
> >     to flash it as is.
> > 4. In general, OOB should be considered as belonging to the driver, and
> >     modern software should not rely on OOB at all.
> > 5. So MTD_OOB_AUTO make free bytes in OOB look like a contiguous buffer
> >     which the _user_ can freely and _independently_ use.
> > 6. In your case only this assumption does not work and your ecclayout is
> >     incorrect because the OOB areas you expose are not independent.
> > 7. So in your case your ecclayout should be changed and you should
> >     expose only independent ECC bytes.
> The independent ECC bytes available only total to eight, which makes it 
> impossible to use YAFFS (which needs at least 16 bytes to stor e its 
> metadata in). 

Are you sure YAFFS can use the dependent bytes? I am not sure, but I
thought YAFFS wants OOB to be independently writable, no?

>  I can add the independent bytes at the end of the layout 
> (and tweak YAFFS to ignore them since it needs only 16 bytes if the 
> metadata is ECC'ed), but I still need to create a fix in JFFS2 (and 
> u-boot and utilities) to skip the first 16 bytes of oobfree area. 

As I said, I think you need to take a good look at MTD and think how you
can teach it to distinguish with dependent and independent OOB bytes.

> That's why I think another ioctl call (GETOOBLAYOUT?) would be useful to 
> describe the oobfree list, as well as lists(or bitfields) that indicates 
> which bytes in oobfree are either ECC'ed as part of the data ECC, or 
> ECC'ed independently.

Why new ioctl? Why not add another OOB access type (like MTD_OOB_AUTO)?
Or may be one of the existing can be re-use? This should be carefully
analyzed.

> Another issue this exposes is that JFFS2 reads/compares the cleanmarker 
> w/o any ECC in the marker data to verify its validity - if a bitflip in 
> an unECC'd cleanmarker is read back, then I think JFFS2 will fail to use 
> that block.

No, I think what JFFS2 should do is just assume the eraseblock needs
erasure and just erase it. The whole purpose of clean markers is to
erase less. If it is corrupted - we just do an extra erase - not big
deal.

> Also, from what I can find, MTD does not provide a method of programming 
> OOB NAND data using MTD_OOB_AUTO as mtd_do_writeoob (called in mtdchar.c 
> from the MTDWRITEOOB ioctl) uses only MTD_OOB_PLACE.

Probably MTD_OOB_AUTO is just a layer on top of MTD_OOB_PLACE? Anyway,
this whole area of OOB is complex and needs some analysis, and even
better documentation, and then you can choose the best way to solve your
issue.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:52:01 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:52:01 +0300
Subject: [PATCH] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <4E09BC89.40306@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
	<1308922482-14967-2-git-send-email-david.wagner@free-electrons.com>
	<1309202771.24805.11.camel@koala> <4E09BC89.40306@free-electrons.com>
Message-ID: <1309330325.23597.123.camel@sauron>

On Tue, 2011-06-28 at 13:35 +0200, David Wagner wrote:
> Hi,
> 
> On 06/27/2011 09:26 PM, Artem Bityutskiy wrote:
> > On Fri, 2011-06-24 at 15:34 +0200, david.wagner at free-electrons.com
> > wrote:
> >> +	/* Stolen from mtd_blkdevs.c */
> >> +	/* Create processing thread */
> >> +	dev->thread = kthread_run(ubi_ubiblk_thread, dev, "%s%d_%d",
> >> +				  "kubiblkd", dev->ubi_num, dev->vol_id);
> >> +	if (IS_ERR(dev->thread)) {
> >> +		ret = PTR_ERR(dev->thread);
> >> +		goto out_thread;
> >> +	}
> > 
> > Why we need a kernel thread? Could you please describe when exactly it
> > is needed and why we cannot avoid having it?
> 
> Do you mean that there could be another/better way ?

No, I just do not understand why it is there. I think this is juts block
layer's design, but I wanted you to explain this - the design, how block
requests are handled, and where exactly the thread is needed. I expected
you just have the explanation.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:54:31 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:54:31 +0300
Subject: [RFC PATCHv2] UBI: new module ubiblk: block layer on top of UBI
In-Reply-To: <1309274691-4898-1-git-send-email-david.wagner@free-electrons.com>
References: <1308922482-14967-1-git-send-email-david.wagner@free-electrons.com>
	<1309274691-4898-1-git-send-email-david.wagner@free-electrons.com>
Message-ID: <1309330476.23597.124.camel@sauron>

On Tue, 2011-06-28 at 17:24 +0200, david.wagner at free-electrons.com
wrote:
> + * Author: David Wagner
> + * Some code taken from gluebi.c (Artem Bityutskiy (???????? ?????),
> + *                                Joern Engel)
> + * Some code taken from mtd_blkdevs.c (David Woodhouse) 

It is important to preserve Copyrights, because it has to do with legal
stuff.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 02:59:04 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 09:59:04 +0300
Subject: [PATCH 0/3] fixups for OOB ECC problems
In-Reply-To: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
References: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309330748.23597.125.camel@sauron>

On Tue, 2011-06-28 at 16:28 -0700, Brian Norris wrote:
> Hello,
> 
> Now that we have added the possibility that mtd->read_oob returns
> -EUCLEAN or -EBADMSG for corrected bitflips and for uncorrectable errors,
> respectively, there are more pieces of code that need to take this into
> account. These patches should address some of these by ignoring bitflips
> when bit accuracy is not needed or by ignoring corrected errors when
> scrubbing would be unnecessary.
> 
> There are still other cases to address, for example, some flash-based BBT
> code.
> 
> This applies on top of l2-mtd-2.6.git. Patch 3 is an amendment to commit
> abf386c475beab813dc9b3366e592e00255e987a, ("mtd: nand: handle ECC errors
> in OOB"), so it can be squashed in if you want. Let me know if you want
> me to do this and do a resend.

Do you test these things somehow? I'd just injected some code to a
driver or nandsim which returns -EUCLEAN for OOB and check what fails.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 03:02:55 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 10:02:55 +0300
Subject: [PATCH 1/3] mtd: nand: ignore ECC errors for simple BBM scans
In-Reply-To: <1309303740-9936-2-git-send-email-computersforpeace@gmail.com>
References: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
	<1309303740-9936-2-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309330980.23597.126.camel@sauron>

On Tue, 2011-06-28 at 16:28 -0700, Brian Norris wrote:
> Now that nand_do_readoob() may return -EUCLEAN or -EBADMSG on ECC errors,
> we need to handle the return value specially in some cases.
> 
> When scanning for simple bad block markers, reacting to an ECC error is
> not very useful, as we assume that the relevant markers are still
> non-0xFF for true bad blocks.
> 
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  drivers/mtd/nand/nand_bbt.c |   13 ++++++++++---
>  1 files changed, 10 insertions(+), 3 deletions(-)

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Wed Jun 29 03:11:22 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 10:11:22 +0300
Subject: [PATCH 2/9] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309319494-17951-3-git-send-email-leiwen@marvell.com>
References: <1309246361.23597.30.camel@sauron>
	<1309319494-17951-3-git-send-email-leiwen@marvell.com>
Message-ID: <1309331487.23597.131.camel@sauron>

On Tue, 2011-06-28 at 20:51 -0700, Lei Wen wrote:
> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
> 
> Update platform driver to support this feature.
> 
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.
> 
> Signed-off-by: Lei Wen <leiwen at marvell.com>
> ---
>  arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
>  drivers/mtd/nand/pxa3xx_nand.c               |  493 +++++++++++++++----------
>  2 files changed, 313 insertions(+), 199 deletions(-)

If someone can review this patch - good let's see how many Reviewed-by
tags we get. But I think it is not very reviewable because of the size.

AFAICK, what you do here is

1. Introduce new structure struct pxa3xx_nand_host
2. Move several fields from struct pxa3xx_nand_info to struct
pxa3xx_nand_host

And only this alone adds a lot of noise to the patch.

And also you have some real functional changes.

So I'd suggest you to split this patch at least on 2 - the first one
would introduce struct pxa3xx_nand_host, moved some fields, and do all
the host<->info renamings. You can split this on several steps and move
only several fields at a time.

Then a separate patch would do some more functional changes. How does
this sound?

-- 
Best Regards,
Artem Bityutskiy



From adrian.wenl at gmail.com  Wed Jun 29 03:16:29 2011
From: adrian.wenl at gmail.com (Lei Wen)
Date: Wed, 29 Jun 2011 15:16:29 +0800
Subject: [PATCH 2/9] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309331487.23597.131.camel@sauron>
References: <1309246361.23597.30.camel@sauron>
	<1309319494-17951-3-git-send-email-leiwen@marvell.com>
	<1309331487.23597.131.camel@sauron>
Message-ID: <BANLkTinSuSFYcsAnfyxgef8o30UcQ_T9ew@mail.gmail.com>

Hi Artem,

On Wed, Jun 29, 2011 at 3:11 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-28 at 20:51 -0700, Lei Wen wrote:
>> Current pxa3xx_nand controller has two chip select which
>> both be workable. This patch enable this feature.
>>
>> Update platform driver to support this feature.
>>
>> Another notice should be taken that:
>> When you want to use this feature, you should not enable the
>> keep configuration feature, for two chip select could be
>> attached with different nand chip. The different page size
>> and timing requirement make the keep configuration impossible.
>>
>> Signed-off-by: Lei Wen <leiwen at marvell.com>
>> ---
>> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 19 +-
>> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?493 +++++++++++++++----------
>> ?2 files changed, 313 insertions(+), 199 deletions(-)
>
> If someone can review this patch - good let's see how many Reviewed-by
> tags we get. But I think it is not very reviewable because of the size.
>
> AFAICK, what you do here is
>
> 1. Introduce new structure struct pxa3xx_nand_host
> 2. Move several fields from struct pxa3xx_nand_info to struct
> pxa3xx_nand_host
>
> And only this alone adds a lot of noise to the patch.
>
> And also you have some real functional changes.
>
> So I'd suggest you to split this patch at least on 2 - the first one
> would introduce struct pxa3xx_nand_host, moved some fields, and do all
> the host<->info renamings. You can split this on several steps and move
> only several fields at a time.
>
> Then a separate patch would do some more functional changes. How does
> this sound?
>

I'm ok with this, patches to come.

Thanks,
Lei


From kmpark at infradead.org  Wed Jun 29 03:22:01 2011
From: kmpark at infradead.org (Kyungmin Park)
Date: Wed, 29 Jun 2011 16:22:01 +0900
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <20110608101804.GA5527@july>
References: <20110608101804.GA5527@july>
Message-ID: <BANLkTi=MMEzE-neUzRqBYqvsGsup_s+VMw@mail.gmail.com>

Hi Artem,

There's missing patch, can you add l2-mtd tree?

Thank you,
Kyungmin Park

On Wed, Jun 8, 2011 at 7:18 PM, Kyungmin Park <kmpark at infradead.org> wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
>
> Implement the write DMA feature. It can reduce the CPU usage when write.
>
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
> diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
> index 3306b5b..f24cb6f 100644
> --- a/drivers/mtd/onenand/samsung.c
> +++ b/drivers/mtd/onenand/samsung.c
> @@ -712,6 +712,74 @@ normal:
> ? ? ? ?return 0;
> ?}
>
> +static int s5pc110_write_bufferram(struct mtd_info *mtd, int area,
> + ? ? ? ? ? ? ? const unsigned char *buffer, int offset, size_t count)
> +{
> + ? ? ? struct onenand_chip *this = mtd->priv;
> + ? ? ? struct device *dev = &onenand->pdev->dev;
> + ? ? ? void __iomem *p;
> + ? ? ? void *buf = (void *) buffer;
> + ? ? ? dma_addr_t dma_src, dma_dst;
> + ? ? ? int err, ofs, page_dma = 0;
> +
> + ? ? ? p = this->base + area;
> + ? ? ? if (ONENAND_CURRENT_BUFFERRAM(this)) {
> + ? ? ? ? ? ? ? if (area == ONENAND_DATARAM)
> + ? ? ? ? ? ? ? ? ? ? ? p += this->writesize;
> + ? ? ? ? ? ? ? else
> + ? ? ? ? ? ? ? ? ? ? ? p += mtd->oobsize;
> + ? ? ? }
> +
> + ? ? ? if (count != mtd->writesize || offset & 3 || (size_t) buf & 3)
> + ? ? ? ? ? ? ? goto normal;
> +
> + ? ? ? /* Handle vmalloc address */
> + ? ? ? if (buf >= high_memory) {
> + ? ? ? ? ? ? ? struct page *page;
> +
> + ? ? ? ? ? ? ? if (((size_t) buf & PAGE_MASK) !=
> + ? ? ? ? ? ? ? ? ? ((size_t) (buf + count - 1) & PAGE_MASK))
> + ? ? ? ? ? ? ? ? ? ? ? goto normal;
> +
> + ? ? ? ? ? ? ? page = vmalloc_to_page(buf);
> + ? ? ? ? ? ? ? if (unlikely(!page))
> + ? ? ? ? ? ? ? ? ? ? ? goto normal;
> +
> + ? ? ? ? ? ? ? /* Page offset */
> + ? ? ? ? ? ? ? ofs = ((size_t) buf & ~PAGE_MASK);
> + ? ? ? ? ? ? ? page_dma = 1;
> +
> + ? ? ? ? ? ? ? /* DMA routine */
> + ? ? ? ? ? ? ? dma_src = dma_map_page(dev, page, ofs, count, DMA_TO_DEVICE);
> + ? ? ? ? ? ? ? dma_dst = onenand->phys_base + (p - this->base);
> + ? ? ? } else {
> + ? ? ? ? ? ? ? /* DMA routine */
> + ? ? ? ? ? ? ? dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
> + ? ? ? ? ? ? ? dma_dst = onenand->phys_base + (p - this->base);
> + ? ? ? }
> +
> + ? ? ? if (dma_mapping_error(dev, dma_src)) {
> + ? ? ? ? ? ? ? dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count);
> + ? ? ? ? ? ? ? goto normal;
> + ? ? ? }
> +
> + ? ? ? err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
> + ? ? ? ? ? ? ? ? ? ? ? count, S5PC110_DMA_DIR_WRITE);
> +
> + ? ? ? if (page_dma)
> + ? ? ? ? ? ? ? dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
> + ? ? ? else
> + ? ? ? ? ? ? ? dma_unmap_single(dev, dma_src, count, DMA_TO_DEVICE);
> +
> + ? ? ? if (!err)
> + ? ? ? ? ? ? ? return 0;
> +
> +normal:
> + ? ? ? memcpy(p + offset, buffer, count);
> +
> + ? ? ? return 0;
> +}
> +
> ?static int s5pc110_chip_probe(struct mtd_info *mtd)
> ?{
> ? ? ? ?/* Now just return 0 */
> @@ -844,6 +912,7 @@ static void s3c_onenand_setup(struct mtd_info *mtd)
> ? ? ? ?} else if (onenand->type == TYPE_S5PC110) {
> ? ? ? ? ? ? ? ?/* Use generic onenand functions */
> ? ? ? ? ? ? ? ?this->read_bufferram = s5pc110_read_bufferram;
> + ? ? ? ? ? ? ? this->write_bufferram = s5pc110_write_bufferram;
> ? ? ? ? ? ? ? ?this->chip_probe = s5pc110_chip_probe;
> ? ? ? ? ? ? ? ?return;
> ? ? ? ?} else {
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>


From b32955 at freescale.com  Wed Jun 29 03:54:39 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 15:54:39 +0800
Subject: [PATCH V4 0/3] add the GPMI-NFC support for imx23/imx28
Message-ID: <1309334082-9501-1-git-send-email-b32955@freescale.com>

The patch is based on branch "imx-for-3.1" of tree :
      git://git.pengutronix.de/git/imx/linux-2.6.git

v3 --> v4:
	merge the GPMI-NFC device code to the new branch.


Huang Shijie (3):
  ARM: mxs: add GPMI-NFC support for imx23/imx28
  ARM: mxs: add GPMI-NFC device for imx23
  ARM: mxs: add GPMI-NFC device for imx28

 arch/arm/mach-mxs/Kconfig                       |    2 +
 arch/arm/mach-mxs/clock-mx23.c                  |    1 +
 arch/arm/mach-mxs/clock-mx28.c                  |    1 +
 arch/arm/mach-mxs/devices-mx23.h                |    4 +
 arch/arm/mach-mxs/devices-mx28.h                |    4 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c   |   90 +++++++++++++++++++++++
 arch/arm/mach-mxs/include/mach/devices-common.h |   10 +++
 arch/arm/mach-mxs/include/mach/gpmi-nfc.h       |   71 ++++++++++++++++++
 arch/arm/mach-mxs/mach-mx23evk.c                |   37 +++++++++
 arch/arm/mach-mxs/mach-mx28evk.c                |   37 +++++++++
 12 files changed, 261 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
 create mode 100644 arch/arm/mach-mxs/include/mach/gpmi-nfc.h




From b32955 at freescale.com  Wed Jun 29 03:54:40 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 15:54:40 +0800
Subject: [PATCH V4 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <1309334082-9501-1-git-send-email-b32955@freescale.com>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
Message-ID: <1309334082-9501-2-git-send-email-b32955@freescale.com>

add GPMI-NFC support for imx23 and imx28.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 arch/arm/mach-mxs/Kconfig                 |    2 +
 arch/arm/mach-mxs/include/mach/gpmi-nfc.h |   71 +++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/include/mach/gpmi-nfc.h

diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 1d3985f..a5b753a 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -32,6 +32,7 @@ config MACH_MX23EVK
 	select SOC_IMX23
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_GPMI_NFC
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
 	help
@@ -46,6 +47,7 @@ config MACH_MX28EVK
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_FEC
 	select MXS_HAVE_PLATFORM_FLEXCAN
+	select MXS_HAVE_PLATFORM_GPMI_NFC
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
 	select MXS_OCOTP
diff --git a/arch/arm/mach-mxs/include/mach/gpmi-nfc.h b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
new file mode 100644
index 0000000..25fc605
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __INCLUDE_GPMI_NFC_H
+#define __INCLUDE_GPMI_NFC_H
+
+/* The size of the resource is fixed. */
+#define RES_SIZE	6
+
+/* Resource names for the GPMI NFC driver. */
+#define GPMI_NFC_GPMI_REGS_ADDR_RES_NAME  "GPMI NFC GPMI Registers"
+#define GPMI_NFC_GPMI_INTERRUPT_RES_NAME  "GPMI NFC GPMI Interrupt"
+#define GPMI_NFC_BCH_REGS_ADDR_RES_NAME   "GPMI NFC BCH Registers"
+#define GPMI_NFC_BCH_INTERRUPT_RES_NAME   "GPMI NFC BCH Interrupt"
+#define GPMI_NFC_DMA_CHANNELS_RES_NAME    "GPMI NFC DMA Channels"
+#define GPMI_NFC_DMA_INTERRUPT_RES_NAME   "GPMI NFC DMA Interrupt"
+
+/**
+ * struct gpmi_nfc_platform_data - GPMI NFC driver platform data.
+ *
+ * This structure communicates platform-specific information to the GPMI NFC
+ * driver that can't be expressed as resources.
+ *
+ * @platform_init:           A pointer to a function the driver will call to
+ *                           initialize the platform (e.g., set up the pin mux).
+ * @platform_exit:           A pointer to a function the driver will call to
+ *                           exit the platform (e.g., free pins).
+ * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
+ *                           from the NAND Flash device, in nanoseconds.
+ * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
+ *                           from the NAND Flash device, in nanoseconds.
+ * @max_chip_count:          The maximum number of chips for which the driver
+ *                           should configure the hardware. This value most
+ *                           likely reflects the number of pins that are
+ *                           connected to a NAND Flash device. If this is
+ *                           greater than the SoC hardware can support, the
+ *                           driver will print a message and fail to initialize.
+ * @partitions:              An optional pointer to an array of partition
+ *                           descriptions.
+ * @partition_count:         The number of elements in the partitions array.
+ */
+struct gpmi_nfc_platform_data {
+	/* SoC hardware information. */
+	int		(*platform_init)(void);
+	void		(*platform_exit)(void);
+
+	/* NAND Flash information. */
+	unsigned int	min_prop_delay_in_ns;
+	unsigned int	max_prop_delay_in_ns;
+	unsigned int	max_chip_count;
+
+	/* Medium information. */
+	struct mtd_partition *partitions;
+	unsigned	partition_count;
+};
+#endif
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 03:54:42 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 15:54:42 +0800
Subject: [PATCH V4 3/3] ARM: mxs: add GPMI-NFC device for imx28
In-Reply-To: <1309334082-9501-1-git-send-email-b32955@freescale.com>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
Message-ID: <1309334082-9501-4-git-send-email-b32955@freescale.com>

add GPMI-NFC device for imx28.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 arch/arm/mach-mxs/clock-mx28.c                |    1 +
 arch/arm/mach-mxs/devices-mx28.h              |    4 +++
 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c |   19 +++++++++++++
 arch/arm/mach-mxs/mach-mx28evk.c              |   37 +++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 5dcc59d..0397f65 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -614,6 +614,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
 	_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
+	_REGISTER_CLOCK("imx28-gpmi-nfc", NULL, gpmi_clk)
 	_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
 	_REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
 	_REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 79b9452..bbc8f0c 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -34,6 +34,10 @@ extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
 #define mx28_add_flexcan0(pdata)	mx28_add_flexcan(0, pdata)
 #define mx28_add_flexcan1(pdata)	mx28_add_flexcan(1, pdata)
 
+extern const struct mxs_gpmi_nfc_data mx28_gpmi_nfc_data __initconst;
+#define mx28_add_gpmi_nfc(pdata)	\
+	mxs_add_gpmi_nfc(pdata, &mx28_gpmi_nfc_data)
+
 extern const struct mxs_mxs_i2c_data mx28_mxs_i2c_data[] __initconst;
 #define mx28_add_mxs_i2c(id)		mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id])
 
diff --git a/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
index 5a68370..ae88672 100644
--- a/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
+++ b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
@@ -17,6 +17,7 @@
  */
 #include <asm/sizes.h>
 #include <mach/mx23.h>
+#include <mach/mx28.h>
 #include <mach/devices-common.h>
 
 #define RES_MEM(soc, _id, _s, _n)				\
@@ -61,6 +62,24 @@ const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst = {
 };
 #endif
 
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_gpmi_nfc_data mx28_gpmi_nfc_data __initconst = {
+	.devid = "imx28-gpmi-nfc",
+	.res = {
+		/* GPMI */
+		RES_MEM(MX28, GPMI, SZ_8K, GPMI_NFC_GPMI_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX28, GPMI, GPMI_NFC_GPMI_INTERRUPT_RES_NAME),
+		/* BCH */
+		RES_MEM(MX28, BCH, SZ_8K, GPMI_NFC_BCH_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX28, BCH, GPMI_NFC_BCH_INTERRUPT_RES_NAME),
+		/* DMA */
+		RES_DMA(MX28, DMA_GPMI0, DMA_GPMI7,
+					GPMI_NFC_DMA_CHANNELS_RES_NAME),
+		RES_IRQ(MX28, GPMI_DMA, GPMI_NFC_DMA_INTERRUPT_RES_NAME),
+	},
+};
+#endif
+
 struct platform_device *__init
 mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
 		const struct mxs_gpmi_nfc_data *data)
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index eaaf6ff..74d0868 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -314,6 +314,42 @@ static const struct flexcan_platform_data
 	}
 };
 
+/* gpmi-nfc */
+#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+static iomux_cfg_t mx28evk_gpmi_nfc_pads[] = {
+	MX28_PAD_GPMI_D00__GPMI_D0 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_RDY1__GPMI_READY1 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MXS_PAD_GPMI_NFC,
+};
+
+static int mx28evk_gpmi_nfc_platform_init(void)
+{
+	return mxs_iomux_setup_multiple_pads(mx28evk_gpmi_nfc_pads,
+				ARRAY_SIZE(mx28evk_gpmi_nfc_pads));
+}
+
+static const struct gpmi_nfc_platform_data
+mx28evk_gpmi_nfc_data __initconst = {
+	.platform_init		= mx28evk_gpmi_nfc_platform_init,
+	.min_prop_delay_in_ns	= 5,
+	.max_prop_delay_in_ns	= 9,
+	.max_chip_count		= 1,
+};
+
 /* mxsfb (lcdif) */
 static struct fb_videomode mx28evk_video_modes[] = {
 	{
@@ -390,6 +426,7 @@ static void __init mx28evk_init(void)
 	else
 		gpio_set_value(MX28EVK_BL_ENABLE, 1);
 
+	mx28_add_gpmi_nfc(&mx28evk_gpmi_nfc_data);
 	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 
 	/* power on mmc slot by writing 0 to the gpio */
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 03:54:41 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 15:54:41 +0800
Subject: [PATCH V4 2/3] ARM: mxs: add GPMI-NFC device for imx23
In-Reply-To: <1309334082-9501-1-git-send-email-b32955@freescale.com>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
Message-ID: <1309334082-9501-3-git-send-email-b32955@freescale.com>

add the gpmi-nfc device for imx23.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 arch/arm/mach-mxs/clock-mx23.c                  |    1 +
 arch/arm/mach-mxs/devices-mx23.h                |    4 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c   |   71 +++++++++++++++++++++++
 arch/arm/mach-mxs/include/mach/devices-common.h |   10 +++
 arch/arm/mach-mxs/mach-mx23evk.c                |   37 ++++++++++++
 7 files changed, 127 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c

diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index 0163b6d..e190c53 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -456,6 +456,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
 	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
 	_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
+	_REGISTER_CLOCK("imx23-gpmi-nfc", NULL, gpmi_clk)
 };
 
 static int clk_misc_init(void)
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index c6f345f..a9c495d 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -21,6 +21,10 @@ extern const struct mxs_auart_data mx23_auart_data[] __initconst;
 #define mx23_add_auart0()		mx23_add_auart(0)
 #define mx23_add_auart1()		mx23_add_auart(1)
 
+extern const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst;
+#define mx23_add_gpmi_nfc(pdata)	\
+	mxs_add_gpmi_nfc(pdata, &mx23_gpmi_nfc_data)
+
 extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
 #define mx23_add_mxs_mmc(id, pdata) \
 	mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index acf9eea..b42a14b 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -12,6 +12,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
 	bool
 
+config MXS_HAVE_PLATFORM_GPMI_NFC
+	bool
+
 config MXS_HAVE_PLATFORM_MXS_I2C
 	bool
 
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 351915c..972abdc 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
 obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_GPMI_NFC) += platform-gpmi-nfc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
diff --git a/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
new file mode 100644
index 0000000..5a68370
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/devices-common.h>
+
+#define RES_MEM(soc, _id, _s, _n)				\
+	{							\
+		.start = soc ##_## _id ## _BASE_ADDR,		\
+		.end   = soc ##_## _id ## _BASE_ADDR + (_s) - 1,\
+		.name  = (_n),					\
+		.flags = IORESOURCE_MEM,			\
+	}
+
+#define RES_IRQ(soc, _id, _n)			\
+	{					\
+		.start = soc ##_INT_## _id,	\
+		.end   = soc ##_INT_## _id,	\
+		.name  = (_n),			\
+		.flags = IORESOURCE_IRQ,	\
+	}
+
+#define RES_DMA(soc, _i_s, _i_e, _n)		\
+	{					\
+		.start = soc ##_## _i_s,	\
+		.end   = soc ##_## _i_e,	\
+		.name  = (_n),			\
+		.flags = IORESOURCE_DMA,	\
+	}
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst = {
+	.devid = "imx23-gpmi-nfc",
+	.res = {
+		/* GPMI */
+		RES_MEM(MX23, GPMI, SZ_8K, GPMI_NFC_GPMI_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX23, GPMI_ATTENTION, GPMI_NFC_GPMI_INTERRUPT_RES_NAME),
+		/* BCH */
+		RES_MEM(MX23, BCH, SZ_8K, GPMI_NFC_BCH_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX23, BCH, GPMI_NFC_BCH_INTERRUPT_RES_NAME),
+		/* DMA */
+		RES_DMA(MX23, DMA_GPMI0, DMA_GPMI3,
+					GPMI_NFC_DMA_CHANNELS_RES_NAME),
+		RES_IRQ(MX23, GPMI_DMA, GPMI_NFC_DMA_INTERRUPT_RES_NAME),
+	},
+};
+#endif
+
+struct platform_device *__init
+mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
+		const struct mxs_gpmi_nfc_data *data)
+{
+	return mxs_add_platform_device_dmamask(data->devid, -1,
+				data->res, RES_SIZE,
+				pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 812d7a8..e032120 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -66,6 +66,16 @@ struct platform_device *__init mxs_add_flexcan(
 		const struct mxs_flexcan_data *data,
 		const struct flexcan_platform_data *pdata);
 
+/* gpmi-nfc */
+#include <mach/gpmi-nfc.h>
+struct mxs_gpmi_nfc_data {
+	const char *devid;
+	const struct resource res[RES_SIZE];
+};
+struct platform_device *__init
+mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
+		const struct mxs_gpmi_nfc_data *data);
+
 /* i2c */
 struct mxs_mxs_i2c_data {
 	int id;
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index 3c2de33..772b373 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -107,6 +107,42 @@ static const iomux_cfg_t mx23evk_pads[] __initconst = {
 		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
 };
 
+/* gpmi-nfc */
+#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+static iomux_cfg_t mx23evk_gpmi_nfc_pads[] = {
+	MX23_PAD_GPMI_D00__GPMI_D00 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D01__GPMI_D01 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D02__GPMI_D02 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D03__GPMI_D03 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D04__GPMI_D04 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D05__GPMI_D05 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D06__GPMI_D06 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D07__GPMI_D07 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_WPN__GPMI_WPN | MXS_PAD_GPMI_NFC,
+	MX23_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
+	MX23_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
+	MX23_PAD_GPMI_RDY0__GPMI_RDY0 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_RDY1__GPMI_RDY1 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
+};
+
+static int mx23evk_gpmi_nfc_platform_init(void)
+{
+	return mxs_iomux_setup_multiple_pads(mx23evk_gpmi_nfc_pads,
+				ARRAY_SIZE(mx23evk_gpmi_nfc_pads));
+}
+
+static const
+struct gpmi_nfc_platform_data mx23evk_gpmi_nfc_data __initconst = {
+	.platform_init		= mx23evk_gpmi_nfc_platform_init,
+	.min_prop_delay_in_ns	= 5,
+	.max_prop_delay_in_ns	= 9,
+	.max_chip_count		= 1,
+};
+
 /* mxsfb (lcdif) */
 static struct fb_videomode mx23evk_video_modes[] = {
 	{
@@ -166,6 +202,7 @@ static void __init mx23evk_init(void)
 	else
 		gpio_set_value(MX23EVK_BL_ENABLE, 1);
 
+	mx23_add_gpmi_nfc(&mx23evk_gpmi_nfc_data);
 	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
 }
 
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 04:24:35 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 16:24:35 +0800
Subject: [PATCH v7 0/3]  add the GPMI controller driver for IMX23/IMX28
Message-ID: <1309335878-16678-1-git-send-email-b32955@freescale.com>

The general-purpose media interface(GPMI) controller is a flexible interface
to up to several NAND flashs.

The Bose Ray-Choudhury Hocquenghem(BCH) module is a hardware ECC accelerator.

With the help of BCH, the GPMI controller can choose to do the hardware ECC or
not.

This driver is a _pure_ MTD NAND controller driver now.

The driver depends on another patch set, you can find them at :
	[1] http://marc.info/?l=linux-arm-kernel&m=130933298731899&w=2
	[2] http://marc.info/?l=linux-arm-kernel&m=130933302531947&w=2
	[3] http://marc.info/?l=linux-arm-kernel&m=130933300431921&w=2

Test environment:
	Using imx23 and imx28 boards for test, and burned the ROOTFS
	in the nand flash.

	imx23 :
	console=ttyAMA0,115200 mtdparts=gpmi-nfc:20m(boot),-(user)  ubi.mtd=1 root=ubi0:rootfs0 rootfstype=ubifs gpmi_debug_init

        imx28 :
	# console=ttyAMA0,115200 mtdparts=gpmi-nfc-main:20m(boot),-(user) ubi.mtd=1 root=ubi0:rootfs0 rootfstype=ubifs gpmi_debug_init


v6 --> v7:
	[0] remove the function wrapping the clock.
	[1] use the module_param() for debugging.
	[2] use the new interface of MTD partitions.
		replace add_mtd_partitions() with mtd_device_register().
	[3] use pr_info() to print log.
	[4] add `__devinit` for some functions, etc.
	[5] add `gpmi_nfc` to control the GPMI-NFC driver's initialization.
	[6] others.

v5 --> v6:
	[0] split out the IMX23/IMX28 arch code to separate patches.
	[1] fix bug : missing empty item in the end of platform_id array.
	[2] inconsistent identation.
	[3] others

v4 --> v5:
	[0] rename the files.
	[1] fix PM bug
	[2] remove the rom_helper code, and move the necessary initialization code
		to the main file.
	[3] change the macros from CPU_IS_* to GPMI_IS_*
	[4] remove the default partition layout init code. revert back the 
		partition parsing command line code.
	[5] others

v3 --> v4:
	[0] use the nand_ids{} as the nand database, drop my own database.
	[1] remove the patch for DMA enginer, Shawn will submit his own version.
	[2] use the platform_id to distinguish different Archs.
	[3] fix the strange coding style.
	[4] others.

v2 --> v3:
	[0] merge the imx23 and imx28 into one file(including the header file).
	[1] remove the unuse registers in the headers.
	[2] fix DMA bugs
	[3] add bus width field to nand_attr{}
	[4] others

v1 --> v2:
	[0] merge the common files into the gpmi-nfc-main.c
	[1] change the code to get the clock.
	[2] remove the timing in the nand_device_info{}
	[3] fix DMA errors
	[4] add the nand_device_info.[ch] to generic code
	[5] use the chip->onfi_version for the ONFI nand
	[6] useless init
	[7] others


Huang Shijie (3):
  MTD : add the common code for GPMI-NFC controller driver
  MTD : add support for imx23 and imx28
  MTD : add GPMI-NFC driver in the config and Makefile

 drivers/mtd/nand/Kconfig              |   11 +
 drivers/mtd/nand/Makefile             |    1 +
 drivers/mtd/nand/gpmi-nfc/Makefile    |    3 +
 drivers/mtd/nand/gpmi-nfc/bch-regs.h  |   88 ++
 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c  | 2484 +++++++++++++++++++++++++++++++++
 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h  |  495 +++++++
 drivers/mtd/nand/gpmi-nfc/gpmi-regs.h |  163 +++
 drivers/mtd/nand/gpmi-nfc/hal-mxs.c   |  554 ++++++++
 8 files changed, 3799 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/gpmi-nfc/Makefile
 create mode 100644 drivers/mtd/nand/gpmi-nfc/bch-regs.h
 create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
 create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
 create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-regs.h
 create mode 100644 drivers/mtd/nand/gpmi-nfc/hal-mxs.c




From b32955 at freescale.com  Wed Jun 29 04:24:38 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 16:24:38 +0800
Subject: [PATCH v7 3/3] MTD : add GPMI-NFC driver in the config and Makefile
In-Reply-To: <1309335878-16678-1-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
Message-ID: <1309335878-16678-4-git-send-email-b32955@freescale.com>

add the GPMI-NFC driver in the relevant Kconfig and Makefile in the MTD.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 drivers/mtd/nand/Kconfig           |   11 +++++++++++
 drivers/mtd/nand/Makefile          |    1 +
 drivers/mtd/nand/gpmi-nfc/Makefile |    3 +++
 3 files changed, 15 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/gpmi-nfc/Makefile

diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig
index 4c34252..d0076f9 100644
--- a/drivers/mtd/nand/Kconfig
+++ b/drivers/mtd/nand/Kconfig
@@ -423,6 +423,17 @@ config MTD_NAND_NANDSIM
 	  The simulator may simulate various NAND flash chips for the
 	  MTD nand layer.
 
+config MTD_NAND_GPMI_NFC
+        bool "GPMI NAND Flash Controller driver"
+        depends on MTD_NAND && (SOC_IMX23 || SOC_IMX28)
+	select MTD_PARTITIONS
+	select MTD_CMDLINE_PARTS
+        help
+	 Enables NAND Flash support for IMX23 or IMX28.
+	 The GPMI controller is very powerful, with the help of BCH
+	 module, it can do the hardware ECC. The GPMI supports several
+	 NAND flashs at the same time.
+
 config MTD_NAND_PLATFORM
 	tristate "Support for generic platform NAND driver"
 	help
diff --git a/drivers/mtd/nand/Makefile b/drivers/mtd/nand/Makefile
index 5745d83..fd33dbf 100644
--- a/drivers/mtd/nand/Makefile
+++ b/drivers/mtd/nand/Makefile
@@ -49,5 +49,6 @@ obj-$(CONFIG_MTD_NAND_BCM_UMI)		+= bcm_umi_nand.o nand_bcm_umi.o
 obj-$(CONFIG_MTD_NAND_MPC5121_NFC)	+= mpc5121_nfc.o
 obj-$(CONFIG_MTD_NAND_RICOH)		+= r852.o
 obj-$(CONFIG_MTD_NAND_JZ4740)		+= jz4740_nand.o
+obj-$(CONFIG_MTD_NAND_GPMI_NFC)		+= gpmi-nfc/
 
 nand-objs := nand_base.o nand_bbt.o
diff --git a/drivers/mtd/nand/gpmi-nfc/Makefile b/drivers/mtd/nand/gpmi-nfc/Makefile
new file mode 100644
index 0000000..918fb52
--- /dev/null
+++ b/drivers/mtd/nand/gpmi-nfc/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_MTD_NAND_GPMI_NFC) += gpmi_nfc.o
+gpmi_nfc-objs += gpmi-nfc.o
+gpmi_nfc-objs += hal-mxs.o
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 04:24:36 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 16:24:36 +0800
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <1309335878-16678-1-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
Message-ID: <1309335878-16678-2-git-send-email-b32955@freescale.com>

These files contain the common code for the GPMI-NFC driver.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c | 2484 ++++++++++++++++++++++++++++++++++
 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h |  495 +++++++
 2 files changed, 2979 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
 create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h

diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
new file mode 100644
index 0000000..187b4a3
--- /dev/null
+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
@@ -0,0 +1,2484 @@
+/*
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "gpmi-nfc.h"
+
+/* add our owner bbt descriptor */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr gpmi_bbt_descr = {
+	.options	= 0,
+	.offs		= 0,
+	.len		= 1,
+	.pattern	= scan_ff_pattern
+};
+
+/* debug control */
+int gpmi_debug;
+module_param(gpmi_debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(gpmi_debug, "print out the debug infomation.");
+
+/* enable the gpmi-nfc. */
+static bool enable_gpmi_nand;
+
+static ssize_t show_ignorebad(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct gpmi_nfc_data *this = dev_get_drvdata(dev);
+	struct mil *mil = &this->mil;
+
+	return sprintf(buf, "%d\n", mil->ignore_bad_block_marks);
+}
+
+static ssize_t
+store_ignorebad(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t size)
+{
+	struct gpmi_nfc_data *this = dev_get_drvdata(dev);
+	struct mil *mil = &this->mil;
+	const char *p = buf;
+	unsigned long v;
+
+	if (strict_strtoul(p, 0, &v) < 0)
+		return -EINVAL;
+
+	if (v > 0)
+		v = 1;
+
+	if (v != mil->ignore_bad_block_marks) {
+		if (v) {
+			/*
+			 * This will cause the NAND Flash MTD code to believe
+			 * that it never created a BBT and force it to call our
+			 * block_bad function.
+			 *
+			 * See mil_block_bad for more details.
+			 */
+			mil->saved_bbt = mil->nand.bbt;
+			mil->nand.bbt  = NULL;
+		} else {
+			/*
+			 * Restore the NAND Flash MTD's pointer
+			 * to its in-memory BBT.
+			 */
+			mil->nand.bbt = mil->saved_bbt;
+		}
+		mil->ignore_bad_block_marks = v;
+	}
+	return size;
+}
+
+static DEVICE_ATTR(ignorebad, 0644, show_ignorebad, store_ignorebad);
+static struct device_attribute *device_attributes[] = {
+	&dev_attr_ignorebad,
+};
+
+static irqreturn_t bch_irq(int irq, void *cookie)
+{
+	struct gpmi_nfc_data *this = cookie;
+	struct nfc_hal *nfc = this->nfc;
+
+	/* Clear the BCH interrupt */
+	nfc->clear_bch(this);
+
+	complete(&nfc->bch_done);
+	return IRQ_HANDLED;
+}
+
+/* calculate the ECC strength by hand */
+static inline int get_ecc_strength(struct gpmi_nfc_data *this)
+{
+	struct mtd_info	*mtd = &this->mil.mtd;
+	int ecc_strength = 0;
+
+	switch (mtd->writesize) {
+	case 2048:
+		ecc_strength = 8;
+		break;
+	case 4096:
+		switch (mtd->oobsize) {
+		case 128:
+			ecc_strength = 8;
+			break;
+		case 224:
+		case 218:
+			ecc_strength = 16;
+			break;
+		}
+		break;
+	case 8192:
+		ecc_strength = 24;
+		break;
+	}
+
+	return ecc_strength;
+}
+
+bool is_ddr_nand(struct gpmi_nfc_data *this)
+{
+	struct nand_chip *chip = &this->mil.nand;
+
+	/* ONFI nand */
+	if (chip->onfi_version != 0)
+		return true;
+
+	/* TOGGLE nand */
+
+	return false;
+}
+
+static inline int get_ecc_chunk_size(struct gpmi_nfc_data *this)
+{
+	/* the ONFI/TOGGLE nands use 1k ecc chunk size */
+	if (is_ddr_nand(this))
+		return 1024;
+
+	/* for historical reason */
+	return 512;
+}
+
+int common_nfc_set_geometry(struct gpmi_nfc_data *this)
+{
+	struct nfc_geometry *geo = &this->nfc_geometry;
+	struct mtd_info *mtd = &this->mil.mtd;
+	unsigned int metadata_size;
+	unsigned int status_size;
+	unsigned int chunk_data_size_in_bits;
+	unsigned int chunk_ecc_size_in_bits;
+	unsigned int chunk_total_size_in_bits;
+	unsigned int block_mark_chunk_number;
+	unsigned int block_mark_chunk_bit_offset;
+	unsigned int block_mark_bit_offset;
+
+	/* We only support BCH now. */
+	geo->ecc_algorithm = "BCH";
+
+	/*
+	 * We always choose a metadata size of 10. Don't try to make sense of
+	 * it -- this is really only for historical compatibility.
+	 */
+	geo->metadata_size_in_bytes = 10;
+
+	/* ECC chunks */
+	geo->ecc_chunk_size_in_bytes = get_ecc_chunk_size(this);
+
+	/*
+	 * Compute the total number of ECC chunks in a page. This includes the
+	 * slightly larger chunk at the beginning of the page, which contains
+	 * both data and metadata.
+	 */
+	geo->ecc_chunk_count = mtd->writesize / geo->ecc_chunk_size_in_bytes;
+
+	/*
+	 * We use the same ECC strength for all chunks, including the first one.
+	 */
+	geo->ecc_strength = get_ecc_strength(this);
+	if (!geo->ecc_strength) {
+		pr_info("Page size:%d, OOB:%d\n", mtd->writesize, mtd->oobsize);
+		return -EINVAL;
+	}
+
+	/* Compute the page size, include page and oob. */
+	geo->page_size_in_bytes = mtd->writesize + mtd->oobsize;
+
+	/*
+	 * ONFI/TOGGLE nand needs GF14, so re-calculate DMA page size.
+	 * The ONFI nand must do the recalculation,
+	 * else it will fail in DMA in some platform(such as imx50).
+	 */
+	if (is_ddr_nand(this))
+		geo->page_size_in_bytes = mtd->writesize +
+				geo->metadata_size_in_bytes +
+			(geo->ecc_strength * 14 * 8 / geo->ecc_chunk_count);
+
+	geo->payload_size_in_bytes = mtd->writesize;
+	/*
+	 * In principle, computing the auxiliary buffer geometry is NFC
+	 * version-specific. However, at this writing, all versions share the
+	 * same model, so this code can also be shared.
+	 *
+	 * The auxiliary buffer contains the metadata and the ECC status. The
+	 * metadata is padded to the nearest 32-bit boundary. The ECC status
+	 * contains one byte for every ECC chunk, and is also padded to the
+	 * nearest 32-bit boundary.
+	 */
+	metadata_size = ALIGN(geo->metadata_size_in_bytes, 4);
+	status_size   = ALIGN(geo->ecc_chunk_count, 4);
+
+	geo->auxiliary_size_in_bytes = metadata_size + status_size;
+	geo->auxiliary_status_offset = metadata_size;
+
+	/* Check if we're going to do block mark swapping. */
+	if (!this->swap_block_mark)
+		return 0;
+
+	/*
+	 * If control arrives here, we're doing block mark swapping, so we need
+	 * to compute the byte and bit offsets of the physical block mark within
+	 * the ECC-based view of the page data. In principle, this isn't a
+	 * difficult computation -- but it's very important and it's easy to get
+	 * it wrong, so we do it carefully.
+	 *
+	 * Note that this calculation is simpler because we use the same ECC
+	 * strength for all chunks, including the zero'th one, which contains
+	 * the metadata. The calculation would be slightly more complicated
+	 * otherwise.
+	 *
+	 * We start by computing the physical bit offset of the block mark. We
+	 * then subtract the number of metadata and ECC bits appearing before
+	 * the mark to arrive at its bit offset within the data alone.
+	 */
+
+	/* Compute some important facts about chunk geometry. */
+	chunk_data_size_in_bits = geo->ecc_chunk_size_in_bytes * 8;
+
+	/* ONFI/TOGGLE nand needs GF14 */
+	if (is_ddr_nand(this))
+		chunk_ecc_size_in_bits  = geo->ecc_strength * 14;
+	else
+		chunk_ecc_size_in_bits  = geo->ecc_strength * 13;
+
+	chunk_total_size_in_bits =
+			chunk_data_size_in_bits + chunk_ecc_size_in_bits;
+
+	/* Compute the bit offset of the block mark within the physical page. */
+	block_mark_bit_offset = mtd->writesize * 8;
+
+	/* Subtract the metadata bits. */
+	block_mark_bit_offset -= geo->metadata_size_in_bytes * 8;
+
+	/*
+	 * Compute the chunk number (starting at zero) in which the block mark
+	 * appears.
+	 */
+	block_mark_chunk_number =
+			block_mark_bit_offset / chunk_total_size_in_bits;
+
+	/*
+	 * Compute the bit offset of the block mark within its chunk, and
+	 * validate it.
+	 */
+	block_mark_chunk_bit_offset =
+		block_mark_bit_offset -
+			(block_mark_chunk_number * chunk_total_size_in_bits);
+
+	if (block_mark_chunk_bit_offset > chunk_data_size_in_bits) {
+		/*
+		 * If control arrives here, the block mark actually appears in
+		 * the ECC bits of this chunk. This wont' work.
+		 */
+		pr_info("Unsupported page geometry : %u:%u\n",
+				mtd->writesize, mtd->oobsize);
+		return -EINVAL;
+	}
+
+	/*
+	 * Now that we know the chunk number in which the block mark appears,
+	 * we can subtract all the ECC bits that appear before it.
+	 */
+	block_mark_bit_offset -=
+			block_mark_chunk_number * chunk_ecc_size_in_bits;
+
+	/*
+	 * We now know the absolute bit offset of the block mark within the
+	 * ECC-based data. We can now compute the byte offset and the bit
+	 * offset within the byte.
+	 */
+	geo->block_mark_byte_offset = block_mark_bit_offset / 8;
+	geo->block_mark_bit_offset  = block_mark_bit_offset % 8;
+
+	return 0;
+}
+
+struct dma_chan *get_dma_chan(struct gpmi_nfc_data *this)
+{
+	int chip = this->mil.current_chip;
+
+	BUG_ON(chip < 0);
+	return this->dma_chans[chip];
+}
+
+/* Can we use the upper's buffer directly for DMA? */
+void prepare_data_dma(struct gpmi_nfc_data *this, enum dma_data_direction dr)
+{
+	struct mil *mil = &this->mil;
+	struct scatterlist *sgl = &mil->data_sgl;
+	int ret;
+
+	mil->direct_dma_map_ok = true;
+
+	/* first try to map the upper buffer directly */
+	sg_init_one(sgl, mil->upper_buf, mil->upper_len);
+	ret = dma_map_sg(this->dev, sgl, 1, dr);
+	if (ret == 0) {
+		/* We have to use our own DMA buffer. */
+		sg_init_one(sgl, mil->data_buffer_dma, PAGE_SIZE);
+
+		if (dr == DMA_TO_DEVICE)
+			memcpy(mil->data_buffer_dma, mil->upper_buf,
+				mil->upper_len);
+
+		ret = dma_map_sg(this->dev, sgl, 1, dr);
+		BUG_ON(ret == 0);
+
+		mil->direct_dma_map_ok = false;
+	}
+}
+
+/* This will be called after the DMA operation is finished. */
+static void dma_irq_callback(void *param)
+{
+	struct gpmi_nfc_data *this = param;
+	struct nfc_hal *nfc = this->nfc;
+	struct mil *mil = &this->mil;
+
+	complete(&nfc->dma_done);
+
+	switch (this->dma_type) {
+	case DMA_FOR_COMMAND:
+		dma_unmap_sg(this->dev, &mil->cmd_sgl, 1, DMA_TO_DEVICE);
+		break;
+
+	case DMA_FOR_READ_DATA:
+		dma_unmap_sg(this->dev, &mil->data_sgl, 1, DMA_FROM_DEVICE);
+		if (mil->direct_dma_map_ok == false)
+			memcpy(mil->upper_buf, mil->data_buffer_dma,
+				mil->upper_len);
+		break;
+
+	case DMA_FOR_WRITE_DATA:
+		dma_unmap_sg(this->dev, &mil->data_sgl, 1, DMA_TO_DEVICE);
+		break;
+
+	case DMA_FOR_READ_ECC_PAGE:
+	case DMA_FOR_WRITE_ECC_PAGE:
+		/* We have to wait the BCH interrupt to finish. */
+		break;
+
+	default:
+		BUG();
+	}
+}
+
+int start_dma_without_bch_irq(struct gpmi_nfc_data *this,
+				struct dma_async_tx_descriptor *desc)
+{
+	struct nfc_hal *nfc = this->nfc;
+	int err;
+
+	init_completion(&nfc->dma_done);
+
+	desc->callback		= dma_irq_callback;
+	desc->callback_param	= this;
+	dmaengine_submit(desc);
+
+	/* Wait for the interrupt from the DMA block. */
+	err = wait_for_completion_timeout(&nfc->dma_done,
+					msecs_to_jiffies(1000));
+	err = (!err) ? -ETIMEDOUT : 0;
+	if (err)
+		pr_info("DMA timeout!!!\n");
+	return err;
+}
+
+/*
+ * This function is used in BCH reading or BCH writing pages.
+ * It will wait for the BCH interrupt as long as ONE second.
+ * Actually, we must wait for two interrupts :
+ *	[1] firstly the DMA interrupt and
+ *	[2] secondly the BCH interrupt.
+ *
+ * @this:	Per-device data structure.
+ * @desc:	DMA channel
+ */
+int start_dma_with_bch_irq(struct gpmi_nfc_data *this,
+			struct dma_async_tx_descriptor *desc)
+{
+	struct nfc_hal *nfc = this->nfc;
+	int err;
+
+	/* Prepare to receive an interrupt from the BCH block. */
+	init_completion(&nfc->bch_done);
+
+	/* start the DMA */
+	start_dma_without_bch_irq(this, desc);
+
+	/* Wait for the interrupt from the BCH block. */
+	err = wait_for_completion_timeout(&nfc->bch_done,
+					msecs_to_jiffies(1000));
+	err = (!err) ? -ETIMEDOUT : 0;
+	if (err)
+		pr_info("bch timeout!!!\n");
+	return err;
+}
+
+/**
+ * ns_to_cycles - Converts time in nanoseconds to cycles.
+ *
+ * @ntime:   The time, in nanoseconds.
+ * @period:  The cycle period, in nanoseconds.
+ * @min:     The minimum allowable number of cycles.
+ */
+static unsigned int ns_to_cycles(unsigned int time,
+					unsigned int period, unsigned int min)
+{
+	unsigned int k;
+
+	/*
+	 * Compute the minimum number of cycles that entirely contain the
+	 * given time.
+	 */
+	k = (time + period - 1) / period;
+	return max(k, min);
+}
+
+/**
+ * gpmi_compute_hardware_timing - Apply timing to current hardware conditions.
+ *
+ * @this:             Per-device data.
+ * @hardware_timing:  A pointer to a hardware timing structure that will receive
+ *                    the results of our calculations.
+ */
+int gpmi_nfc_compute_hardware_timing(struct gpmi_nfc_data *this,
+					struct gpmi_nfc_hardware_timing *hw)
+{
+	struct gpmi_nfc_platform_data *pdata = this->pdata;
+	struct nfc_hal *nfc = this->nfc;
+	struct nand_chip *nand = &this->mil.nand;
+	struct nand_timing target = nfc->timing;
+	bool improved_timing_is_available;
+	unsigned long clock_frequency_in_hz;
+	unsigned int clock_period_in_ns;
+	bool dll_use_half_periods;
+	unsigned int dll_delay_shift;
+	unsigned int max_sample_delay_in_ns;
+	unsigned int address_setup_in_cycles;
+	unsigned int data_setup_in_ns;
+	unsigned int data_setup_in_cycles;
+	unsigned int data_hold_in_cycles;
+	int ideal_sample_delay_in_ns;
+	unsigned int sample_delay_factor;
+	int tEYE;
+	unsigned int min_prop_delay_in_ns = pdata->min_prop_delay_in_ns;
+	unsigned int max_prop_delay_in_ns = pdata->max_prop_delay_in_ns;
+
+	/*
+	 * If there are multiple chips, we need to relax the timings to allow
+	 * for signal distortion due to higher capacitance.
+	 */
+	if (nand->numchips > 2) {
+		target.data_setup_in_ns    += 10;
+		target.data_hold_in_ns     += 10;
+		target.address_setup_in_ns += 10;
+	} else if (nand->numchips > 1) {
+		target.data_setup_in_ns    += 5;
+		target.data_hold_in_ns     += 5;
+		target.address_setup_in_ns += 5;
+	}
+
+	/* Check if improved timing information is available. */
+	improved_timing_is_available =
+		(target.tREA_in_ns  >= 0) &&
+		(target.tRLOH_in_ns >= 0) &&
+		(target.tRHOH_in_ns >= 0) ;
+
+	/* Inspect the clock. */
+	clock_frequency_in_hz = nfc->clock_frequency_in_hz;
+	clock_period_in_ns    = 1000000000 / clock_frequency_in_hz;
+
+	/*
+	 * The NFC quantizes setup and hold parameters in terms of clock cycles.
+	 * Here, we quantize the setup and hold timing parameters to the
+	 * next-highest clock period to make sure we apply at least the
+	 * specified times.
+	 *
+	 * For data setup and data hold, the hardware interprets a value of zero
+	 * as the largest possible delay. This is not what's intended by a zero
+	 * in the input parameter, so we impose a minimum of one cycle.
+	 */
+	data_setup_in_cycles    = ns_to_cycles(target.data_setup_in_ns,
+							clock_period_in_ns, 1);
+	data_hold_in_cycles     = ns_to_cycles(target.data_hold_in_ns,
+							clock_period_in_ns, 1);
+	address_setup_in_cycles = ns_to_cycles(target.address_setup_in_ns,
+							clock_period_in_ns, 0);
+
+	/*
+	 * The clock's period affects the sample delay in a number of ways:
+	 *
+	 * (1) The NFC HAL tells us the maximum clock period the sample delay
+	 *     DLL can tolerate. If the clock period is greater than half that
+	 *     maximum, we must configure the DLL to be driven by half periods.
+	 *
+	 * (2) We need to convert from an ideal sample delay, in ns, to a
+	 *     "sample delay factor," which the NFC uses. This factor depends on
+	 *     whether we're driving the DLL with full or half periods.
+	 *     Paraphrasing the reference manual:
+	 *
+	 *         AD = SDF x 0.125 x RP
+	 *
+	 * where:
+	 *
+	 *     AD   is the applied delay, in ns.
+	 *     SDF  is the sample delay factor, which is dimensionless.
+	 *     RP   is the reference period, in ns, which is a full clock period
+	 *          if the DLL is being driven by full periods, or half that if
+	 *          the DLL is being driven by half periods.
+	 *
+	 * Let's re-arrange this in a way that's more useful to us:
+	 *
+	 *                        8
+	 *         SDF  =  AD x ----
+	 *                       RP
+	 *
+	 * The reference period is either the clock period or half that, so this
+	 * is:
+	 *
+	 *                        8       AD x DDF
+	 *         SDF  =  AD x -----  =  --------
+	 *                      f x P        P
+	 *
+	 * where:
+	 *
+	 *       f  is 1 or 1/2, depending on how we're driving the DLL.
+	 *       P  is the clock period.
+	 *     DDF  is the DLL Delay Factor, a dimensionless value that
+	 *          incorporates all the constants in the conversion.
+	 *
+	 * DDF will be either 8 or 16, both of which are powers of two. We can
+	 * reduce the cost of this conversion by using bit shifts instead of
+	 * multiplication or division. Thus:
+	 *
+	 *                 AD << DDS
+	 *         SDF  =  ---------
+	 *                     P
+	 *
+	 *     or
+	 *
+	 *         AD  =  (SDF >> DDS) x P
+	 *
+	 * where:
+	 *
+	 *     DDS  is the DLL Delay Shift, the logarithm to base 2 of the DDF.
+	 */
+	if (clock_period_in_ns > (nfc->max_dll_clock_period_in_ns >> 1)) {
+		dll_use_half_periods = true;
+		dll_delay_shift      = 3 + 1;
+	} else {
+		dll_use_half_periods = false;
+		dll_delay_shift      = 3;
+	}
+
+	/*
+	 * Compute the maximum sample delay the NFC allows, under current
+	 * conditions. If the clock is running too slowly, no sample delay is
+	 * possible.
+	 */
+	if (clock_period_in_ns > nfc->max_dll_clock_period_in_ns)
+		max_sample_delay_in_ns = 0;
+	else {
+		/*
+		 * Compute the delay implied by the largest sample delay factor
+		 * the NFC allows.
+		 */
+		max_sample_delay_in_ns =
+			(nfc->max_sample_delay_factor * clock_period_in_ns) >>
+								dll_delay_shift;
+
+		/*
+		 * Check if the implied sample delay larger than the NFC
+		 * actually allows.
+		 */
+		if (max_sample_delay_in_ns > nfc->max_dll_delay_in_ns)
+			max_sample_delay_in_ns = nfc->max_dll_delay_in_ns;
+	}
+
+	/*
+	 * Check if improved timing information is available. If not, we have to
+	 * use a less-sophisticated algorithm.
+	 */
+	if (!improved_timing_is_available) {
+		/*
+		 * Fold the read setup time required by the NFC into the ideal
+		 * sample delay.
+		 */
+		ideal_sample_delay_in_ns = target.gpmi_sample_delay_in_ns +
+						nfc->internal_data_setup_in_ns;
+
+		/*
+		 * The ideal sample delay may be greater than the maximum
+		 * allowed by the NFC. If so, we can trade off sample delay time
+		 * for more data setup time.
+		 *
+		 * In each iteration of the following loop, we add a cycle to
+		 * the data setup time and subtract a corresponding amount from
+		 * the sample delay until we've satisified the constraints or
+		 * can't do any better.
+		 */
+		while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+
+			data_setup_in_cycles++;
+			ideal_sample_delay_in_ns -= clock_period_in_ns;
+
+			if (ideal_sample_delay_in_ns < 0)
+				ideal_sample_delay_in_ns = 0;
+
+		}
+
+		/*
+		 * Compute the sample delay factor that corresponds most closely
+		 * to the ideal sample delay. If the result is too large for the
+		 * NFC, use the maximum value.
+		 *
+		 * Notice that we use the ns_to_cycles function to compute the
+		 * sample delay factor. We do this because the form of the
+		 * computation is the same as that for calculating cycles.
+		 */
+		sample_delay_factor =
+			ns_to_cycles(
+				ideal_sample_delay_in_ns << dll_delay_shift,
+							clock_period_in_ns, 0);
+
+		if (sample_delay_factor > nfc->max_sample_delay_factor)
+			sample_delay_factor = nfc->max_sample_delay_factor;
+
+		/* Skip to the part where we return our results. */
+		goto return_results;
+	}
+
+	/*
+	 * If control arrives here, we have more detailed timing information,
+	 * so we can use a better algorithm.
+	 */
+
+	/*
+	 * Fold the read setup time required by the NFC into the maximum
+	 * propagation delay.
+	 */
+	max_prop_delay_in_ns += nfc->internal_data_setup_in_ns;
+
+	/*
+	 * Earlier, we computed the number of clock cycles required to satisfy
+	 * the data setup time. Now, we need to know the actual nanoseconds.
+	 */
+	data_setup_in_ns = clock_period_in_ns * data_setup_in_cycles;
+
+	/*
+	 * Compute tEYE, the width of the data eye when reading from the NAND
+	 * Flash. The eye width is fundamentally determined by the data setup
+	 * time, perturbed by propagation delays and some characteristics of the
+	 * NAND Flash device.
+	 *
+	 * start of the eye = max_prop_delay + tREA
+	 * end of the eye   = min_prop_delay + tRHOH + data_setup
+	 */
+	tEYE = (int)min_prop_delay_in_ns + (int)target.tRHOH_in_ns +
+							(int)data_setup_in_ns;
+
+	tEYE -= (int)max_prop_delay_in_ns + (int)target.tREA_in_ns;
+
+	/*
+	 * The eye must be open. If it's not, we can try to open it by
+	 * increasing its main forcer, the data setup time.
+	 *
+	 * In each iteration of the following loop, we increase the data setup
+	 * time by a single clock cycle. We do this until either the eye is
+	 * open or we run into NFC limits.
+	 */
+	while ((tEYE <= 0) &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+		/* Give a cycle to data setup. */
+		data_setup_in_cycles++;
+		/* Synchronize the data setup time with the cycles. */
+		data_setup_in_ns += clock_period_in_ns;
+		/* Adjust tEYE accordingly. */
+		tEYE += clock_period_in_ns;
+	}
+
+	/*
+	 * When control arrives here, the eye is open. The ideal time to sample
+	 * the data is in the center of the eye:
+	 *
+	 *     end of the eye + start of the eye
+	 *     ---------------------------------  -  data_setup
+	 *                    2
+	 *
+	 * After some algebra, this simplifies to the code immediately below.
+	 */
+	ideal_sample_delay_in_ns =
+		((int)max_prop_delay_in_ns +
+			(int)target.tREA_in_ns +
+				(int)min_prop_delay_in_ns +
+					(int)target.tRHOH_in_ns -
+						(int)data_setup_in_ns) >> 1;
+
+	/*
+	 * The following figure illustrates some aspects of a NAND Flash read:
+	 *
+	 *
+	 *           __                   _____________________________________
+	 * RDN         \_________________/
+	 *
+	 *                                         <---- tEYE ----->
+	 *                                        /-----------------\
+	 * Read Data ----------------------------<                   >---------
+	 *                                        \-----------------/
+	 *             ^                 ^                 ^              ^
+	 *             |                 |                 |              |
+	 *             |<--Data Setup -->|<--Delay Time -->|              |
+	 *             |                 |                 |              |
+	 *             |                 |                                |
+	 *             |                 |<--   Quantized Delay Time   -->|
+	 *             |                 |                                |
+	 *
+	 *
+	 * We have some issues we must now address:
+	 *
+	 * (1) The *ideal* sample delay time must not be negative. If it is, we
+	 *     jam it to zero.
+	 *
+	 * (2) The *ideal* sample delay time must not be greater than that
+	 *     allowed by the NFC. If it is, we can increase the data setup
+	 *     time, which will reduce the delay between the end of the data
+	 *     setup and the center of the eye. It will also make the eye
+	 *     larger, which might help with the next issue...
+	 *
+	 * (3) The *quantized* sample delay time must not fall either before the
+	 *     eye opens or after it closes (the latter is the problem
+	 *     illustrated in the above figure).
+	 */
+
+	/* Jam a negative ideal sample delay to zero. */
+	if (ideal_sample_delay_in_ns < 0)
+		ideal_sample_delay_in_ns = 0;
+
+	/*
+	 * Extend the data setup as needed to reduce the ideal sample delay
+	 * below the maximum permitted by the NFC.
+	 */
+	while ((ideal_sample_delay_in_ns > max_sample_delay_in_ns) &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+
+		/* Give a cycle to data setup. */
+		data_setup_in_cycles++;
+		/* Synchronize the data setup time with the cycles. */
+		data_setup_in_ns += clock_period_in_ns;
+		/* Adjust tEYE accordingly. */
+		tEYE += clock_period_in_ns;
+
+		/*
+		 * Decrease the ideal sample delay by one half cycle, to keep it
+		 * in the middle of the eye.
+		 */
+		ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
+
+		/* Jam a negative ideal sample delay to zero. */
+		if (ideal_sample_delay_in_ns < 0)
+			ideal_sample_delay_in_ns = 0;
+	}
+
+	/*
+	 * Compute the sample delay factor that corresponds to the ideal sample
+	 * delay. If the result is too large, then use the maximum allowed
+	 * value.
+	 *
+	 * Notice that we use the ns_to_cycles function to compute the sample
+	 * delay factor. We do this because the form of the computation is the
+	 * same as that for calculating cycles.
+	 */
+	sample_delay_factor =
+		ns_to_cycles(ideal_sample_delay_in_ns << dll_delay_shift,
+							clock_period_in_ns, 0);
+
+	if (sample_delay_factor > nfc->max_sample_delay_factor)
+		sample_delay_factor = nfc->max_sample_delay_factor;
+
+	/*
+	 * These macros conveniently encapsulate a computation we'll use to
+	 * continuously evaluate whether or not the data sample delay is inside
+	 * the eye.
+	 */
+	#define IDEAL_DELAY  ((int) ideal_sample_delay_in_ns)
+
+	#define QUANTIZED_DELAY  \
+		((int) ((sample_delay_factor * clock_period_in_ns) >> \
+							dll_delay_shift))
+
+	#define DELAY_ERROR  (abs(QUANTIZED_DELAY - IDEAL_DELAY))
+
+	#define SAMPLE_IS_NOT_WITHIN_THE_EYE  (DELAY_ERROR > (tEYE >> 1))
+
+	/*
+	 * While the quantized sample time falls outside the eye, reduce the
+	 * sample delay or extend the data setup to move the sampling point back
+	 * toward the eye. Do not allow the number of data setup cycles to
+	 * exceed the maximum allowed by the NFC.
+	 */
+	while (SAMPLE_IS_NOT_WITHIN_THE_EYE &&
+			(data_setup_in_cycles < nfc->max_data_setup_cycles)) {
+		/*
+		 * If control arrives here, the quantized sample delay falls
+		 * outside the eye. Check if it's before the eye opens, or after
+		 * the eye closes.
+		 */
+		if (QUANTIZED_DELAY > IDEAL_DELAY) {
+			/*
+			 * If control arrives here, the quantized sample delay
+			 * falls after the eye closes. Decrease the quantized
+			 * delay time and then go back to re-evaluate.
+			 */
+			if (sample_delay_factor != 0)
+				sample_delay_factor--;
+			continue;
+		}
+
+		/*
+		 * If control arrives here, the quantized sample delay falls
+		 * before the eye opens. Shift the sample point by increasing
+		 * data setup time. This will also make the eye larger.
+		 */
+
+		/* Give a cycle to data setup. */
+		data_setup_in_cycles++;
+		/* Synchronize the data setup time with the cycles. */
+		data_setup_in_ns += clock_period_in_ns;
+		/* Adjust tEYE accordingly. */
+		tEYE += clock_period_in_ns;
+
+		/*
+		 * Decrease the ideal sample delay by one half cycle, to keep it
+		 * in the middle of the eye.
+		 */
+		ideal_sample_delay_in_ns -= (clock_period_in_ns >> 1);
+
+		/* ...and one less period for the delay time. */
+		ideal_sample_delay_in_ns -= clock_period_in_ns;
+
+		/* Jam a negative ideal sample delay to zero. */
+		if (ideal_sample_delay_in_ns < 0)
+			ideal_sample_delay_in_ns = 0;
+
+		/*
+		 * We have a new ideal sample delay, so re-compute the quantized
+		 * delay.
+		 */
+		sample_delay_factor =
+			ns_to_cycles(
+				ideal_sample_delay_in_ns << dll_delay_shift,
+							clock_period_in_ns, 0);
+
+		if (sample_delay_factor > nfc->max_sample_delay_factor)
+			sample_delay_factor = nfc->max_sample_delay_factor;
+	}
+
+	/* Control arrives here when we're ready to return our results. */
+return_results:
+	hw->data_setup_in_cycles    = data_setup_in_cycles;
+	hw->data_hold_in_cycles     = data_hold_in_cycles;
+	hw->address_setup_in_cycles = address_setup_in_cycles;
+	hw->use_half_periods        = dll_use_half_periods;
+	hw->sample_delay_factor     = sample_delay_factor;
+
+	/* Return success. */
+	return 0;
+}
+
+static int __devinit acquire_register_block(struct gpmi_nfc_data *this,
+			const char *resource_name, void **reg_block_base)
+{
+	struct platform_device *pdev = this->pdev;
+	struct resource *r;
+	void *p;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, resource_name);
+	if (!r) {
+		pr_info("Can't get resource for %s\n", resource_name);
+		return -ENXIO;
+	}
+
+	/* remap the register block */
+	p = ioremap(r->start, resource_size(r));
+	if (!p) {
+		pr_info("Can't remap %s\n", resource_name);
+		return -ENOMEM;
+	}
+
+	*reg_block_base = p;
+	return 0;
+}
+
+static void release_register_block(struct gpmi_nfc_data *this,
+				void *reg_block_base)
+{
+	iounmap(reg_block_base);
+}
+
+static int __devinit acquire_interrupt(struct gpmi_nfc_data *this,
+			const char *resource_name,
+			irq_handler_t interrupt_handler, int *lno, int *hno)
+{
+	struct platform_device *pdev = this->pdev;
+	struct resource *r;
+	int err;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, resource_name);
+	if (!r) {
+		pr_info("Can't get resource for %s\n", resource_name);
+		return -ENXIO;
+	}
+
+	BUG_ON(r->start != r->end);
+	err = request_irq(r->start, interrupt_handler, 0, resource_name, this);
+	if (err) {
+		pr_info("Can't own %s\n", resource_name);
+		return err;
+	}
+
+	*lno = r->start;
+	*hno = r->end;
+	return 0;
+}
+
+static void release_interrupt(struct gpmi_nfc_data *this,
+			int low_interrupt_number, int high_interrupt_number)
+{
+	int i;
+	for (i = low_interrupt_number; i <= high_interrupt_number; i++)
+		free_irq(i, this);
+}
+
+static bool gpmi_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct gpmi_nfc_data *this = param;
+	struct resource *r = this->private;
+
+	if (!mxs_dma_is_apbh(chan))
+		return false;
+	/*
+	 * only catch the GPMI dma channels :
+	 *	for mx23 :	MX23_DMA_GPMI0 ~ MX23_DMA_GPMI3
+	 *		(These four channels share the same IRQ!)
+	 *
+	 *	for mx28 :	MX28_DMA_GPMI0 ~ MX28_DMA_GPMI7
+	 *		(These eight channels share the same IRQ!)
+	 */
+	if (r->start <= chan->chan_id && chan->chan_id <= r->end) {
+		chan->private = &this->dma_data;
+		return true;
+	}
+	return false;
+}
+
+static void release_dma_channels(struct gpmi_nfc_data *this)
+{
+	unsigned int i;
+	for (i = 0; i < DMA_CHANS; i++)
+		if (this->dma_chans[i]) {
+			dma_release_channel(this->dma_chans[i]);
+			this->dma_chans[i] = NULL;
+		}
+}
+
+static int __devinit acquire_dma_channels(struct gpmi_nfc_data *this,
+				const char *resource_name,
+				unsigned *low_channel, unsigned *high_channel)
+{
+	struct platform_device *pdev = this->pdev;
+	struct gpmi_nfc_platform_data *pdata = this->pdata;
+	struct resource *r, *r_dma;
+	unsigned int i;
+
+	r = platform_get_resource_byname(pdev, IORESOURCE_DMA, resource_name);
+	r_dma = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+					GPMI_NFC_DMA_INTERRUPT_RES_NAME);
+	if (!r || !r_dma) {
+		pr_info("Can't get resource for DMA\n");
+		return -ENXIO;
+	}
+
+	/* used in gpmi_dma_filter() */
+	this->private = r;
+
+	for (i = r->start; i <= r->end; i++) {
+		dma_cap_mask_t		mask;
+		struct dma_chan		*dma_chan;
+
+		if (i - r->start >= pdata->max_chip_count)
+			break;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		/* get the DMA interrupt */
+		this->dma_data.chan_irq = r_dma->start +
+			((r_dma->start != r_dma->end) ? (i - r->start) : 0);
+
+		dma_chan = dma_request_channel(mask, gpmi_dma_filter, this);
+		if (!dma_chan)
+			goto acquire_err;
+		/* fill the first empty item */
+		this->dma_chans[i - r->start] = dma_chan;
+	}
+
+	*low_channel  = r->start;
+	*high_channel = i;
+	return 0;
+
+acquire_err:
+	pr_info("Can't acquire DMA channel %u\n", i);
+	release_dma_channels(this);
+	return -EINVAL;
+}
+
+static int __devinit acquire_resources(struct gpmi_nfc_data *this)
+{
+	struct resources *resources = &this->resources;
+	int error;
+
+	/* Attempt to acquire the GPMI register block. */
+	error = acquire_register_block(this,
+				GPMI_NFC_GPMI_REGS_ADDR_RES_NAME,
+				&resources->gpmi_regs);
+	if (error)
+		goto exit_gpmi_regs;
+
+	/* Attempt to acquire the BCH register block. */
+	error = acquire_register_block(this,
+				GPMI_NFC_BCH_REGS_ADDR_RES_NAME,
+				&resources->bch_regs);
+	if (error)
+		goto exit_bch_regs;
+
+	/* Attempt to acquire the BCH interrupt. */
+	error = acquire_interrupt(this,
+				GPMI_NFC_BCH_INTERRUPT_RES_NAME,
+				bch_irq,
+				&resources->bch_low_interrupt,
+				&resources->bch_high_interrupt);
+	if (error)
+		goto exit_bch_interrupt;
+
+	/* Attempt to acquire the DMA channels. */
+	error = acquire_dma_channels(this,
+				GPMI_NFC_DMA_CHANNELS_RES_NAME,
+				&resources->dma_low_channel,
+				&resources->dma_high_channel);
+	if (error)
+		goto exit_dma_channels;
+
+	/* Attempt to acquire our clock. */
+	resources->clock = clk_get(&this->pdev->dev, NULL);
+	if (IS_ERR(resources->clock)) {
+		pr_info("can not get the clock\n");
+		error = -ENOENT;
+		goto exit_clock;
+	}
+	return 0;
+
+exit_clock:
+	release_dma_channels(this);
+exit_dma_channels:
+	release_interrupt(this, resources->bch_low_interrupt,
+				resources->bch_high_interrupt);
+exit_bch_interrupt:
+	release_register_block(this, resources->bch_regs);
+exit_bch_regs:
+	release_register_block(this, resources->gpmi_regs);
+exit_gpmi_regs:
+	return error;
+}
+
+static void release_resources(struct gpmi_nfc_data *this)
+{
+	struct resources  *resources = &this->resources;
+
+	clk_put(resources->clock);
+	release_register_block(this, resources->gpmi_regs);
+	release_register_block(this, resources->bch_regs);
+	release_interrupt(this, resources->bch_low_interrupt,
+				resources->bch_low_interrupt);
+	release_dma_channels(this);
+}
+
+static void exit_nfc_hal(struct gpmi_nfc_data *this)
+{
+	if (this->nfc)
+		this->nfc->exit(this);
+}
+
+static int __devinit set_up_nfc_hal(struct gpmi_nfc_data *this)
+{
+	struct nfc_hal *nfc = NULL;
+	int error;
+
+	/*
+	 * This structure contains the "safe" GPMI timing that should succeed
+	 * with any NAND Flash device
+	 * (although, with less-than-optimal performance).
+	 */
+	static struct nand_timing  safe_timing = {
+		.data_setup_in_ns        = 80,
+		.data_hold_in_ns         = 60,
+		.address_setup_in_ns     = 25,
+		.gpmi_sample_delay_in_ns =  6,
+		.tREA_in_ns              = -1,
+		.tRLOH_in_ns             = -1,
+		.tRHOH_in_ns             = -1,
+	};
+
+	if (GPMI_IS_MX23(this) || GPMI_IS_MX28(this))
+		nfc = &gpmi_nfc_hal_mxs;
+
+	BUG_ON(nfc == NULL);
+	this->nfc = nfc;
+
+	/* Initialize the NFC HAL. */
+	error = nfc->init(this);
+	if (error)
+		return error;
+
+	/* Set up safe timing. */
+	nfc->set_timing(this, &safe_timing);
+	return 0;
+}
+
+/* Creates/Removes sysfs files for this device.*/
+static void manage_sysfs_files(struct gpmi_nfc_data *this, int create)
+{
+	struct device *dev = this->dev;
+	struct device_attribute **attr;
+	unsigned int i;
+	int error;
+
+	for (i = 0, attr = device_attributes;
+			i < ARRAY_SIZE(device_attributes); i++, attr++) {
+
+		if (create) {
+			error = device_create_file(dev, *attr);
+			if (error) {
+				while (--attr >= device_attributes)
+					device_remove_file(dev, *attr);
+				return;
+			}
+		} else {
+			device_remove_file(dev, *attr);
+		}
+	}
+}
+
+static int read_page_prepare(struct gpmi_nfc_data *this,
+			void *destination, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			void **use_virt, dma_addr_t *use_phys)
+{
+	struct device  *dev = this->dev;
+	dma_addr_t destination_phys = ~0;
+
+	if (virt_addr_valid(destination))
+		destination_phys = dma_map_single(dev, destination,
+						length, DMA_FROM_DEVICE);
+
+	if (dma_mapping_error(dev, destination_phys)) {
+		if (alt_size < length) {
+			pr_info("Alternate buffer is too small\n");
+			return -ENOMEM;
+		}
+
+		*use_virt = alt_virt;
+		*use_phys = alt_phys;
+		this->mil.direct_dma_map_ok = false;
+	} else {
+		*use_virt = destination;
+		*use_phys = destination_phys;
+		this->mil.direct_dma_map_ok = true;
+	}
+	return 0;
+}
+
+static void read_page_end(struct gpmi_nfc_data *this,
+			void *destination, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			void *used_virt, dma_addr_t used_phys)
+{
+	if (this->mil.direct_dma_map_ok)
+		dma_unmap_single(this->dev, used_phys, length, DMA_FROM_DEVICE);
+}
+
+static void read_page_swap_end(struct gpmi_nfc_data *this,
+			void *destination, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			void *used_virt, dma_addr_t used_phys)
+{
+	if (!this->mil.direct_dma_map_ok)
+		memcpy(destination, alt_virt, length);
+}
+
+static int send_page_prepare(struct gpmi_nfc_data *this,
+			const void *source, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			const void **use_virt, dma_addr_t *use_phys)
+{
+	dma_addr_t source_phys = ~0;
+	struct device *dev = this->dev;
+
+	if (virt_addr_valid(source))
+		source_phys = dma_map_single(dev,
+				(void *)source, length, DMA_TO_DEVICE);
+
+	if (dma_mapping_error(dev, source_phys)) {
+		if (alt_size < length) {
+			pr_info("Alternate buffer is too small\n");
+			return -ENOMEM;
+		}
+
+		/*
+		 * Copy the contents of the source buffer into the alternate
+		 * buffer and set up the return values accordingly.
+		 */
+		memcpy(alt_virt, source, length);
+
+		*use_virt = alt_virt;
+		*use_phys = alt_phys;
+	} else {
+		*use_virt = source;
+		*use_phys = source_phys;
+	}
+	return 0;
+}
+
+static void send_page_end(struct gpmi_nfc_data *this,
+			const void *source, unsigned length,
+			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
+			const void *used_virt, dma_addr_t used_phys)
+{
+	struct device *dev = this->dev;
+	if (used_virt == source)
+		dma_unmap_single(dev, used_phys, length, DMA_TO_DEVICE);
+}
+
+static void mil_free_dma_buffer(struct gpmi_nfc_data *this)
+{
+	struct device *dev = this->dev;
+	struct mil *mil	= &this->mil;
+
+	if (mil->page_buffer_virt && virt_addr_valid(mil->page_buffer_virt))
+		dma_free_coherent(dev, mil->page_buffer_size,
+					mil->page_buffer_virt,
+					mil->page_buffer_phys);
+	kfree(mil->cmd_buffer);
+	kfree(mil->data_buffer_dma);
+
+	mil->cmd_buffer		= NULL;
+	mil->data_buffer_dma	= NULL;
+	mil->page_buffer_virt	= NULL;
+	mil->page_buffer_size	=  0;
+	mil->page_buffer_phys	= ~0;
+}
+
+/* Allocate the DMA buffers */
+static int mil_alloc_dma_buffer(struct gpmi_nfc_data *this)
+{
+	struct nfc_geometry *geo = &this->nfc_geometry;
+	struct device *dev = this->dev;
+	struct mil *mil = &this->mil;
+
+	/* [1] Allocate a command buffer. PAGE_SIZE is enough. */
+	mil->cmd_buffer = kzalloc(PAGE_SIZE, GFP_DMA);
+	if (mil->cmd_buffer == NULL)
+		goto error_alloc;
+
+	/* [2] Allocate a read/write data buffer. PAGE_SIZE is enough. */
+	mil->data_buffer_dma = kzalloc(PAGE_SIZE, GFP_DMA);
+	if (mil->data_buffer_dma == NULL)
+		goto error_alloc;
+
+	/*
+	 * [3] Allocate the page buffer.
+	 *
+	 * Both the payload buffer and the auxiliary buffer must appear on
+	 * 32-bit boundaries. We presume the size of the payload buffer is a
+	 * power of two and is much larger than four, which guarantees the
+	 * auxiliary buffer will appear on a 32-bit boundary.
+	 */
+	mil->page_buffer_size = geo->payload_size_in_bytes +
+				geo->auxiliary_size_in_bytes;
+
+	mil->page_buffer_virt = dma_alloc_coherent(dev, mil->page_buffer_size,
+					&mil->page_buffer_phys, GFP_DMA);
+	if (!mil->page_buffer_virt)
+		goto error_alloc;
+
+
+	/* Slice up the page buffer. */
+	mil->payload_virt = mil->page_buffer_virt;
+	mil->payload_phys = mil->page_buffer_phys;
+	mil->auxiliary_virt = mil->payload_virt + geo->payload_size_in_bytes;
+	mil->auxiliary_phys = mil->payload_phys + geo->payload_size_in_bytes;
+	return 0;
+
+error_alloc:
+	mil_free_dma_buffer(this);
+	pr_info("allocate DMA buffer error!!\n");
+	return -ENOMEM;
+}
+
+static void mil_cmd_ctrl(struct mtd_info *mtd, int data, unsigned int ctrl)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	struct mil *mil = &this->mil;
+	struct nfc_hal *nfc = this->nfc;
+	int error;
+
+	/*
+	 * Every operation begins with a command byte and a series of zero or
+	 * more address bytes. These are distinguished by either the Address
+	 * Latch Enable (ALE) or Command Latch Enable (CLE) signals being
+	 * asserted. When MTD is ready to execute the command, it will deassert
+	 * both latch enables.
+	 *
+	 * Rather than run a separate DMA operation for every single byte, we
+	 * queue them up and run a single DMA operation for the entire series
+	 * of command and data bytes. NAND_CMD_NONE means the END of the queue.
+	 */
+	if ((ctrl & (NAND_ALE | NAND_CLE))) {
+		if (data != NAND_CMD_NONE)
+			mil->cmd_buffer[mil->command_length++] = data;
+		return;
+	}
+
+	if (!mil->command_length)
+		return;
+
+	error = nfc->send_command(this);
+	if (error)
+		pr_info("Chip: %u, Error %d\n", mil->current_chip, error);
+
+	mil->command_length = 0;
+}
+
+static int mil_dev_ready(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	struct nfc_hal *nfc = this->nfc;
+	struct mil *mil = &this->mil;
+
+	return nfc->is_ready(this, mil->current_chip);
+}
+
+static void mil_select_chip(struct mtd_info *mtd, int chip)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	struct nfc_hal *nfc = this->nfc;
+	struct mil *mil = &this->mil;
+
+	if ((mil->current_chip < 0) && (chip >= 0))
+		nfc->begin(this);
+	else if ((mil->current_chip >= 0) && (chip < 0))
+		nfc->end(this);
+	else
+		;
+
+	mil->current_chip = chip;
+}
+
+static void mil_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	struct nfc_hal *nfc = this->nfc;
+	struct mil *mil = &this->mil;
+
+	logio(GPMI_DEBUG_READ);
+	/* save the info in mil{} for future */
+	mil->upper_buf	= buf;
+	mil->upper_len	= len;
+
+	nfc->read_data(this);
+}
+
+static void mil_write_buf(struct mtd_info *mtd, const uint8_t *buf, int len)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	struct nfc_hal *nfc = this->nfc;
+	struct mil *mil = &this->mil;
+
+	logio(GPMI_DEBUG_WRITE);
+	/* save the info in mil{} for future */
+	mil->upper_buf	= (uint8_t *)buf;
+	mil->upper_len	= len;
+
+	nfc->send_data(this);
+}
+
+static uint8_t mil_read_byte(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	struct mil *mil = &this->mil;
+	uint8_t *buf = mil->data_buffer_dma;
+
+	mil_read_buf(mtd, buf, 1);
+	return buf[0];
+}
+
+/**
+ * mil_handle_block_mark_swapping() - Handles block mark swapping.
+ *
+ * Note that, when this function is called, it doesn't know whether it's
+ * swapping the block mark, or swapping it *back* -- but it doesn't matter
+ * because the the operation is the same.
+ *
+ * @this:       Per-device data.
+ * @payload:    A pointer to the payload buffer.
+ * @auxiliary:  A pointer to the auxiliary buffer.
+ */
+static void mil_handle_block_mark_swapping(struct gpmi_nfc_data *this,
+						void *payload, void *auxiliary)
+{
+	struct nfc_geometry *nfc_geo = &this->nfc_geometry;
+	unsigned char *p;
+	unsigned char *a;
+	unsigned int  bit;
+	unsigned char mask;
+	unsigned char from_data;
+	unsigned char from_oob;
+
+	/* Check if we're doing block mark swapping. */
+	if (!this->swap_block_mark)
+		return;
+
+	/*
+	 * If control arrives here, we're swapping. Make some convenience
+	 * variables.
+	 */
+	bit = nfc_geo->block_mark_bit_offset;
+	p   = payload + nfc_geo->block_mark_byte_offset;
+	a   = auxiliary;
+
+	/*
+	 * Get the byte from the data area that overlays the block mark. Since
+	 * the ECC engine applies its own view to the bits in the page, the
+	 * physical block mark won't (in general) appear on a byte boundary in
+	 * the data.
+	 */
+	from_data = (p[0] >> bit) | (p[1] << (8 - bit));
+
+	/* Get the byte from the OOB. */
+	from_oob = a[0];
+
+	/* Swap them. */
+	a[0] = from_data;
+
+	mask = (0x1 << bit) - 1;
+	p[0] = (p[0] & mask) | (from_oob << bit);
+
+	mask = ~0 << bit;
+	p[1] = (p[1] & mask) | (from_oob >> (8 - bit));
+}
+
+static int mil_ecc_read_page(struct mtd_info *mtd, struct nand_chip *nand,
+				uint8_t *buf, int page)
+{
+	struct gpmi_nfc_data *this = nand->priv;
+	struct nfc_hal *nfc = this->nfc;
+	struct nfc_geometry *nfc_geo = &this->nfc_geometry;
+	struct mil *mil = &this->mil;
+	void          *payload_virt;
+	dma_addr_t    payload_phys;
+	void          *auxiliary_virt;
+	dma_addr_t    auxiliary_phys;
+	unsigned int  i;
+	unsigned char *status;
+	unsigned int  failed;
+	unsigned int  corrected;
+	int           error;
+
+	logio(GPMI_DEBUG_ECC_READ);
+	error = read_page_prepare(this, buf, mtd->writesize,
+					mil->payload_virt, mil->payload_phys,
+					nfc_geo->payload_size_in_bytes,
+					&payload_virt, &payload_phys);
+	if (error) {
+		pr_info("Inadequate DMA buffer\n");
+		error = -ENOMEM;
+		return error;
+	}
+	auxiliary_virt = mil->auxiliary_virt;
+	auxiliary_phys = mil->auxiliary_phys;
+
+	/* ask the NFC */
+	error = nfc->read_page(this, payload_phys, auxiliary_phys);
+	read_page_end(this, buf, mtd->writesize,
+			mil->payload_virt, mil->payload_phys,
+			nfc_geo->payload_size_in_bytes,
+			payload_virt, payload_phys);
+	if (error) {
+		pr_info("Error in ECC-based read: %d\n", error);
+		goto exit_nfc;
+	}
+
+	/* handle the block mark swapping */
+	mil_handle_block_mark_swapping(this, payload_virt, auxiliary_virt);
+
+	/* Loop over status bytes, accumulating ECC status. */
+	failed		= 0;
+	corrected	= 0;
+	status		= auxiliary_virt + nfc_geo->auxiliary_status_offset;
+
+	for (i = 0; i < nfc_geo->ecc_chunk_count; i++, status++) {
+		if ((*status == STATUS_GOOD) || (*status == STATUS_ERASED))
+			continue;
+
+		if (*status == STATUS_UNCORRECTABLE) {
+			failed++;
+			continue;
+		}
+		corrected += *status;
+	}
+
+	/*
+	 * Propagate ECC status to the owning MTD only when failed or
+	 * corrected times nearly reaches our ECC correction threshold.
+	 */
+	if (failed || corrected >= (nfc_geo->ecc_strength - 1)) {
+		mtd->ecc_stats.failed    += failed;
+		mtd->ecc_stats.corrected += corrected;
+	}
+
+	/*
+	 * It's time to deliver the OOB bytes. See mil_ecc_read_oob() for
+	 * details about our policy for delivering the OOB.
+	 *
+	 * We fill the caller's buffer with set bits, and then copy the block
+	 * mark to th caller's buffer. Note that, if block mark swapping was
+	 * necessary, it has already been done, so we can rely on the first
+	 * byte of the auxiliary buffer to contain the block mark.
+	 */
+	memset(nand->oob_poi, ~0, mtd->oobsize);
+	nand->oob_poi[0] = ((uint8_t *) auxiliary_virt)[0];
+
+	read_page_swap_end(this, buf, mtd->writesize,
+			mil->payload_virt, mil->payload_phys,
+			nfc_geo->payload_size_in_bytes,
+			payload_virt, payload_phys);
+exit_nfc:
+	return error;
+}
+
+static void mil_ecc_write_page(struct mtd_info *mtd,
+				struct nand_chip *nand, const uint8_t *buf)
+{
+	struct gpmi_nfc_data *this = nand->priv;
+	struct nfc_hal *nfc =  this->nfc;
+	struct nfc_geometry *nfc_geo = &this->nfc_geometry;
+	struct mil *mil = &this->mil;
+	const void *payload_virt;
+	dma_addr_t payload_phys;
+	const void *auxiliary_virt;
+	dma_addr_t auxiliary_phys;
+	int        error;
+
+	logio(GPMI_DEBUG_ECC_WRITE);
+	if (this->swap_block_mark) {
+		/*
+		 * If control arrives here, we're doing block mark swapping.
+		 * Since we can't modify the caller's buffers, we must copy them
+		 * into our own.
+		 */
+		memcpy(mil->payload_virt, buf, mtd->writesize);
+		payload_virt = mil->payload_virt;
+		payload_phys = mil->payload_phys;
+
+		memcpy(mil->auxiliary_virt, nand->oob_poi,
+				nfc_geo->auxiliary_size_in_bytes);
+		auxiliary_virt = mil->auxiliary_virt;
+		auxiliary_phys = mil->auxiliary_phys;
+
+		/* Handle block mark swapping. */
+		mil_handle_block_mark_swapping(this,
+				(void *) payload_virt, (void *) auxiliary_virt);
+	} else {
+		/*
+		 * If control arrives here, we're not doing block mark swapping,
+		 * so we can to try and use the caller's buffers.
+		 */
+		error = send_page_prepare(this,
+				buf, mtd->writesize,
+				mil->payload_virt, mil->payload_phys,
+				nfc_geo->payload_size_in_bytes,
+				&payload_virt, &payload_phys);
+		if (error) {
+			pr_info("Inadequate payload DMA buffer\n");
+			return;
+		}
+
+		error = send_page_prepare(this,
+				nand->oob_poi, mtd->oobsize,
+				mil->auxiliary_virt, mil->auxiliary_phys,
+				nfc_geo->auxiliary_size_in_bytes,
+				&auxiliary_virt, &auxiliary_phys);
+		if (error) {
+			pr_info("Inadequate auxiliary DMA buffer\n");
+			goto exit_auxiliary;
+		}
+	}
+
+	/* Ask the NFC. */
+	error = nfc->send_page(this, payload_phys, auxiliary_phys);
+	if (error)
+		pr_info("Error in ECC-based write: %d\n", error);
+
+	if (!this->swap_block_mark) {
+		send_page_end(this, nand->oob_poi, mtd->oobsize,
+				mil->auxiliary_virt, mil->auxiliary_phys,
+				nfc_geo->auxiliary_size_in_bytes,
+				auxiliary_virt, auxiliary_phys);
+exit_auxiliary:
+		send_page_end(this, buf, mtd->writesize,
+				mil->payload_virt, mil->payload_phys,
+				nfc_geo->payload_size_in_bytes,
+				payload_virt, payload_phys);
+	}
+}
+
+static int mil_hook_block_markbad(struct mtd_info *mtd, loff_t ofs)
+{
+	register struct nand_chip *chip = mtd->priv;
+	struct gpmi_nfc_data *this = chip->priv;
+	struct mil *mil = &this->mil;
+	int ret;
+
+	mil->marking_a_bad_block = true;
+	ret = mil->hooked_block_markbad(mtd, ofs);
+	mil->marking_a_bad_block = false;
+	return ret;
+}
+
+/**
+ * mil_ecc_read_oob() - MTD Interface ecc.read_oob().
+ *
+ * There are several places in this driver where we have to handle the OOB and
+ * block marks. This is the function where things are the most complicated, so
+ * this is where we try to explain it all. All the other places refer back to
+ * here.
+ *
+ * These are the rules, in order of decreasing importance:
+ *
+ * 1) Nothing the caller does can be allowed to imperil the block mark, so all
+ *    write operations take measures to protect it.
+ *
+ * 2) In read operations, the first byte of the OOB we return must reflect the
+ *    true state of the block mark, no matter where that block mark appears in
+ *    the physical page.
+ *
+ * 3) ECC-based read operations return an OOB full of set bits (since we never
+ *    allow ECC-based writes to the OOB, it doesn't matter what ECC-based reads
+ *    return).
+ *
+ * 4) "Raw" read operations return a direct view of the physical bytes in the
+ *    page, using the conventional definition of which bytes are data and which
+ *    are OOB. This gives the caller a way to see the actual, physical bytes
+ *    in the page, without the distortions applied by our ECC engine.
+ *
+ *
+ * What we do for this specific read operation depends on two questions:
+ *
+ * 1) Are we doing a "raw" read, or an ECC-based read?
+ *
+ * 2) Are we using block mark swapping or transcription?
+ *
+ * There are four cases, illustrated by the following Karnaugh map:
+ *
+ *                    |           Raw           |         ECC-based       |
+ *       -------------+-------------------------+-------------------------+
+ *                    | Read the conventional   |                         |
+ *                    | OOB at the end of the   |                         |
+ *       Swapping     | page and return it. It  |                         |
+ *                    | contains exactly what   |                         |
+ *                    | we want.                | Read the block mark and |
+ *       -------------+-------------------------+ return it in a buffer   |
+ *                    | Read the conventional   | full of set bits.       |
+ *                    | OOB at the end of the   |                         |
+ *                    | page and also the block |                         |
+ *       Transcribing | mark in the metadata.   |                         |
+ *                    | Copy the block mark     |                         |
+ *                    | into the first byte of  |                         |
+ *                    | the OOB.                |                         |
+ *       -------------+-------------------------+-------------------------+
+ *
+ * Note that we break rule #4 in the Transcribing/Raw case because we're not
+ * giving an accurate view of the actual, physical bytes in the page (we're
+ * overwriting the block mark). That's OK because it's more important to follow
+ * rule #2.
+ *
+ * It turns out that knowing whether we want an "ECC-based" or "raw" read is not
+ * easy. When reading a page, for example, the NAND Flash MTD code calls our
+ * ecc.read_page or ecc.read_page_raw function. Thus, the fact that MTD wants an
+ * ECC-based or raw view of the page is implicit in which function it calls
+ * (there is a similar pair of ECC-based/raw functions for writing).
+ *
+ * Since MTD assumes the OOB is not covered by ECC, there is no pair of
+ * ECC-based/raw functions for reading or or writing the OOB. The fact that the
+ * caller wants an ECC-based or raw view of the page is not propagated down to
+ * this driver.
+ *
+ * @mtd:     A pointer to the owning MTD.
+ * @nand:    A pointer to the owning NAND Flash MTD.
+ * @page:    The page number to read.
+ * @sndcmd:  Indicates this function should send a command to the chip before
+ *           reading the out-of-band bytes. This is only false for small page
+ *           chips that support auto-increment.
+ */
+static int mil_ecc_read_oob(struct mtd_info *mtd, struct nand_chip *nand,
+							int page, int sndcmd)
+{
+	struct gpmi_nfc_data *this = nand->priv;
+
+	/* clear the OOB buffer */
+	memset(nand->oob_poi, ~0, mtd->oobsize);
+
+	/* Read out the conventional OOB. */
+	nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+	nand->read_buf(mtd, nand->oob_poi, mtd->oobsize);
+
+	/*
+	 * Now, we want to make sure the block mark is correct. In the
+	 * Swapping/Raw case, we already have it. Otherwise, we need to
+	 * explicitly read it.
+	 */
+	if (!this->swap_block_mark) {
+		/* Read the block mark into the first byte of the OOB buffer. */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
+		nand->oob_poi[0] = nand->read_byte(mtd);
+	}
+
+	/*
+	 * Return true, indicating that the next call to this function must send
+	 * a command.
+	 */
+	return true;
+}
+
+static int mil_ecc_write_oob(struct mtd_info *mtd,
+				struct nand_chip *nand, int page)
+{
+	struct gpmi_nfc_data *this = nand->priv;
+	struct device *dev = this->dev;
+	struct mil *mil	= &this->mil;
+	uint8_t *block_mark;
+	int block_mark_column;
+	int status;
+	int error = 0;
+
+	/* Only marking a block bad is permitted to write the OOB. */
+	if (!mil->marking_a_bad_block) {
+		dev_emerg(dev, "This driver doesn't support writing the OOB\n");
+		WARN_ON(1);
+		error = -EIO;
+		goto exit;
+	}
+
+	if (this->swap_block_mark)
+		block_mark_column = mtd->writesize;
+	else
+		block_mark_column = 0;
+
+	/* Write the block mark. */
+	block_mark = mil->data_buffer_dma;
+	block_mark[0] = 0; /* bad block marker */
+
+	nand->cmdfunc(mtd, NAND_CMD_SEQIN, block_mark_column, page);
+	nand->write_buf(mtd, block_mark, 1);
+	nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+	status = nand->waitfunc(mtd, nand);
+
+	/* Check if it worked. */
+	if (status & NAND_STATUS_FAIL)
+		error = -EIO;
+exit:
+	return error;
+}
+
+/**
+ * mil_block_bad - Claims all blocks are good.
+ *
+ * In principle, this function is *only* called when the NAND Flash MTD system
+ * isn't allowed to keep an in-memory bad block table, so it is forced to ask
+ * the driver for bad block information.
+ *
+ * In fact, we permit the NAND Flash MTD system to have an in-memory BBT, so
+ * this function is *only* called when we take it away.
+ *
+ * We take away the in-memory BBT when the user sets the "ignorebad" parameter,
+ * which indicates that all blocks should be reported good.
+ *
+ * Thus, this function is only called when we want *all* blocks to look good,
+ * so it *always* return success.
+ *
+ * @mtd:      Ignored.
+ * @ofs:      Ignored.
+ * @getchip:  Ignored.
+ */
+static int mil_block_bad(struct mtd_info *mtd, loff_t ofs, int getchip)
+{
+	return 0;
+}
+
+static int __devinit nand_boot_set_geometry(struct gpmi_nfc_data *this)
+{
+	struct boot_rom_geometry *geometry = &this->rom_geometry;
+
+	/*
+	 * Set the boot block stride size.
+	 *
+	 * In principle, we should be reading this from the OTP bits, since
+	 * that's where the ROM is going to get it. In fact, we don't have any
+	 * way to read the OTP bits, so we go with the default and hope for the
+	 * best.
+	 */
+	geometry->stride_size_in_pages = 64;
+
+	/*
+	 * Set the search area stride exponent.
+	 *
+	 * In principle, we should be reading this from the OTP bits, since
+	 * that's where the ROM is going to get it. In fact, we don't have any
+	 * way to read the OTP bits, so we go with the default and hope for the
+	 * best.
+	 */
+	geometry->search_area_stride_exponent = 2;
+
+	if (gpmi_debug & GPMI_DEBUG_INIT)
+		pr_info("stride size in page : %d, search areas : %d\n",
+			geometry->stride_size_in_pages,
+			geometry->search_area_stride_exponent);
+	return 0;
+}
+
+static const char  *fingerprint = "STMP";
+static int __devinit mx23_check_transcription_stamp(struct gpmi_nfc_data *this)
+{
+	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
+	struct mil *mil = &this->mil;
+	struct mtd_info *mtd = &mil->mtd;
+	struct nand_chip *nand = &mil->nand;
+	unsigned int search_area_size_in_strides;
+	unsigned int stride;
+	unsigned int page;
+	loff_t byte;
+	uint8_t *buffer = nand->buffers->databuf;
+	int saved_chip_number;
+	int found_an_ncb_fingerprint = false;
+
+	/* Compute the number of strides in a search area. */
+	search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
+
+	/* Select chip 0. */
+	saved_chip_number = mil->current_chip;
+	nand->select_chip(mtd, 0);
+
+	/*
+	 * Loop through the first search area, looking for the NCB fingerprint.
+	 */
+	pr_info("Scanning for an NCB fingerprint...\n");
+
+	for (stride = 0; stride < search_area_size_in_strides; stride++) {
+		/* Compute the page and byte addresses. */
+		page = stride * rom_geo->stride_size_in_pages;
+		byte = page   * mtd->writesize;
+
+		pr_info("  Looking for a fingerprint in page 0x%x\n", page);
+
+		/*
+		 * Read the NCB fingerprint. The fingerprint is four bytes long
+		 * and starts in the 12th byte of the page.
+		 */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, 12, page);
+		nand->read_buf(mtd, buffer, strlen(fingerprint));
+
+		/* Look for the fingerprint. */
+		if (!memcmp(buffer, fingerprint, strlen(fingerprint))) {
+			found_an_ncb_fingerprint = true;
+			break;
+		}
+
+	}
+
+	/* Deselect chip 0. */
+	nand->select_chip(mtd, saved_chip_number);
+
+	if (found_an_ncb_fingerprint)
+		pr_info("  Found a fingerprint\n");
+	else
+		pr_info("  No fingerprint found\n");
+	return found_an_ncb_fingerprint;
+}
+
+/* Writes a transcription stamp. */
+static int __devinit mx23_write_transcription_stamp(struct gpmi_nfc_data *this)
+{
+	struct device *dev = this->dev;
+	struct boot_rom_geometry *rom_geo = &this->rom_geometry;
+	struct mil *mil = &this->mil;
+	struct mtd_info *mtd = &mil->mtd;
+	struct nand_chip *nand = &mil->nand;
+	unsigned int block_size_in_pages;
+	unsigned int search_area_size_in_strides;
+	unsigned int search_area_size_in_pages;
+	unsigned int search_area_size_in_blocks;
+	unsigned int block;
+	unsigned int stride;
+	unsigned int page;
+	loff_t       byte;
+	uint8_t      *buffer = nand->buffers->databuf;
+	int saved_chip_number;
+	int status;
+
+	/* Compute the search area geometry. */
+	block_size_in_pages = mtd->erasesize / mtd->writesize;
+	search_area_size_in_strides = 1 << rom_geo->search_area_stride_exponent;
+	search_area_size_in_pages = search_area_size_in_strides *
+					rom_geo->stride_size_in_pages;
+	search_area_size_in_blocks =
+		  (search_area_size_in_pages + (block_size_in_pages - 1)) /
+				    block_size_in_pages;
+
+	pr_info("-------------------------------------------\n");
+	pr_info("Search Area Geometry\n");
+	pr_info("-------------------------------------------\n");
+	pr_info("Search Area in Blocks : %u\n", search_area_size_in_blocks);
+	pr_info("Search Area in Strides: %u\n", search_area_size_in_strides);
+	pr_info("Search Area in Pages  : %u\n", search_area_size_in_pages);
+
+	/* Select chip 0. */
+	saved_chip_number = mil->current_chip;
+	nand->select_chip(mtd, 0);
+
+	/* Loop over blocks in the first search area, erasing them. */
+	pr_info("Erasing the search area...\n");
+
+	for (block = 0; block < search_area_size_in_blocks; block++) {
+		/* Compute the page address. */
+		page = block * block_size_in_pages;
+
+		/* Erase this block. */
+		pr_info("  Erasing block 0x%x\n", block);
+		nand->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
+		nand->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
+
+		/* Wait for the erase to finish. */
+		status = nand->waitfunc(mtd, nand);
+		if (status & NAND_STATUS_FAIL)
+			dev_err(dev, "[%s] Erase failed.\n", __func__);
+	}
+
+	/* Write the NCB fingerprint into the page buffer. */
+	memset(buffer, ~0, mtd->writesize);
+	memset(nand->oob_poi, ~0, mtd->oobsize);
+	memcpy(buffer + 12, fingerprint, strlen(fingerprint));
+
+	/* Loop through the first search area, writing NCB fingerprints. */
+	pr_info("Writing NCB fingerprints...\n");
+	for (stride = 0; stride < search_area_size_in_strides; stride++) {
+		/* Compute the page and byte addresses. */
+		page = stride * rom_geo->stride_size_in_pages;
+		byte = page   * mtd->writesize;
+
+		/* Write the first page of the current stride. */
+		pr_info("  Writing an NCB fingerprint in page 0x%x\n", page);
+		nand->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
+		nand->ecc.write_page_raw(mtd, nand, buffer);
+		nand->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
+
+		/* Wait for the write to finish. */
+		status = nand->waitfunc(mtd, nand);
+		if (status & NAND_STATUS_FAIL)
+			dev_err(dev, "[%s] Write failed.\n", __func__);
+	}
+
+	/* Deselect chip 0. */
+	nand->select_chip(mtd, saved_chip_number);
+	return 0;
+}
+
+static int __devinit mx23_boot_init(struct gpmi_nfc_data  *this)
+{
+	struct device *dev = this->dev;
+	struct mil *mil = &this->mil;
+	struct nand_chip *nand = &mil->nand;
+	struct mtd_info *mtd = &mil->mtd;
+	unsigned int block_count;
+	unsigned int block;
+	int     chip;
+	int     page;
+	loff_t  byte;
+	uint8_t block_mark;
+	int     error = 0;
+
+	/*
+	 * If control arrives here, we can't use block mark swapping, which
+	 * means we're forced to use transcription. First, scan for the
+	 * transcription stamp. If we find it, then we don't have to do
+	 * anything -- the block marks are already transcribed.
+	 */
+	if (mx23_check_transcription_stamp(this))
+		return 0;
+
+	/*
+	 * If control arrives here, we couldn't find a transcription stamp, so
+	 * so we presume the block marks are in the conventional location.
+	 */
+	pr_info("Transcribing bad block marks...\n");
+
+	/* Compute the number of blocks in the entire medium. */
+	block_count = nand->chipsize >> nand->phys_erase_shift;
+
+	/*
+	 * Loop over all the blocks in the medium, transcribing block marks as
+	 * we go.
+	 */
+	for (block = 0; block < block_count; block++) {
+		/*
+		 * Compute the chip, page and byte addresses for this block's
+		 * conventional mark.
+		 */
+		chip = block >> (nand->chip_shift - nand->phys_erase_shift);
+		page = block << (nand->phys_erase_shift - nand->page_shift);
+		byte = block <<  nand->phys_erase_shift;
+
+		/* Select the chip. */
+		nand->select_chip(mtd, chip);
+
+		/* Send the command to read the conventional block mark. */
+		nand->cmdfunc(mtd, NAND_CMD_READ0, mtd->writesize, page);
+
+		/* Read the conventional block mark. */
+		block_mark = nand->read_byte(mtd);
+
+		/*
+		 * Check if the block is marked bad. If so, we need to mark it
+		 * again, but this time the result will be a mark in the
+		 * location where we transcribe block marks.
+		 *
+		 * Notice that we have to explicitly set the marking_a_bad_block
+		 * member before we call through the block_markbad function
+		 * pointer in the owning struct nand_chip. If we could call
+		 * though the block_markbad function pointer in the owning
+		 * struct mtd_info, which we have hooked, then this would be
+		 * taken care of for us. Unfortunately, we can't because that
+		 * higher-level code path will do things like consulting the
+		 * in-memory bad block table -- which doesn't even exist yet!
+		 * So, we have to call at a lower level and handle some details
+		 * ourselves.
+		 */
+		if (block_mark != 0xff) {
+			pr_info("Transcribing mark in block %u\n", block);
+			mil->marking_a_bad_block = true;
+			error = nand->block_markbad(mtd, byte);
+			mil->marking_a_bad_block = false;
+			if (error)
+				dev_err(dev, "Failed to mark block bad with "
+							"error %d\n", error);
+		}
+
+		/* Deselect the chip. */
+		nand->select_chip(mtd, -1);
+	}
+
+	/* Write the stamp that indicates we've transcribed the block marks. */
+	mx23_write_transcription_stamp(this);
+	return 0;
+}
+
+static int __devinit nand_boot_init(struct gpmi_nfc_data  *this)
+{
+	nand_boot_set_geometry(this);
+
+	/* This is ROM arch-specific initilization before the BBT scanning. */
+	if (GPMI_IS_MX23(this))
+		return mx23_boot_init(this);
+	return 0;
+}
+
+static void show_nfc_geometry(struct nfc_geometry *geo)
+{
+	pr_info("---------------------------------------\n");
+	pr_info("	NFC Geometry (used by BCH)\n");
+	pr_info("---------------------------------------\n");
+	pr_info("ECC Algorithm          : %s\n", geo->ecc_algorithm);
+	pr_info("ECC Strength           : %u\n", geo->ecc_strength);
+	pr_info("Page Size in Bytes     : %u\n", geo->page_size_in_bytes);
+	pr_info("Metadata Size in Bytes : %u\n", geo->metadata_size_in_bytes);
+	pr_info("ECC Chunk Size in Bytes: %u\n", geo->ecc_chunk_size_in_bytes);
+	pr_info("ECC Chunk Count        : %u\n", geo->ecc_chunk_count);
+	pr_info("Payload Size in Bytes  : %u\n", geo->payload_size_in_bytes);
+	pr_info("Auxiliary Size in Bytes: %u\n", geo->auxiliary_size_in_bytes);
+	pr_info("Auxiliary Status Offset: %u\n", geo->auxiliary_status_offset);
+	pr_info("Block Mark Byte Offset : %u\n", geo->block_mark_byte_offset);
+	pr_info("Block Mark Bit Offset  : %u\n", geo->block_mark_bit_offset);
+}
+
+static int __devinit mil_set_geometry(struct gpmi_nfc_data *this)
+{
+	struct nfc_hal *nfc = this->nfc;
+	struct nfc_geometry *geo = &this->nfc_geometry;
+	int error;
+
+	/* Free the temporary DMA memory for read ID case */
+	mil_free_dma_buffer(this);
+
+	/* Set up the NFC geometry which is used by BCH. */
+	error = nfc->set_geometry(this);
+	if (error != 0) {
+		pr_info("NFC set geometry error : %d\n", error);
+		return error;
+	}
+	if (gpmi_debug & GPMI_DEBUG_INIT)
+		show_nfc_geometry(geo);
+
+	/* Alloc the new DMA buffers according to the pagesize and oobsize */
+	return mil_alloc_dma_buffer(this);
+}
+
+static int mil_pre_bbt_scan(struct gpmi_nfc_data  *this)
+{
+	struct nand_chip *nand = &this->mil.nand;
+	struct mtd_info *mtd = &this->mil.mtd;
+	struct nand_ecclayout *layout = nand->ecc.layout;
+	struct nfc_hal *nfc = this->nfc;
+	int error;
+
+	/* fix the ECC layout before the scanning */
+	layout->eccbytes          = 0;
+	layout->oobavail          = mtd->oobsize;
+	layout->oobfree[0].offset = 0;
+	layout->oobfree[0].length = mtd->oobsize;
+
+	mtd->oobavail = nand->ecc.layout->oobavail;
+
+	/* Set up swap block-mark, must be set before the mil_set_geometry() */
+	if (GPMI_IS_MX23(this))
+		this->swap_block_mark = false;
+	else
+		this->swap_block_mark = true;
+
+	/* Set up the medium geometry */
+	error = mil_set_geometry(this);
+	if (error)
+		return error;
+
+	/* extra init */
+	if (nfc->extra_init) {
+		error = nfc->extra_init(this);
+		if (error != 0)
+			return error;
+	}
+
+	/* NAND boot init, depends on the mil_set_geometry(). */
+	return nand_boot_init(this);
+}
+
+static int mil_scan_bbt(struct mtd_info *mtd)
+{
+	struct nand_chip *nand = mtd->priv;
+	struct gpmi_nfc_data *this = nand->priv;
+	int error;
+
+	/* Prepare for the BBT scan. */
+	error = mil_pre_bbt_scan(this);
+	if (error)
+		return error;
+
+	/* use the default BBT implementation */
+	return nand_default_bbt(mtd);
+}
+
+static const char *cmd_parse[] = {"cmdlinepart", NULL};
+static int __devinit mil_partitions_init(struct gpmi_nfc_data *this)
+{
+	struct gpmi_nfc_platform_data *pdata = this->pdata;
+	struct mil *mil = &this->mil;
+	struct mtd_info *mtd = &mil->mtd;
+
+	/* use the command line for simple partitions layout */
+	mil->partition_count = parse_mtd_partitions(mtd, cmd_parse,
+						&mil->partitions, 0);
+	if (mil->partition_count)
+		return mtd_device_register(mtd, mil->partitions,
+					mil->partition_count);
+
+	/* The complicated partitions layout uses this. */
+	if (pdata->partitions && pdata->partition_count > 0)
+		return mtd_device_register(mtd, pdata->partitions,
+					pdata->partition_count);
+	return mtd_device_register(mtd, NULL, 0);
+}
+
+static void mil_partitions_exit(struct gpmi_nfc_data *this)
+{
+	struct mil *mil = &this->mil;
+
+	if (mil->partition_count) {
+		struct mtd_info *mtd = &mil->mtd;
+
+		mtd_device_unregister(mtd);
+		kfree(mil->partitions);
+		mil->partition_count = 0;
+	}
+}
+
+/* Initializes the MTD Interface Layer */
+static int __devinit gpmi_nfc_mil_init(struct gpmi_nfc_data *this)
+{
+	struct gpmi_nfc_platform_data *pdata = this->pdata;
+	struct mil *mil = &this->mil;
+	struct mtd_info  *mtd = &mil->mtd;
+	struct nand_chip *nand = &mil->nand;
+	int error;
+
+	/* Initialize MIL data */
+	mil->current_chip	= -1;
+	mil->command_length	=  0;
+	mil->page_buffer_virt	=  NULL;
+	mil->page_buffer_phys	= ~0;
+	mil->page_buffer_size	=  0;
+
+	/* Initialize the MTD data structures */
+	mtd->priv		= nand;
+	mtd->name		= "gpmi-nfc";
+	mtd->owner		= THIS_MODULE;
+	nand->priv		= this;
+
+	/* Controls */
+	nand->select_chip	= mil_select_chip;
+	nand->cmd_ctrl		= mil_cmd_ctrl;
+	nand->dev_ready		= mil_dev_ready;
+
+	/*
+	 * Low-level I/O :
+	 *	We don't support a 16-bit NAND Flash bus,
+	 *	so we don't implement read_word.
+	 */
+	nand->read_byte		= mil_read_byte;
+	nand->read_buf		= mil_read_buf;
+	nand->write_buf		= mil_write_buf;
+
+	/* ECC-aware I/O */
+	nand->ecc.read_page	= mil_ecc_read_page;
+	nand->ecc.write_page	= mil_ecc_write_page;
+
+	/* High-level I/O */
+	nand->ecc.read_oob	= mil_ecc_read_oob;
+	nand->ecc.write_oob	= mil_ecc_write_oob;
+
+	/* Bad Block Management */
+	nand->block_bad		= mil_block_bad;
+	nand->scan_bbt		= mil_scan_bbt;
+	nand->badblock_pattern	= &gpmi_bbt_descr;
+
+	/* Disallow partial page writes */
+	nand->options		|= NAND_NO_SUBPAGE_WRITE;
+
+	/*
+	 * Tell the NAND Flash MTD system that we'll be handling ECC with our
+	 * own hardware. It turns out that we still have to fill in the ECC size
+	 * because the MTD code will divide by it -- even though it doesn't
+	 * actually care.
+	 */
+	nand->ecc.mode		= NAND_ECC_HW;
+	nand->ecc.size		= 1;
+
+	/* use our layout */
+	nand->ecc.layout = &mil->oob_layout;
+
+	/* Allocate a temporary DMA buffer for reading ID in the nand_scan() */
+	this->nfc_geometry.payload_size_in_bytes	= 1024;
+	this->nfc_geometry.auxiliary_size_in_bytes	= 128;
+	error = mil_alloc_dma_buffer(this);
+	if (error)
+		goto exit_dma_allocation;
+
+	printk(KERN_INFO "GPMI-NFC : Scanning for NAND Flash chips...\n");
+	error = nand_scan(mtd, pdata->max_chip_count);
+	if (error) {
+		pr_info("Chip scan failed\n");
+		goto exit_nand_scan;
+	}
+
+	/* Take over the management of the OOB */
+	mil->hooked_block_markbad = mtd->block_markbad;
+	mtd->block_markbad        = mil_hook_block_markbad;
+
+	/* Construct partitions as necessary. */
+	error = mil_partitions_init(this);
+	if (error)
+		goto exit_partitions;
+	return 0;
+
+exit_partitions:
+	nand_release(&mil->mtd);
+exit_nand_scan:
+	mil_free_dma_buffer(this);
+exit_dma_allocation:
+	return error;
+}
+
+void gpmi_nfc_mil_exit(struct gpmi_nfc_data *this)
+{
+	struct mil *mil = &this->mil;
+
+	mil_partitions_exit(this);
+	nand_release(&mil->mtd);
+	mil_free_dma_buffer(this);
+}
+
+static int __devinit gpmi_nfc_probe(struct platform_device *pdev)
+{
+	struct gpmi_nfc_platform_data *pdata = pdev->dev.platform_data;
+	struct gpmi_nfc_data *this;
+	int error;
+
+	this = kzalloc(sizeof(*this), GFP_KERNEL);
+	if (!this) {
+		pr_info("Failed to allocate per-device memory\n");
+		return -ENOMEM;
+	}
+
+	/* Set up our data structures. */
+	platform_set_drvdata(pdev, this);
+	this->pdev  = pdev;
+	this->dev   = &pdev->dev;
+	this->pdata = pdata;
+
+	/* setup the platform */
+	if (pdata->platform_init) {
+		error = pdata->platform_init();
+		if (error)
+			goto platform_init_error;
+	}
+
+	/* Acquire the resources we need. */
+	error = acquire_resources(this);
+	if (error)
+		goto exit_acquire_resources;
+
+	/* Set up the NFC. */
+	error = set_up_nfc_hal(this);
+	if (error)
+		goto exit_nfc_init;
+
+	/* Initialize the MTD Interface Layer. */
+	error = gpmi_nfc_mil_init(this);
+	if (error)
+		goto exit_mil_init;
+
+	manage_sysfs_files(this, true);
+	return 0;
+
+exit_mil_init:
+	exit_nfc_hal(this);
+exit_nfc_init:
+	release_resources(this);
+platform_init_error:
+exit_acquire_resources:
+	platform_set_drvdata(pdev, NULL);
+	kfree(this);
+	return error;
+}
+
+static int __exit gpmi_nfc_remove(struct platform_device *pdev)
+{
+	struct gpmi_nfc_data *this = platform_get_drvdata(pdev);
+
+	manage_sysfs_files(this, false);
+	gpmi_nfc_mil_exit(this);
+	exit_nfc_hal(this);
+	release_resources(this);
+	platform_set_drvdata(pdev, NULL);
+	kfree(this);
+	return 0;
+}
+
+static const struct platform_device_id gpmi_ids[] = {
+	{
+		.name = "imx23-gpmi-nfc",
+		.driver_data = IS_MX23,
+	}, {
+		.name = "imx28-gpmi-nfc",
+		.driver_data = IS_MX28,
+	}, {},
+};
+
+/* This structure represents this driver to the platform management system. */
+static struct platform_driver gpmi_nfc_driver = {
+	.driver = {
+		.name = "gpmi-nfc",
+	},
+	.probe   = gpmi_nfc_probe,
+	.remove  = __exit_p(gpmi_nfc_remove),
+	.id_table = gpmi_ids,
+};
+
+static int __init gpmi_nfc_init(void)
+{
+	int err;
+
+	if (!enable_gpmi_nand)
+		return 0;
+
+	err = platform_driver_register(&gpmi_nfc_driver);
+	if (err == 0)
+		printk(KERN_INFO "GPMI NFC driver registered. (IMX)\n");
+	else
+		pr_err("i.MX GPMI NFC driver registration failed\n");
+	return err;
+}
+
+static void __exit gpmi_nfc_exit(void)
+{
+	platform_driver_unregister(&gpmi_nfc_driver);
+}
+
+static int __init gpmi_nand_setup(char *__unused)
+{
+	enable_gpmi_nand = true;
+	return 1;
+}
+__setup("gpmi_nfc", gpmi_nand_setup);
+
+static int __init gpmi_debug_setup(char *__unused)
+{
+	gpmi_debug = GPMI_DEBUG_INIT;
+	enable_gpmi_nand = true;
+	return 1;
+}
+__setup("gpmi_debug_init", gpmi_debug_setup);
+
+module_init(gpmi_nfc_init);
+module_exit(gpmi_nfc_exit);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("i.MX GPMI NAND Flash Controller Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
new file mode 100644
index 0000000..1e092e0
--- /dev/null
+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
@@ -0,0 +1,495 @@
+/*
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, 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.
+ */
+#ifndef __DRIVERS_MTD_NAND_GPMI_NFC_H
+#define __DRIVERS_MTD_NAND_GPMI_NFC_H
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/concat.h>
+#include <linux/dmaengine.h>
+#include <asm/sizes.h>
+
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/gpmi-nfc.h>
+#include <mach/system.h>
+#include <mach/clock.h>
+
+/**
+ * struct resources - The collection of resources the driver needs.
+ *
+ * @gpmi_regs:         A pointer to the GPMI registers.
+ * @bch_regs:          A pointer to the BCH registers.
+ * @bch_interrupt:     The BCH interrupt number.
+ * @dma_low_channel:   The low  DMA channel.
+ * @dma_high_channel:  The high DMA channel.
+ * @clock:             A pointer to the struct clk for the NFC's clock.
+ */
+struct resources {
+	void          *gpmi_regs;
+	void          *bch_regs;
+	unsigned int  bch_low_interrupt;
+	unsigned int  bch_high_interrupt;
+	unsigned int  dma_low_channel;
+	unsigned int  dma_high_channel;
+	struct clk    *clock;
+};
+
+/**
+ * struct mil - State for the MTD Interface Layer.
+ *
+ * @nand:                    The NAND Flash MTD data structure that represents
+ *                           the NAND Flash medium.
+ * @mtd:                     The MTD data structure that represents the NAND
+ *                           Flash medium.
+ * @oob_layout:              A structure that describes how bytes are laid out
+ *                           in the OOB.
+ * @partitions:              A pointer to a set of partitions.
+ * @partition_count:         The number of partitions.
+ * @current_chip:            The chip currently selected by the NAND Fash MTD
+ *                           code. A negative value indicates that no chip is
+ *                           selected.
+ * @command_length:          The length of the command that appears in the
+ *                           command buffer (see cmd_virt, below).
+ * @ignore_bad_block_marks:  Indicates we are ignoring bad block marks.
+ * @saved_bbt:               A saved pointer to the in-memory NAND Flash MTD bad
+ *                           block table. See show_device_ignorebad() for more
+ *                           details.
+ * @marking_a_bad_block:     Indicates the caller is marking a bad block. See
+ *                           mil_ecc_write_oob() for details.
+ * @hooked_block_markbad:    A pointer to the block_markbad() function we
+ *                           we "hooked." See mil_ecc_write_oob() for details.
+ * @upper_buf:               The buffer passed from upper layer.
+ * @upper_len:               The buffer len passed from upper layer.
+ * @direct_dma_map_ok:       Is the direct DMA map is good for the upper_buf?
+ * @cmd_sgl/cmd_buffer:      For NAND command.
+ * @data_sgl/data_buffer_dma:For NAND DATA ops.
+ * @page_buffer_virt:        A pointer to a DMA-coherent buffer we use for
+ *                           reading and writing pages. This buffer includes
+ *                           space for both the payload data and the auxiliary
+ *                           data (including status bytes, but not syndrome
+ *                           bytes).
+ * @page_buffer_phys:        The physical address for the page_buffer_virt
+ *                           buffer.
+ * @page_buffer_size:        The size of the page buffer.
+ * @payload_virt:            A pointer to a location in the page buffer used
+ *                           for payload bytes. The size of this buffer is
+ *                           determined by struct nfc_geometry.
+ * @payload_phys:            The physical address for payload_virt.
+ * @auxiliary_virt:          A pointer to a location in the page buffer used
+ *                           for auxiliary bytes. The size of this buffer is
+ *                           determined by struct nfc_geometry.
+ * @auxiliary_phys:          The physical address for auxiliary_virt.
+ */
+struct mil {
+	/* MTD Data Structures */
+	struct nand_chip       nand;
+	struct mtd_info        mtd;
+	struct nand_ecclayout  oob_layout;
+
+	/* Partitions*/
+	struct mtd_partition   *partitions;
+	unsigned int           partition_count;
+
+	/* General-use Variables */
+	int                    current_chip;
+	unsigned int           command_length;
+	int                    ignore_bad_block_marks;
+	void                   *saved_bbt;
+
+	/* MTD Function Pointer Hooks */
+	int                    marking_a_bad_block;
+	int                    (*hooked_block_markbad)(struct mtd_info *mtd,
+					loff_t ofs);
+
+	/* from upper layer */
+	uint8_t			*upper_buf;
+	int			upper_len;
+
+	/* DMA */
+	bool			direct_dma_map_ok;
+
+	struct scatterlist	cmd_sgl;
+	char			*cmd_buffer;
+
+	struct scatterlist	data_sgl;
+	char			*data_buffer_dma;
+
+	void                   *page_buffer_virt;
+	dma_addr_t             page_buffer_phys;
+	unsigned int           page_buffer_size;
+
+	void                   *payload_virt;
+	dma_addr_t             payload_phys;
+
+	void                   *auxiliary_virt;
+	dma_addr_t             auxiliary_phys;
+};
+
+/**
+ * struct nfc_geometry - NFC geometry description.
+ *
+ * This structure describes the NFC's view of the medium geometry.
+ *
+ * @ecc_algorithm:            The human-readable name of the ECC algorithm
+ *                            (e.g., "Reed-Solomon" or "BCH").
+ * @ecc_strength:             A number that describes the strength of the ECC
+ *                            algorithm.
+ * @page_size_in_bytes:       The size, in bytes, of a physical page, including
+ *                            both data and OOB.
+ * @metadata_size_in_bytes:   The size, in bytes, of the metadata.
+ * @ecc_chunk_size_in_bytes:  The size, in bytes, of a single ECC chunk. Note
+ *                            the first chunk in the page includes both data and
+ *                            metadata, so it's a bit larger than this value.
+ * @ecc_chunk_count:          The number of ECC chunks in the page,
+ * @payload_size_in_bytes:    The size, in bytes, of the payload buffer.
+ * @auxiliary_size_in_bytes:  The size, in bytes, of the auxiliary buffer.
+ * @auxiliary_status_offset:  The offset into the auxiliary buffer at which
+ *                            the ECC status appears.
+ * @block_mark_byte_offset:   The byte offset in the ECC-based page view at
+ *                            which the underlying physical block mark appears.
+ * @block_mark_bit_offset:    The bit offset into the ECC-based page view at
+ *                            which the underlying physical block mark appears.
+ */
+struct nfc_geometry {
+	char          *ecc_algorithm;
+	unsigned int  ecc_strength;
+	unsigned int  page_size_in_bytes;
+	unsigned int  metadata_size_in_bytes;
+	unsigned int  ecc_chunk_size_in_bytes;
+	unsigned int  ecc_chunk_count;
+	unsigned int  payload_size_in_bytes;
+	unsigned int  auxiliary_size_in_bytes;
+	unsigned int  auxiliary_status_offset;
+	unsigned int  block_mark_byte_offset;
+	unsigned int  block_mark_bit_offset;
+};
+
+/**
+ * struct boot_rom_geometry - Boot ROM geometry description.
+ *
+ * @stride_size_in_pages:        The size of a boot block stride, in pages.
+ * @search_area_stride_exponent: The logarithm to base 2 of the size of a
+ *                               search area in boot block strides.
+ */
+struct boot_rom_geometry {
+	unsigned int  stride_size_in_pages;
+	unsigned int  search_area_stride_exponent;
+};
+
+/* DMA operations types */
+enum dma_ops_type {
+	DMA_FOR_COMMAND = 1,
+	DMA_FOR_READ_DATA,
+	DMA_FOR_WRITE_DATA,
+	DMA_FOR_READ_ECC_PAGE,
+	DMA_FOR_WRITE_ECC_PAGE
+};
+
+/**
+ * This structure contains the fundamental timing attributes for NAND.
+ *
+ * @data_setup_in_ns:         The data setup time, in nanoseconds. Usually the
+ *                            maximum of tDS and tWP. A negative value
+ *                            indicates this characteristic isn't known.
+ * @data_hold_in_ns:          The data hold time, in nanoseconds. Usually the
+ *                            maximum of tDH, tWH and tREH. A negative value
+ *                            indicates this characteristic isn't known.
+ * @address_setup_in_ns:      The address setup time, in nanoseconds. Usually
+ *                            the maximum of tCLS, tCS and tALS. A negative
+ *                            value indicates this characteristic isn't known.
+ * @gpmi_sample_delay_in_ns:  A GPMI-specific timing parameter. A negative value
+ *                            indicates this characteristic isn't known.
+ * @tREA_in_ns:               tREA, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ * @tRLOH_in_ns:              tRLOH, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ * @tRHOH_in_ns:              tRHOH, in nanoseconds, from the data sheet. A
+ *                            negative value indicates this characteristic isn't
+ *                            known.
+ */
+struct nand_timing {
+	int8_t  data_setup_in_ns;
+	int8_t  data_hold_in_ns;
+	int8_t  address_setup_in_ns;
+	int8_t  gpmi_sample_delay_in_ns;
+	int8_t  tREA_in_ns;
+	int8_t  tRLOH_in_ns;
+	int8_t  tRHOH_in_ns;
+};
+
+/**
+ * struct gpmi_nfc_data - i.MX NFC per-device data.
+ *
+ * @dev:                 A pointer to the owning struct device.
+ * @pdev:                A pointer to the owning struct platform_device.
+ * @pdata:               A pointer to the device's platform data.
+ * @resources:           Information about system resources used by this driver.
+ * @device_info:         A structure that contains detailed information about
+ *                       the NAND Flash device.
+ * @nfc:                 A pointer to a structure that represents the underlying
+ *                       NFC hardware.
+ * @nfc_geometry:        A description of the medium geometry as viewed by the
+ *                       NFC.
+ * @swap_block_mark:     Does it support the swap-block-mark feature?
+ *                       Boot ROM.
+ * @rom_geometry:        A description of the medium geometry as viewed by the
+ *                       Boot ROM.
+ * @mil:                 A collection of information used by the MTD Interface
+ *                       Layer.
+ */
+struct gpmi_nfc_data {
+	/* System Interface */
+	struct device                  *dev;
+	struct platform_device         *pdev;
+	struct gpmi_nfc_platform_data  *pdata;
+
+	/* Resources */
+	struct resources               resources;
+
+	/* Flash Hardware */
+	struct nand_timing		timing;
+
+	/* NFC HAL */
+	struct nfc_hal                 *nfc;
+	struct nfc_geometry            nfc_geometry;
+
+	/* NAND Boot issue */
+	bool				swap_block_mark;
+	struct boot_rom_geometry       rom_geometry;
+
+	/* MTD Interface Layer */
+	struct mil                     mil;
+
+	/* DMA channels */
+#define DMA_CHANS			8
+	struct dma_chan			*dma_chans[DMA_CHANS];
+	struct mxs_dma_data		dma_data;
+	enum dma_ops_type		dma_type;
+
+	/* private */
+	void				*private;
+};
+
+/**
+ * struct gpmi_nfc_hardware_timing - GPMI NFC hardware timing parameters.
+ *
+ * This structure contains timing information expressed in a form directly
+ * usable by the GPMI NFC hardware.
+ *
+ * @data_setup_in_cycles:      The data setup time, in cycles.
+ * @data_hold_in_cycles:       The data hold time, in cycles.
+ * @address_setup_in_cycles:   The address setup time, in cycles.
+ * @use_half_periods:          Indicates the clock is running slowly, so the
+ *                             NFC DLL should use half-periods.
+ * @sample_delay_factor:       The sample delay factor.
+ */
+struct gpmi_nfc_hardware_timing {
+	uint8_t  data_setup_in_cycles;
+	uint8_t  data_hold_in_cycles;
+	uint8_t  address_setup_in_cycles;
+	bool     use_half_periods;
+	uint8_t  sample_delay_factor;
+};
+
+/**
+ * struct nfc_hal - GPMI NFC HAL
+ *
+ * @description:                 description.
+ * @max_chip_count:              The maximum number of chips the NFC can
+ *                               possibly support (this value is a constant for
+ *                               each NFC version). This may *not* be the actual
+ *                               number of chips connected.
+ * @max_data_setup_cycles:       The maximum number of data setup cycles that
+ *                               can be expressed in the hardware.
+ * @internal_data_setup_in_ns:   The time, in ns, that the NFC hardware requires
+ *                               for data read internal setup. In the Reference
+ *                               Manual, see the chapter "High-Speed NAND
+ *                               Timing" for more details.
+ * @max_sample_delay_factor:     The maximum sample delay factor that can be
+ *                               expressed in the hardware.
+ * @max_dll_clock_period_in_ns:  The maximum period of the GPMI clock that the
+ *                               sample delay DLL hardware can possibly work
+ *                               with (the DLL is unusable with longer periods).
+ *                               If the full-cycle period is greater than HALF
+ *                               this value, the DLL must be configured to use
+ *                               half-periods.
+ * @max_dll_delay_in_ns:         The maximum amount of delay, in ns, that the
+ *                               DLL can implement.
+ * @dma_descriptors:             A pool of DMA descriptors.
+ * @isr_dma_channel:             The DMA channel with which the NFC HAL is
+ *                               working. We record this here so the ISR knows
+ *                               which DMA channel to acknowledge.
+ * @dma_done:                    The completion structure used for DMA
+ *                               interrupts.
+ * @bch_done:                    The completion structure used for BCH
+ *                               interrupts.
+ * @timing:                      The current timing configuration.
+ * @clock_frequency_in_hz:       The clock frequency, in Hz, during the current
+ *                               I/O transaction. If no I/O transaction is in
+ *                               progress, this is the clock frequency during
+ *                               the most recent I/O transaction.
+ * @hardware_timing:             The hardware timing configuration in effect
+ *                               during the current I/O transaction. If no I/O
+ *                               transaction is in progress, this is the
+ *                               hardware timing configuration during the most
+ *                               recent I/O transaction.
+ * @init:                        Initializes the NFC hardware and data
+ *                               structures. This function will be called after
+ *                               everything has been set up for communication
+ *                               with the NFC itself, but before the platform
+ *                               has set up off-chip communication. Thus, this
+ *                               function must not attempt to communicate with
+ *                               the NAND Flash hardware.
+ * @set_geometry:                Configures the NFC hardware and data structures
+ *                               to match the physical NAND Flash geometry.
+ * @set_timing:                  Configures the NFC hardware and data structures
+ *                               to match the given NAND Flash bus timing.
+ * @get_timing:                  Returns the the clock frequency, in Hz, and
+ *                               the hardware timing configuration during the
+ *                               current I/O transaction. If no I/O transaction
+ *                               is in progress, this is the timing state during
+ *                               the most recent I/O transaction.
+ * @exit:                        Shuts down the NFC hardware and data
+ *                               structures. This function will be called after
+ *                               the platform has shut down off-chip
+ *                               communication but while communication with the
+ *                               NFC itself still works.
+ * @clear_bch:                   Clears a BCH interrupt (intended to be called
+ *                               by a more general interrupt handler to do
+ *                               device-specific clearing).
+ * @is_ready:                    Returns true if the given chip is ready.
+ * @begin:                       Begins an interaction with the NFC. This
+ *                               function must be called before *any* of the
+ *                               following functions so the NFC can prepare
+ *                               itself.
+ * @end:                         Ends interaction with the NFC. This function
+ *                               should be called to give the NFC a chance to,
+ *                               among other things, enter a lower-power state.
+ * @send_command:                Sends the given buffer of command bytes.
+ * @send_data:                   Sends the given buffer of data bytes.
+ * @read_data:                   Reads data bytes into the given buffer.
+ * @send_page:                   Sends the given given data and OOB bytes,
+ *                               using the ECC engine.
+ * @read_page:                   Reads a page through the ECC engine and
+ *                               delivers the data and OOB bytes to the given
+ *                               buffers.
+ */
+struct nfc_hal {
+	/* Hardware attributes. */
+	const char              *description;
+	const unsigned int      max_chip_count;
+	const unsigned int      max_data_setup_cycles;
+	const unsigned int      internal_data_setup_in_ns;
+	const unsigned int      max_sample_delay_factor;
+	const unsigned int      max_dll_clock_period_in_ns;
+	const unsigned int      max_dll_delay_in_ns;
+
+	int                     isr_dma_channel;
+	struct completion       dma_done;
+	struct completion       bch_done;
+	struct nand_timing      timing;
+	unsigned long           clock_frequency_in_hz;
+
+	/* Configuration functions. */
+	int   (*init)        (struct gpmi_nfc_data *);
+	int   (*extra_init)  (struct gpmi_nfc_data *);
+	int   (*set_geometry)(struct gpmi_nfc_data *);
+	int   (*set_timing)  (struct gpmi_nfc_data *,
+					const struct nand_timing *);
+	void  (*get_timing)  (struct gpmi_nfc_data *,
+					unsigned long *clock_frequency_in_hz,
+					struct gpmi_nfc_hardware_timing *);
+	void  (*exit)        (struct gpmi_nfc_data *);
+
+	/* Call these functions to begin and end I/O. */
+	void  (*begin)       (struct gpmi_nfc_data *);
+	void  (*end)         (struct gpmi_nfc_data *);
+
+	/* Call these I/O functions only between begin() and end(). */
+	void  (*clear_bch)   (struct gpmi_nfc_data *);
+	int   (*is_ready)    (struct gpmi_nfc_data *, unsigned chip);
+	int   (*send_command)(struct gpmi_nfc_data *);
+	int   (*send_data)   (struct gpmi_nfc_data *);
+	int   (*read_data)   (struct gpmi_nfc_data *);
+	int   (*send_page)   (struct gpmi_nfc_data *,
+				dma_addr_t payload, dma_addr_t auxiliary);
+	int   (*read_page)   (struct gpmi_nfc_data *,
+				dma_addr_t payload, dma_addr_t auxiliary);
+};
+
+/* NFC HAL Common Services */
+extern int common_nfc_set_geometry(struct gpmi_nfc_data *this);
+extern int gpmi_nfc_compute_hardware_timing(struct gpmi_nfc_data *this,
+					struct gpmi_nfc_hardware_timing *hw);
+extern struct dma_chan *get_dma_chan(struct gpmi_nfc_data *this);
+extern void prepare_data_dma(struct gpmi_nfc_data *this,
+				enum dma_data_direction dr);
+extern int start_dma_without_bch_irq(struct gpmi_nfc_data *this,
+					struct dma_async_tx_descriptor *desc);
+extern int start_dma_with_bch_irq(struct gpmi_nfc_data *this,
+					struct dma_async_tx_descriptor *desc);
+/* NFC HAL Structures */
+extern struct nfc_hal  gpmi_nfc_hal_mxs;
+
+/* ONFI or TOGGLE nand */
+bool is_ddr_nand(struct gpmi_nfc_data *);
+
+/* for log */
+extern int gpmi_debug;
+#define GPMI_DEBUG_INIT		0x0001
+#define GPMI_DEBUG_READ		0x0002
+#define GPMI_DEBUG_WRITE	0x0004
+#define GPMI_DEBUG_ECC_READ	0x0008
+#define GPMI_DEBUG_ECC_WRITE	0x0010
+
+#ifdef pr_fmt
+#undef pr_fmt
+#endif
+
+#define pr_fmt(fmt) "[ %s : %.3d ] " fmt, __func__, __LINE__
+
+#define logio(level)				\
+		do {				\
+			if (gpmi_debug & level)	\
+				pr_info("\n");	\
+		} while (0)
+
+/* BCH : Status Block Completion Codes */
+#define STATUS_GOOD		0x00
+#define STATUS_ERASED		0xff
+#define STATUS_UNCORRECTABLE	0xfe
+
+/* Use the platform_id to distinguish different Archs. */
+#define IS_MX23			0x1
+#define IS_MX28			0x2
+#define GPMI_IS_MX23(x)		((x)->pdev->id_entry->driver_data == IS_MX23)
+#define GPMI_IS_MX28(x)		((x)->pdev->id_entry->driver_data == IS_MX28)
+#endif
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 04:24:37 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 16:24:37 +0800
Subject: [PATCH v7 2/3] MTD : add support for imx23 and imx28
In-Reply-To: <1309335878-16678-1-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
Message-ID: <1309335878-16678-3-git-send-email-b32955@freescale.com>

Add the implementation code for imx23 and imx28.
The imx23 and imx28 share most of the same code.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 drivers/mtd/nand/gpmi-nfc/bch-regs.h  |   88 ++++++
 drivers/mtd/nand/gpmi-nfc/gpmi-regs.h |  163 ++++++++++
 drivers/mtd/nand/gpmi-nfc/hal-mxs.c   |  554 +++++++++++++++++++++++++++++++++
 3 files changed, 805 insertions(+), 0 deletions(-)
 create mode 100644 drivers/mtd/nand/gpmi-nfc/bch-regs.h
 create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-regs.h
 create mode 100644 drivers/mtd/nand/gpmi-nfc/hal-mxs.c

diff --git a/drivers/mtd/nand/gpmi-nfc/bch-regs.h b/drivers/mtd/nand/gpmi-nfc/bch-regs.h
new file mode 100644
index 0000000..90af8cf
--- /dev/null
+++ b/drivers/mtd/nand/gpmi-nfc/bch-regs.h
@@ -0,0 +1,88 @@
+/*
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __GPMI_NFC_BCH_REGS_H
+#define __GPMI_NFC_BCH_REGS_H
+
+/*============================================================================*/
+#define HW_BCH_CTRL				0x00000000
+#define HW_BCH_CTRL_SET				0x00000004
+#define HW_BCH_CTRL_CLR				0x00000008
+#define HW_BCH_CTRL_TOG				0x0000000c
+
+#define BM_BCH_CTRL_COMPLETE_IRQ_EN		(1 << 8)
+#define BM_BCH_CTRL_COMPLETE_IRQ		(1 << 0)
+
+/*============================================================================*/
+#define HW_BCH_STATUS0				0x00000010
+#define HW_BCH_MODE				0x00000020
+#define HW_BCH_ENCODEPTR			0x00000030
+#define HW_BCH_DATAPTR				0x00000040
+#define HW_BCH_METAPTR				0x00000050
+#define HW_BCH_LAYOUTSELECT			0x00000070
+
+/*============================================================================*/
+#define HW_BCH_FLASH0LAYOUT0			0x00000080
+
+#define BP_BCH_FLASH0LAYOUT0_NBLOCKS		24
+#define BM_BCH_FLASH0LAYOUT0_NBLOCKS	(0xff << BP_BCH_FLASH0LAYOUT0_NBLOCKS)
+#define BF_BCH_FLASH0LAYOUT0_NBLOCKS(v)		\
+	(((v) << BP_BCH_FLASH0LAYOUT0_NBLOCKS) & BM_BCH_FLASH0LAYOUT0_NBLOCKS)
+
+#define BP_BCH_FLASH0LAYOUT0_META_SIZE		16
+#define BM_BCH_FLASH0LAYOUT0_META_SIZE	(0xff << BP_BCH_FLASH0LAYOUT0_META_SIZE)
+#define BF_BCH_FLASH0LAYOUT0_META_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT0_META_SIZE)\
+					 & BM_BCH_FLASH0LAYOUT0_META_SIZE)
+
+#define BP_BCH_FLASH0LAYOUT0_ECC0		12
+#define BM_BCH_FLASH0LAYOUT0_ECC0	(0xf << BP_BCH_FLASH0LAYOUT0_ECC0)
+#define BF_BCH_FLASH0LAYOUT0_ECC0(v)		\
+	(((v) << BP_BCH_FLASH0LAYOUT0_ECC0) & BM_BCH_FLASH0LAYOUT0_ECC0)
+
+#define BP_BCH_FLASH0LAYOUT0_DATA0_SIZE		0
+#define BM_BCH_FLASH0LAYOUT0_DATA0_SIZE		\
+			(0xfff << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)
+#define BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT0_DATA0_SIZE)\
+					 & BM_BCH_FLASH0LAYOUT0_DATA0_SIZE)
+
+/*============================================================================*/
+#define HW_BCH_FLASH0LAYOUT1			0x00000090
+
+#define BP_BCH_FLASH0LAYOUT1_PAGE_SIZE		16
+#define BM_BCH_FLASH0LAYOUT1_PAGE_SIZE		\
+			(0xffff << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE)
+#define BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT1_PAGE_SIZE) \
+					 & BM_BCH_FLASH0LAYOUT1_PAGE_SIZE)
+
+#define BP_BCH_FLASH0LAYOUT1_ECCN		12
+#define BM_BCH_FLASH0LAYOUT1_ECCN	(0xf << BP_BCH_FLASH0LAYOUT1_ECCN)
+#define BF_BCH_FLASH0LAYOUT1_ECCN(v)		\
+	(((v) << BP_BCH_FLASH0LAYOUT1_ECCN) & BM_BCH_FLASH0LAYOUT1_ECCN)
+
+#define BP_BCH_FLASH0LAYOUT1_DATAN_SIZE		0
+#define BM_BCH_FLASH0LAYOUT1_DATAN_SIZE		\
+			(0xfff << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE)
+#define BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(v)	\
+	(((v) << BP_BCH_FLASH0LAYOUT1_DATAN_SIZE) \
+					 & BM_BCH_FLASH0LAYOUT1_DATAN_SIZE)
+#endif
diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-regs.h b/drivers/mtd/nand/gpmi-nfc/gpmi-regs.h
new file mode 100644
index 0000000..d012c76
--- /dev/null
+++ b/drivers/mtd/nand/gpmi-nfc/gpmi-regs.h
@@ -0,0 +1,163 @@
+/*
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright 2008 Embedded Alley Solutions, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#ifndef __GPMI_NFC_GPMI_REGS_H
+#define __GPMI_NFC_GPMI_REGS_H
+
+/*============================================================================*/
+#define HW_GPMI_CTRL0					0x00000000
+#define HW_GPMI_CTRL0_SET				0x00000004
+#define HW_GPMI_CTRL0_CLR				0x00000008
+#define HW_GPMI_CTRL0_TOG				0x0000000c
+
+#define BP_GPMI_CTRL0_COMMAND_MODE			24
+#define BM_GPMI_CTRL0_COMMAND_MODE	(3 << BP_GPMI_CTRL0_COMMAND_MODE)
+#define BF_GPMI_CTRL0_COMMAND_MODE(v)	\
+	(((v) << BP_GPMI_CTRL0_COMMAND_MODE) & BM_GPMI_CTRL0_COMMAND_MODE)
+#define BV_GPMI_CTRL0_COMMAND_MODE__WRITE		0x0
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ		0x1
+#define BV_GPMI_CTRL0_COMMAND_MODE__READ_AND_COMPARE	0x2
+#define BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY	0x3
+
+#define BM_GPMI_CTRL0_WORD_LENGTH			(1 << 23)
+#define BV_GPMI_CTRL0_WORD_LENGTH__16_BIT		0x0
+#define BV_GPMI_CTRL0_WORD_LENGTH__8_BIT		0x1
+
+/* different in CS between imx23 and imx28 */
+#define BP_GPMI_CTRL0_CS				20
+#define MX23_BM_GPMI_CTRL0_CS		(3 << BP_GPMI_CTRL0_CS)
+#define MX28_BM_GPMI_CTRL0_CS		(7 << BP_GPMI_CTRL0_CS)
+#define BF_GPMI_CTRL0_CS(v, x)		(((v) << 20) & (GPMI_IS_MX23((x)) \
+						? MX23_BM_GPMI_CTRL0_CS	\
+						: MX28_BM_GPMI_CTRL0_CS))
+
+#define BP_GPMI_CTRL0_ADDRESS				17
+#define BM_GPMI_CTRL0_ADDRESS		(3 << BP_GPMI_CTRL0_ADDRESS)
+#define BF_GPMI_CTRL0_ADDRESS(v)	\
+		(((v) << BP_GPMI_CTRL0_ADDRESS) & BM_GPMI_CTRL0_ADDRESS)
+#define BV_GPMI_CTRL0_ADDRESS__NAND_DATA		0x0
+#define BV_GPMI_CTRL0_ADDRESS__NAND_CLE			0x1
+#define BV_GPMI_CTRL0_ADDRESS__NAND_ALE			0x2
+
+#define BM_GPMI_CTRL0_ADDRESS_INCREMENT			(1 << 16)
+#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__DISABLED	0x0
+#define BV_GPMI_CTRL0_ADDRESS_INCREMENT__ENABLED	0x1
+
+#define BP_GPMI_CTRL0_XFER_COUNT			0
+#define BM_GPMI_CTRL0_XFER_COUNT	(0xffff << BP_GPMI_CTRL0_XFER_COUNT)
+#define BF_GPMI_CTRL0_XFER_COUNT(v)	\
+		(((v) << BP_GPMI_CTRL0_XFER_COUNT) & BM_GPMI_CTRL0_XFER_COUNT)
+
+/*============================================================================*/
+#define HW_GPMI_COMPARE					0x00000010
+/*============================================================================*/
+#define HW_GPMI_ECCCTRL					0x00000020
+#define HW_GPMI_ECCCTRL_SET				0x00000024
+#define HW_GPMI_ECCCTRL_CLR				0x00000028
+#define HW_GPMI_ECCCTRL_TOG				0x0000002c
+
+#define BP_GPMI_ECCCTRL_ECC_CMD				13
+#define BM_GPMI_ECCCTRL_ECC_CMD		(3 << BP_GPMI_ECCCTRL_ECC_CMD)
+#define BF_GPMI_ECCCTRL_ECC_CMD(v)	\
+		(((v) << BP_GPMI_ECCCTRL_ECC_CMD) & BM_GPMI_ECCCTRL_ECC_CMD)
+#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE		0x0
+#define BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE		0x1
+
+#define BM_GPMI_ECCCTRL_ENABLE_ECC			(1 << 12)
+#define BV_GPMI_ECCCTRL_ENABLE_ECC__ENABLE		0x1
+#define BV_GPMI_ECCCTRL_ENABLE_ECC__DISABLE		0x0
+
+#define BP_GPMI_ECCCTRL_BUFFER_MASK			0
+#define BM_GPMI_ECCCTRL_BUFFER_MASK	(0x1ff << BP_GPMI_ECCCTRL_BUFFER_MASK)
+#define BF_GPMI_ECCCTRL_BUFFER_MASK(v)	\
+	(((v) << BP_GPMI_ECCCTRL_BUFFER_MASK) & BM_GPMI_ECCCTRL_BUFFER_MASK)
+#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY	0x100
+#define BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE		0x1FF
+
+/*============================================================================*/
+#define HW_GPMI_ECCCOUNT				0x00000030
+#define HW_GPMI_PAYLOAD					0x00000040
+#define HW_GPMI_AUXILIARY				0x00000050
+/*============================================================================*/
+#define HW_GPMI_CTRL1					0x00000060
+#define HW_GPMI_CTRL1_SET				0x00000064
+#define HW_GPMI_CTRL1_CLR				0x00000068
+#define HW_GPMI_CTRL1_TOG				0x0000006c
+
+#define BM_GPMI_CTRL1_BCH_MODE				(1 << 18)
+
+#define BP_GPMI_CTRL1_DLL_ENABLE			17
+#define BM_GPMI_CTRL1_DLL_ENABLE	(1 << BP_GPMI_CTRL1_DLL_ENABLE)
+
+#define BP_GPMI_CTRL1_HALF_PERIOD			16
+#define BM_GPMI_CTRL1_HALF_PERIOD	(1 << BP_GPMI_CTRL1_HALF_PERIOD)
+
+#define BP_GPMI_CTRL1_RDN_DELAY				12
+#define BM_GPMI_CTRL1_RDN_DELAY		(0xf << BP_GPMI_CTRL1_RDN_DELAY)
+#define BF_GPMI_CTRL1_RDN_DELAY(v)	\
+		(((v) << BP_GPMI_CTRL1_RDN_DELAY) & BM_GPMI_CTRL1_RDN_DELAY)
+
+#define BM_GPMI_CTRL1_DEV_RESET				(1 << 3)
+#define BV_GPMI_CTRL1_DEV_RESET__ENABLED		0x0
+#define BV_GPMI_CTRL1_DEV_RESET__DISABLED		0x1
+
+#define BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY		(1 << 2)
+#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVELOW	0x0
+#define BV_GPMI_CTRL1_ATA_IRQRDY_POLARITY__ACTIVEHIGH	0x1
+
+#define BM_GPMI_CTRL1_CAMERA_MODE			(1 << 1)
+#define BV_GPMI_CTRL1_GPMI_MODE__NAND			0x0
+#define BV_GPMI_CTRL1_GPMI_MODE__ATA			0x1
+
+#define BM_GPMI_CTRL1_GPMI_MODE				(1 << 0)
+
+/*============================================================================*/
+#define HW_GPMI_TIMING0					0x00000070
+
+#define BP_GPMI_TIMING0_ADDRESS_SETUP			16
+#define BM_GPMI_TIMING0_ADDRESS_SETUP	(0xff << BP_GPMI_TIMING0_ADDRESS_SETUP)
+#define BF_GPMI_TIMING0_ADDRESS_SETUP(v)	\
+	(((v) << BP_GPMI_TIMING0_ADDRESS_SETUP) & BM_GPMI_TIMING0_ADDRESS_SETUP)
+
+#define BP_GPMI_TIMING0_DATA_HOLD			8
+#define BM_GPMI_TIMING0_DATA_HOLD	(0xff << BP_GPMI_TIMING0_DATA_HOLD)
+#define BF_GPMI_TIMING0_DATA_HOLD(v)		\
+	(((v) << BP_GPMI_TIMING0_DATA_HOLD) & BM_GPMI_TIMING0_DATA_HOLD)
+
+#define BP_GPMI_TIMING0_DATA_SETUP			0
+#define BM_GPMI_TIMING0_DATA_SETUP	(0xff << BP_GPMI_TIMING0_DATA_SETUP)
+#define BF_GPMI_TIMING0_DATA_SETUP(v)		\
+	(((v) << BP_GPMI_TIMING0_DATA_SETUP) & BM_GPMI_TIMING0_DATA_SETUP)
+
+/*============================================================================*/
+#define HW_GPMI_TIMING1					0x00000080
+#define HW_GPMI_TIMING2					0x00000090
+#define HW_GPMI_DATA					0x000000a0
+/*============================ MX28 uses this to detect READY ================*/
+#define HW_GPMI_STAT					0x000000b0
+#define MX28_BP_GPMI_STAT_READY_BUSY			24
+#define MX28_BM_GPMI_STAT_READY_BUSY	(0xff << MX28_BP_GPMI_STAT_READY_BUSY)
+#define MX28_BF_GPMI_STAT_READY_BUSY(v)		\
+	(((v) << MX28_BP_GPMI_STAT_READY_BUSY) & MX28_BM_GPMI_STAT_READY_BUSY)
+/*============================ MX23 uses this to detect READY ================*/
+#define HW_GPMI_DEBUG					0x000000c0
+#define MX23_BP_GPMI_DEBUG_READY0			28
+#define MX23_BM_GPMI_DEBUG_READY0	(1 << MX23_BP_GPMI_DEBUG_READY0)
+#endif
diff --git a/drivers/mtd/nand/gpmi-nfc/hal-mxs.c b/drivers/mtd/nand/gpmi-nfc/hal-mxs.c
new file mode 100644
index 0000000..4a94d44
--- /dev/null
+++ b/drivers/mtd/nand/gpmi-nfc/hal-mxs.c
@@ -0,0 +1,554 @@
+/*
+ * Freescale GPMI NFC NAND Flash Driver
+ *
+ * Copyright (C) 2008-2011 Freescale Semiconductor, Inc.
+ * Copyright (C) 2008 Embedded Alley Solutions, 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "gpmi-nfc.h"
+#include "gpmi-regs.h"
+#include "bch-regs.h"
+
+static int init_hal(struct gpmi_nfc_data *this)
+{
+	struct resources *resources = &this->resources;
+
+	/* Enable the clock */
+	clk_enable(resources->clock);
+
+	/* Reset the GPMI block. */
+	mxs_reset_block(resources->gpmi_regs);
+
+	/* Choose NAND mode. */
+	__raw_writel(BM_GPMI_CTRL1_GPMI_MODE,
+				resources->gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+	/* Set the IRQ polarity. */
+	__raw_writel(BM_GPMI_CTRL1_ATA_IRQRDY_POLARITY,
+				resources->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Disable write protection. */
+	__raw_writel(BM_GPMI_CTRL1_DEV_RESET,
+				resources->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Select BCH ECC. */
+	__raw_writel(BM_GPMI_CTRL1_BCH_MODE,
+				resources->gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Disable the clock. */
+	clk_disable(resources->clock);
+	return 0;
+}
+
+/* Configures the NFC geometry for BCH.  */
+static int set_geometry(struct gpmi_nfc_data *this)
+{
+	struct resources *resources = &this->resources;
+	struct nfc_geometry *nfc = &this->nfc_geometry;
+	unsigned int block_count;
+	unsigned int block_size;
+	unsigned int metadata_size;
+	unsigned int ecc_strength;
+	unsigned int page_size;
+
+	if (common_nfc_set_geometry(this))
+		return !0;
+
+	block_count   = nfc->ecc_chunk_count - 1;
+	block_size    = nfc->ecc_chunk_size_in_bytes;
+	metadata_size = nfc->metadata_size_in_bytes;
+	ecc_strength  = nfc->ecc_strength >> 1;
+	page_size     = nfc->page_size_in_bytes;
+
+	clk_enable(resources->clock);
+
+	/*
+	 * Reset the BCH block. Notice that we pass in true for the just_enable
+	 * flag. This is because the soft reset for the version 0 BCH block
+	 * doesn't work. If you try to soft reset the BCH block, it becomes
+	 * unusable until the next hard reset.
+	 */
+	mxs_reset_block(resources->bch_regs);
+
+	/* Configure layout 0. */
+	__raw_writel(BF_BCH_FLASH0LAYOUT0_NBLOCKS(block_count)
+		| BF_BCH_FLASH0LAYOUT0_META_SIZE(metadata_size)
+		| BF_BCH_FLASH0LAYOUT0_ECC0(ecc_strength)
+		| BF_BCH_FLASH0LAYOUT0_DATA0_SIZE(block_size),
+		resources->bch_regs + HW_BCH_FLASH0LAYOUT0);
+
+	__raw_writel(BF_BCH_FLASH0LAYOUT1_PAGE_SIZE(page_size)
+		| BF_BCH_FLASH0LAYOUT1_ECCN(ecc_strength)
+		| BF_BCH_FLASH0LAYOUT1_DATAN_SIZE(block_size),
+		resources->bch_regs + HW_BCH_FLASH0LAYOUT1);
+
+	/* Set *all* chip selects to use layout 0. */
+	__raw_writel(0, resources->bch_regs + HW_BCH_LAYOUTSELECT);
+
+	/* Enable interrupts. */
+	__raw_writel(BM_BCH_CTRL_COMPLETE_IRQ_EN,
+				resources->bch_regs + HW_BCH_CTRL_SET);
+
+	clk_disable(resources->clock);
+	return 0;
+}
+
+static int set_timing(struct gpmi_nfc_data *this,
+			const struct nand_timing *timing)
+{
+	struct nfc_hal *nfc = this->nfc;
+
+	nfc->timing = *timing;
+	return 0;
+}
+
+/**
+ * get_timing() - Retrieves the NFC hardware timing.
+ *
+ * @this:                    Per-device data.
+ * @clock_frequency_in_hz:   The clock frequency, in Hz, during the current
+ *                           I/O transaction. If no I/O transaction is in
+ *                           progress, this is the clock frequency during the
+ *                           most recent I/O transaction.
+ * @hardware_timing:         The hardware timing configuration in effect during
+ *                           the current I/O transaction. If no I/O transaction
+ *                           is in progress, this is the hardware timing
+ *                           configuration during the most recent I/O
+ *                           transaction.
+ */
+static void get_timing(struct gpmi_nfc_data *this,
+			unsigned long *clock_frequency_in_hz,
+			struct gpmi_nfc_hardware_timing *hardware_timing)
+{
+	struct resources *resources = &this->resources;
+	struct nfc_hal *nfc = this->nfc;
+	unsigned char *gpmi_regs = resources->gpmi_regs;
+	uint32_t register_image;
+
+	/* Return the clock frequency. */
+	*clock_frequency_in_hz = nfc->clock_frequency_in_hz;
+
+	/* We'll be reading the hardware, so let's enable the clock. */
+	clk_enable(resources->clock);
+
+	/* Retrieve the hardware timing. */
+	register_image = __raw_readl(gpmi_regs + HW_GPMI_TIMING0);
+
+	hardware_timing->data_setup_in_cycles =
+		(register_image & BM_GPMI_TIMING0_DATA_SETUP) >>
+						BP_GPMI_TIMING0_DATA_SETUP;
+
+	hardware_timing->data_hold_in_cycles =
+		(register_image & BM_GPMI_TIMING0_DATA_HOLD) >>
+						BP_GPMI_TIMING0_DATA_HOLD;
+
+	hardware_timing->address_setup_in_cycles =
+		(register_image & BM_GPMI_TIMING0_ADDRESS_SETUP) >>
+						BP_GPMI_TIMING0_ADDRESS_SETUP;
+
+	register_image = __raw_readl(gpmi_regs + HW_GPMI_CTRL1);
+
+	hardware_timing->use_half_periods =
+		(register_image & BM_GPMI_CTRL1_HALF_PERIOD) >>
+						BP_GPMI_CTRL1_HALF_PERIOD;
+
+	hardware_timing->sample_delay_factor =
+		(register_image & BM_GPMI_CTRL1_RDN_DELAY) >>
+						BP_GPMI_CTRL1_RDN_DELAY;
+
+	/* We're done reading the hardware, so disable the clock. */
+	clk_disable(resources->clock);
+}
+
+static void exit(struct gpmi_nfc_data *this)
+{
+}
+
+/* Begin the I/O */
+static void begin(struct gpmi_nfc_data *this)
+{
+	struct resources *resources = &this->resources;
+	struct nfc_hal *nfc = this->nfc;
+	unsigned char  *gpmi_regs = resources->gpmi_regs;
+	unsigned int   clock_period_in_ns;
+	uint32_t       register_image;
+	unsigned int   dll_wait_time_in_us;
+	struct gpmi_nfc_hardware_timing  hw;
+
+	/* Enable the clock. */
+	clk_enable(resources->clock);
+
+	/* set the timing for imx23 */
+	if (!GPMI_IS_MX23(this))
+		return;
+
+	/* Get the timing information we need. */
+	nfc->clock_frequency_in_hz = clk_get_rate(resources->clock);
+	clock_period_in_ns = 1000000000 / nfc->clock_frequency_in_hz;
+
+	gpmi_nfc_compute_hardware_timing(this, &hw);
+
+	/* Set up all the simple timing parameters. */
+	register_image =
+		BF_GPMI_TIMING0_ADDRESS_SETUP(hw.address_setup_in_cycles) |
+		BF_GPMI_TIMING0_DATA_HOLD(hw.data_hold_in_cycles)         |
+		BF_GPMI_TIMING0_DATA_SETUP(hw.data_setup_in_cycles)       ;
+
+	__raw_writel(register_image, gpmi_regs + HW_GPMI_TIMING0);
+
+	/*
+	 * HEY - PAY ATTENTION!
+	 *
+	 * DLL_ENABLE must be set to zero when setting RDN_DELAY or HALF_PERIOD.
+	 */
+	__raw_writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+	/* Clear out the DLL control fields. */
+	__raw_writel(BM_GPMI_CTRL1_RDN_DELAY,   gpmi_regs + HW_GPMI_CTRL1_CLR);
+	__raw_writel(BM_GPMI_CTRL1_HALF_PERIOD, gpmi_regs + HW_GPMI_CTRL1_CLR);
+
+	/* If no sample delay is called for, return immediately. */
+	if (!hw.sample_delay_factor)
+		return;
+
+	/* Configure the HALF_PERIOD flag. */
+	if (hw.use_half_periods)
+		__raw_writel(BM_GPMI_CTRL1_HALF_PERIOD,
+						gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Set the delay factor. */
+	__raw_writel(BF_GPMI_CTRL1_RDN_DELAY(hw.sample_delay_factor),
+						gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/* Enable the DLL. */
+	__raw_writel(BM_GPMI_CTRL1_DLL_ENABLE, gpmi_regs + HW_GPMI_CTRL1_SET);
+
+	/*
+	 * After we enable the GPMI DLL, we have to wait 64 clock cycles before
+	 * we can use the GPMI.
+	 *
+	 * Calculate the amount of time we need to wait, in microseconds.
+	 */
+	dll_wait_time_in_us = (clock_period_in_ns * 64) / 1000;
+
+	if (!dll_wait_time_in_us)
+		dll_wait_time_in_us = 1;
+
+	/* Wait for the DLL to settle. */
+	udelay(dll_wait_time_in_us);
+}
+
+static void end(struct gpmi_nfc_data *this)
+{
+	struct resources *r = &this->resources;
+	clk_disable(r->clock);
+}
+
+/* Clears a BCH interrupt. */
+static void clear_bch(struct gpmi_nfc_data *this)
+{
+	struct resources *r = &this->resources;
+	__raw_writel(BM_BCH_CTRL_COMPLETE_IRQ, r->bch_regs + HW_BCH_CTRL_CLR);
+}
+
+/* Returns the Ready/Busy status of the given chip. */
+static int is_ready(struct gpmi_nfc_data *this, unsigned chip)
+{
+	struct resources *r = &this->resources;
+	uint32_t mask;
+	uint32_t reg;
+
+	if (GPMI_IS_MX23(this)) {
+		mask = MX23_BM_GPMI_DEBUG_READY0 << chip;
+		reg = __raw_readl(r->gpmi_regs + HW_GPMI_DEBUG);
+	} else if (GPMI_IS_MX28(this)) {
+		mask = MX28_BF_GPMI_STAT_READY_BUSY(1 << chip);
+		reg = __raw_readl(r->gpmi_regs + HW_GPMI_STAT);
+	} else
+		BUG();
+	return !!(reg & mask);
+}
+
+static int send_command(struct gpmi_nfc_data *this)
+{
+	struct dma_chan *channel = get_dma_chan(this);
+	struct mil *mil	= &this->mil;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl;
+	u32 pio[3];
+
+	/* [1] send out the PIO words */
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__WRITE)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(mil->current_chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_CLE)
+		| BM_GPMI_CTRL0_ADDRESS_INCREMENT
+		| BF_GPMI_CTRL0_XFER_COUNT(mil->command_length);
+	pio[1] = pio[2] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_info("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] send out the COMMAND + ADDRESS string stored in @buffer */
+	sgl = &mil->cmd_sgl;
+
+	sg_init_one(sgl, mil->cmd_buffer, mil->command_length);
+	dma_map_sg(this->dev, sgl, 1, DMA_TO_DEVICE);
+	desc = channel->device->device_prep_slave_sg(channel,
+					sgl, 1, DMA_TO_DEVICE, 1);
+	if (!desc) {
+		pr_info("step 2 error\n");
+		return -1;
+	}
+
+	/* [3] submit the DMA */
+	this->dma_type = DMA_FOR_COMMAND;
+	start_dma_without_bch_irq(this, desc);
+	return 0;
+}
+
+static int send_data(struct gpmi_nfc_data *this)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	struct mil *mil	= &this->mil;
+	uint32_t command_mode;
+	uint32_t address;
+	u32 pio[2];
+
+	/* [1] PIO */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(mil->current_chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(mil->upper_len);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_info("step 1 error\n");
+		return -1;
+	}
+
+	/* [2]  send DMA request */
+	prepare_data_dma(this, DMA_TO_DEVICE);
+	desc = channel->device->device_prep_slave_sg(channel, &mil->data_sgl,
+						1, DMA_TO_DEVICE, 1);
+	if (!desc) {
+		pr_info("step 2 error\n");
+		return -1;
+	}
+	/* [3] submit the DMA */
+	this->dma_type = DMA_FOR_WRITE_DATA;
+	start_dma_without_bch_irq(this, desc);
+	return 0;
+}
+
+static int read_data(struct gpmi_nfc_data *this)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	struct mil *mil = &this->mil;
+	u32 pio[2];
+
+	/* [1] : send PIO */
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(BV_GPMI_CTRL0_COMMAND_MODE__READ)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(mil->current_chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(BV_GPMI_CTRL0_ADDRESS__NAND_DATA)
+		| BF_GPMI_CTRL0_XFER_COUNT(mil->upper_len);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_info("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] : send DMA request */
+	prepare_data_dma(this, DMA_FROM_DEVICE);
+	desc = channel->device->device_prep_slave_sg(channel, &mil->data_sgl,
+						1, DMA_FROM_DEVICE, 1);
+	if (!desc) {
+		pr_info("step 2 error\n");
+		return -1;
+	}
+
+	/* [3] : submit the DMA */
+	this->dma_type = DMA_FOR_READ_DATA;
+	start_dma_without_bch_irq(this, desc);
+	return 0;
+}
+
+static int send_page(struct gpmi_nfc_data *this,
+			dma_addr_t payload, dma_addr_t auxiliary)
+{
+	struct nfc_geometry *geo = &this->nfc_geometry;
+	uint32_t command_mode;
+	uint32_t address;
+	uint32_t ecc_command;
+	uint32_t buffer_mask;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	struct mil *mil = &this->mil;
+	int chip = mil->current_chip;
+	u32 pio[6];
+
+	/* A DMA descriptor that does an ECC page read. */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WRITE;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+	ecc_command  = BV_GPMI_ECCCTRL_ECC_CMD__BCH_ENCODE;
+	buffer_mask  = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE |
+				BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
+
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(0);
+	pio[1] = 0;
+	pio[2] = BM_GPMI_ECCCTRL_ENABLE_ECC
+		| BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
+		| BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
+	pio[3] = geo->page_size_in_bytes;
+	pio[4] = payload;
+	pio[5] = auxiliary;
+
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 0);
+	if (!desc) {
+		pr_info("step 2 error\n");
+		return -1;
+	}
+	this->dma_type = DMA_FOR_WRITE_ECC_PAGE;
+	return start_dma_with_bch_irq(this, desc);
+}
+
+static int read_page(struct gpmi_nfc_data *this,
+				dma_addr_t payload, dma_addr_t auxiliary)
+{
+	struct nfc_geometry *geo = &this->nfc_geometry;
+	uint32_t command_mode;
+	uint32_t address;
+	uint32_t ecc_command;
+	uint32_t buffer_mask;
+	struct dma_async_tx_descriptor *desc;
+	struct dma_chan *channel = get_dma_chan(this);
+	struct mil *mil = &this->mil;
+	int chip = mil->current_chip;
+	u32 pio[6];
+
+	/* [1] Wait for the chip to report ready. */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+	pio[0] =  BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(0);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+				(struct scatterlist *)pio, 2, DMA_NONE, 0);
+	if (!desc) {
+		pr_info("step 1 error\n");
+		return -1;
+	}
+
+	/* [2] Enable the BCH block and read. */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__READ;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+	ecc_command  = BV_GPMI_ECCCTRL_ECC_CMD__BCH_DECODE;
+	buffer_mask  = BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_PAGE
+			| BV_GPMI_ECCCTRL_BUFFER_MASK__BCH_AUXONLY;
+
+	pio[0] =  BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size_in_bytes);
+
+	pio[1] = 0;
+	pio[2] =  BM_GPMI_ECCCTRL_ENABLE_ECC
+		| BF_GPMI_ECCCTRL_ECC_CMD(ecc_command)
+		| BF_GPMI_ECCCTRL_BUFFER_MASK(buffer_mask);
+	pio[3] = geo->page_size_in_bytes;
+	pio[4] = payload;
+	pio[5] = auxiliary;
+	desc = channel->device->device_prep_slave_sg(channel,
+					(struct scatterlist *)pio,
+					ARRAY_SIZE(pio), DMA_NONE, 1);
+	if (!desc) {
+		pr_info("step 2 error\n");
+		return -1;
+	}
+
+	/* [3] Disable the BCH block */
+	command_mode = BV_GPMI_CTRL0_COMMAND_MODE__WAIT_FOR_READY;
+	address      = BV_GPMI_CTRL0_ADDRESS__NAND_DATA;
+
+	pio[0] = BF_GPMI_CTRL0_COMMAND_MODE(command_mode)
+		| BM_GPMI_CTRL0_WORD_LENGTH
+		| BF_GPMI_CTRL0_CS(chip, this)
+		| BF_GPMI_CTRL0_ADDRESS(address)
+		| BF_GPMI_CTRL0_XFER_COUNT(geo->page_size_in_bytes);
+	pio[1] = 0;
+	desc = channel->device->device_prep_slave_sg(channel,
+				(struct scatterlist *)pio, 2, DMA_NONE, 1);
+	if (!desc) {
+		pr_info("step 3 error\n");
+		return -1;
+	}
+
+	/* [4] submit the DMA */
+	this->dma_type = DMA_FOR_READ_ECC_PAGE;
+	return start_dma_with_bch_irq(this, desc);
+}
+
+struct nfc_hal  gpmi_nfc_hal_mxs = {
+	.description                 = "GPMI and BCH for IMX23/IMX28",
+	.max_data_setup_cycles       = (BM_GPMI_TIMING0_DATA_SETUP >>
+						BP_GPMI_TIMING0_DATA_SETUP),
+	.internal_data_setup_in_ns   = 0,
+	.max_sample_delay_factor     = (BM_GPMI_CTRL1_RDN_DELAY >>
+						BP_GPMI_CTRL1_RDN_DELAY),
+	.max_dll_clock_period_in_ns  = 32,
+	.max_dll_delay_in_ns         = 16,
+	.init                        = init_hal,
+	.set_geometry                = set_geometry,
+	.set_timing                  = set_timing,
+	.get_timing                  = get_timing,
+	.exit                        = exit,
+	.begin                       = begin,
+	.end                         = end,
+	.clear_bch                   = clear_bch,
+	.is_ready                    = is_ready,
+	.send_command                = send_command,
+	.read_data                   = read_data,
+	.send_data                   = send_data,
+	.read_page                   = read_page,
+	.send_page                   = send_page,
+};
-- 
1.7.0.4




From u.kleine-koenig at pengutronix.de  Wed Jun 29 04:05:58 2011
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Wed, 29 Jun 2011 10:05:58 +0200
Subject: [PATCH V4 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <1309334082-9501-2-git-send-email-b32955@freescale.com>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
	<1309334082-9501-2-git-send-email-b32955@freescale.com>
Message-ID: <20110629080558.GJ6588@pengutronix.de>

On Wed, Jun 29, 2011 at 03:54:40PM +0800, Huang Shijie wrote:
> add GPMI-NFC support for imx23 and imx28.
> 
> Signed-off-by: Huang Shijie <b32955 at freescale.com>
> ---
>  arch/arm/mach-mxs/Kconfig                 |    2 +
>  arch/arm/mach-mxs/include/mach/gpmi-nfc.h |   71 +++++++++++++++++++++++++++++
>  2 files changed, 73 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-mxs/include/mach/gpmi-nfc.h
> 
> diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
> index 1d3985f..a5b753a 100644
> --- a/arch/arm/mach-mxs/Kconfig
> +++ b/arch/arm/mach-mxs/Kconfig
> @@ -32,6 +32,7 @@ config MACH_MX23EVK
>  	select SOC_IMX23
>  	select MXS_HAVE_AMBA_DUART
>  	select MXS_HAVE_PLATFORM_AUART
> +	select MXS_HAVE_PLATFORM_GPMI_NFC
This symbol is only introduced in patch 2, so the select doesn't belong
here.

>  	select MXS_HAVE_PLATFORM_MXS_MMC
>  	select MXS_HAVE_PLATFORM_MXSFB
>  	help
> @@ -46,6 +47,7 @@ config MACH_MX28EVK
>  	select MXS_HAVE_PLATFORM_AUART
>  	select MXS_HAVE_PLATFORM_FEC
>  	select MXS_HAVE_PLATFORM_FLEXCAN
> +	select MXS_HAVE_PLATFORM_GPMI_NFC
>  	select MXS_HAVE_PLATFORM_MXS_MMC
>  	select MXS_HAVE_PLATFORM_MXSFB
>  	select MXS_OCOTP
> diff --git a/arch/arm/mach-mxs/include/mach/gpmi-nfc.h b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
> new file mode 100644
> index 0000000..25fc605
> --- /dev/null
> +++ b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
> @@ -0,0 +1,71 @@
> +/*
> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +
> +#ifndef __INCLUDE_GPMI_NFC_H
> +#define __INCLUDE_GPMI_NFC_H
Applying the scheme other files in arch/arm/mach-mxs/include/mach this
should read:

	#ifndef __MACH_MXS_GPMI_NFC_H__

(though it's not consistent, so you could choose between

	__MACH_MXS_GPMI_NFC_H__
	__MACH_GPMI_NFC_H__
	__MACH_GPMI_NFC_H

)
> +
> +/* The size of the resource is fixed. */
> +#define RES_SIZE	6
> +
> +/* Resource names for the GPMI NFC driver. */
> +#define GPMI_NFC_GPMI_REGS_ADDR_RES_NAME  "GPMI NFC GPMI Registers"
> +#define GPMI_NFC_GPMI_INTERRUPT_RES_NAME  "GPMI NFC GPMI Interrupt"
> +#define GPMI_NFC_BCH_REGS_ADDR_RES_NAME   "GPMI NFC BCH Registers"
> +#define GPMI_NFC_BCH_INTERRUPT_RES_NAME   "GPMI NFC BCH Interrupt"
> +#define GPMI_NFC_DMA_CHANNELS_RES_NAME    "GPMI NFC DMA Channels"
> +#define GPMI_NFC_DMA_INTERRUPT_RES_NAME   "GPMI NFC DMA Interrupt"
> +
> +/**
> + * struct gpmi_nfc_platform_data - GPMI NFC driver platform data.
> + *
> + * This structure communicates platform-specific information to the GPMI NFC
> + * driver that can't be expressed as resources.
> + *
> + * @platform_init:           A pointer to a function the driver will call to
> + *                           initialize the platform (e.g., set up the pin mux).
> + * @platform_exit:           A pointer to a function the driver will call to
> + *                           exit the platform (e.g., free pins).
> + * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
> + *                           from the NAND Flash device, in nanoseconds.
> + * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
> + *                           from the NAND Flash device, in nanoseconds.
> + * @max_chip_count:          The maximum number of chips for which the driver
> + *                           should configure the hardware. This value most
> + *                           likely reflects the number of pins that are
> + *                           connected to a NAND Flash device. If this is
> + *                           greater than the SoC hardware can support, the
> + *                           driver will print a message and fail to initialize.
> + * @partitions:              An optional pointer to an array of partition
> + *                           descriptions.
> + * @partition_count:         The number of elements in the partitions array.
> + */
> +struct gpmi_nfc_platform_data {
> +	/* SoC hardware information. */
> +	int		(*platform_init)(void);
> +	void		(*platform_exit)(void);
> +
> +	/* NAND Flash information. */
> +	unsigned int	min_prop_delay_in_ns;
> +	unsigned int	max_prop_delay_in_ns;
> +	unsigned int	max_chip_count;
> +
> +	/* Medium information. */
> +	struct mtd_partition *partitions;
> +	unsigned	partition_count;
> +};
> +#endif

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From u.kleine-koenig at pengutronix.de  Wed Jun 29 04:08:44 2011
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Wed, 29 Jun 2011 10:08:44 +0200
Subject: [PATCH V4 2/3] ARM: mxs: add GPMI-NFC device for imx23
In-Reply-To: <1309334082-9501-3-git-send-email-b32955@freescale.com>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
	<1309334082-9501-3-git-send-email-b32955@freescale.com>
Message-ID: <20110629080844.GK6588@pengutronix.de>

On Wed, Jun 29, 2011 at 03:54:41PM +0800, Huang Shijie wrote:
> add the gpmi-nfc device for imx23.
> 
> Signed-off-by: Huang Shijie <b32955 at freescale.com>
> ---
>  arch/arm/mach-mxs/clock-mx23.c                  |    1 +
>  arch/arm/mach-mxs/devices-mx23.h                |    4 +
>  arch/arm/mach-mxs/devices/Kconfig               |    3 +
>  arch/arm/mach-mxs/devices/Makefile              |    1 +
>  arch/arm/mach-mxs/devices/platform-gpmi-nfc.c   |   71 +++++++++++++++++++++++
>  arch/arm/mach-mxs/include/mach/devices-common.h |   10 +++
>  arch/arm/mach-mxs/mach-mx23evk.c                |   37 ++++++++++++
Can you split between arch and machine support please?
(I'd not split between imx28 and imx23, but that's up to you.)

>  7 files changed, 127 insertions(+), 0 deletions(-)
>  create mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
> 
> diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
> index 0163b6d..e190c53 100644
> --- a/arch/arm/mach-mxs/clock-mx23.c
> +++ b/arch/arm/mach-mxs/clock-mx23.c
> @@ -456,6 +456,7 @@ static struct clk_lookup lookups[] = {
>  	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
>  	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
>  	_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
> +	_REGISTER_CLOCK("imx23-gpmi-nfc", NULL, gpmi_clk)
>  };
>  
>  static int clk_misc_init(void)
> diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
> index c6f345f..a9c495d 100644
> --- a/arch/arm/mach-mxs/devices-mx23.h
> +++ b/arch/arm/mach-mxs/devices-mx23.h
> @@ -21,6 +21,10 @@ extern const struct mxs_auart_data mx23_auart_data[] __initconst;
>  #define mx23_add_auart0()		mx23_add_auart(0)
>  #define mx23_add_auart1()		mx23_add_auart(1)
>  
> +extern const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst;
> +#define mx23_add_gpmi_nfc(pdata)	\
> +	mxs_add_gpmi_nfc(pdata, &mx23_gpmi_nfc_data)
> +
>  extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
>  #define mx23_add_mxs_mmc(id, pdata) \
>  	mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)
> diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
> index acf9eea..b42a14b 100644
> --- a/arch/arm/mach-mxs/devices/Kconfig
> +++ b/arch/arm/mach-mxs/devices/Kconfig
> @@ -12,6 +12,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
>  	select HAVE_CAN_FLEXCAN if CAN
>  	bool
>  
> +config MXS_HAVE_PLATFORM_GPMI_NFC
> +	bool
> +
>  config MXS_HAVE_PLATFORM_MXS_I2C
>  	bool
>  
> diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
> index 351915c..972abdc 100644
> --- a/arch/arm/mach-mxs/devices/Makefile
> +++ b/arch/arm/mach-mxs/devices/Makefile
> @@ -3,6 +3,7 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
>  obj-y += platform-dma.o
>  obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
>  obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
> +obj-$(CONFIG_MXS_HAVE_PLATFORM_GPMI_NFC) += platform-gpmi-nfc.o
>  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
>  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
>  obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
> diff --git a/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
> new file mode 100644
> index 0000000..5a68370
> --- /dev/null
> +++ b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
> @@ -0,0 +1,71 @@
> +/*
> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
> + *
> + * 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.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +#include <asm/sizes.h>
> +#include <mach/mx23.h>
> +#include <mach/devices-common.h>
> +
> +#define RES_MEM(soc, _id, _s, _n)				\
> +	{							\
> +		.start = soc ##_## _id ## _BASE_ADDR,		\
> +		.end   = soc ##_## _id ## _BASE_ADDR + (_s) - 1,\
> +		.name  = (_n),					\
> +		.flags = IORESOURCE_MEM,			\
> +	}
> +
> +#define RES_IRQ(soc, _id, _n)			\
> +	{					\
> +		.start = soc ##_INT_## _id,	\
> +		.end   = soc ##_INT_## _id,	\
> +		.name  = (_n),			\
> +		.flags = IORESOURCE_IRQ,	\
> +	}
> +
> +#define RES_DMA(soc, _i_s, _i_e, _n)		\
> +	{					\
> +		.start = soc ##_## _i_s,	\
> +		.end   = soc ##_## _i_e,	\
> +		.name  = (_n),			\
> +		.flags = IORESOURCE_DMA,	\
> +	}
> +
> +#ifdef CONFIG_SOC_IMX23
> +const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst = {
> +	.devid = "imx23-gpmi-nfc",
> +	.res = {
> +		/* GPMI */
> +		RES_MEM(MX23, GPMI, SZ_8K, GPMI_NFC_GPMI_REGS_ADDR_RES_NAME),
> +		RES_IRQ(MX23, GPMI_ATTENTION, GPMI_NFC_GPMI_INTERRUPT_RES_NAME),
> +		/* BCH */
> +		RES_MEM(MX23, BCH, SZ_8K, GPMI_NFC_BCH_REGS_ADDR_RES_NAME),
> +		RES_IRQ(MX23, BCH, GPMI_NFC_BCH_INTERRUPT_RES_NAME),
> +		/* DMA */
> +		RES_DMA(MX23, DMA_GPMI0, DMA_GPMI3,
> +					GPMI_NFC_DMA_CHANNELS_RES_NAME),
> +		RES_IRQ(MX23, GPMI_DMA, GPMI_NFC_DMA_INTERRUPT_RES_NAME),
> +	},
> +};
> +#endif
> +
> +struct platform_device *__init
> +mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
> +		const struct mxs_gpmi_nfc_data *data)
> +{
> +	return mxs_add_platform_device_dmamask(data->devid, -1,
> +				data->res, RES_SIZE,
> +				pdata, sizeof(*pdata), DMA_BIT_MASK(32));
> +}
> diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
> index 812d7a8..e032120 100644
> --- a/arch/arm/mach-mxs/include/mach/devices-common.h
> +++ b/arch/arm/mach-mxs/include/mach/devices-common.h
> @@ -66,6 +66,16 @@ struct platform_device *__init mxs_add_flexcan(
>  		const struct mxs_flexcan_data *data,
>  		const struct flexcan_platform_data *pdata);
>  
> +/* gpmi-nfc */
> +#include <mach/gpmi-nfc.h>
> +struct mxs_gpmi_nfc_data {
> +	const char *devid;
> +	const struct resource res[RES_SIZE];
> +};
> +struct platform_device *__init
> +mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
> +		const struct mxs_gpmi_nfc_data *data);
> +
>  /* i2c */
>  struct mxs_mxs_i2c_data {
>  	int id;
> diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
> index 3c2de33..772b373 100644
> --- a/arch/arm/mach-mxs/mach-mx23evk.c
> +++ b/arch/arm/mach-mxs/mach-mx23evk.c
> @@ -107,6 +107,42 @@ static const iomux_cfg_t mx23evk_pads[] __initconst = {
>  		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
>  };
>  
> +/* gpmi-nfc */
> +#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
> +static iomux_cfg_t mx23evk_gpmi_nfc_pads[] = {
> +	MX23_PAD_GPMI_D00__GPMI_D00 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D01__GPMI_D01 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D02__GPMI_D02 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D03__GPMI_D03 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D04__GPMI_D04 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D05__GPMI_D05 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D06__GPMI_D06 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D07__GPMI_D07 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_WPN__GPMI_WPN | MXS_PAD_GPMI_NFC,
> +	MX23_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
> +	MX23_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
> +	MX23_PAD_GPMI_RDY0__GPMI_RDY0 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_RDY1__GPMI_RDY1 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
> +};
> +
> +static int mx23evk_gpmi_nfc_platform_init(void)
> +{
> +	return mxs_iomux_setup_multiple_pads(mx23evk_gpmi_nfc_pads,
> +				ARRAY_SIZE(mx23evk_gpmi_nfc_pads));
> +}
> +
> +static const
> +struct gpmi_nfc_platform_data mx23evk_gpmi_nfc_data __initconst = {
> +	.platform_init		= mx23evk_gpmi_nfc_platform_init,
> +	.min_prop_delay_in_ns	= 5,
> +	.max_prop_delay_in_ns	= 9,
> +	.max_chip_count		= 1,
> +};
> +
>  /* mxsfb (lcdif) */
>  static struct fb_videomode mx23evk_video_modes[] = {
>  	{
> @@ -166,6 +202,7 @@ static void __init mx23evk_init(void)
>  	else
>  		gpio_set_value(MX23EVK_BL_ENABLE, 1);
>  
> +	mx23_add_gpmi_nfc(&mx23evk_gpmi_nfc_data);
>  	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
>  }
>  
> -- 
> 1.7.0.4
> 
> 
> 

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From b32955 at freescale.com  Wed Jun 29 04:21:26 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 16:21:26 +0800
Subject: [PATCH V4 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <20110629080558.GJ6588@pengutronix.de>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
	<1309334082-9501-2-git-send-email-b32955@freescale.com>
	<20110629080558.GJ6588@pengutronix.de>
Message-ID: <4E0AE086.5030202@freescale.com>

Hi:
> On Wed, Jun 29, 2011 at 03:54:40PM +0800, Huang Shijie wrote:
>> add GPMI-NFC support for imx23 and imx28.
>>
>> Signed-off-by: Huang Shijie<b32955 at freescale.com>
>> ---
>>   arch/arm/mach-mxs/Kconfig                 |    2 +
>>   arch/arm/mach-mxs/include/mach/gpmi-nfc.h |   71 +++++++++++++++++++++++++++++
>>   2 files changed, 73 insertions(+), 0 deletions(-)
>>   create mode 100644 arch/arm/mach-mxs/include/mach/gpmi-nfc.h
>>
>> diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
>> index 1d3985f..a5b753a 100644
>> --- a/arch/arm/mach-mxs/Kconfig
>> +++ b/arch/arm/mach-mxs/Kconfig
>> @@ -32,6 +32,7 @@ config MACH_MX23EVK
>>   	select SOC_IMX23
>>   	select MXS_HAVE_AMBA_DUART
>>   	select MXS_HAVE_PLATFORM_AUART
>> +	select MXS_HAVE_PLATFORM_GPMI_NFC
> This symbol is only introduced in patch 2, so the select doesn't belong
> here.
>
ok. I can move the symbol to this patch.

thanks.
>>   	select MXS_HAVE_PLATFORM_MXS_MMC
>>   	select MXS_HAVE_PLATFORM_MXSFB
>>   	help
>> @@ -46,6 +47,7 @@ config MACH_MX28EVK
>>   	select MXS_HAVE_PLATFORM_AUART
>>   	select MXS_HAVE_PLATFORM_FEC
>>   	select MXS_HAVE_PLATFORM_FLEXCAN
>> +	select MXS_HAVE_PLATFORM_GPMI_NFC
>>   	select MXS_HAVE_PLATFORM_MXS_MMC
>>   	select MXS_HAVE_PLATFORM_MXSFB
>>   	select MXS_OCOTP
>> diff --git a/arch/arm/mach-mxs/include/mach/gpmi-nfc.h b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
>> new file mode 100644
>> index 0000000..25fc605
>> --- /dev/null
>> +++ b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
>> @@ -0,0 +1,71 @@
>> +/*
>> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> + */
>> +
>> +#ifndef __INCLUDE_GPMI_NFC_H
>> +#define __INCLUDE_GPMI_NFC_H
> Applying the scheme other files in arch/arm/mach-mxs/include/mach this
> should read:
>
> 	#ifndef __MACH_MXS_GPMI_NFC_H__
>
> (though it's not consistent, so you could choose between
>
> 	__MACH_MXS_GPMI_NFC_H__
> 	__MACH_GPMI_NFC_H__
> 	__MACH_GPMI_NFC_H
>
> )
thanks.
I will change it in the next version.

Best Regards
Huang Shijie
>> +
>> +/* The size of the resource is fixed. */
>> +#define RES_SIZE	6
>> +
>> +/* Resource names for the GPMI NFC driver. */
>> +#define GPMI_NFC_GPMI_REGS_ADDR_RES_NAME  "GPMI NFC GPMI Registers"
>> +#define GPMI_NFC_GPMI_INTERRUPT_RES_NAME  "GPMI NFC GPMI Interrupt"
>> +#define GPMI_NFC_BCH_REGS_ADDR_RES_NAME   "GPMI NFC BCH Registers"
>> +#define GPMI_NFC_BCH_INTERRUPT_RES_NAME   "GPMI NFC BCH Interrupt"
>> +#define GPMI_NFC_DMA_CHANNELS_RES_NAME    "GPMI NFC DMA Channels"
>> +#define GPMI_NFC_DMA_INTERRUPT_RES_NAME   "GPMI NFC DMA Interrupt"
>> +
>> +/**
>> + * struct gpmi_nfc_platform_data - GPMI NFC driver platform data.
>> + *
>> + * This structure communicates platform-specific information to the GPMI NFC
>> + * driver that can't be expressed as resources.
>> + *
>> + * @platform_init:           A pointer to a function the driver will call to
>> + *                           initialize the platform (e.g., set up the pin mux).
>> + * @platform_exit:           A pointer to a function the driver will call to
>> + *                           exit the platform (e.g., free pins).
>> + * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
>> + *                           from the NAND Flash device, in nanoseconds.
>> + * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
>> + *                           from the NAND Flash device, in nanoseconds.
>> + * @max_chip_count:          The maximum number of chips for which the driver
>> + *                           should configure the hardware. This value most
>> + *                           likely reflects the number of pins that are
>> + *                           connected to a NAND Flash device. If this is
>> + *                           greater than the SoC hardware can support, the
>> + *                           driver will print a message and fail to initialize.
>> + * @partitions:              An optional pointer to an array of partition
>> + *                           descriptions.
>> + * @partition_count:         The number of elements in the partitions array.
>> + */
>> +struct gpmi_nfc_platform_data {
>> +	/* SoC hardware information. */
>> +	int		(*platform_init)(void);
>> +	void		(*platform_exit)(void);
>> +
>> +	/* NAND Flash information. */
>> +	unsigned int	min_prop_delay_in_ns;
>> +	unsigned int	max_prop_delay_in_ns;
>> +	unsigned int	max_chip_count;
>> +
>> +	/* Medium information. */
>> +	struct mtd_partition *partitions;
>> +	unsigned	partition_count;
>> +};
>> +#endif
> Best regards
> Uwe
>




From b32955 at freescale.com  Wed Jun 29 04:24:15 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 16:24:15 +0800
Subject: [PATCH v7 0/3]  add the GPMI controller driver for IMX23/IMX28
In-Reply-To: <1309335878-16678-1-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
Message-ID: <4E0AE12F.6000200@freescale.com>

Hi:

I attach my tested .config file in the attachment.


Best Regards
Huang Shijie

> The general-purpose media interface(GPMI) controller is a flexible interface
> to up to several NAND flashs.
>
> The Bose Ray-Choudhury Hocquenghem(BCH) module is a hardware ECC accelerator.
>
> With the help of BCH, the GPMI controller can choose to do the hardware ECC or
> not.
>
> This driver is a _pure_ MTD NAND controller driver now.
>
> The driver depends on another patch set, you can find them at :
> 	[1] http://marc.info/?l=linux-arm-kernel&m=130933298731899&w=2
> 	[2] http://marc.info/?l=linux-arm-kernel&m=130933302531947&w=2
> 	[3] http://marc.info/?l=linux-arm-kernel&m=130933300431921&w=2
>
> Test environment:
> 	Using imx23 and imx28 boards for test, and burned the ROOTFS
> 	in the nand flash.
>
> 	imx23 :
> 	console=ttyAMA0,115200 mtdparts=gpmi-nfc:20m(boot),-(user)  ubi.mtd=1 root=ubi0:rootfs0 rootfstype=ubifs gpmi_debug_init
>
>         imx28 :
> 	# console=ttyAMA0,115200 mtdparts=gpmi-nfc-main:20m(boot),-(user) ubi.mtd=1 root=ubi0:rootfs0 rootfstype=ubifs gpmi_debug_init
>
>
> v6 --> v7:
> 	[0] remove the function wrapping the clock.
> 	[1] use the module_param() for debugging.
> 	[2] use the new interface of MTD partitions.
> 		replace add_mtd_partitions() with mtd_device_register().
> 	[3] use pr_info() to print log.
> 	[4] add `__devinit` for some functions, etc.
> 	[5] add `gpmi_nfc` to control the GPMI-NFC driver's initialization.
> 	[6] others.
>
> v5 --> v6:
> 	[0] split out the IMX23/IMX28 arch code to separate patches.
> 	[1] fix bug : missing empty item in the end of platform_id array.
> 	[2] inconsistent identation.
> 	[3] others
>
> v4 --> v5:
> 	[0] rename the files.
> 	[1] fix PM bug
> 	[2] remove the rom_helper code, and move the necessary initialization code
> 		to the main file.
> 	[3] change the macros from CPU_IS_* to GPMI_IS_*
> 	[4] remove the default partition layout init code. revert back the 
> 		partition parsing command line code.
> 	[5] others
>
> v3 --> v4:
> 	[0] use the nand_ids{} as the nand database, drop my own database.
> 	[1] remove the patch for DMA enginer, Shawn will submit his own version.
> 	[2] use the platform_id to distinguish different Archs.
> 	[3] fix the strange coding style.
> 	[4] others.
>
> v2 --> v3:
> 	[0] merge the imx23 and imx28 into one file(including the header file).
> 	[1] remove the unuse registers in the headers.
> 	[2] fix DMA bugs
> 	[3] add bus width field to nand_attr{}
> 	[4] others
>
> v1 --> v2:
> 	[0] merge the common files into the gpmi-nfc-main.c
> 	[1] change the code to get the clock.
> 	[2] remove the timing in the nand_device_info{}
> 	[3] fix DMA errors
> 	[4] add the nand_device_info.[ch] to generic code
> 	[5] use the chip->onfi_version for the ONFI nand
> 	[6] useless init
> 	[7] others
>
>
> Huang Shijie (3):
>   MTD : add the common code for GPMI-NFC controller driver
>   MTD : add support for imx23 and imx28
>   MTD : add GPMI-NFC driver in the config and Makefile
>
>  drivers/mtd/nand/Kconfig              |   11 +
>  drivers/mtd/nand/Makefile             |    1 +
>  drivers/mtd/nand/gpmi-nfc/Makefile    |    3 +
>  drivers/mtd/nand/gpmi-nfc/bch-regs.h  |   88 ++
>  drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c  | 2484 +++++++++++++++++++++++++++++++++
>  drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h  |  495 +++++++
>  drivers/mtd/nand/gpmi-nfc/gpmi-regs.h |  163 +++
>  drivers/mtd/nand/gpmi-nfc/hal-mxs.c   |  554 ++++++++
>  8 files changed, 3799 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/Makefile
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/bch-regs.h
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-regs.h
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/hal-mxs.c
>

-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: config
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110629/f8724a78/attachment-0001.ksh>

From grinberg at compulab.co.il  Wed Jun 29 05:00:32 2011
From: grinberg at compulab.co.il (Igor Grinberg)
Date: Wed, 29 Jun 2011 12:00:32 +0300
Subject: [PATCH V3 0/9] pxa3xx_nand: add two chip select support
In-Reply-To: <1309319494-17951-1-git-send-email-leiwen@marvell.com>
References: <1309246361.23597.30.camel@sauron>
	<1309319494-17951-1-git-send-email-leiwen@marvell.com>
Message-ID: <4E0AE9B0.7000908@compulab.co.il>

Hi Lei,

On 06/29/11 06:51, Lei Wen wrote:

> V2:
> Choose to at most keep original pxa3xx_nand_info structure to reduce
> patch size
>
> V3:
> Seperate original one patch into a patch set
>
> Lei Wen (9):
>   MTD: pxa3xx_nand: convert all printk into dev_*
>   MTD: pxa3xx_nand: enable multiple chip select support
>   ARM: aspenite: fix nand platform data
>   ARM: cm-x300: fix nand platform data
>   ARM: colibri-pxa3xx: fix nand platform data
>   ARM: littleton: fix nand platform data
>   ARM: mxm8x10: fix nand platform data
>   ARM: raumfeld: fix nand platform data
>   ARM: zylonite: fix nand platform data

While I agree with Artem, that reviewing patch sets are much more easier,
than a one single big patch, I think you should keep the
"fix nand platform data" changes all in one patch.
All of them do the same change, but for different boards.

>  arch/arm/mach-mmp/aspenite.c                 |    5 +-
>  arch/arm/mach-pxa/cm-x300.c                  |    5 +-
>  arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
>  arch/arm/mach-pxa/littleton.c                |    5 +-
>  arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
>  arch/arm/mach-pxa/raumfeld.c                 |    5 +-
>  arch/arm/mach-pxa/zylonite.c                 |    5 +-
>  arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
>  drivers/mtd/nand/pxa3xx_nand.c               |  512 +++++++++++++++-----------
>  9 files changed, 346 insertions(+), 224 deletions(-)
>
>

-- 
Regards,
Igor.



From b32955 at freescale.com  Wed Jun 29 05:21:00 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 17:21:00 +0800
Subject: [PATCH V4 2/3] ARM: mxs: add GPMI-NFC device for imx23
In-Reply-To: <20110629080844.GK6588@pengutronix.de>
References: <1309334082-9501-1-git-send-email-b32955@freescale.com>
	<1309334082-9501-3-git-send-email-b32955@freescale.com>
	<20110629080844.GK6588@pengutronix.de>
Message-ID: <4E0AEE7C.8090100@freescale.com>

Hi :
> On Wed, Jun 29, 2011 at 03:54:41PM +0800, Huang Shijie wrote:
>> add the gpmi-nfc device for imx23.
>>
>> Signed-off-by: Huang Shijie<b32955 at freescale.com>
>> ---
>>   arch/arm/mach-mxs/clock-mx23.c                  |    1 +
>>   arch/arm/mach-mxs/devices-mx23.h                |    4 +
>>   arch/arm/mach-mxs/devices/Kconfig               |    3 +
>>   arch/arm/mach-mxs/devices/Makefile              |    1 +
>>   arch/arm/mach-mxs/devices/platform-gpmi-nfc.c   |   71 +++++++++++++++++++++++
>>   arch/arm/mach-mxs/include/mach/devices-common.h |   10 +++
>>   arch/arm/mach-mxs/mach-mx23evk.c                |   37 ++++++++++++
> Can you split between arch and machine support please?
> (I'd not split between imx28 and imx23, but that's up to you.)
>
Ok , i will split it in the next version.

Best Regards
Huang Shijie
>>   7 files changed, 127 insertions(+), 0 deletions(-)
>>   create mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
>>
>> diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
>> index 0163b6d..e190c53 100644
>> --- a/arch/arm/mach-mxs/clock-mx23.c
>> +++ b/arch/arm/mach-mxs/clock-mx23.c
>> @@ -456,6 +456,7 @@ static struct clk_lookup lookups[] = {
>>   	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
>>   	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
>>   	_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
>> +	_REGISTER_CLOCK("imx23-gpmi-nfc", NULL, gpmi_clk)
>>   };
>>
>>   static int clk_misc_init(void)
>> diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
>> index c6f345f..a9c495d 100644
>> --- a/arch/arm/mach-mxs/devices-mx23.h
>> +++ b/arch/arm/mach-mxs/devices-mx23.h
>> @@ -21,6 +21,10 @@ extern const struct mxs_auart_data mx23_auart_data[] __initconst;
>>   #define mx23_add_auart0()		mx23_add_auart(0)
>>   #define mx23_add_auart1()		mx23_add_auart(1)
>>
>> +extern const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst;
>> +#define mx23_add_gpmi_nfc(pdata)	\
>> +	mxs_add_gpmi_nfc(pdata,&mx23_gpmi_nfc_data)
>> +
>>   extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
>>   #define mx23_add_mxs_mmc(id, pdata) \
>>   	mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)
>> diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
>> index acf9eea..b42a14b 100644
>> --- a/arch/arm/mach-mxs/devices/Kconfig
>> +++ b/arch/arm/mach-mxs/devices/Kconfig
>> @@ -12,6 +12,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
>>   	select HAVE_CAN_FLEXCAN if CAN
>>   	bool
>>
>> +config MXS_HAVE_PLATFORM_GPMI_NFC
>> +	bool
>> +
>>   config MXS_HAVE_PLATFORM_MXS_I2C
>>   	bool
>>
>> diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
>> index 351915c..972abdc 100644
>> --- a/arch/arm/mach-mxs/devices/Makefile
>> +++ b/arch/arm/mach-mxs/devices/Makefile
>> @@ -3,6 +3,7 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
>>   obj-y += platform-dma.o
>>   obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
>>   obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
>> +obj-$(CONFIG_MXS_HAVE_PLATFORM_GPMI_NFC) += platform-gpmi-nfc.o
>>   obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
>>   obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
>>   obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
>> diff --git a/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
>> new file mode 100644
>> index 0000000..5a68370
>> --- /dev/null
>> +++ b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
>> @@ -0,0 +1,71 @@
>> +/*
>> + * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
>> + *
>> + * 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.
>> + *
>> + * You should have received a copy of the GNU General Public License along
>> + * with this program; if not, write to the Free Software Foundation, Inc.,
>> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
>> + */
>> +#include<asm/sizes.h>
>> +#include<mach/mx23.h>
>> +#include<mach/devices-common.h>
>> +
>> +#define RES_MEM(soc, _id, _s, _n)				\
>> +	{							\
>> +		.start = soc ##_## _id ## _BASE_ADDR,		\
>> +		.end   = soc ##_## _id ## _BASE_ADDR + (_s) - 1,\
>> +		.name  = (_n),					\
>> +		.flags = IORESOURCE_MEM,			\
>> +	}
>> +
>> +#define RES_IRQ(soc, _id, _n)			\
>> +	{					\
>> +		.start = soc ##_INT_## _id,	\
>> +		.end   = soc ##_INT_## _id,	\
>> +		.name  = (_n),			\
>> +		.flags = IORESOURCE_IRQ,	\
>> +	}
>> +
>> +#define RES_DMA(soc, _i_s, _i_e, _n)		\
>> +	{					\
>> +		.start = soc ##_## _i_s,	\
>> +		.end   = soc ##_## _i_e,	\
>> +		.name  = (_n),			\
>> +		.flags = IORESOURCE_DMA,	\
>> +	}
>> +
>> +#ifdef CONFIG_SOC_IMX23
>> +const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst = {
>> +	.devid = "imx23-gpmi-nfc",
>> +	.res = {
>> +		/* GPMI */
>> +		RES_MEM(MX23, GPMI, SZ_8K, GPMI_NFC_GPMI_REGS_ADDR_RES_NAME),
>> +		RES_IRQ(MX23, GPMI_ATTENTION, GPMI_NFC_GPMI_INTERRUPT_RES_NAME),
>> +		/* BCH */
>> +		RES_MEM(MX23, BCH, SZ_8K, GPMI_NFC_BCH_REGS_ADDR_RES_NAME),
>> +		RES_IRQ(MX23, BCH, GPMI_NFC_BCH_INTERRUPT_RES_NAME),
>> +		/* DMA */
>> +		RES_DMA(MX23, DMA_GPMI0, DMA_GPMI3,
>> +					GPMI_NFC_DMA_CHANNELS_RES_NAME),
>> +		RES_IRQ(MX23, GPMI_DMA, GPMI_NFC_DMA_INTERRUPT_RES_NAME),
>> +	},
>> +};
>> +#endif
>> +
>> +struct platform_device *__init
>> +mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
>> +		const struct mxs_gpmi_nfc_data *data)
>> +{
>> +	return mxs_add_platform_device_dmamask(data->devid, -1,
>> +				data->res, RES_SIZE,
>> +				pdata, sizeof(*pdata), DMA_BIT_MASK(32));
>> +}
>> diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
>> index 812d7a8..e032120 100644
>> --- a/arch/arm/mach-mxs/include/mach/devices-common.h
>> +++ b/arch/arm/mach-mxs/include/mach/devices-common.h
>> @@ -66,6 +66,16 @@ struct platform_device *__init mxs_add_flexcan(
>>   		const struct mxs_flexcan_data *data,
>>   		const struct flexcan_platform_data *pdata);
>>
>> +/* gpmi-nfc */
>> +#include<mach/gpmi-nfc.h>
>> +struct mxs_gpmi_nfc_data {
>> +	const char *devid;
>> +	const struct resource res[RES_SIZE];
>> +};
>> +struct platform_device *__init
>> +mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
>> +		const struct mxs_gpmi_nfc_data *data);
>> +
>>   /* i2c */
>>   struct mxs_mxs_i2c_data {
>>   	int id;
>> diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
>> index 3c2de33..772b373 100644
>> --- a/arch/arm/mach-mxs/mach-mx23evk.c
>> +++ b/arch/arm/mach-mxs/mach-mx23evk.c
>> @@ -107,6 +107,42 @@ static const iomux_cfg_t mx23evk_pads[] __initconst = {
>>   		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
>>   };
>>
>> +/* gpmi-nfc */
>> +#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
>> +static iomux_cfg_t mx23evk_gpmi_nfc_pads[] = {
>> +	MX23_PAD_GPMI_D00__GPMI_D00 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D01__GPMI_D01 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D02__GPMI_D02 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D03__GPMI_D03 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D04__GPMI_D04 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D05__GPMI_D05 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D06__GPMI_D06 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D07__GPMI_D07 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_WPN__GPMI_WPN | MXS_PAD_GPMI_NFC,
>> +	MX23_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
>> +	MX23_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
>> +	MX23_PAD_GPMI_RDY0__GPMI_RDY0 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_RDY1__GPMI_RDY1 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
>> +};
>> +
>> +static int mx23evk_gpmi_nfc_platform_init(void)
>> +{
>> +	return mxs_iomux_setup_multiple_pads(mx23evk_gpmi_nfc_pads,
>> +				ARRAY_SIZE(mx23evk_gpmi_nfc_pads));
>> +}
>> +
>> +static const
>> +struct gpmi_nfc_platform_data mx23evk_gpmi_nfc_data __initconst = {
>> +	.platform_init		= mx23evk_gpmi_nfc_platform_init,
>> +	.min_prop_delay_in_ns	= 5,
>> +	.max_prop_delay_in_ns	= 9,
>> +	.max_chip_count		= 1,
>> +};
>> +
>>   /* mxsfb (lcdif) */
>>   static struct fb_videomode mx23evk_video_modes[] = {
>>   	{
>> @@ -166,6 +202,7 @@ static void __init mx23evk_init(void)
>>   	else
>>   		gpio_set_value(MX23EVK_BL_ENABLE, 1);
>>
>> +	mx23_add_gpmi_nfc(&mx23evk_gpmi_nfc_data);
>>   	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
>>   }
>>
>> -- 
>> 1.7.0.4
>>
>>
>>




From w.sang at pengutronix.de  Wed Jun 29 06:06:58 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Wed, 29 Jun 2011 12:06:58 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <1309335878-16678-2-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
Message-ID: <20110629100658.GE1992@pengutronix.de>

Hi Huang,

On Wed, Jun 29, 2011 at 04:24:36PM +0800, Huang Shijie wrote:
> These files contain the common code for the GPMI-NFC driver.
> 
> Signed-off-by: Huang Shijie <b32955 at freescale.com>

Thanks for the update. Good news, the DMA problem is gone now.
I am just running the mtd-stresstest-suite...

> ---
>  drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c | 2484 ++++++++++++++++++++++++++++++++++
>  drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h |  495 +++++++
>  2 files changed, 2979 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
>  create mode 100644 drivers/mtd/nand/gpmi-nfc/gpmi-nfc.h
> 
> diff --git a/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
> new file mode 100644
> index 0000000..187b4a3
> --- /dev/null
> +++ b/drivers/mtd/nand/gpmi-nfc/gpmi-nfc.c
> @@ -0,0 +1,2484 @@
> +/*
> + * Freescale GPMI NFC NAND Flash Driver
> + *
> + * Copyright (C) 2010-2011 Freescale Semiconductor, Inc.
> + * Copyright (C) 2008 Embedded Alley Solutions, 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.
> + *
> + * You should have received a copy of the GNU General Public License along
> + * with this program; if not, write to the Free Software Foundation, Inc.,
> + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
> + */
> +#include "gpmi-nfc.h"

Usually in the kernel, every file includes the stuff it needs for
itself.

> +
> +/* add our owner bbt descriptor */
> +static uint8_t scan_ff_pattern[] = { 0xff };
> +static struct nand_bbt_descr gpmi_bbt_descr = {
> +	.options	= 0,
> +	.offs		= 0,
> +	.len		= 1,
> +	.pattern	= scan_ff_pattern
> +};
> +
> +/* debug control */
> +int gpmi_debug;
> +module_param(gpmi_debug, int, S_IRUGO | S_IWUSR);
> +MODULE_PARM_DESC(gpmi_debug, "print out the debug infomation.");
> +
> +/* enable the gpmi-nfc. */
> +static bool enable_gpmi_nand;

Hmm, disabled by default? I somehow have the impression that it was not
exactly _this_ patch you tested ;) Should go, of course; probably debug
cruft?

> +static int __devinit acquire_interrupt(struct gpmi_nfc_data *this,
> +			const char *resource_name,
> +			irq_handler_t interrupt_handler, int *lno, int *hno)
> +{
> +	struct platform_device *pdev = this->pdev;
> +	struct resource *r;
> +	int err;
> +
> +	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, resource_name);
> +	if (!r) {
> +		pr_info("Can't get resource for %s\n", resource_name);
> +		return -ENXIO;
> +	}
> +
> +	BUG_ON(r->start != r->end);
> +	err = request_irq(r->start, interrupt_handler, 0, resource_name, this);
> +	if (err) {
> +		pr_info("Can't own %s\n", resource_name);
> +		return err;
> +	}
> +
> +	*lno = r->start;
> +	*hno = r->end;
> +	return 0;
> +}

This will not work if max_chip_count > 1, because the irq is already
taken. (Also, I am not convinced of the resource handling, but I need to
delve into the code more, first.)

Back to testing, thanks for the update,

   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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110629/a898b0d1/attachment.sig>

From dedekind1 at gmail.com  Wed Jun 29 06:20:00 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Wed, 29 Jun 2011 13:20:00 +0300
Subject: [PATCH V3 0/9] pxa3xx_nand: add two chip select support
In-Reply-To: <4E0AE9B0.7000908@compulab.co.il>
References: <1309246361.23597.30.camel@sauron>
	<1309319494-17951-1-git-send-email-leiwen@marvell.com>
	<4E0AE9B0.7000908@compulab.co.il>
Message-ID: <1309342805.23597.136.camel@sauron>

On Wed, 2011-06-29 at 12:00 +0300, Igor Grinberg wrote:
> Hi Lei,
> 
> On 06/29/11 06:51, Lei Wen wrote:
> 
> > V2:
> > Choose to at most keep original pxa3xx_nand_info structure to reduce
> > patch size
> >
> > V3:
> > Seperate original one patch into a patch set
> >
> > Lei Wen (9):
> >   MTD: pxa3xx_nand: convert all printk into dev_*
> >   MTD: pxa3xx_nand: enable multiple chip select support
> >   ARM: aspenite: fix nand platform data
> >   ARM: cm-x300: fix nand platform data
> >   ARM: colibri-pxa3xx: fix nand platform data
> >   ARM: littleton: fix nand platform data
> >   ARM: mxm8x10: fix nand platform data
> >   ARM: raumfeld: fix nand platform data
> >   ARM: zylonite: fix nand platform data
> 
> While I agree with Artem, that reviewing patch sets are much more easier,
> than a one single big patch, I think you should keep the
> "fix nand platform data" changes all in one patch.
> All of them do the same change, but for different boards.

Yeah, I did not suggest to split a large patch to a number of
micro-patches plus another large patch :-) My suggestion is to have a
set of easily reviewable patches. If you do the same thing in many
platform data structures, it is reviewable and can be in one patch.

-- 
Best Regards,
Artem Bityutskiy



From w.sang at pengutronix.de  Wed Jun 29 06:33:37 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Wed, 29 Jun 2011 12:33:37 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <20110629100658.GE1992@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
Message-ID: <20110629103337.GF1992@pengutronix.de>

> > +static int __devinit acquire_interrupt(struct gpmi_nfc_data *this,
> > +			const char *resource_name,
> > +			irq_handler_t interrupt_handler, int *lno, int *hno)
> > +{
> > +	struct platform_device *pdev = this->pdev;
> > +	struct resource *r;
> > +	int err;
> > +
> > +	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, resource_name);
> > +	if (!r) {
> > +		pr_info("Can't get resource for %s\n", resource_name);
> > +		return -ENXIO;
> > +	}
> > +
> > +	BUG_ON(r->start != r->end);
> > +	err = request_irq(r->start, interrupt_handler, 0, resource_name, this);
> > +	if (err) {
> > +		pr_info("Can't own %s\n", resource_name);
> > +		return err;
> > +	}
> > +
> > +	*lno = r->start;
> > +	*hno = r->end;
> > +	return 0;
> > +}
> 
> This will not work if max_chip_count > 1, because the irq is already
> taken. (Also, I am not convinced of the resource handling, but I need to

Doh, I wrote that below the wrong codepath. This is another irq here.
Still, the problem exists: When a second channel GPMI channel is
requested, dmaengine will return -EBUSY, because the DMAIRQ is already
taken.

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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110629/c51e4f00/attachment-0001.sig>

From b32955 at freescale.com  Wed Jun 29 06:46:46 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Wed, 29 Jun 2011 18:46:46 +0800
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <20110629103337.GF1992@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
Message-ID: <4E0B0296.6060902@freescale.com>

Hi Wolfram:
>>> +static int __devinit acquire_interrupt(struct gpmi_nfc_data *this,
>>> +			const char *resource_name,
>>> +			irq_handler_t interrupt_handler, int *lno, int *hno)
>>> +{
>>> +	struct platform_device *pdev = this->pdev;
>>> +	struct resource *r;
>>> +	int err;
>>> +
>>> +	r = platform_get_resource_byname(pdev, IORESOURCE_IRQ, resource_name);
>>> +	if (!r) {
>>> +		pr_info("Can't get resource for %s\n", resource_name);
>>> +		return -ENXIO;
>>> +	}
>>> +
>>> +	BUG_ON(r->start != r->end);
>>> +	err = request_irq(r->start, interrupt_handler, 0, resource_name, this);
>>> +	if (err) {
>>> +		pr_info("Can't own %s\n", resource_name);
>>> +		return err;
>>> +	}
>>> +
>>> +	*lno = r->start;
>>> +	*hno = r->end;
>>> +	return 0;
>>> +}
>> This will not work if max_chip_count > 1, because the irq is already
>> taken. (Also, I am not convinced of the resource handling, but I need to
> Doh, I wrote that below the wrong codepath. This is another irq here.
> Still, the problem exists: When a second channel GPMI channel is
> requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> taken.
>
Yes, we should change the DMA code, it is a DMA bug.
I ever submitted a patch about the issue:
http://patchwork.ozlabs.org/patch/87145/

Best Regards
Huang Shijie




> Regards,
>
>    Wolfram
>




From w.sang at pengutronix.de  Wed Jun 29 08:29:42 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Wed, 29 Jun 2011 14:29:42 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <4E0B0296.6060902@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
Message-ID: <20110629122942.GH1992@pengutronix.de>


> > Still, the problem exists: When a second channel GPMI channel is
> > requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> > taken.
> >
> Yes, we should change the DMA code, it is a DMA bug.
> I ever submitted a patch about the issue:
> http://patchwork.ozlabs.org/patch/87145/

That approach was rejected because it would register the same handler
n-times where one time would do. Your other approach puts too much
mach-specific details into the driver IMO and probably won't scale very
well. Maybe we should add something to the private dma_data (like flags
indicating SHARED) and then do some refcounting?

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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110629/7f3e7426/attachment.sig>

From linux at arm.linux.org.uk  Wed Jun 29 08:38:03 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 29 Jun 2011 13:38:03 +0100
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <1309335878-16678-2-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
Message-ID: <20110629123803.GM21898@n2100.arm.linux.org.uk>

On Wed, Jun 29, 2011 at 04:24:36PM +0800, Huang Shijie wrote:
> +	dma_addr_t destination_phys = ~0;
> +
> +	if (virt_addr_valid(destination))
> +		destination_phys = dma_map_single(dev, destination,
> +						length, DMA_FROM_DEVICE);
> +
> +	if (dma_mapping_error(dev, destination_phys)) {

This is buggy.  There is no guarantee that we'll keep using ~0 as the
value for dma_mapping_error().  Please don't rely on this, but instead
code this better to avoid having to play these games.

> +static int send_page_prepare(struct gpmi_nfc_data *this,
> +			const void *source, unsigned length,
> +			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
> +			const void **use_virt, dma_addr_t *use_phys)
> +{
> +	dma_addr_t source_phys = ~0;
> +	struct device *dev = this->dev;
> +
> +	if (virt_addr_valid(source))
> +		source_phys = dma_map_single(dev,
> +				(void *)source, length, DMA_TO_DEVICE);
> +
> +	if (dma_mapping_error(dev, source_phys)) {

Ditto.


From linux at arm.linux.org.uk  Wed Jun 29 08:42:14 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 29 Jun 2011 13:42:14 +0100
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <20110629122942.GH1992@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
Message-ID: <20110629124214.GN21898@n2100.arm.linux.org.uk>

On Wed, Jun 29, 2011 at 02:29:42PM +0200, Wolfram Sang wrote:
> 
> > > Still, the problem exists: When a second channel GPMI channel is
> > > requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> > > taken.
> > >
> > Yes, we should change the DMA code, it is a DMA bug.
> > I ever submitted a patch about the issue:
> > http://patchwork.ozlabs.org/patch/87145/
> 
> That approach was rejected because it would register the same handler
> n-times where one time would do. Your other approach puts too much
> mach-specific details into the driver IMO and probably won't scale very
> well. Maybe we should add something to the private dma_data (like flags
> indicating SHARED) and then do some refcounting?

Why not just request the interrupt once when the mxs-dma stuff probes,
rather than requesting it every time a channel is allocated?

The interrupt handler itself is written to process all channels on the
device anyway, so you only need it registered once.  Using IRQF_SHARED
to register multiple identical handlers is just idiotic, and adding
refcounting is needless complexity.


From w.sang at pengutronix.de  Wed Jun 29 08:49:02 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Wed, 29 Jun 2011 14:49:02 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <20110629124214.GN21898@n2100.arm.linux.org.uk>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
	<20110629124214.GN21898@n2100.arm.linux.org.uk>
Message-ID: <20110629124902.GI1992@pengutronix.de>

On Wed, Jun 29, 2011 at 01:42:14PM +0100, Russell King - ARM Linux wrote:
> On Wed, Jun 29, 2011 at 02:29:42PM +0200, Wolfram Sang wrote:
> > 
> > > > Still, the problem exists: When a second channel GPMI channel is
> > > > requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> > > > taken.
> > > >
> > > Yes, we should change the DMA code, it is a DMA bug.
> > > I ever submitted a patch about the issue:
> > > http://patchwork.ozlabs.org/patch/87145/
> > 
> > That approach was rejected because it would register the same handler
> > n-times where one time would do. Your other approach puts too much
> > mach-specific details into the driver IMO and probably won't scale very
> > well. Maybe we should add something to the private dma_data (like flags
> > indicating SHARED) and then do some refcounting?
> 
> Why not just request the interrupt once when the mxs-dma stuff probes,
> rather than requesting it every time a channel is allocated?

It is only the NAND DMA channels which share one dma-irq. All other
channels have a seperate interrupt.

-- 
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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110629/4ebf5f45/attachment.sig>

From nicolas.ferre at atmel.com  Wed Jun 29 09:09:59 2011
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Wed, 29 Jun 2011 15:09:59 +0200
Subject: [RFC PATCH] MTD: atmel_nand: optimize read/write buffer	functions
In-Reply-To: <20110628145937.GG21898@n2100.arm.linux.org.uk>
References: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>
	<20110628111043.GH6588@pengutronix.de>
	<20110628145937.GG21898@n2100.arm.linux.org.uk>
Message-ID: <4E0B2427.9020202@atmel.com>

Le 28/06/2011 16:59, Russell King - ARM Linux :
> On Tue, Jun 28, 2011 at 01:10:43PM +0200, Uwe Kleine-K?nig wrote:
>>> @@ -265,33 +234,53 @@ err_buf:
>>>  static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
>>>  {
>>>  	struct nand_chip *chip = mtd->priv;
>>> -	struct atmel_nand_host *host = chip->priv;
>>> +	u32 align;
>>> +	u8 *pbuf;
>>>  
>>>  	if (use_dma && len > mtd->oobsize)
>>>  		/* only use DMA for bigger than oob size: better performances */
>>>  		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
>>>  			return;
>>>  
>>> -	if (host->board->bus_width_16)
>>> -		atmel_read_buf16(mtd, buf, len);
>>> -	else
>>> -		atmel_read_buf8(mtd, buf, len);
>>> +	/* if no DMA operation possible, use PIO */
>>> +	pbuf = buf;
>>> +	align = 0x03 & ((unsigned)pbuf);
>>> +
>>> +	if (align) {
>>> +		u32 align_len = 4 - align;
>>> +
>>> +		/* non aligned buffer: re-align to next word boundary */
>>> +		ioread8_rep(chip->IO_ADDR_R, pbuf, align_len);
>>> +		pbuf += align_len;
>>> +		len -= align_len;
>>> +	}
>>> +	memcpy((void *)pbuf, chip->IO_ADDR_R, len);
>> I think you don't need to cast to (void *). I think you need to cast the
>> 2nd parameter instead because sparse don't like you passing an void
>> __iomem *.
>> Is it correct to read from chip->IO_ADDR_R, don't you need
>> chip->IO_ADDR_R + align_len? Taking this into account, does it really
>> help to align pbuf?
> 
> I think you need to read Documentation/bus-virt-phys-mapping.txt,
> particularly the part after "NOTE NOTE NOTE".
> 
> Dereferencing ioremap'd memory is not permitted.  That includes passing
> it to memcpy.  Even with a cast.

So that means that I should use memcpy_fromio() even if the code if far
less optimized.

Shouldn't I re-implement some kind of IO copying function to deal with
this IO memory so that I could take advantage of 8 words bursts?

Best regards,
-- 
Nicolas Ferre



From jwboyer at gmail.com  Wed Jun 29 09:22:26 2011
From: jwboyer at gmail.com (Josh Boyer)
Date: Wed, 29 Jun 2011 09:22:26 -0400
Subject: [PATCH 02/10] mtd-tests: io_paral: build error,
	"variable length strings"
In-Reply-To: <1309199247-19248-3-git-send-email-computersforpeace@gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<1309199247-19248-3-git-send-email-computersforpeace@gmail.com>
Message-ID: <BANLkTin6-=8sH8HazumX577-94TRk5Wi2g@mail.gmail.com>

On Mon, Jun 27, 2011 at 2:27 PM, Brian Norris
<computersforpeace at gmail.com> wrote:
> Some compilers will complain about use of strlen() within a static array
> size declaration. For this type of string, "sizeof() - 1" is equivalent
> and prevents the build error.
>
> Error:
>
> ? io_paral.c:48:13: error: variably modified 'vol_nodes' at file scope

Out of curiosity, which compiler does that?  Newer versions of GCC, or
some other compiler altogether?

josh


From linux at arm.linux.org.uk  Wed Jun 29 09:31:24 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Wed, 29 Jun 2011 14:31:24 +0100
Subject: [RFC PATCH] MTD: atmel_nand: optimize read/write buffer functions
In-Reply-To: <4E0B2427.9020202@atmel.com>
References: <1309261856-27402-1-git-send-email-nicolas.ferre@atmel.com>
	<20110628111043.GH6588@pengutronix.de>
	<20110628145937.GG21898@n2100.arm.linux.org.uk>
	<4E0B2427.9020202@atmel.com>
Message-ID: <20110629133124.GO21898@n2100.arm.linux.org.uk>

On Wed, Jun 29, 2011 at 03:09:59PM +0200, Nicolas Ferre wrote:
> Le 28/06/2011 16:59, Russell King - ARM Linux :
> > I think you need to read Documentation/bus-virt-phys-mapping.txt,
> > particularly the part after "NOTE NOTE NOTE".
> > 
> > Dereferencing ioremap'd memory is not permitted.  That includes passing
> > it to memcpy.  Even with a cast.
> 
> So that means that I should use memcpy_fromio() even if the code if far
> less optimized.
> 
> Shouldn't I re-implement some kind of IO copying function to deal with
> this IO memory so that I could take advantage of 8 words bursts?

You could improve the IO memcpy/set etc implementations, which are
currently mostly unloved - I think that's a catch-22 which really needs
solving.  They're not efficient because no one has taken the time to use
them, and everyone's avoiding them because they're not very efficient.
So, as no one's using them no one's motivated to improve them.


From shawn.guo at freescale.com  Wed Jun 29 10:00:39 2011
From: shawn.guo at freescale.com (Shawn Guo)
Date: Wed, 29 Jun 2011 22:00:39 +0800
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <20110629122942.GH1992@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
Message-ID: <20110629140038.GB25931@S2100-06.ap.freescale.net>

On Wed, Jun 29, 2011 at 02:29:42PM +0200, Wolfram Sang wrote:
> 
> > > Still, the problem exists: When a second channel GPMI channel is
> > > requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> > > taken.
> > >
> > Yes, we should change the DMA code, it is a DMA bug.
> > I ever submitted a patch about the issue:
> > http://patchwork.ozlabs.org/patch/87145/
> 
> That approach was rejected because it would register the same handler
> n-times where one time would do. Your other approach puts too much
> mach-specific details into the driver IMO and probably won't scale very
> well. Maybe we should add something to the private dma_data (like flags
> indicating SHARED) and then do some refcounting?
> 
I would suggest leave this gpmi specific quirk to gpmi driver to sort
out.  With the following mxs-dma change, it should work if gpmi driver
can pass the valid gpmi irq number for only one gpmi channel, and -1
for all others.

diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 88aad4f..ea27002 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -327,10 +327,12 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)

        memset(mxs_chan->ccw, 0, PAGE_SIZE);

-       ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
-                               0, "mxs-dma", mxs_dma);
-       if (ret)
-               goto err_irq;
+       if (mxs_chan->chan_irq >= 0) {
+               ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
+                                       0, "mxs-dma", mxs_dma);
+               if (ret)
+                       goto err_irq;
+       }

        ret = clk_enable(mxs_dma->clk);
        if (ret)

-- 
Regards,
Shawn



From ivan.djelic at parrot.com  Wed Jun 29 09:59:34 2011
From: ivan.djelic at parrot.com (Ivan Djelic)
Date: Wed, 29 Jun 2011 15:59:34 +0200
Subject: [PATCH 2/6] nand_wait : warn if the nand is busy on exit
In-Reply-To: <1309287916.7411.9.camel@koala>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>
	<1309247836.23597.42.camel@sauron> <4E09ED56.2070704@parrot.com>
	<1309287916.7411.9.camel@koala>
Message-ID: <20110629135934.GA18102@parrot.com>

On Tue, Jun 28, 2011 at 08:05:14PM +0100, Artem Bityutskiy wrote:
> On Tue, 2011-06-28 at 17:03 +0200, Matthieu CASTET wrote:
> > Artem Bityutskiy a ?crit :
> > > On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> > >> This patch allow to detect buggy driver/hardware with
> > >> bad RnB (dev_ready) management.
> > >> This check cost nothing and could help to detect bugs.
> > >>
> > >> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> > >> ---
> > >>  drivers/mtd/nand/nand_base.c |    2 ++
> > >>  1 files changed, 2 insertions(+), 0 deletions(-)
> > >>
> > >> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> > >> index a3c7fd3..095dfea 100644
> > >> --- a/drivers/mtd/nand/nand_base.c
> > >> +++ b/drivers/mtd/nand/nand_base.c
> > >> @@ -885,6 +885,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
> > >>  	led_trigger_event(nand_led_trigger, LED_OFF);
> > >>  
> > >>  	status = (int)chip->read_byte(mtd);
> > >> +	/* This can happen if in case of timeout or buggy dev_ready */
> > >> +	WARN_ON(!(status & NAND_STATUS_READY));
> > >>  	return status;
> > > 
> > > This seem to completely miss the chip->dev_ready != NULL case, e.g.,
> > > piece of code above is like this
> > > 
> > >                 while (time_before(jiffies, timeo)) {
> > >                         if (chip->dev_ready) {
> > >                                 if (chip->dev_ready(mtd))
> > >                                         break;
> > >                         } else {
> > >                                 if (chip->read_byte(mtd) & NAND_STATUS_READY)
> > >                                         break;
> > >                         }
> > >                         cond_resched();
> > >                 }
> > > 
> > Sorry, I don't understand what you mean.
> > 
> > We don't care what's done in the loop (chip->dev_ready != NULL or, not). We only
> > check when the loop exit, that READY bit is set in the status.
> 
> Well, the logic is suspicious.
> 
> 1. For NAND with chip->dev_ready != NULL, why NAND_STATUS_READY should
> be set? We do not check for this in the loop.
> 
> 2. For NAND with chip->dev_ready != NULL, if NAND_STATUS_READY has to be
> set at the end, why wouldn't we drop this chip_ready part completely? We
> could just loop while NAND_STATUS_READY is not set.
> 
> Isn't this strange?

Not really. There are 2 methods to wait for an erase/program command completion:

1. Wait until nand RnB pin goes high (that's what chip->dev_ready usually does)
2. Poll the device: send a status (0x70) command and read status byte in a loop
   until bit NAND_STATUS_READY is set

In all cases, you should send a status command after completion, to check if
the operation was successful. And if the operation completed, the status should
have bit NAND_STATUS_READY set.

Method 1 is optimal, you can often use an interrupt to signal completion, and
no cpu cycles are lost in a polling loop. But flaky hardware (bad pull-ups) or
bad gpio configuration can make it unreliable.

Method 2 is the safest, it always works, but it is less efficient.

Here, Matthieu wants to detect cases where method 1 is unreliable or a timeout
occurs (e.g. somebody forgot to put a nand device on the board :).
Both conditions are not expected on working hardware.

Another option (that I used on other systems) is to systematically perform
method 1 first (if chip->dev_ready != NULL), _then_ method 2.
If method 1 works as expected, then the polling loop in method 2 finishes
immediately because nand status already has bit NAND_STATUS_READY set.

--
Best Regards,

Ivan


From w.sang at pengutronix.de  Wed Jun 29 10:15:57 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Wed, 29 Jun 2011 16:15:57 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <20110629140038.GB25931@S2100-06.ap.freescale.net>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
	<20110629140038.GB25931@S2100-06.ap.freescale.net>
Message-ID: <20110629141557.GK1992@pengutronix.de>

On Wed, Jun 29, 2011 at 10:00:39PM +0800, Shawn Guo wrote:
> On Wed, Jun 29, 2011 at 02:29:42PM +0200, Wolfram Sang wrote:
> > 
> > > > Still, the problem exists: When a second channel GPMI channel is
> > > > requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> > > > taken.
> > > >
> > > Yes, we should change the DMA code, it is a DMA bug.
> > > I ever submitted a patch about the issue:
> > > http://patchwork.ozlabs.org/patch/87145/
> > 
> > That approach was rejected because it would register the same handler
> > n-times where one time would do. Your other approach puts too much
> > mach-specific details into the driver IMO and probably won't scale very
> > well. Maybe we should add something to the private dma_data (like flags
> > indicating SHARED) and then do some refcounting?
> > 
> I would suggest leave this gpmi specific quirk to gpmi driver to sort
> out.  With the following mxs-dma change, it should work if gpmi driver
> can pass the valid gpmi irq number for only one gpmi channel, and -1
> for all others.

...which brings us right into the 'NO_IRQ is 0' discussion :)

Other than that, [thinking loud] this will help if all irq-sharing
channels are handled by the same driver. If not, we would just add
IRQF_SHARED (hopefully this will never be needed). Yup, sounds
reasonable to me. Will give it a second thought later, though.

-- 
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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110629/efe4df09/attachment.sig>

From shawn.guo at freescale.com  Wed Jun 29 10:37:02 2011
From: shawn.guo at freescale.com (Shawn Guo)
Date: Wed, 29 Jun 2011 22:37:02 +0800
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <20110629141557.GK1992@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
	<20110629140038.GB25931@S2100-06.ap.freescale.net>
	<20110629141557.GK1992@pengutronix.de>
Message-ID: <20110629143701.GC25931@S2100-06.ap.freescale.net>

On Wed, Jun 29, 2011 at 04:15:57PM +0200, Wolfram Sang wrote:
> On Wed, Jun 29, 2011 at 10:00:39PM +0800, Shawn Guo wrote:
> > On Wed, Jun 29, 2011 at 02:29:42PM +0200, Wolfram Sang wrote:
> > > 
> > > > > Still, the problem exists: When a second channel GPMI channel is
> > > > > requested, dmaengine will return -EBUSY, because the DMAIRQ is already
> > > > > taken.
> > > > >
> > > > Yes, we should change the DMA code, it is a DMA bug.
> > > > I ever submitted a patch about the issue:
> > > > http://patchwork.ozlabs.org/patch/87145/
> > > 
> > > That approach was rejected because it would register the same handler
> > > n-times where one time would do. Your other approach puts too much
> > > mach-specific details into the driver IMO and probably won't scale very
> > > well. Maybe we should add something to the private dma_data (like flags
> > > indicating SHARED) and then do some refcounting?
> > > 
> > I would suggest leave this gpmi specific quirk to gpmi driver to sort
> > out.  With the following mxs-dma change, it should work if gpmi driver
> > can pass the valid gpmi irq number for only one gpmi channel, and -1
> > for all others.
> 
> ...which brings us right into the 'NO_IRQ is 0' discussion :)
> 
Though I do not know what it means exactly, number 0 is an valid IRQ
on both mx23 and mx28 (see mx23.h and mx28.h).

> Other than that, [thinking loud] this will help if all irq-sharing
> channels are handled by the same driver. If not, we would just add
> IRQF_SHARED (hopefully this will never be needed). Yup, sounds
> reasonable to me. Will give it a second thought later, though.
> 
GPMI is the only mxs-dma user that gets irq-sharing.  So yes, all
irq-sharing channels are handled by the same driver, gpmi-nfc :)

-- 
Regards,
Shawn



From nicolas.ferre at atmel.com  Wed Jun 29 12:41:16 2011
From: nicolas.ferre at atmel.com (Nicolas Ferre)
Date: Wed, 29 Jun 2011 18:41:16 +0200
Subject: [PATCH] MTD: atmel_nand: fix wrong use of 0 as NULL
Message-ID: <1309365676-19210-1-git-send-email-nicolas.ferre@atmel.com>

Fixing this error:
atmel_nand.c:718:20: warning: Using plain integer as NULL pointer

Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
---
 drivers/mtd/nand/atmel_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/atmel_nand.c b/drivers/mtd/nand/atmel_nand.c
index b300705..bbdf062 100644
--- a/drivers/mtd/nand/atmel_nand.c
+++ b/drivers/mtd/nand/atmel_nand.c
@@ -593,7 +593,7 @@ static int __init atmel_nand_probe(struct platform_device *pdev)
 
 		dma_cap_zero(mask);
 		dma_cap_set(DMA_MEMCPY, mask);
-		host->dma_chan = dma_request_channel(mask, 0, NULL);
+		host->dma_chan = dma_request_channel(mask, NULL, NULL);
 		if (!host->dma_chan) {
 			dev_err(host->dev, "Failed to request DMA channel\n");
 			use_dma = 0;
-- 
1.7.3



From computersforpeace at gmail.com  Wed Jun 29 11:45:10 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 29 Jun 2011 08:45:10 -0700
Subject: [PATCH 02/10] mtd-tests: io_paral: build error,
	"variable length strings"
In-Reply-To: <BANLkTin6-=8sH8HazumX577-94TRk5Wi2g@mail.gmail.com>
References: <1309199247-19248-1-git-send-email-computersforpeace@gmail.com>
	<1309199247-19248-3-git-send-email-computersforpeace@gmail.com>
	<BANLkTin6-=8sH8HazumX577-94TRk5Wi2g@mail.gmail.com>
Message-ID: <BANLkTimcJZ14Uxs0d0Tf4ObmkH-BfehwhQ@mail.gmail.com>

On Wed, Jun 29, 2011 at 6:22 AM, Josh Boyer <jwboyer at gmail.com> wrote:
> On Mon, Jun 27, 2011 at 2:27 PM, Brian Norris
> <computersforpeace at gmail.com> wrote:
>> Some compilers will complain about use of strlen() within a static array
>> size declaration. For this type of string, "sizeof() - 1" is equivalent
>> and prevents the build error.
>>
>> Error:
>>
>> ? io_paral.c:48:13: error: variably modified 'vol_nodes' at file scope
>
> Out of curiosity, which compiler does that? ?Newer versions of GCC, or
> some other compiler altogether?

I think it's just newer versions of GCC. I found the error on MIPS GCC
on versions 4.5.2 and 4.5.3. It didn't occur on MIPS or x86_64 for
version 4.4.3.

Brian


From computersforpeace at gmail.com  Wed Jun 29 12:09:29 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 29 Jun 2011 09:09:29 -0700
Subject: [PATCH v2] mtdinfo: remove -m leftovers
In-Reply-To: <1309327350.23597.96.camel@sauron>
References: <1309327350.23597.96.camel@sauron>
Message-ID: <1309363769-7904-1-git-send-email-computersforpeace@gmail.com>

From: Artem Bityutskiy <dedekind1 at gmail.com>

Looks OK to me, except it seems you did everything but actually removing
the field in struct args :) So here's a quick v2 from me...

From: Artem Bityutskiy <dedekind1 at gmail.com>
Date: Wed, 29 Jun 2011 08:56:39 +0300
Subject: [PATCH v2] mtdinfo: remove -m leftovers

We have removed the -m option, but did not remove args.mtdn which represents
the -m parameters. Kill args.mtdn as well.

Signed-off-by: Artem Bityutskiy <dedekind1 at gmail.com>
Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 ubi-utils/mtdinfo.c |   24 +++++++++---------------
 1 files changed, 9 insertions(+), 15 deletions(-)

diff --git a/ubi-utils/mtdinfo.c b/ubi-utils/mtdinfo.c
index dd5da53..e72d69e 100644
--- a/ubi-utils/mtdinfo.c
+++ b/ubi-utils/mtdinfo.c
@@ -38,7 +38,6 @@
 
 /* The variables below are set by command line arguments */
 struct args {
-	int mtdn;
 	unsigned int all:1;
 	unsigned int ubinfo:1;
 	unsigned int map:1;
@@ -46,7 +45,6 @@ struct args {
 };
 
 static struct args args = {
-	.mtdn = -1,
 	.ubinfo = 0,
 	.all = 0,
 	.node = NULL,
@@ -128,10 +126,8 @@ static int parse_opt(int argc, char * const argv[])
 	else if (optind < argc)
 		return errmsg("more then one MTD device specified (use -h for help)");
 
-	if (args.all && (args.node || args.mtdn != -1)) {
-		args.mtdn = -1;
+	if (args.all && args.node)
 		args.node = NULL;
-	}
 
 	if (args.map && !args.node)
 		return errmsg("-M requires MTD device node name");
@@ -153,8 +149,7 @@ static int translate_dev(libmtd_t libmtd, const char *node)
 				  "device \"%s\"", node);
 	}
 
-	args.mtdn = mtd.mtd_num;
-	return 0;
+	return mtd.mtd_num;
 }
 
 static void print_ubi_info(const struct mtd_info *mtd_info,
@@ -406,20 +401,19 @@ int main(int argc, char * const argv[])
 		return sys_errmsg("cannot get MTD information");
 	}
 
-	if (args.node) {
+	if (!args.all) {
+		int mtdn;
+
 		/*
 		 * A character device was specified, translate this to MTD
 		 * device number.
 		 */
-		err = translate_dev(libmtd, args.node);
-		if (err)
+		mtdn = translate_dev(libmtd, args.node);
+		if (mtdn < 0)
 			goto out_libmtd;
-	}
-
-	if (args.mtdn == -1)
+		err = print_dev_info(libmtd, &mtd_info, mtdn);
+	} else
 		err = print_general_info(libmtd, &mtd_info, args.all);
-	else
-		err = print_dev_info(libmtd, &mtd_info, args.mtdn);
 	if (err)
 		goto out_libmtd;
 
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 29 12:38:05 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 29 Jun 2011 09:38:05 -0700
Subject: [PATCH 5/6] nand_flash_detect_onfi propagate busw info
In-Reply-To: <1309105616-3609-5-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-5-git-send-email-matthieu.castet@parrot.com>
Message-ID: <BANLkTi=FGiGVgv0+_Kt3eGamEefdRtdnEQ@mail.gmail.com>

On Sun, Jun 26, 2011 at 9:26 AM, Matthieu CASTET
<matthieu.castet at parrot.com> wrote:
> there is a bug in nand_flash_detect_onfi, busw need to be passed
> by pointer to return it.
>
> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> ---
> ?drivers/mtd/nand/nand_base.c | ? ?8 ++++----
> ?1 files changed, 4 insertions(+), 4 deletions(-)

Acked-by: Brian Norris <computersforpeace at gmail.com>


From computersforpeace at gmail.com  Wed Jun 29 12:37:39 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 29 Jun 2011 09:37:39 -0700
Subject: [PATCH 6/6] add NAND_BUSWIDTH_AUTO
In-Reply-To: <1309105616-3609-6-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-6-git-send-email-matthieu.castet@parrot.com>
Message-ID: <BANLkTinwT=63yoqfJnab6RUSB4wL-92iEg@mail.gmail.com>

Hi,

I have a few comments below.

On Sun, Jun 26, 2011 at 9:26 AM, Matthieu CASTET
<matthieu.castet at parrot.com> wrote:
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -3096,11 +3096,16 @@ ident_done:
...
> + ? ? ? if (chip->options & NAND_BUSWIDTH_AUTO) {
> + ? ? ? ? ? ? ? BUG_ON(chip->options & NAND_BUSWIDTH_16);
> + ? ? ? ? ? ? ? chip->options |= busw;
> + ? ? ? ? ? ? ? nand_set_defaults(chip, busw);
> + ? ? ? }

Doesn't this get called after nand_set_defaults() is already called?
(see nand_scan_ident) If so, then changing the buswidth here won't
actually affect any of the function assignments. That's probably not
your expected behavior, is it?

> --- a/include/linux/mtd/nand.h
> +++ b/include/linux/mtd/nand.h
> @@ -240,6 +240,11 @@ typedef enum {
...
> +/* autodetect nand buswidth with readid. This suppose the driver will
> + * configure the hardware has 8 bit in nand_scan_ident, and update
> + * configuration before calling nand_scan_tail
> + */

This is not the correct multi-line comment format.

> +#define NAND_BUSWIDTH_AUTO ? ? ? ? ? ? ? ? ? ? 0x02000000

I recently did some revamping of a lot of these flags, so the
numbering has all changed in Artem's staging tree, l2-mtd-2.6.git.
Assuming both our patches are taken into mainline, it'd probably be
good if you rebased on the l2 tree and choose a new bit value for this
flag. AFAICT it'd be good like:

+#define NAND_BUSWIDTH_AUTO                     0x00080000

Brian


From scottwood at freescale.com  Wed Jun 29 12:43:29 2011
From: scottwood at freescale.com (Scott Wood)
Date: Wed, 29 Jun 2011 11:43:29 -0500
Subject: [PATCH 2/2] mtd/nand : workaround for Freescale FCM to support
	large-page Nand chip
In-Reply-To: <1309328529.23597.106.camel@sauron>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
	<1309225852-1664-2-git-send-email-b35362@freescale.com>
	<1309328529.23597.106.camel@sauron>
Message-ID: <20110629114329.154aaef2@schlenkerla.am.freescale.net>

On Wed, 29 Jun 2011 09:22:04 +0300
Artem Bityutskiy <dedekind1 at gmail.com> wrote:

> On Tue, 2011-06-28 at 09:50 +0800, b35362 at freescale.com wrote:
> > +	/* Hack for supporting the flash chip whose writesize is
> > +	 * larger than 2K bytes.
> > +	 */
> 
> Please, use proper kernel multi-line comments. Please, make sure
> checkpatch.pl does not generate 13 errors with this patch.

Most of the checkpatch complaints are about existing style in the file --
particularly, the use of tabs only for indentation, with spaces used for
alignment beyond the indentation point.

-Scott



From scottwood at freescale.com  Wed Jun 29 12:45:58 2011
From: scottwood at freescale.com (Scott Wood)
Date: Wed, 29 Jun 2011 11:45:58 -0500
Subject: [PATCH 1/2] mtd/nand : don't free the global data
	fsl_lbc_ctrl_dev->nand in fsl_elbc_chip_remove()
In-Reply-To: <1309328435.23597.104.camel@sauron>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
	<1309328435.23597.104.camel@sauron>
Message-ID: <20110629114558.13975519@schlenkerla.am.freescale.net>

On Wed, 29 Jun 2011 09:20:25 +0300
Artem Bityutskiy <dedekind1 at gmail.com> wrote:

> On Tue, 2011-06-28 at 09:50 +0800, b35362 at freescale.com wrote:
> > From: Liu Shuo <b35362 at freescale.com>
> > 
> > The global data fsl_lbc_ctrl_dev->nand don't have to be freed in
> > fsl_elbc_chip_remove(). The right place to do that is in fsl_elbc_nand_remove()
> > if elbc_fcm_ctrl->counter is zero.
> > 
> > Signed-off-by: Liu Shuo <b35362 at freescale.com>
> > ---
> >  drivers/mtd/nand/fsl_elbc_nand.c |    1 -
> >  1 files changed, 0 insertions(+), 1 deletions(-)
> > 
> > diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> > index 0bb254c..a212116 100644
> > --- a/drivers/mtd/nand/fsl_elbc_nand.c
> > +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> > @@ -829,7 +829,6 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
> >  
> >  	elbc_fcm_ctrl->chips[priv->bank] = NULL;
> >  	kfree(priv);
> > -	kfree(elbc_fcm_ctrl);
> >  	return 0;
> >  }
> 
> Do we have to assign fsl_lbc_ctrl_dev->nand to NULL in
> fsl_elbc_nand_remove() then? I think that assignment can be killed then.
> 
>         if (!elbc_fcm_ctrl->counter) {
>                 fsl_lbc_ctrl_dev->nand = NULL;
>                 kfree(elbc_fcm_ctrl);
>         }
> 

If we're freeing fsl_lbc_ctrl, we'd better get rid of references to it...

-Scott



From computersforpeace at gmail.com  Wed Jun 29 14:14:18 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 29 Jun 2011 11:14:18 -0700
Subject: [PATCH] flash_erase: fix incorrect help message
Message-ID: <1309371258-18936-1-git-send-email-computersforpeace@gmail.com>

Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 flash_erase.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/flash_erase.c b/flash_erase.c
index 220f85a..fe2eaca 100644
--- a/flash_erase.c
+++ b/flash_erase.c
@@ -66,7 +66,7 @@ static void display_help (void)
 			"  -j, --jffs2       format the device for jffs2\n"
 			"  -N, --noskipbad   don't skip bad blocks\n"
 			"  -u, --unlock      unlock sectors before erasing\n"
-			"  -q, --quiet       display progress messages\n"
+			"  -q, --quiet       do not display progress messages\n"
 			"      --silent      same as --quiet\n"
 			"      --help        display this help and exit\n"
 			"      --version     output version information and exit\n",
-- 
1.7.0.4




From computersforpeace at gmail.com  Wed Jun 29 16:24:36 2011
From: computersforpeace at gmail.com (Brian Norris)
Date: Wed, 29 Jun 2011 13:24:36 -0700
Subject: [PATCH 0/3] fixups for OOB ECC problems
In-Reply-To: <1309330748.23597.125.camel@sauron>
References: <1309303740-9936-1-git-send-email-computersforpeace@gmail.com>
	<1309330748.23597.125.camel@sauron>
Message-ID: <BANLkTi=-RbAx+gTUenA0gFgfTAWRMeds+w@mail.gmail.com>

On Tue, Jun 28, 2011 at 11:59 PM, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Tue, 2011-06-28 at 16:28 -0700, Brian Norris wrote:
>> Now that we have added the possibility that mtd->read_oob returns
>> -EUCLEAN or -EBADMSG for corrected bitflips and for uncorrectable errors,
>> respectively, there are more pieces of code that need to take this into
>> account. These patches should address some of these by ignoring bitflips
>> when bit accuracy is not needed or by ignoring corrected errors when
>> scrubbing would be unnecessary.
>
> Do you test these things somehow? I'd just injected some code to a
> driver or nandsim which returns -EUCLEAN for OOB and check what fails.

Yes, I've done some testing.

Particularly, I was seeing a problem on boot-time BBM scan (scanning
each block's spare area for a bad block marker), since every ECC error
(correctable or uncorrectable) caused the scan to panic and quit. So
if there were any ECC problems on the whole device, our BBM scan would
fail and the device wouldn't be initialized. I tested this fix on this
particular BBM scan issue, and I've tested some other general OOB
injections and it looks good for now.

Brian


From plagnioj at jcrosoft.com  Wed Jun 29 21:06:28 2011
From: plagnioj at jcrosoft.com (Jean-Christophe PLAGNIOL-VILLARD)
Date: Thu, 30 Jun 2011 03:06:28 +0200
Subject: [PATCH] MTD: atmel_nand: fix wrong use of 0 as NULL
In-Reply-To: <1309365676-19210-1-git-send-email-nicolas.ferre@atmel.com>
References: <1309365676-19210-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <20110630010628.GI17355@game.jcrosoft.org>

On 18:41 Wed 29 Jun     , Nicolas Ferre wrote:
> Fixing this error:
> atmel_nand.c:718:20: warning: Using plain integer as NULL pointer
> 
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>
Acked-by: Jean-Christophe PLAGNIOL-VILLARD <plagnioj at jcrosoft.com>

Best Regards,
J.


From b32955 at freescale.com  Wed Jun 29 21:50:15 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Thu, 30 Jun 2011 09:50:15 +0800
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC	controller
	driver
In-Reply-To: <20110629123803.GM21898@n2100.arm.linux.org.uk>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629123803.GM21898@n2100.arm.linux.org.uk>
Message-ID: <4E0BD657.3070400@freescale.com>

Hi Russell:
> On Wed, Jun 29, 2011 at 04:24:36PM +0800, Huang Shijie wrote:
>> +	dma_addr_t destination_phys = ~0;
>> +
>> +	if (virt_addr_valid(destination))
>> +		destination_phys = dma_map_single(dev, destination,
>> +						length, DMA_FROM_DEVICE);
>> +
>> +	if (dma_mapping_error(dev, destination_phys)) {
> This is buggy.  There is no guarantee that we'll keep using ~0 as the
> value for dma_mapping_error().  Please don't rely on this, but instead
> code this better to avoid having to play these games.
>
thanks a lot. I will change it in the next version.

>> +static int send_page_prepare(struct gpmi_nfc_data *this,
>> +			const void *source, unsigned length,
>> +			void *alt_virt, dma_addr_t alt_phys, unsigned alt_size,
>> +			const void **use_virt, dma_addr_t *use_phys)
>> +{
>> +	dma_addr_t source_phys = ~0;
>> +	struct device *dev = this->dev;
>> +
>> +	if (virt_addr_valid(source))
>> +		source_phys = dma_map_single(dev,
>> +				(void *)source, length, DMA_TO_DEVICE);
>> +
>> +	if (dma_mapping_error(dev, source_phys)) {
> Ditto.
>
Best Regards
Huang Shijie




From b32955 at freescale.com  Wed Jun 29 23:53:45 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Thu, 30 Jun 2011 11:53:45 +0800
Subject: [PATCH v5 0/3] add the GPMI-NFC support for imx23/imx28
Message-ID: <1309406028-2924-1-git-send-email-b32955@freescale.com>

The patch is based on branch "imx-for-3.1" of tree :
      git://git.pengutronix.de/git/imx/linux-2.6.git

v4 --> v5:
	[0] split out the mach code and the machine code.

v3 --> v4:
	merge the GPMI-NFC device code to the new branch.

Huang Shijie (3):
  ARM: mxs: add GPMI-NFC support for imx23/imx28
  ARM: mxs/mx23evk: add GPMI-NFC device
  ARM: mxs/mx28evk: add GPMI-NFC device

 arch/arm/mach-mxs/Kconfig                       |    2 +
 arch/arm/mach-mxs/clock-mx23.c                  |    1 +
 arch/arm/mach-mxs/clock-mx28.c                  |    1 +
 arch/arm/mach-mxs/devices-mx23.h                |    4 +
 arch/arm/mach-mxs/devices-mx28.h                |    4 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c   |   90 +++++++++++++++++++++++
 arch/arm/mach-mxs/include/mach/devices-common.h |   10 +++
 arch/arm/mach-mxs/include/mach/gpmi-nfc.h       |   71 ++++++++++++++++++
 arch/arm/mach-mxs/mach-mx23evk.c                |   37 +++++++++
 arch/arm/mach-mxs/mach-mx28evk.c                |   37 +++++++++
 12 files changed, 261 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
 create mode 100644 arch/arm/mach-mxs/include/mach/gpmi-nfc.h




From b32955 at freescale.com  Wed Jun 29 23:53:47 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Thu, 30 Jun 2011 11:53:47 +0800
Subject: [PATCH v5 2/3] ARM: mxs/mx23evk: add GPMI-NFC device
In-Reply-To: <1309406028-2924-1-git-send-email-b32955@freescale.com>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
Message-ID: <1309406028-2924-3-git-send-email-b32955@freescale.com>

add the GPMI-NFC device for mx23evk borad.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 arch/arm/mach-mxs/Kconfig        |    1 +
 arch/arm/mach-mxs/mach-mx23evk.c |   37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index 1d3985f..f55bcfe 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -32,6 +32,7 @@ config MACH_MX23EVK
 	select SOC_IMX23
 	select MXS_HAVE_AMBA_DUART
 	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_GPMI_NFC
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
 	help
diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
index 3c2de33..772b373 100644
--- a/arch/arm/mach-mxs/mach-mx23evk.c
+++ b/arch/arm/mach-mxs/mach-mx23evk.c
@@ -107,6 +107,42 @@ static const iomux_cfg_t mx23evk_pads[] __initconst = {
 		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
 };
 
+/* gpmi-nfc */
+#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+static iomux_cfg_t mx23evk_gpmi_nfc_pads[] = {
+	MX23_PAD_GPMI_D00__GPMI_D00 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D01__GPMI_D01 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D02__GPMI_D02 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D03__GPMI_D03 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D04__GPMI_D04 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D05__GPMI_D05 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D06__GPMI_D06 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D07__GPMI_D07 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_WPN__GPMI_WPN | MXS_PAD_GPMI_NFC,
+	MX23_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
+	MX23_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
+	MX23_PAD_GPMI_RDY0__GPMI_RDY0 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_RDY1__GPMI_RDY1 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
+};
+
+static int mx23evk_gpmi_nfc_platform_init(void)
+{
+	return mxs_iomux_setup_multiple_pads(mx23evk_gpmi_nfc_pads,
+				ARRAY_SIZE(mx23evk_gpmi_nfc_pads));
+}
+
+static const
+struct gpmi_nfc_platform_data mx23evk_gpmi_nfc_data __initconst = {
+	.platform_init		= mx23evk_gpmi_nfc_platform_init,
+	.min_prop_delay_in_ns	= 5,
+	.max_prop_delay_in_ns	= 9,
+	.max_chip_count		= 1,
+};
+
 /* mxsfb (lcdif) */
 static struct fb_videomode mx23evk_video_modes[] = {
 	{
@@ -166,6 +202,7 @@ static void __init mx23evk_init(void)
 	else
 		gpio_set_value(MX23EVK_BL_ENABLE, 1);
 
+	mx23_add_gpmi_nfc(&mx23evk_gpmi_nfc_data);
 	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
 }
 
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 23:53:46 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Thu, 30 Jun 2011 11:53:46 +0800
Subject: [PATCH v5 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <1309406028-2924-1-git-send-email-b32955@freescale.com>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
Message-ID: <1309406028-2924-2-git-send-email-b32955@freescale.com>

add GPMI-NFC support for imx23 and imx28.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 arch/arm/mach-mxs/clock-mx23.c                  |    1 +
 arch/arm/mach-mxs/clock-mx28.c                  |    1 +
 arch/arm/mach-mxs/devices-mx23.h                |    4 +
 arch/arm/mach-mxs/devices-mx28.h                |    4 +
 arch/arm/mach-mxs/devices/Kconfig               |    3 +
 arch/arm/mach-mxs/devices/Makefile              |    1 +
 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c   |   90 +++++++++++++++++++++++
 arch/arm/mach-mxs/include/mach/devices-common.h |   10 +++
 arch/arm/mach-mxs/include/mach/gpmi-nfc.h       |   71 ++++++++++++++++++
 9 files changed, 185 insertions(+), 0 deletions(-)
 create mode 100644 arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
 create mode 100644 arch/arm/mach-mxs/include/mach/gpmi-nfc.h

diff --git a/arch/arm/mach-mxs/clock-mx23.c b/arch/arm/mach-mxs/clock-mx23.c
index 0163b6d..e190c53 100644
--- a/arch/arm/mach-mxs/clock-mx23.c
+++ b/arch/arm/mach-mxs/clock-mx23.c
@@ -456,6 +456,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
 	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
 	_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
+	_REGISTER_CLOCK("imx23-gpmi-nfc", NULL, gpmi_clk)
 };
 
 static int clk_misc_init(void)
diff --git a/arch/arm/mach-mxs/clock-mx28.c b/arch/arm/mach-mxs/clock-mx28.c
index 5dcc59d..0397f65 100644
--- a/arch/arm/mach-mxs/clock-mx28.c
+++ b/arch/arm/mach-mxs/clock-mx28.c
@@ -614,6 +614,7 @@ static struct clk_lookup lookups[] = {
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
 	_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
+	_REGISTER_CLOCK("imx28-gpmi-nfc", NULL, gpmi_clk)
 	_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
 	_REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
 	_REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
diff --git a/arch/arm/mach-mxs/devices-mx23.h b/arch/arm/mach-mxs/devices-mx23.h
index c6f345f..a9c495d 100644
--- a/arch/arm/mach-mxs/devices-mx23.h
+++ b/arch/arm/mach-mxs/devices-mx23.h
@@ -21,6 +21,10 @@ extern const struct mxs_auart_data mx23_auart_data[] __initconst;
 #define mx23_add_auart0()		mx23_add_auart(0)
 #define mx23_add_auart1()		mx23_add_auart(1)
 
+extern const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst;
+#define mx23_add_gpmi_nfc(pdata)	\
+	mxs_add_gpmi_nfc(pdata, &mx23_gpmi_nfc_data)
+
 extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
 #define mx23_add_mxs_mmc(id, pdata) \
 	mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)
diff --git a/arch/arm/mach-mxs/devices-mx28.h b/arch/arm/mach-mxs/devices-mx28.h
index 79b9452..bbc8f0c 100644
--- a/arch/arm/mach-mxs/devices-mx28.h
+++ b/arch/arm/mach-mxs/devices-mx28.h
@@ -34,6 +34,10 @@ extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
 #define mx28_add_flexcan0(pdata)	mx28_add_flexcan(0, pdata)
 #define mx28_add_flexcan1(pdata)	mx28_add_flexcan(1, pdata)
 
+extern const struct mxs_gpmi_nfc_data mx28_gpmi_nfc_data __initconst;
+#define mx28_add_gpmi_nfc(pdata)	\
+	mxs_add_gpmi_nfc(pdata, &mx28_gpmi_nfc_data)
+
 extern const struct mxs_mxs_i2c_data mx28_mxs_i2c_data[] __initconst;
 #define mx28_add_mxs_i2c(id)		mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id])
 
diff --git a/arch/arm/mach-mxs/devices/Kconfig b/arch/arm/mach-mxs/devices/Kconfig
index acf9eea..b42a14b 100644
--- a/arch/arm/mach-mxs/devices/Kconfig
+++ b/arch/arm/mach-mxs/devices/Kconfig
@@ -12,6 +12,9 @@ config MXS_HAVE_PLATFORM_FLEXCAN
 	select HAVE_CAN_FLEXCAN if CAN
 	bool
 
+config MXS_HAVE_PLATFORM_GPMI_NFC
+	bool
+
 config MXS_HAVE_PLATFORM_MXS_I2C
 	bool
 
diff --git a/arch/arm/mach-mxs/devices/Makefile b/arch/arm/mach-mxs/devices/Makefile
index 351915c..972abdc 100644
--- a/arch/arm/mach-mxs/devices/Makefile
+++ b/arch/arm/mach-mxs/devices/Makefile
@@ -3,6 +3,7 @@ obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
 obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_GPMI_NFC) += platform-gpmi-nfc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
diff --git a/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
new file mode 100644
index 0000000..ae88672
--- /dev/null
+++ b/arch/arm/mach-mxs/devices/platform-gpmi-nfc.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define RES_MEM(soc, _id, _s, _n)				\
+	{							\
+		.start = soc ##_## _id ## _BASE_ADDR,		\
+		.end   = soc ##_## _id ## _BASE_ADDR + (_s) - 1,\
+		.name  = (_n),					\
+		.flags = IORESOURCE_MEM,			\
+	}
+
+#define RES_IRQ(soc, _id, _n)			\
+	{					\
+		.start = soc ##_INT_## _id,	\
+		.end   = soc ##_INT_## _id,	\
+		.name  = (_n),			\
+		.flags = IORESOURCE_IRQ,	\
+	}
+
+#define RES_DMA(soc, _i_s, _i_e, _n)		\
+	{					\
+		.start = soc ##_## _i_s,	\
+		.end   = soc ##_## _i_e,	\
+		.name  = (_n),			\
+		.flags = IORESOURCE_DMA,	\
+	}
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_gpmi_nfc_data mx23_gpmi_nfc_data __initconst = {
+	.devid = "imx23-gpmi-nfc",
+	.res = {
+		/* GPMI */
+		RES_MEM(MX23, GPMI, SZ_8K, GPMI_NFC_GPMI_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX23, GPMI_ATTENTION, GPMI_NFC_GPMI_INTERRUPT_RES_NAME),
+		/* BCH */
+		RES_MEM(MX23, BCH, SZ_8K, GPMI_NFC_BCH_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX23, BCH, GPMI_NFC_BCH_INTERRUPT_RES_NAME),
+		/* DMA */
+		RES_DMA(MX23, DMA_GPMI0, DMA_GPMI3,
+					GPMI_NFC_DMA_CHANNELS_RES_NAME),
+		RES_IRQ(MX23, GPMI_DMA, GPMI_NFC_DMA_INTERRUPT_RES_NAME),
+	},
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_gpmi_nfc_data mx28_gpmi_nfc_data __initconst = {
+	.devid = "imx28-gpmi-nfc",
+	.res = {
+		/* GPMI */
+		RES_MEM(MX28, GPMI, SZ_8K, GPMI_NFC_GPMI_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX28, GPMI, GPMI_NFC_GPMI_INTERRUPT_RES_NAME),
+		/* BCH */
+		RES_MEM(MX28, BCH, SZ_8K, GPMI_NFC_BCH_REGS_ADDR_RES_NAME),
+		RES_IRQ(MX28, BCH, GPMI_NFC_BCH_INTERRUPT_RES_NAME),
+		/* DMA */
+		RES_DMA(MX28, DMA_GPMI0, DMA_GPMI7,
+					GPMI_NFC_DMA_CHANNELS_RES_NAME),
+		RES_IRQ(MX28, GPMI_DMA, GPMI_NFC_DMA_INTERRUPT_RES_NAME),
+	},
+};
+#endif
+
+struct platform_device *__init
+mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
+		const struct mxs_gpmi_nfc_data *data)
+{
+	return mxs_add_platform_device_dmamask(data->devid, -1,
+				data->res, RES_SIZE,
+				pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
diff --git a/arch/arm/mach-mxs/include/mach/devices-common.h b/arch/arm/mach-mxs/include/mach/devices-common.h
index 812d7a8..e032120 100644
--- a/arch/arm/mach-mxs/include/mach/devices-common.h
+++ b/arch/arm/mach-mxs/include/mach/devices-common.h
@@ -66,6 +66,16 @@ struct platform_device *__init mxs_add_flexcan(
 		const struct mxs_flexcan_data *data,
 		const struct flexcan_platform_data *pdata);
 
+/* gpmi-nfc */
+#include <mach/gpmi-nfc.h>
+struct mxs_gpmi_nfc_data {
+	const char *devid;
+	const struct resource res[RES_SIZE];
+};
+struct platform_device *__init
+mxs_add_gpmi_nfc(const struct gpmi_nfc_platform_data *pdata,
+		const struct mxs_gpmi_nfc_data *data);
+
 /* i2c */
 struct mxs_mxs_i2c_data {
 	int id;
diff --git a/arch/arm/mach-mxs/include/mach/gpmi-nfc.h b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
new file mode 100644
index 0000000..eda8192
--- /dev/null
+++ b/arch/arm/mach-mxs/include/mach/gpmi-nfc.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __MACH_MXS_GPMI_NFC_H__
+#define __MACH_MXS_GPMI_NFC_H__
+
+/* The size of the resource is fixed. */
+#define RES_SIZE	6
+
+/* Resource names for the GPMI NFC driver. */
+#define GPMI_NFC_GPMI_REGS_ADDR_RES_NAME  "GPMI NFC GPMI Registers"
+#define GPMI_NFC_GPMI_INTERRUPT_RES_NAME  "GPMI NFC GPMI Interrupt"
+#define GPMI_NFC_BCH_REGS_ADDR_RES_NAME   "GPMI NFC BCH Registers"
+#define GPMI_NFC_BCH_INTERRUPT_RES_NAME   "GPMI NFC BCH Interrupt"
+#define GPMI_NFC_DMA_CHANNELS_RES_NAME    "GPMI NFC DMA Channels"
+#define GPMI_NFC_DMA_INTERRUPT_RES_NAME   "GPMI NFC DMA Interrupt"
+
+/**
+ * struct gpmi_nfc_platform_data - GPMI NFC driver platform data.
+ *
+ * This structure communicates platform-specific information to the GPMI NFC
+ * driver that can't be expressed as resources.
+ *
+ * @platform_init:           A pointer to a function the driver will call to
+ *                           initialize the platform (e.g., set up the pin mux).
+ * @platform_exit:           A pointer to a function the driver will call to
+ *                           exit the platform (e.g., free pins).
+ * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
+ *                           from the NAND Flash device, in nanoseconds.
+ * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
+ *                           from the NAND Flash device, in nanoseconds.
+ * @max_chip_count:          The maximum number of chips for which the driver
+ *                           should configure the hardware. This value most
+ *                           likely reflects the number of pins that are
+ *                           connected to a NAND Flash device. If this is
+ *                           greater than the SoC hardware can support, the
+ *                           driver will print a message and fail to initialize.
+ * @partitions:              An optional pointer to an array of partition
+ *                           descriptions.
+ * @partition_count:         The number of elements in the partitions array.
+ */
+struct gpmi_nfc_platform_data {
+	/* SoC hardware information. */
+	int		(*platform_init)(void);
+	void		(*platform_exit)(void);
+
+	/* NAND Flash information. */
+	unsigned int	min_prop_delay_in_ns;
+	unsigned int	max_prop_delay_in_ns;
+	unsigned int	max_chip_count;
+
+	/* Medium information. */
+	struct mtd_partition *partitions;
+	unsigned	partition_count;
+};
+#endif
-- 
1.7.0.4




From b32955 at freescale.com  Wed Jun 29 23:53:48 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Thu, 30 Jun 2011 11:53:48 +0800
Subject: [PATCH v5 3/3] ARM: mxs/mx28evk: add GPMI-NFC device
In-Reply-To: <1309406028-2924-1-git-send-email-b32955@freescale.com>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
Message-ID: <1309406028-2924-4-git-send-email-b32955@freescale.com>

add GPMI-NFC device for mx28evk board.

Signed-off-by: Huang Shijie <b32955 at freescale.com>
---
 arch/arm/mach-mxs/Kconfig        |    1 +
 arch/arm/mach-mxs/mach-mx28evk.c |   37 +++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
index f55bcfe..a5b753a 100644
--- a/arch/arm/mach-mxs/Kconfig
+++ b/arch/arm/mach-mxs/Kconfig
@@ -47,6 +47,7 @@ config MACH_MX28EVK
 	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_FEC
 	select MXS_HAVE_PLATFORM_FLEXCAN
+	select MXS_HAVE_PLATFORM_GPMI_NFC
 	select MXS_HAVE_PLATFORM_MXS_MMC
 	select MXS_HAVE_PLATFORM_MXSFB
 	select MXS_OCOTP
diff --git a/arch/arm/mach-mxs/mach-mx28evk.c b/arch/arm/mach-mxs/mach-mx28evk.c
index eaaf6ff..74d0868 100644
--- a/arch/arm/mach-mxs/mach-mx28evk.c
+++ b/arch/arm/mach-mxs/mach-mx28evk.c
@@ -314,6 +314,42 @@ static const struct flexcan_platform_data
 	}
 };
 
+/* gpmi-nfc */
+#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+static iomux_cfg_t mx28evk_gpmi_nfc_pads[] = {
+	MX28_PAD_GPMI_D00__GPMI_D0 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D01__GPMI_D1 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D02__GPMI_D2 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D03__GPMI_D3 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D04__GPMI_D4 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D05__GPMI_D5 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D06__GPMI_D6 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_D07__GPMI_D7 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_RDY0__GPMI_READY0 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_RDY1__GPMI_READY1 | MXS_PAD_CTRL,
+	MX28_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
+	MX28_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
+	MX28_PAD_GPMI_RESETN__GPMI_RESETN | MXS_PAD_GPMI_NFC,
+};
+
+static int mx28evk_gpmi_nfc_platform_init(void)
+{
+	return mxs_iomux_setup_multiple_pads(mx28evk_gpmi_nfc_pads,
+				ARRAY_SIZE(mx28evk_gpmi_nfc_pads));
+}
+
+static const struct gpmi_nfc_platform_data
+mx28evk_gpmi_nfc_data __initconst = {
+	.platform_init		= mx28evk_gpmi_nfc_platform_init,
+	.min_prop_delay_in_ns	= 5,
+	.max_prop_delay_in_ns	= 9,
+	.max_chip_count		= 1,
+};
+
 /* mxsfb (lcdif) */
 static struct fb_videomode mx28evk_video_modes[] = {
 	{
@@ -390,6 +426,7 @@ static void __init mx28evk_init(void)
 	else
 		gpio_set_value(MX28EVK_BL_ENABLE, 1);
 
+	mx28_add_gpmi_nfc(&mx28evk_gpmi_nfc_data);
 	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
 
 	/* power on mmc slot by writing 0 to the gpio */
-- 
1.7.0.4




From axel.lin at gmail.com  Thu Jun 30 00:34:54 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Thu, 30 Jun 2011 12:34:54 +0800
Subject: [PATCH] mtd: tmio_nand: fix build error
Message-ID: <1309408494.10500.1.camel@phoenix>

Fix a mistake introduced by commit 33f4a3b
"mtd: tmio_nand.c: use mtd_device_parse_register"

  CC [M]  drivers/mtd/nand/tmio_nand.o
drivers/mtd/nand/tmio_nand.c:461:35: error: macro "mtd_device_register" passed 5 arguments, but takes just 3
drivers/mtd/nand/tmio_nand.c: In function 'tmio_probe':
drivers/mtd/nand/tmio_nand.c:459: error: 'mtd_device_register' undeclared (first use in this function)
drivers/mtd/nand/tmio_nand.c:459: error: (Each undeclared identifier is reported only once
drivers/mtd/nand/tmio_nand.c:459: error: for each function it appears in.)
make[3]: *** [drivers/mtd/nand/tmio_nand.o] Error 1
make[2]: *** [drivers/mtd/nand] Error 2
make[1]: *** [drivers/mtd] Error 2
make: *** [drivers] Error 2

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/tmio_nand.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/mtd/nand/tmio_nand.c b/drivers/mtd/nand/tmio_nand.c
index d476857..beebd95 100644
--- a/drivers/mtd/nand/tmio_nand.c
+++ b/drivers/mtd/nand/tmio_nand.c
@@ -456,7 +456,7 @@ static int tmio_probe(struct platform_device *dev)
 		goto err_scan;
 	}
 	/* Register the partitions */
-	retval = mtd_device_register(mtd, NULL, 0,
+	retval = mtd_device_parse_register(mtd, NULL, 0,
 			data ? data->partition : NULL,
 			data ? data->num_partitions : 0);
 	if (!retval)
-- 
1.7.4.1





From w.sang at pengutronix.de  Thu Jun 30 00:46:55 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Thu, 30 Jun 2011 06:46:55 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <20110629143701.GC25931@S2100-06.ap.freescale.net>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
	<20110629140038.GB25931@S2100-06.ap.freescale.net>
	<20110629141557.GK1992@pengutronix.de>
	<20110629143701.GC25931@S2100-06.ap.freescale.net>
Message-ID: <20110630044655.GA19841@pengutronix.de>

Hi Shawn,

> > > I would suggest leave this gpmi specific quirk to gpmi driver to sort
> > > out.  With the following mxs-dma change, it should work if gpmi driver
> > > can pass the valid gpmi irq number for only one gpmi channel, and -1
> > > for all others.
> > 
> > ...which brings us right into the 'NO_IRQ is 0' discussion :)
> > 
> Though I do not know what it means exactly, number 0 is an valid IRQ
> on both mx23 and mx28 (see mx23.h and mx28.h).

It could be remapped. It is a looong story. Start here if you are interested:

http://lkml.org/lkml/2005/11/21/221
http://yarchive.net/comp/linux/no_irq.html

Currently, it's a can of worms. Hopefully, irq_desc might help somewhen.

> > Other than that, [thinking loud] this will help if all irq-sharing
> > channels are handled by the same driver. If not, we would just add
> > IRQF_SHARED (hopefully this will never be needed). Yup, sounds
> > reasonable to me. Will give it a second thought later, though.
> > 
> GPMI is the only mxs-dma user that gets irq-sharing.  So yes, all
> irq-sharing channels are handled by the same driver, gpmi-nfc :)

Currently, yes. But we have to make it future-proof.

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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110630/2f10ab83/attachment.sig>

From shawn.guo at freescale.com  Thu Jun 30 01:28:56 2011
From: shawn.guo at freescale.com (Shawn Guo)
Date: Thu, 30 Jun 2011 13:28:56 +0800
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <20110630044655.GA19841@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110629100658.GE1992@pengutronix.de>
	<20110629103337.GF1992@pengutronix.de>
	<4E0B0296.6060902@freescale.com>
	<20110629122942.GH1992@pengutronix.de>
	<20110629140038.GB25931@S2100-06.ap.freescale.net>
	<20110629141557.GK1992@pengutronix.de>
	<20110629143701.GC25931@S2100-06.ap.freescale.net>
	<20110630044655.GA19841@pengutronix.de>
Message-ID: <20110630052855.GE25931@S2100-06.ap.freescale.net>

On Thu, Jun 30, 2011 at 06:46:55AM +0200, Wolfram Sang wrote:
> Hi Shawn,
> 
> > > > I would suggest leave this gpmi specific quirk to gpmi driver to sort
> > > > out.  With the following mxs-dma change, it should work if gpmi driver
> > > > can pass the valid gpmi irq number for only one gpmi channel, and -1
> > > > for all others.
> > > 
> > > ...which brings us right into the 'NO_IRQ is 0' discussion :)
> > > 
> > Though I do not know what it means exactly, number 0 is an valid IRQ
> > on both mx23 and mx28 (see mx23.h and mx28.h).
> 
> It could be remapped. It is a looong story. Start here if you are interested:
> 
> http://lkml.org/lkml/2005/11/21/221
> http://yarchive.net/comp/linux/no_irq.html
> 
> Currently, it's a can of worms. Hopefully, irq_desc might help somewhen.
> 
Thanks for the info.  It deserves a good study.  With your comment,
I would use macro NO_IRQ than -1 for the mxs-dma change.

> > > Other than that, [thinking loud] this will help if all irq-sharing
> > > channels are handled by the same driver. If not, we would just add
> > > IRQF_SHARED (hopefully this will never be needed). Yup, sounds
> > > reasonable to me. Will give it a second thought later, though.
> > > 
> > GPMI is the only mxs-dma user that gets irq-sharing.  So yes, all
> > irq-sharing channels are handled by the same driver, gpmi-nfc :)
> 
> Currently, yes. But we have to make it future-proof.
> 
For the SoCs coming in future, some, e.g. mx6 series, is the same
case, and some, like mx50, has separate irq for each gpmi channel,
which is even better.  So we can survive for quite a long time.

-- 
Regards,
Shawn



From dedekind1 at gmail.com  Thu Jun 30 03:03:13 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 10:03:13 +0300
Subject: [PATCH v2] mtdinfo: remove -m leftovers
In-Reply-To: <1309363769-7904-1-git-send-email-computersforpeace@gmail.com>
References: <1309327350.23597.96.camel@sauron>
	<1309363769-7904-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309417402.23597.141.camel@sauron>

On Wed, 2011-06-29 at 09:09 -0700, Brian Norris wrote:
> From: Artem Bityutskiy <dedekind1 at gmail.com>
> 
> Looks OK to me, except it seems you did everything but actually removing
> the field in struct args :) So here's a quick v2 from me...
> 
> From: Artem Bityutskiy <dedekind1 at gmail.com>
> Date: Wed, 29 Jun 2011 08:56:39 +0300
> Subject: [PATCH v2] mtdinfo: remove -m leftovers
> 
> We have removed the -m option, but did not remove args.mtdn which represents
> the -m parameters. Kill args.mtdn as well.
> 
> Signed-off-by: Artem Bityutskiy <dedekind1 at gmail.com>
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>

Pushed, thanks you!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 03:21:09 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 10:21:09 +0300
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <BANLkTi=MMEzE-neUzRqBYqvsGsup_s+VMw@mail.gmail.com>
References: <20110608101804.GA5527@july>
	<BANLkTi=MMEzE-neUzRqBYqvsGsup_s+VMw@mail.gmail.com>
Message-ID: <1309418473.23597.143.camel@sauron>

On Wed, 2011-06-29 at 16:22 +0900, Kyungmin Park wrote:
> Hi Artem,
> 
> There's missing patch, can you add l2-mtd tree?
> 
Sorry, I missed this. I have few minor comments which will come shortly,
and also I'd ask to re-send this patch with the arm mailing list in CC -
you use DMA API which I am not very good at, and I'd like others to
validate this.

Thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 03:55:25 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 10:55:25 +0300
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <20110608101804.GA5527@july>
References: <20110608101804.GA5527@july>
Message-ID: <1309420530.23597.153.camel@sauron>

On Wed, 2011-06-08 at 19:18 +0900, Kyungmin Park wrote:
> From: Kyungmin Park <kyungmin.park at samsung.com>
> 
> Implement the write DMA feature. It can reduce the CPU usage when write.
> 
> Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
> ---
> diff --git a/drivers/mtd/onenand/samsung.c b/drivers/mtd/onenand/samsung.c
> index 3306b5b..f24cb6f 100644
> --- a/drivers/mtd/onenand/samsung.c
> +++ b/drivers/mtd/onenand/samsung.c
> @@ -712,6 +712,74 @@ normal:
>  	return 0;
>  }
>  
> +static int s5pc110_write_bufferram(struct mtd_info *mtd, int area,
> +		const unsigned char *buffer, int offset, size_t count)
> +{
> +	struct onenand_chip *this = mtd->priv;
> +	struct device *dev = &onenand->pdev->dev;
> +	void __iomem *p;
> +	void *buf = (void *) buffer;

No, this is bad - if buffer is marked as const then it should be
constant, or remove the const modifier in the function declaration. And
when you remove the const modifier you can kill the cast, because
assigning to a void pointer does not require it. 

> +	dma_addr_t dma_src, dma_dst;
> +	int err, ofs, page_dma = 0;
> +
> +	p = this->base + area;
> +	if (ONENAND_CURRENT_BUFFERRAM(this)) {
> +		if (area == ONENAND_DATARAM)
> +			p += this->writesize;
> +		else
> +			p += mtd->oobsize;
> +	}
> +
> +	if (count != mtd->writesize || offset & 3 || (size_t) buf & 3)
> +		goto normal;
> +
> +	/* Handle vmalloc address */
> +	if (buf >= high_memory) {
> +		struct page *page;

OK, Russell will yell at this, but we do DMA vmalloc'ed addresses for
many years in the OneNAND driver and it works, and there are products
out there with this code (e.g., Nokia N900) and it works. But I'd like
to understand better why exactly this is a no-no, and why this works in
practice - were we lucky and how exactly ....

> +
> +		if (((size_t) buf & PAGE_MASK) !=
> +		    ((size_t) (buf + count - 1) & PAGE_MASK))

Something is fishy with these size_t casts, could you revisit this piece
of code - and turn it to something simpler, if possible?

> +			goto normal;
> +
> +		page = vmalloc_to_page(buf);
> +		if (unlikely(!page))
> +			goto normal;
> +
> +		/* Page offset */
> +		ofs = ((size_t) buf & ~PAGE_MASK);
> +		page_dma = 1;
> +
> +		/* DMA routine */
> +		dma_src = dma_map_page(dev, page, ofs, count, DMA_TO_DEVICE);
> +		dma_dst = onenand->phys_base + (p - this->base);
> +	} else {
> +		/* DMA routine */
> +		dma_src = dma_map_single(dev, buf, count, DMA_TO_DEVICE);
> +		dma_dst = onenand->phys_base + (p - this->base);
> +	}
> +
> +	if (dma_mapping_error(dev, dma_src)) {
> +		dev_err(dev, "Couldn't map a %d byte buffer for DMA\n", count);
> +		goto normal;
> +	}
> +
> +	err = s5pc110_dma_ops((void *) dma_dst, (void *) dma_src,
> +			count, S5PC110_DMA_DIR_WRITE);

Why casting to void? Please, revise all casts you do.

> +
> +	if (page_dma)
> +		dma_unmap_page(dev, dma_src, count, DMA_TO_DEVICE);
> +	else
> +		dma_unmap_single(dev, dma_src, count, DMA_TO_DEVICE);
> +
> +	if (!err)
> +		return 0;
> +
> +normal:
> +	memcpy(p + offset, buffer, count);

p is iomem, and it cannot be involved in memcpy as Russell pointed
recently in another e-mail, see Documentation/bus-virt-phys-mapping.txt

Please, re-send this with the arm mailing list in CC.

-- 
Best Regards,
Artem Bityutskiy



From u.kleine-koenig at pengutronix.de  Thu Jun 30 03:55:01 2011
From: u.kleine-koenig at pengutronix.de (Uwe =?iso-8859-1?Q?Kleine-K=F6nig?=)
Date: Thu, 30 Jun 2011 09:55:01 +0200
Subject: [PATCH v5 2/3] ARM: mxs/mx23evk: add GPMI-NFC device
In-Reply-To: <1309406028-2924-3-git-send-email-b32955@freescale.com>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
	<1309406028-2924-3-git-send-email-b32955@freescale.com>
Message-ID: <20110630075501.GE11559@pengutronix.de>

On Thu, Jun 30, 2011 at 11:53:47AM +0800, Huang Shijie wrote:
> add the GPMI-NFC device for mx23evk borad.
s/borad/board/

> Signed-off-by: Huang Shijie <b32955 at freescale.com>
> ---
>  arch/arm/mach-mxs/Kconfig        |    1 +
>  arch/arm/mach-mxs/mach-mx23evk.c |   37 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 38 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
> index 1d3985f..f55bcfe 100644
> --- a/arch/arm/mach-mxs/Kconfig
> +++ b/arch/arm/mach-mxs/Kconfig
> @@ -32,6 +32,7 @@ config MACH_MX23EVK
>  	select SOC_IMX23
>  	select MXS_HAVE_AMBA_DUART
>  	select MXS_HAVE_PLATFORM_AUART
> +	select MXS_HAVE_PLATFORM_GPMI_NFC
>  	select MXS_HAVE_PLATFORM_MXS_MMC
>  	select MXS_HAVE_PLATFORM_MXSFB
>  	help
> diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
> index 3c2de33..772b373 100644
> --- a/arch/arm/mach-mxs/mach-mx23evk.c
> +++ b/arch/arm/mach-mxs/mach-mx23evk.c
> @@ -107,6 +107,42 @@ static const iomux_cfg_t mx23evk_pads[] __initconst = {
>  		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
>  };
>  
> +/* gpmi-nfc */
> +#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
Maybe put that into a more central place, as mach-mx28evk uses it, too?
OTOH the name sounds more generic than its use. Do you really need 12mA
for the Write protect pin? If not, you could rename it to
MXS_PAD_GPMI_NFC_STROBE.

> +static iomux_cfg_t mx23evk_gpmi_nfc_pads[] = {
> +	MX23_PAD_GPMI_D00__GPMI_D00 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D01__GPMI_D01 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D02__GPMI_D02 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D03__GPMI_D03 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D04__GPMI_D04 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D05__GPMI_D05 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D06__GPMI_D06 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_D07__GPMI_D07 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_WPN__GPMI_WPN | MXS_PAD_GPMI_NFC,
> +	MX23_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
> +	MX23_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
> +	MX23_PAD_GPMI_RDY0__GPMI_RDY0 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_RDY1__GPMI_RDY1 | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
> +	MX23_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
> +};

Best regards
Uwe

-- 
Pengutronix e.K.                           | Uwe Kleine-K?nig            |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |


From shawn.guo at linaro.org  Thu Jun 30 04:06:33 2011
From: shawn.guo at linaro.org (Shawn Guo)
Date: Thu, 30 Jun 2011 16:06:33 +0800
Subject: [PATCH] dmaengine: mxs-dma: skip request_irq for NO_IRQ
In-Reply-To: <20110630052855.GE25931@S2100-06.ap.freescale.net>
References: <20110630052855.GE25931@S2100-06.ap.freescale.net>
Message-ID: <1309421193-7785-1-git-send-email-shawn.guo@linaro.org>

In general, the mxs-dma users get separate irq for each channel,
but gpmi is special one which has only one irq shared by all gpmi
channels.  It causes mxs_dma channel allocation function fail for
all other gpmi channels except the first one calling into the
function.

The patch gets request_irq call skipped for NO_IRQ case, and leaves
this gpmi specific quirk to gpmi driver to sort out.  It will fix
above problem if gpmi driver sets chan_irq as gpmi irq for only one
channel and NO_IRQ for all the rest channels.

Signed-off-by: Shawn Guo <shawn.guo at linaro.org>
Cc: Vinod Koul <vinod.koul at intel.com>
---
 drivers/dma/mxs-dma.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 88aad4f..2870d91 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -327,10 +327,12 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
 
 	memset(mxs_chan->ccw, 0, PAGE_SIZE);
 
-	ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
-				0, "mxs-dma", mxs_dma);
-	if (ret)
-		goto err_irq;
+	if (mxs_chan->chan_irq != NO_IRQ) {
+		ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
+					0, "mxs-dma", mxs_dma);
+		if (ret)
+			goto err_irq;
+	}
 
 	ret = clk_enable(mxs_dma->clk);
 	if (ret)
-- 
1.7.4.1




From dbaryshkov at gmail.com  Thu Jun 30 04:23:45 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 30 Jun 2011 12:23:45 +0400
Subject: [PATCH] mtd: tmio_nand: fix build error
In-Reply-To: <1309408494.10500.1.camel@phoenix>
References: <1309408494.10500.1.camel@phoenix>
Message-ID: <BANLkTikonD2fcbkBU2ESYm_XncBXNZc_hw@mail.gmail.com>

On 6/30/11, Axel Lin <axel.lin at gmail.com> wrote:
> Fix a mistake introduced by commit 33f4a3b
> "mtd: tmio_nand.c: use mtd_device_parse_register"

Already sumbited 27 June 2011. Strangely Artem remains silent.

>   CC [M]  drivers/mtd/nand/tmio_nand.o
> drivers/mtd/nand/tmio_nand.c:461:35: error: macro "mtd_device_register"
> passed 5 arguments, but takes just 3
> drivers/mtd/nand/tmio_nand.c: In function 'tmio_probe':
> drivers/mtd/nand/tmio_nand.c:459: error: 'mtd_device_register' undeclared
> (first use in this function)
> drivers/mtd/nand/tmio_nand.c:459: error: (Each undeclared identifier is
> reported only once
> drivers/mtd/nand/tmio_nand.c:459: error: for each function it appears in.)
> make[3]: *** [drivers/mtd/nand/tmio_nand.o] Error 1
> make[2]: *** [drivers/mtd/nand] Error 2
> make[1]: *** [drivers/mtd] Error 2
> make: *** [drivers] Error 2

-- 
With best wishes
Dmitry


From b32955 at freescale.com  Thu Jun 30 04:37:48 2011
From: b32955 at freescale.com (Huang Shijie)
Date: Thu, 30 Jun 2011 16:37:48 +0800
Subject: [PATCH v5 2/3] ARM: mxs/mx23evk: add GPMI-NFC device
In-Reply-To: <20110630075501.GE11559@pengutronix.de>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
	<1309406028-2924-3-git-send-email-b32955@freescale.com>
	<20110630075501.GE11559@pengutronix.de>
Message-ID: <4E0C35DC.2040107@freescale.com>

Hi:
> On Thu, Jun 30, 2011 at 11:53:47AM +0800, Huang Shijie wrote:
>> add the GPMI-NFC device for mx23evk borad.
> s/borad/board/
>
>> Signed-off-by: Huang Shijie<b32955 at freescale.com>
>> ---
>>   arch/arm/mach-mxs/Kconfig        |    1 +
>>   arch/arm/mach-mxs/mach-mx23evk.c |   37 +++++++++++++++++++++++++++++++++++++
>>   2 files changed, 38 insertions(+), 0 deletions(-)
>>
>> diff --git a/arch/arm/mach-mxs/Kconfig b/arch/arm/mach-mxs/Kconfig
>> index 1d3985f..f55bcfe 100644
>> --- a/arch/arm/mach-mxs/Kconfig
>> +++ b/arch/arm/mach-mxs/Kconfig
>> @@ -32,6 +32,7 @@ config MACH_MX23EVK
>>   	select SOC_IMX23
>>   	select MXS_HAVE_AMBA_DUART
>>   	select MXS_HAVE_PLATFORM_AUART
>> +	select MXS_HAVE_PLATFORM_GPMI_NFC
>>   	select MXS_HAVE_PLATFORM_MXS_MMC
>>   	select MXS_HAVE_PLATFORM_MXSFB
>>   	help
>> diff --git a/arch/arm/mach-mxs/mach-mx23evk.c b/arch/arm/mach-mxs/mach-mx23evk.c
>> index 3c2de33..772b373 100644
>> --- a/arch/arm/mach-mxs/mach-mx23evk.c
>> +++ b/arch/arm/mach-mxs/mach-mx23evk.c
>> @@ -107,6 +107,42 @@ static const iomux_cfg_t mx23evk_pads[] __initconst = {
>>   		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
>>   };
>>
>> +/* gpmi-nfc */
>> +#define MXS_PAD_GPMI_NFC	(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
> Maybe put that into a more central place, as mach-mx28evk uses it, too?
yes. The mach-mx28evk needs it too.

If I put it into the iomux.h, what's the name for it?
      MXS_PAD_CTRL_12MA , or something else ?

> OTOH the name sounds more generic than its use. Do you really need 12mA
Yes, I need the 12mA for the Write protect pin, and other two pins.


Best Regards
Huang Shijie
> for the Write protect pin? If not, you could rename it to
> MXS_PAD_GPMI_NFC_STROBE.
>
>> +static iomux_cfg_t mx23evk_gpmi_nfc_pads[] = {
>> +	MX23_PAD_GPMI_D00__GPMI_D00 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D01__GPMI_D01 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D02__GPMI_D02 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D03__GPMI_D03 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D04__GPMI_D04 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D05__GPMI_D05 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D06__GPMI_D06 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_D07__GPMI_D07 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_CLE__GPMI_CLE | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_ALE__GPMI_ALE | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_WPN__GPMI_WPN | MXS_PAD_GPMI_NFC,
>> +	MX23_PAD_GPMI_WRN__GPMI_WRN | MXS_PAD_GPMI_NFC,
>> +	MX23_PAD_GPMI_RDN__GPMI_RDN | MXS_PAD_GPMI_NFC,
>> +	MX23_PAD_GPMI_RDY0__GPMI_RDY0 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_RDY1__GPMI_RDY1 | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_CE0N__GPMI_CE0N | MXS_PAD_CTRL,
>> +	MX23_PAD_GPMI_CE1N__GPMI_CE1N | MXS_PAD_CTRL,
>> +};
> Best regards
> Uwe
>




From linux at arm.linux.org.uk  Thu Jun 30 05:19:51 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 30 Jun 2011 10:19:51 +0100
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <1309420530.23597.153.camel@sauron>
References: <20110608101804.GA5527@july> <1309420530.23597.153.camel@sauron>
Message-ID: <20110630091951.GQ21898@n2100.arm.linux.org.uk>

On Thu, Jun 30, 2011 at 10:55:25AM +0300, Artem Bityutskiy wrote:
> > +	/* Handle vmalloc address */
> > +	if (buf >= high_memory) {
> > +		struct page *page;
> 
> OK, Russell will yell at this, but we do DMA vmalloc'ed addresses for

I most certainly will, because its broken.

> > +
> > +		if (((size_t) buf & PAGE_MASK) !=
> > +		    ((size_t) (buf + count - 1) & PAGE_MASK))
> 
> Something is fishy with these size_t casts, could you revisit this piece
> of code - and turn it to something simpler, if possible?
> 
> > +			goto normal;
> > +
> > +		page = vmalloc_to_page(buf);
> > +		if (unlikely(!page))
> > +			goto normal;
> > +
> > +		/* Page offset */
> > +		ofs = ((size_t) buf & ~PAGE_MASK);
> > +		page_dma = 1;
> > +
> > +		/* DMA routine */
> > +		dma_src = dma_map_page(dev, page, ofs, count, DMA_TO_DEVICE);

Which is that this code is trying to work around the restriction in the
DMA API that dma_map_single() can only take virtual addresses in the
kernel direct mapped region.

The key thing here is that with CPUs which lookup by virtual address,
like ARMs, you _must_ handle the cache aliases associated with the mapping
which you are accessing the memory via.

This means if you are accessing a DMA buffer at address X, and address X
is cacheable, address X needs cache maintainence performed on it.  Address
Y, which may correspond with the same memory as X through a different
mapping is no good.  It has to be X.

However, there is NO API for mapping DMA buffers from vmalloc space.
What we do now have are a pair of functions which must be used _correctly_
(iow, one before and one after) to ensure that virtual cached architectures
can access the data correctly - and its documented at the bottom of
cachetlb.txt.

As this is something which keeps coming up in connection with MTD, it
may be a good idea if MTD gave driver authors a helping hand with DMA
setup/teardown so that the chances of driver authors getting this right
is greater...


From w.sang at pengutronix.de  Thu Jun 30 06:27:28 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Thu, 30 Jun 2011 12:27:28 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <1309335878-16678-2-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
Message-ID: <20110630102728.GB1997@pengutronix.de>


> +static int mil_ecc_write_oob(struct mtd_info *mtd,
> +				struct nand_chip *nand, int page)
> +{
> +	struct gpmi_nfc_data *this = nand->priv;
> +	struct device *dev = this->dev;
> +	struct mil *mil	= &this->mil;
> +	uint8_t *block_mark;
> +	int block_mark_column;
> +	int status;
> +	int error = 0;
> +
> +	/* Only marking a block bad is permitted to write the OOB. */
> +	if (!mil->marking_a_bad_block) {
> +		dev_emerg(dev, "This driver doesn't support writing the OOB\n");
> +		WARN_ON(1);
> +		error = -EIO;
> +		goto exit;
> +	}

Huh? Why is that? This will break JFFS2, for example.

-- 
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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110630/1c60291e/attachment.sig>

From w.sang at pengutronix.de  Thu Jun 30 06:40:09 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Thu, 30 Jun 2011 12:40:09 +0200
Subject: [PATCH v7 0/3]  add the GPMI controller driver for IMX23/IMX28
In-Reply-To: <1309335878-16678-1-git-send-email-b32955@freescale.com>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
Message-ID: <20110630104009.GC1997@pengutronix.de>

On Wed, Jun 29, 2011 at 04:24:35PM +0800, Huang Shijie wrote:
> The general-purpose media interface(GPMI) controller is a flexible interface
> to up to several NAND flashs.
> 
> The Bose Ray-Choudhury Hocquenghem(BCH) module is a hardware ECC accelerator.
> 
> With the help of BCH, the GPMI controller can choose to do the hardware ECC or
> not.
> 
> This driver is a _pure_ MTD NAND controller driver now.

It seems writing does not work for me. I use a MX28EVK, NAND is reported as:

[    1.670000] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xdc (Micron MT29F4G08ABADAWP)

With ubiformat or the mtd_stresstest-module, I get stuff like this:

root at device:~ ubiformat /dev/mtd0
ubiformat: mtd0 (nand), size 536870912 bytes (512.0 MiB), 4096 eraseblocks of 131072 bytes (128.0 KiB), min. I/O size 2048 bytes
libscan: scanning eraseblock 4095 -- 100 % complete  
ubiformat: 4094 eraseblocks are supposedly empty
ubiformat: 2 bad eraseblocks found, numbers: 1243, 3935
ubiformat: formatting eraseblock 2 --  0 % complete  
[  172.430000] [ start_dma_without_bch_irq : 393 ] DMA timeout!!!
[  173.430000] [ start_dma_with_bch_irq : 424 ] bch timeout!!!
[  173.430000] [ mil_ecc_write_page : 1647 ] Error in ECC-based write: -110
[  173.440000] [ send_command : 305 ] step 1 error
[  173.440000] [ mil_cmd_ctrl : 1369 ] Chip: 0, Error -1
[  173.450000] [ send_command : 305 ] step 1 error
[  173.450000] [ mil_cmd_ctrl : 1369 ] Chip: 0, Error -1
[  173.460000] [ read_data : 386 ] step 1 error
...

Reading works though, mtd_readtest passes. Wild guess: something wrong
with the safe timings, perhaps?

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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110630/391f685e/attachment-0001.sig>

From dedekind1 at gmail.com  Thu Jun 30 06:45:31 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 13:45:31 +0300
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <20110630091951.GQ21898@n2100.arm.linux.org.uk>
References: <20110608101804.GA5527@july> <1309420530.23597.153.camel@sauron>
	<20110630091951.GQ21898@n2100.arm.linux.org.uk>
Message-ID: <1309430735.23597.165.camel@sauron>

Hi,

On Thu, 2011-06-30 at 10:19 +0100, Russell King - ARM Linux wrote:
> Which is that this code is trying to work around the restriction in the
> DMA API that dma_map_single() can only take virtual addresses in the
> kernel direct mapped region.

OK.

> The key thing here is that with CPUs which lookup by virtual address,
> like ARMs, you _must_ handle the cache aliases associated with the mapping
> which you are accessing the memory via.
> 
> This means if you are accessing a DMA buffer at address X, and address X
> is cacheable, address X needs cache maintainence performed on it.  Address
> Y, which may correspond with the same memory as X through a different
> mapping is no good.  It has to be X.

Jut to make sure I understand the issue (I am not good at all in this
stuff, this is why I CCed the arm ML):

* if I vmalloc a buffer, I and up with physical memory which has 2
mappings - X which is the direct kernel mapping and Y, which is the
vmalloc mapping.
* The DMA API takes care only about direct mapping in terms of CPU cache
flushing and invalidating. The vmalloc mapping is not taken care of.

And this may cause memory corruptions.

Correct?

> However, there is NO API for mapping DMA buffers from vmalloc space.
> What we do now have are a pair of functions which must be used _correctly_
> (iow, one before and one after) to ensure that virtual cached architectures
> can access the data correctly - and its documented at the bottom of
> cachetlb.txt.

OK, so you do not say it is fundamentally impossible to DMA vmalloc'ed
memory, it is just that no one bothered to invent an API for this.

> As this is something which keeps coming up in connection with MTD, it
> may be a good idea if MTD gave driver authors a helping hand with DMA
> setup/teardown so that the chances of driver authors getting this right
> is greater...

Yes, or the MTD community may push back all hacks and force someone to
invent the API...

Am I right that if we add a helper function which flushes and
invalidates CPU caches for the vmalloc mapping, and then calls the DMA
API function which will take care of the direct mapping, we should be
fine?

Thanks!

P.S.: we really need to document this issue somewhere - either on the
MTD web site or in Documentation/dma-vmalloced-memory.txt.

-- 
Best Regards,
Artem Bityutskiy



From linux at arm.linux.org.uk  Thu Jun 30 07:23:54 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 30 Jun 2011 12:23:54 +0100
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <1309430735.23597.165.camel@sauron>
References: <20110608101804.GA5527@july> <1309420530.23597.153.camel@sauron>
	<20110630091951.GQ21898@n2100.arm.linux.org.uk>
	<1309430735.23597.165.camel@sauron>
Message-ID: <20110630112354.GW21898@n2100.arm.linux.org.uk>

On Thu, Jun 30, 2011 at 01:45:31PM +0300, Artem Bityutskiy wrote:
> Hi,
> 
> On Thu, 2011-06-30 at 10:19 +0100, Russell King - ARM Linux wrote:
> > Which is that this code is trying to work around the restriction in the
> > DMA API that dma_map_single() can only take virtual addresses in the
> > kernel direct mapped region.
> 
> OK.
> 
> > The key thing here is that with CPUs which lookup by virtual address,
> > like ARMs, you _must_ handle the cache aliases associated with the mapping
> > which you are accessing the memory via.
> > 
> > This means if you are accessing a DMA buffer at address X, and address X
> > is cacheable, address X needs cache maintainence performed on it.  Address
> > Y, which may correspond with the same memory as X through a different
> > mapping is no good.  It has to be X.
> 
> Jut to make sure I understand the issue (I am not good at all in this
> stuff, this is why I CCed the arm ML):
> 
> * if I vmalloc a buffer, I and up with physical memory which has 2
> mappings - X which is the direct kernel mapping and Y, which is the
> vmalloc mapping.
> * The DMA API takes care only about direct mapping in terms of CPU cache
> flushing and invalidating. The vmalloc mapping is not taken care of.
> 
> And this may cause memory corruptions.
> 
> Correct?

Yes.

> > However, there is NO API for mapping DMA buffers from vmalloc space.
> > What we do now have are a pair of functions which must be used _correctly_
> > (iow, one before and one after) to ensure that virtual cached architectures
> > can access the data correctly - and its documented at the bottom of
> > cachetlb.txt.
> 
> OK, so you do not say it is fundamentally impossible to DMA vmalloc'ed
> memory, it is just that no one bothered to invent an API for this.

It is not impossible, and XFS has had exactly the same issues - but
remember that XFS has to work with the block layer with drivers which
have no idea that the memory they're writing/reading may be also mapped
into vmalloc space.  The two functions at the bottom of cachetlb.txt were
invented to allow XFS to do this.

> > As this is something which keeps coming up in connection with MTD, it
> > may be a good idea if MTD gave driver authors a helping hand with DMA
> > setup/teardown so that the chances of driver authors getting this right
> > is greater...
> 
> Yes, or the MTD community may push back all hacks and force someone to
> invent the API...

It's probably going to be better to have a MTD block API for DMA which
provides a scatterlist to the MTD block driver, and which knows whether
the memory is from vmalloc.  When it is, it takes care of the flushing
via those two functions I referred to in cachetlb.txt.

This keeps the magic out of the individual MTD block drivers, and stops
them replicating the same mistakes time and time again - and also means
that you won't have to teach everyone about this.

It doesn't make sense for the DMA API to deal with vmalloc - MTD is
one of the very few (the only?) subsystems which does this.


From dedekind1 at gmail.com  Thu Jun 30 07:47:33 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 14:47:33 +0300
Subject: [PATCH 5/6] nand_flash_detect_onfi propagate busw info
In-Reply-To: <1309105616-3609-5-git-send-email-matthieu.castet@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-5-git-send-email-matthieu.castet@parrot.com>
Message-ID: <1309434458.23597.173.camel@sauron>

On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> there is a bug in nand_flash_detect_onfi, busw need to be passed
> by pointer to return it.
> 
> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> ---
>  drivers/mtd/nand/nand_base.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)

Pushed this patch to the l2 tree. It did not apply cleanly, though,
would be nice if your patches were based on l2-mtd-2.6.git.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 07:49:14 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 14:49:14 +0300
Subject: [PATCH] MTD: atmel_nand: fix wrong use of 0 as NULL
In-Reply-To: <1309365676-19210-1-git-send-email-nicolas.ferre@atmel.com>
References: <1309365676-19210-1-git-send-email-nicolas.ferre@atmel.com>
Message-ID: <1309434559.23597.174.camel@sauron>

On Wed, 2011-06-29 at 18:41 +0200, Nicolas Ferre wrote:
> Fixing this error:
> atmel_nand.c:718:20: warning: Using plain integer as NULL pointer
> 
> Signed-off-by: Nicolas Ferre <nicolas.ferre at atmel.com>

Pushed to l2-mtd-2.6.git, thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 07:51:08 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 14:51:08 +0300
Subject: [PATCH 2/2] mtd/nand : workaround for Freescale FCM to support
	large-page Nand chip
In-Reply-To: <20110629114329.154aaef2@schlenkerla.am.freescale.net>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
	<1309225852-1664-2-git-send-email-b35362@freescale.com>
	<1309328529.23597.106.camel@sauron>
	<20110629114329.154aaef2@schlenkerla.am.freescale.net>
Message-ID: <1309434673.23597.176.camel@sauron>

On Wed, 2011-06-29 at 11:43 -0500, Scott Wood wrote:
> On Wed, 29 Jun 2011 09:22:04 +0300
> Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> 
> > On Tue, 2011-06-28 at 09:50 +0800, b35362 at freescale.com wrote:
> > > +	/* Hack for supporting the flash chip whose writesize is
> > > +	 * larger than 2K bytes.
> > > +	 */
> > 
> > Please, use proper kernel multi-line comments. Please, make sure
> > checkpatch.pl does not generate 13 errors with this patch.
> 
> Most of the checkpatch complaints are about existing style in the file --
> particularly, the use of tabs only for indentation, with spaces used for
> alignment beyond the indentation point.

OK, fair enough, but the multi-line comment is a valid complain,
although minor. And you guys could just fix the style issues as well in
a separate patch-set.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 07:53:13 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 14:53:13 +0300
Subject: [PATCH 1/2] mtd/nand : don't free the global data
	fsl_lbc_ctrl_dev->nand in fsl_elbc_chip_remove()
In-Reply-To: <20110629114558.13975519@schlenkerla.am.freescale.net>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
	<1309328435.23597.104.camel@sauron>
	<20110629114558.13975519@schlenkerla.am.freescale.net>
Message-ID: <1309434797.23597.178.camel@sauron>

On Wed, 2011-06-29 at 11:45 -0500, Scott Wood wrote:
> On Wed, 29 Jun 2011 09:20:25 +0300
> Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> 
> > On Tue, 2011-06-28 at 09:50 +0800, b35362 at freescale.com wrote:
> > > From: Liu Shuo <b35362 at freescale.com>
> > > 
> > > The global data fsl_lbc_ctrl_dev->nand don't have to be freed in
> > > fsl_elbc_chip_remove(). The right place to do that is in fsl_elbc_nand_remove()
> > > if elbc_fcm_ctrl->counter is zero.
> > > 
> > > Signed-off-by: Liu Shuo <b35362 at freescale.com>
> > > ---
> > >  drivers/mtd/nand/fsl_elbc_nand.c |    1 -
> > >  1 files changed, 0 insertions(+), 1 deletions(-)
> > > 
> > > diff --git a/drivers/mtd/nand/fsl_elbc_nand.c b/drivers/mtd/nand/fsl_elbc_nand.c
> > > index 0bb254c..a212116 100644
> > > --- a/drivers/mtd/nand/fsl_elbc_nand.c
> > > +++ b/drivers/mtd/nand/fsl_elbc_nand.c
> > > @@ -829,7 +829,6 @@ static int fsl_elbc_chip_remove(struct fsl_elbc_mtd *priv)
> > >  
> > >  	elbc_fcm_ctrl->chips[priv->bank] = NULL;
> > >  	kfree(priv);
> > > -	kfree(elbc_fcm_ctrl);
> > >  	return 0;
> > >  }
> > 
> > Do we have to assign fsl_lbc_ctrl_dev->nand to NULL in
> > fsl_elbc_nand_remove() then? I think that assignment can be killed then.
> > 
> >         if (!elbc_fcm_ctrl->counter) {
> >                 fsl_lbc_ctrl_dev->nand = NULL;
> >                 kfree(elbc_fcm_ctrl);
> >         }
> > 
> 
> If we're freeing fsl_lbc_ctrl, we'd better get rid of references to it...

Yes, on the one hand this is a good defensive programming practice, on
the other hand it hides double-free bugs. Like this patch fixes a
double-free bug, and why it was noticed before? I thought may be because
of this NULL assignment?

I do not insist though, that was just a suggestion/question.

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 07:54:27 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 14:54:27 +0300
Subject: [PATCH] flash_erase: fix incorrect help message
In-Reply-To: <1309371258-18936-1-git-send-email-computersforpeace@gmail.com>
References: <1309371258-18936-1-git-send-email-computersforpeace@gmail.com>
Message-ID: <1309434871.23597.179.camel@sauron>

On Wed, 2011-06-29 at 11:14 -0700, Brian Norris wrote:
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> ---
>  flash_erase.c |    2 +-
>  1 files changed, 1 insertions(+), 1 deletions(-)

Pushed, thanks Brian!

-- 
Best Regards,
Artem Bityutskiy



From axel.lin at gmail.com  Thu Jun 30 07:53:09 2011
From: axel.lin at gmail.com (Axel Lin)
Date: Thu, 30 Jun 2011 19:53:09 +0800
Subject: [PATCH] mtd: fsl_upm: fix a memory leak in fun_chip_init error path
Message-ID: <1309434789.3256.1.camel@phoenix>

Signed-off-by: Axel Lin <axel.lin at gmail.com>
---
 drivers/mtd/nand/fsl_upm.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/mtd/nand/fsl_upm.c b/drivers/mtd/nand/fsl_upm.c
index da92fed..b4f3cc9 100644
--- a/drivers/mtd/nand/fsl_upm.c
+++ b/drivers/mtd/nand/fsl_upm.c
@@ -196,6 +196,8 @@ static int __devinit fun_chip_init(struct fsl_upm_nand *fun,
 	ret = mtd_device_parse_register(&fun->mtd, NULL, &ppdata, NULL, 0);
 err:
 	of_node_put(flash_np);
+	if (ret)
+		kfree(fun->mtd.name);
 	return ret;
 }
 
-- 
1.7.4.1





From dedekind1 at gmail.com  Thu Jun 30 08:08:29 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 15:08:29 +0300
Subject: [PATCH] mtd: tmio_nand: fix build error
In-Reply-To: <BANLkTikonD2fcbkBU2ESYm_XncBXNZc_hw@mail.gmail.com>
References: <1309408494.10500.1.camel@phoenix>
	<BANLkTikonD2fcbkBU2ESYm_XncBXNZc_hw@mail.gmail.com>
Message-ID: <1309435714.23597.181.camel@sauron>

On Thu, 2011-06-30 at 12:23 +0400, Dmitry Eremin-Solenikov wrote:
> On 6/30/11, Axel Lin <axel.lin at gmail.com> wrote:
> > Fix a mistake introduced by commit 33f4a3b
> > "mtd: tmio_nand.c: use mtd_device_parse_register"
> 
> Already sumbited 27 June 2011. Strangely Artem remains silent.

I handle my mailbox in FIFO order (with exceptions) so I have not
reached your patch yet. Now I've merged it with one of your previous
patches to keep the kernel bisectable.

Thanks!

-- 
Best Regards,
Artem Bityutskiy



From dedekind1 at gmail.com  Thu Jun 30 08:36:39 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 15:36:39 +0300
Subject: [PATCH 2/6] nand_wait : warn if the nand is busy on exit
In-Reply-To: <20110629135934.GA18102@parrot.com>
References: <1309105616-3609-1-git-send-email-matthieu.castet@parrot.com>
	<1309105616-3609-2-git-send-email-matthieu.castet@parrot.com>
	<1309247836.23597.42.camel@sauron> <4E09ED56.2070704@parrot.com>
	<1309287916.7411.9.camel@koala> <20110629135934.GA18102@parrot.com>
Message-ID: <1309437403.23597.194.camel@sauron>

On Wed, 2011-06-29 at 15:59 +0200, Ivan Djelic wrote:
> On Tue, Jun 28, 2011 at 08:05:14PM +0100, Artem Bityutskiy wrote:
> > On Tue, 2011-06-28 at 17:03 +0200, Matthieu CASTET wrote:
> > > Artem Bityutskiy a ?crit :
> > > > On Sun, 2011-06-26 at 18:26 +0200, Matthieu CASTET wrote:
> > > >> This patch allow to detect buggy driver/hardware with
> > > >> bad RnB (dev_ready) management.
> > > >> This check cost nothing and could help to detect bugs.
> > > >>
> > > >> Signed-off-by: Matthieu CASTET <matthieu.castet at parrot.com>
> > > >> ---
> > > >>  drivers/mtd/nand/nand_base.c |    2 ++
> > > >>  1 files changed, 2 insertions(+), 0 deletions(-)
> > > >>
> > > >> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> > > >> index a3c7fd3..095dfea 100644
> > > >> --- a/drivers/mtd/nand/nand_base.c
> > > >> +++ b/drivers/mtd/nand/nand_base.c
> > > >> @@ -885,6 +885,8 @@ static int nand_wait(struct mtd_info *mtd, struct nand_chip *chip)
> > > >>  	led_trigger_event(nand_led_trigger, LED_OFF);
> > > >>  
> > > >>  	status = (int)chip->read_byte(mtd);
> > > >> +	/* This can happen if in case of timeout or buggy dev_ready */
> > > >> +	WARN_ON(!(status & NAND_STATUS_READY));
> > > >>  	return status;
> > > > 
> > > > This seem to completely miss the chip->dev_ready != NULL case, e.g.,
> > > > piece of code above is like this
> > > > 
> > > >                 while (time_before(jiffies, timeo)) {
> > > >                         if (chip->dev_ready) {
> > > >                                 if (chip->dev_ready(mtd))
> > > >                                         break;
> > > >                         } else {
> > > >                                 if (chip->read_byte(mtd) & NAND_STATUS_READY)
> > > >                                         break;
> > > >                         }
> > > >                         cond_resched();
> > > >                 }
> > > > 
> > > Sorry, I don't understand what you mean.
> > > 
> > > We don't care what's done in the loop (chip->dev_ready != NULL or, not). We only
> > > check when the loop exit, that READY bit is set in the status.
> > 
> > Well, the logic is suspicious.
> > 
> > 1. For NAND with chip->dev_ready != NULL, why NAND_STATUS_READY should
> > be set? We do not check for this in the loop.
> > 
> > 2. For NAND with chip->dev_ready != NULL, if NAND_STATUS_READY has to be
> > set at the end, why wouldn't we drop this chip_ready part completely? We
> > could just loop while NAND_STATUS_READY is not set.
> > 
> > Isn't this strange?
> 
> Not really. There are 2 methods to wait for an erase/program command completion:
> 
> 1. Wait until nand RnB pin goes high (that's what chip->dev_ready usually does)
> 2. Poll the device: send a status (0x70) command and read status byte in a loop
>    until bit NAND_STATUS_READY is set
> 
> In all cases, you should send a status command after completion, to check if
> the operation was successful. And if the operation completed, the status should
> have bit NAND_STATUS_READY set.
> 
> Method 1 is optimal, you can often use an interrupt to signal completion, and
> no cpu cycles are lost in a polling loop. But flaky hardware (bad pull-ups) or
> bad gpio configuration can make it unreliable.
> 
> Method 2 is the safest, it always works, but it is less efficient.

Thanks, this is basically the reply I waited for - the explanation how
it works. You guys should not assume that I know everything - I just do
my best to keep MTD subsystem working and make people improve it :-) And
sometimes I just have no time to dig things and ask people to educate
me, to save my time :-)

> Here, Matthieu wants to detect cases where method 1 is unreliable or a timeout
> occurs (e.g. somebody forgot to put a nand device on the board :).
> Both conditions are not expected on working hardware.

Fair enough, thanks!

However, the code is not easy to follow, and this assumption which you
explained - "if dev_ready() returns truth, the status command has to be
sent anyway and the READY bit has to be there anyway" - it is subtle,
and makes the nand_base.c less readable, and more error prone.

And there are tons of things like this. And what the community do in
these cases - it forces people who just want to do a simple thing to
also do general clean-ups, at least some reasonable amount of it.

E.g., recently people cleaned-up the partitions stuff, and this started
with our refusal to take a simple path which touched the MTD_PARTITIONS
macro.

So, what I suggested to Matthieu, although in a vague way, is to look
how this subtle dev_ready things could be cleaned-up.

I said that we probably may:

1. Introduce something like default_dev_ready() which falls-back to the
status polling unless the driver provides it's own.
2. Look to all the if (chip->dev_ready) do A else do B things and try to
remove them.

To put it differently, I am trying to encourage you guys to clean-up the
code a bit in this dev_ready/status area before changing this area.

Any ideas? :-)

-- 
Best Regards,
Artem Bityutskiy



From dbaryshkov at gmail.com  Thu Jun 30 08:41:02 2011
From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov)
Date: Thu, 30 Jun 2011 16:41:02 +0400
Subject: [PATCH] mtd: tmio_nand: fix build error
In-Reply-To: <1309435714.23597.181.camel@sauron>
References: <1309408494.10500.1.camel@phoenix>
	<BANLkTikonD2fcbkBU2ESYm_XncBXNZc_hw@mail.gmail.com>
	<1309435714.23597.181.camel@sauron>
Message-ID: <BANLkTik-pWfbC3J9LkB-jL9H8cnoLR=R-Q@mail.gmail.com>

On 6/30/11, Artem Bityutskiy <dedekind1 at gmail.com> wrote:
> On Thu, 2011-06-30 at 12:23 +0400, Dmitry Eremin-Solenikov wrote:
>> On 6/30/11, Axel Lin <axel.lin at gmail.com> wrote:
>> > Fix a mistake introduced by commit 33f4a3b
>> > "mtd: tmio_nand.c: use mtd_device_parse_register"
>>
>> Already sumbited 27 June 2011. Strangely Artem remains silent.
>
> I handle my mailbox in FIFO order (with exceptions) so I have not
> reached your patch yet. Now I've merged it with one of your previous
> patches to keep the kernel bisectable.

Thanks and sorry if my comment offended you! It's just I see most of
MLs/patches in threads, so I was a bit puzzled.

-- 
With best wishes
Dmitry


From dedekind1 at gmail.com  Thu Jun 30 09:38:33 2011
From: dedekind1 at gmail.com (Artem Bityutskiy)
Date: Thu, 30 Jun 2011 16:38:33 +0300
Subject: [PATCH] mtd: OneNAND: samsung: Write DMA support
In-Reply-To: <20110630112354.GW21898@n2100.arm.linux.org.uk>
References: <20110608101804.GA5527@july> <1309420530.23597.153.camel@sauron>
	<20110630091951.GQ21898@n2100.arm.linux.org.uk>
	<1309430735.23597.165.camel@sauron>
	<20110630112354.GW21898@n2100.arm.linux.org.uk>
Message-ID: <1309441118.23597.198.camel@sauron>

On Thu, 2011-06-30 at 12:23 +0100, Russell King - ARM Linux wrote:
> It's probably going to be better to have a MTD block API for DMA which
> provides a scatterlist to the MTD block driver, and which knows whether
> the memory is from vmalloc.  When it is, it takes care of the flushing
> via those two functions I referred to in cachetlb.txt.
> 
> This keeps the magic out of the individual MTD block drivers, and stops
> them replicating the same mistakes time and time again - and also means
> that you won't have to teach everyone about this.

Yeah, something like this. The MTD API is not very suitable for this and
would need some rework to make sure we achieve 2 goals:

1. No need to change current MTD API users
2. Keep the vmalloced memory handling in one place and not replicate it
   in each driver.

Currently only OneNAND drivers do these hacks, so I guess Kyungmin will
suffer most...

> It doesn't make sense for the DMA API to deal with vmalloc - MTD is
> one of the very few (the only?) subsystems which does this.

OK, thank you!

-- 
Best Regards,
Artem Bityutskiy



From arnd at arndb.de  Thu Jun 30 09:55:19 2011
From: arnd at arndb.de (Arnd Bergmann)
Date: Thu, 30 Jun 2011 15:55:19 +0200
Subject: [PATCH v5 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <1309406028-2924-2-git-send-email-b32955@freescale.com>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
	<1309406028-2924-2-git-send-email-b32955@freescale.com>
Message-ID: <201106301555.19440.arnd@arndb.de>

On Thursday 30 June 2011, Huang Shijie wrote:
> add GPMI-NFC support for imx23 and imx28.
> 
> Signed-off-by: Huang Shijie <b32955 at freescale.com>

This needs a better changelog, please at least spell out what GPMI-NFC means.
I'm probably not the only one who gets confused into reading this as
'near field communication' instead of 'nand flash controller'.

Could you rename this all into gpmi-nand or gpmi-flash instead, to avoid
confusion when you add support for near field communication?

> +#define RES_MEM(soc, _id, _s, _n)				\
> +	{							\
> +		.start = soc ##_## _id ## _BASE_ADDR,		\
> +		.end   = soc ##_## _id ## _BASE_ADDR + (_s) - 1,\
> +		.name  = (_n),					\
> +		.flags = IORESOURCE_MEM,			\
> +	}
> +
> +#define RES_IRQ(soc, _id, _n)			\
> +	{					\
> +		.start = soc ##_INT_## _id,	\
> +		.end   = soc ##_INT_## _id,	\
> +		.name  = (_n),			\
> +		.flags = IORESOURCE_IRQ,	\
> +	}
> +
> +#define RES_DMA(soc, _i_s, _i_e, _n)		\
> +	{					\
> +		.start = soc ##_## _i_s,	\
> +		.end   = soc ##_## _i_e,	\
> +		.name  = (_n),			\
> +		.flags = IORESOURCE_DMA,	\
> +	}

I know that you didn't start this pattern, but I find these macros
extremely annoying. It obscures the use of the macros with the
string concatenation and the macro names are way too generic
for something platform specific. If people think it's a good idea
to have these, please submit a patch to add macros (without the
string concatenation) into include/linux/ioport.h.

Until then, better spell out the resources.

> +/**
> + * struct gpmi_nfc_platform_data - GPMI NFC driver platform data.
> + *
> + * This structure communicates platform-specific information to the GPMI NFC
> + * driver that can't be expressed as resources.
> + *
> + * @platform_init:           A pointer to a function the driver will call to
> + *                           initialize the platform (e.g., set up the pin mux).
> + * @platform_exit:           A pointer to a function the driver will call to
> + *                           exit the platform (e.g., free pins).
> + * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
> + *                           from the NAND Flash device, in nanoseconds.
> + * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
> + *                           from the NAND Flash device, in nanoseconds.
> + * @max_chip_count:          The maximum number of chips for which the driver
> + *                           should configure the hardware. This value most
> + *                           likely reflects the number of pins that are
> + *                           connected to a NAND Flash device. If this is
> + *                           greater than the SoC hardware can support, the
> + *                           driver will print a message and fail to initialize.
> + * @partitions:              An optional pointer to an array of partition
> + *                           descriptions.
> + * @partition_count:         The number of elements in the partitions array.
> + */
> +struct gpmi_nfc_platform_data {
> +	/* SoC hardware information. */
> +	int		(*platform_init)(void);
> +	void		(*platform_exit)(void);
> +
> +	/* NAND Flash information. */
> +	unsigned int	min_prop_delay_in_ns;
> +	unsigned int	max_prop_delay_in_ns;
> +	unsigned int	max_chip_count;
> +
> +	/* Medium information. */
> +	struct mtd_partition *partitions;
> +	unsigned	partition_count;
> +};

When adding new infrastructure, always keep in mind how you want it to look
after the device tree conversion. The partitions and min/max_* are easily covered
with that, but the init/exit function pointers are somewhat problematic.

Fortunately, you don't really require these functions for this driver. The _exit
function is completely unused, so just get rid of it.

The init function is used only to set up iomux, so the logical replacement is
a pointer to the iomux data, and calling mxs_iomux_setup_multiple_pads
directly from the driver.

	Arnd


From LW at KARO-electronics.de  Thu Jun 30 10:58:38 2011
From: LW at KARO-electronics.de (=?utf-8?Q?Lothar_Wa=C3=9Fmann?=)
Date: Thu, 30 Jun 2011 16:58:38 +0200
Subject: [PATCH v5 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <201106301555.19440.arnd@arndb.de>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
	<1309406028-2924-2-git-send-email-b32955@freescale.com>
	<201106301555.19440.arnd@arndb.de>
Message-ID: <19980.36638.134045.743619@ipc1.ka-ro>

Hi,

Arnd Bergmann writes:
> On Thursday 30 June 2011, Huang Shijie wrote:
> > add GPMI-NFC support for imx23 and imx28.
> > 
> > Signed-off-by: Huang Shijie <b32955 at freescale.com>
> 
[...]
> > +struct gpmi_nfc_platform_data {
> > +	/* SoC hardware information. */
> > +	int		(*platform_init)(void);
> > +	void		(*platform_exit)(void);
> > +
> > +	/* NAND Flash information. */
> > +	unsigned int	min_prop_delay_in_ns;
> > +	unsigned int	max_prop_delay_in_ns;
> > +	unsigned int	max_chip_count;
> > +
> > +	/* Medium information. */
> > +	struct mtd_partition *partitions;
> > +	unsigned	partition_count;
> > +};
> 
> When adding new infrastructure, always keep in mind how you want it to look
> after the device tree conversion. The partitions and min/max_* are easily covered
> with that, but the init/exit function pointers are somewhat problematic.
> 
> Fortunately, you don't really require these functions for this driver. The _exit
> function is completely unused, so just get rid of it.
> 
> The init function is used only to set up iomux, so the logical replacement is
> a pointer to the iomux data, and calling mxs_iomux_setup_multiple_pads
> directly from the driver.
> 
NO! I strongly object that. mxs_iomux_setup_multiple_pads() is a
platform specific function and has no business inside a device driver
that should be platform agnostic.
Consider the same controller being part of a different SoC that
requires you to call mxs_iomux_v2_setup_multiple_pads() instead. You
would then have to check for the SoC type inside the driver to find
the right function to call which is quite obscene.

I would rather live with the iomux statically configured in the
platform init code than having direct calls into platform specific
code from device drivers.


Lothar Wa?mann
-- 
___________________________________________________________

Ka-Ro electronics GmbH | Pascalstra?e 22 | D - 52076 Aachen
Phone: +49 2408 1402-0 | Fax: +49 2408 1402-10
Gesch?ftsf?hrer: Matthias Kaussen
Handelsregistereintrag: Amtsgericht Aachen, HRB 4996

www.karo-electronics.de | info at karo-electronics.de
___________________________________________________________


From B32955 at freescale.com  Thu Jun 30 11:21:21 2011
From: B32955 at freescale.com (Huang Shijie-B32955)
Date: Thu, 30 Jun 2011 15:21:21 +0000
Subject: reply: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
Message-ID: <14C4E31473AF7E4B98176CB73615181C19FB3C@039-SN1MPN1-006.039d.mgd.msft.net>


Hi Wolfram:

> +static int mil_ecc_write_oob(struct mtd_info *mtd,
> +                             struct nand_chip *nand, int page)
> +{
> +     struct gpmi_nfc_data *this = nand->priv;
> +     struct device *dev = this->dev;
> +     struct mil *mil = &this->mil;
> +     uint8_t *block_mark;
> +     int block_mark_column;
> +     int status;
> +     int error = 0;
> +
> +     /* Only marking a block bad is permitted to write the OOB. */
> +     if (!mil->marking_a_bad_block) {
> +             dev_emerg(dev, "This driver doesn't support writing the OOB\n");
> +             WARN_ON(1);
> +             error = -EIO;
> +             goto exit;
> +     }

Huh? Why is that? This will break JFFS2, for example.

-----------------------------------------------------------------
The GPMI-NFC driver will use the OOB(BCH will use the OOB for a special layout), so we forbid any others to use the OOB.
But marking a block bad is permitted.

If the JFFS2 use the OOB, we have to disable it
We use UBIFS by default.

Thanks.

Best Regards
Huang Shijie




-----------------------------------------------------------------

--
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |



From B32955 at freescale.com  Thu Jun 30 11:30:48 2011
From: B32955 at freescale.com (Huang Shijie-B32955)
Date: Thu, 30 Jun 2011 15:30:48 +0000
Subject: reply: [PATCH v7 0/3]  add the GPMI controller driver for IMX23/IMX28
Message-ID: <14C4E31473AF7E4B98176CB73615181C19FB66@039-SN1MPN1-006.039d.mgd.msft.net>

Hi Wolfram:

Thanks for your hard work.

On Wed, Jun 29, 2011 at 04:24:35PM +0800, Huang Shijie wrote:
> The general-purpose media interface(GPMI) controller is a flexible interface
> to up to several NAND flashs.
>
> The Bose Ray-Choudhury Hocquenghem(BCH) module is a hardware ECC accelerator.
>
> With the help of BCH, the GPMI controller can choose to do the hardware ECC or
> not.
>
> This driver is a _pure_ MTD NAND controller driver now.

It seems writing does not work for me. I use a MX28EVK, NAND is reported as:

[    1.670000] NAND device: Manufacturer ID: 0x2c, Chip ID: 0xdc (Micron MT29F4G08ABADAWP)

With ubiformat or the mtd_stresstest-module, I get stuff like this:

root at device:~ ubiformat /dev/mtd0
ubiformat: mtd0 (nand), size 536870912 bytes (512.0 MiB), 4096 eraseblocks of 131072 bytes (128.0 KiB), min. I/O size 2048 bytes
libscan: scanning eraseblock 4095 -- 100 % complete
ubiformat: 4094 eraseblocks are supposedly empty
ubiformat: 2 bad eraseblocks found, numbers: 1243, 3935
ubiformat: formatting eraseblock 2 --  0 % complete
[  172.430000] [ start_dma_without_bch_irq : 393 ] DMA timeout!!!
[  173.430000] [ start_dma_with_bch_irq : 424 ] bch timeout!!!
[  173.430000] [ mil_ecc_write_page : 1647 ] Error in ECC-based write: -110
[  173.440000] [ send_command : 305 ] step 1 error
[  173.440000] [ mil_cmd_ctrl : 1369 ] Chip: 0, Error -1
[  173.450000] [ send_command : 305 ] step 1 error
[  173.450000] [ mil_cmd_ctrl : 1369 ] Chip: 0, Error -1
[  173.460000] [ read_data : 386 ] step 1 error
...

Reading works though, mtd_readtest passes. Wild guess: something wrong
with the safe timings, perhaps?
------------------------------------------------------------------------------------------------------
The log shows that it's a DMA failure.

I will debug it when i am free.

Best Regards
Huang Shijie


------------------------------------------------------------------------------------------------------

Regards,

   Wolfram

--
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |



From B32955 at freescale.com  Thu Jun 30 12:12:27 2011
From: B32955 at freescale.com (Huang Shijie-B32955)
Date: Thu, 30 Jun 2011 16:12:27 +0000
Subject: reply: [PATCH v5 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
Message-ID: <14C4E31473AF7E4B98176CB73615181C19FBD3@039-SN1MPN1-006.039d.mgd.msft.net>

Hi Arnd:

On Thursday 30 June 2011, Huang Shijie wrote:
> add GPMI-NFC support for imx23 and imx28.
>
> Signed-off-by: Huang Shijie <b32955 at freescale.com>

>This needs a better changelog, please at least spell out what GPMI-NFC means.
>I'm probably not the only one who gets confused into reading this as
>'near field communication' instead of 'nand flash controller'.

=============================================
thanks.
I will add more information in the following version.


=============================================

>Could you rename this all into gpmi-nand or gpmi-flash instead, to avoid
>confusion when you add support for near field communication?

==========================================
This is a nand flash controller driver.

I think gpmi-nfc is much better then gpmi-nand or gpmi-flash.
==========================================

> +#define RES_MEM(soc, _id, _s, _n)                            \
> +     {                                                       \
> +             .start = soc ##_## _id ## _BASE_ADDR,           \
> +             .end   = soc ##_## _id ## _BASE_ADDR + (_s) - 1,\
> +             .name  = (_n),                                  \
> +             .flags = IORESOURCE_MEM,                        \
> +     }
> +
> +#define RES_IRQ(soc, _id, _n)                        \
> +     {                                       \
> +             .start = soc ##_INT_## _id,     \
> +             .end   = soc ##_INT_## _id,     \
> +             .name  = (_n),                  \
> +             .flags = IORESOURCE_IRQ,        \
> +     }
> +
> +#define RES_DMA(soc, _i_s, _i_e, _n)         \
> +     {                                       \
> +             .start = soc ##_## _i_s,        \
> +             .end   = soc ##_## _i_e,        \
> +             .name  = (_n),                  \
> +             .flags = IORESOURCE_DMA,        \
> +     }

>I know that you didn't start this pattern, but I find these macros
>extremely annoying. It obscures the use of the macros with the
>string concatenation and the macro names are way too generic
>for something platform specific. If people think it's a good idea
>to have these, please submit a patch to add macros (without the
>string concatenation) into include/linux/ioport.h.

>Until then, better spell out the resources.

==============================================
I ever tried several methods,  but  I can not find a better method to
replace the current method.

It's annoying, but it really saves some lines.

==============================================


> +/**
> + * struct gpmi_nfc_platform_data - GPMI NFC driver platform data.
> + *
> + * This structure communicates platform-specific information to the GPMI NFC
> + * driver that can't be expressed as resources.
> + *
> + * @platform_init:           A pointer to a function the driver will call to
> + *                           initialize the platform (e.g., set up the pin mux).
> + * @platform_exit:           A pointer to a function the driver will call to
> + *                           exit the platform (e.g., free pins).
> + * @min_prop_delay_in_ns:    Minimum propagation delay of GPMI signals to and
> + *                           from the NAND Flash device, in nanoseconds.
> + * @max_prop_delay_in_ns:    Maximum propagation delay of GPMI signals to and
> + *                           from the NAND Flash device, in nanoseconds.
> + * @max_chip_count:          The maximum number of chips for which the driver
> + *                           should configure the hardware. This value most
> + *                           likely reflects the number of pins that are
> + *                           connected to a NAND Flash device. If this is
> + *                           greater than the SoC hardware can support, the
> + *                           driver will print a message and fail to initialize.
> + * @partitions:              An optional pointer to an array of partition
> + *                           descriptions.
> + * @partition_count:         The number of elements in the partitions array.
> + */
> +struct gpmi_nfc_platform_data {
> +     /* SoC hardware information. */
> +     int             (*platform_init)(void);
> +     void            (*platform_exit)(void);
> +
> +     /* NAND Flash information. */
> +     unsigned int    min_prop_delay_in_ns;
> +     unsigned int    max_prop_delay_in_ns;
> +     unsigned int    max_chip_count;
> +
> +     /* Medium information. */
> +     struct mtd_partition *partitions;
> +     unsigned        partition_count;
> +};

>When adding new infrastructure, always keep in mind how you want it to look
>after the device tree conversion. The partitions and min/max_* are easily covered
>with that, but the init/exit function pointers are somewhat problematic.

>Fortunately, you don't really require these functions for this driver. The _exit
>function is completely unused, so just get rid of it.
===================================================
I am reluctant to remove it, I am not sure whether I will use the _exit() in future.
But, yes, it can be removed now.



Best Regards
Huang Shijie

===================================================

The init function is used only to set up iomux, so the logical replacement is
a pointer to the iomux data, and calling mxs_iomux_setup_multiple_pads
directly from the driver.

        Arnd

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel




From linux at arm.linux.org.uk  Thu Jun 30 12:26:36 2011
From: linux at arm.linux.org.uk (Russell King - ARM Linux)
Date: Thu, 30 Jun 2011 17:26:36 +0100
Subject: reply: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC
	controller driver
In-Reply-To: <14C4E31473AF7E4B98176CB73615181C19FB3C@039-SN1MPN1-006.039d.mgd.msft.net>
References: <14C4E31473AF7E4B98176CB73615181C19FB3C@039-SN1MPN1-006.039d.mgd.msft.net>
Message-ID: <20110630162636.GB21898@n2100.arm.linux.org.uk>

Please can to use a mailer which:

1. Understands the convention for subject lines which are replies
   (iow doesn't prefix it with "reply")
2. Understands threading enough to put In-reply-to: and/or References:
   headers into your emails.

Your current mailer makes all your messages look like new threads of
conversation, and are completely disconnected from their real thread.
Not only does that makes it hard to follow the threads, but also
makes it harder to filter messages for reading.

With the amount of email on these mailing lists, this should be a
mandatory requirement for everyone sending messages there.

Thanks.


From scottwood at freescale.com  Thu Jun 30 12:26:56 2011
From: scottwood at freescale.com (Scott Wood)
Date: Thu, 30 Jun 2011 11:26:56 -0500
Subject: [PATCH 1/2] mtd/nand : don't free the global data
	fsl_lbc_ctrl_dev->nand in fsl_elbc_chip_remove()
In-Reply-To: <1309434797.23597.178.camel@sauron>
References: <1309225852-1664-1-git-send-email-b35362@freescale.com>
	<1309328435.23597.104.camel@sauron>
	<20110629114558.13975519@schlenkerla.am.freescale.net>
	<1309434797.23597.178.camel@sauron>
Message-ID: <20110630112656.3257116a@schlenkerla.am.freescale.net>

On Thu, 30 Jun 2011 14:53:13 +0300
Artem Bityutskiy <dedekind1 at gmail.com> wrote:

> On Wed, 2011-06-29 at 11:45 -0500, Scott Wood wrote:
> > If we're freeing fsl_lbc_ctrl, we'd better get rid of references to it...
> 
> Yes, on the one hand this is a good defensive programming practice, on
> the other hand it hides double-free bugs. Like this patch fixes a
> double-free bug, and why it was noticed before? I thought may be because
> of this NULL assignment?

I'm not sure how the NULL assignment was hiding anything here.  It was
probably hidden only because nobody tested it with suitable debug options
enabled since the code was last reorganized.

If the NULL assignment is dropped, consider what happens if the
fsl_elbc_nand module is removed then reinserted.  On reinsertion, it will
see a non-NULL fsl_lbc_ctrl_dev->nand, and will skip allocating a new one.
Then you're referencing freed memory.

Looking more closely, the MAX_BANKS loop should be removed.  Since the
reorganization, the platform device represents one chip, not the
controller, so we should only be removing that one chip.

-Scott



From w.sang at pengutronix.de  Thu Jun 30 13:04:32 2011
From: w.sang at pengutronix.de (Wolfram Sang)
Date: Thu, 30 Jun 2011 19:04:32 +0200
Subject: [PATCH v7 1/3] MTD : add the common code for GPMI-NFC controller
	driver
In-Reply-To: <20110630102728.GB1997@pengutronix.de>
References: <1309335878-16678-1-git-send-email-b32955@freescale.com>
	<1309335878-16678-2-git-send-email-b32955@freescale.com>
	<20110630102728.GB1997@pengutronix.de>
Message-ID: <20110630170432.GA20948@pengutronix.de>

On Thu, Jun 30, 2011 at 12:27:28PM +0200, Wolfram Sang wrote:
> 
> > +static int mil_ecc_write_oob(struct mtd_info *mtd,
> > +				struct nand_chip *nand, int page)
> > +{
> > +	struct gpmi_nfc_data *this = nand->priv;
> > +	struct device *dev = this->dev;
> > +	struct mil *mil	= &this->mil;
> > +	uint8_t *block_mark;
> > +	int block_mark_column;
> > +	int status;
> > +	int error = 0;
> > +
> > +	/* Only marking a block bad is permitted to write the OOB. */
> > +	if (!mil->marking_a_bad_block) {
> > +		dev_emerg(dev, "This driver doesn't support writing the OOB\n");
> > +		WARN_ON(1);
> > +		error = -EIO;
> > +		goto exit;
> > +	}
> 
> Huh? Why is that? This will break JFFS2, for example.

-----------------------------------------------------------------
The GPMI-NFC driver will use the OOB(BCH will use the OOB for a special layout), so we forbid any others to use the OOB.
But marking a block bad is permitted.

If the JFFS2 use the OOB, we have to disable it
We use UBIFS by default.

-----------------------------------------------------------------

(Please use a proper mailer)

Why can't you define a nand_ecclayout with no free space?

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: 198 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-mtd/attachments/20110630/d4438e44/attachment.sig>

From peter.barada at gmail.com  Thu Jun 30 14:05:25 2011
From: peter.barada at gmail.com (Peter Barada)
Date: Thu, 30 Jun 2011 14:05:25 -0400
Subject: Preventing JFFS2 partial page writes?
In-Reply-To: <1309329223.23597.116.camel@sauron>
References: <4DF789FC.1030305@gmail.com> <1308722655.18119.40.camel@sauron>			
	<4E020A36.6070708@gmail.com> <1308943581.13493.15.camel@koala>		
	<4E089441.3010809@gmail.com> <1309253646.23597.58.camel@sauron>	
	<4E0A23D3.8060303@gmail.com> <1309329223.23597.116.camel@sauron>
Message-ID: <4E0CBAE5.6050604@gmail.com>

On 06/29/2011 02:33 AM, Artem Bityutskiy wrote:
> On Tue, 2011-06-28 at 14:56 -0400, Peter Barada wrote:
>> On 06/28/2011 05:34 AM, Artem Bityutskiy wrote:
>>> On Mon, 2011-06-27 at 10:31 -0400, Peter Barada wrote:
>>>> On 06/24/2011 03:26 PM, Artem Bityutskiy wrote:
>>>>> On Wed, 2011-06-22 at 11:28 -0400, Peter Barada wrote:
>>>>>> Thoughts?
>>>>> Sorry, could you please define the problem you are trying to solve?
>>>>> Sorry if you did define it in your long post, but I could not easily
>>>>> find it.
>>>> The problem I'm trying to solve is that the Micron NAND  I'm using has
>>>> an internal 4-bit ECC engine and uses four 8-byte ECCs that provide
>>>> 4-bit protection per 512 data bytes + four OOB bytes.  The ecclayout I'm
>>>> using is:
>>>>
>>>> ecclayout = {
>>>>            eccbytes = 32,
>>>>            eccpos = { 8, 9, 10, 11, 12, 13, 14, 15, /* ECC data bytes
>>>> 0-511 + OOB bytes 4-7 */
>>>>                    24, 25, 26, 27, 28, 19, 30, 31, /* ECC data bytes
>>>> 512-1023 + OOB bytes 20-23 */
>>>>                    40, 41, 42, 43, 44, 45, 46, 47,  /* ECC data bytes
>>>> 1024-1535 + OOB bytes 36-39 */
>>>>                    56, 57, 58, 59, 60, 61, 62, 63},  /* ECC data bytes
>>>> 1536-2047 + OOB bytes 52-55 */
>>>>            .oobfree = {
>>>>                    { .offset = 4,
>>>>                      .length = 4},
>>>>                    { .offset = 20,
>>>>                      .length = 4},
>>>>                    { .offset = 36,
>>>>                      .length = 4},
>>>>                    { .offset = 52,
>>>>                      .length = 4},
>>>>            },
>>>> };
>>>>
>>>> After the JFFS2 cleanmarker is written into bytes 4-7 and 16-23 of the
>>>> OOB, nanddump shows:
>>>>
>>>>      OOB Data: ff ff ff ff 85 19 03 20 5a e3 da 69 01 40 f1 36
>>>>      OOB Data: ff ff ff ff 08 00 00 00 91 99 3c 05 01 d0 5d b3
>>>>      OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>>>>      OOB Data: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>>>>
>>>> Note that the ECC bytes 8-15 and 24-31 are no longer FF due to bytes 4-7
>>>> and bytes 20-23 being written with non-zero data.
>>>>
>>>> When data is later written to this same page (w/o an intervening erase
>>>> of its block) reading the page causes an uncorrectable ECC error.
>>>>
>>>> There are eight additional bytes of OOB space available for writing, but
>>>> they are not ECC'd.
>>>>
>>>> The issue I'm trying to solve is how to communicate from MTD to JFFS2
>>>> that some bytes of the oobfree array perturb the data ECC and can not be
>>>> used to write the cleanmarker.
>>> OK, thanks for explanation. I am not very good in this area as I do not
>>> have much experience dealing with OOB, but here is what I thing.
>>>
>>> 1. Linux MTD code was _not_ designed for "ECC'ed OOB".
>>> 2. I do not really know what MTD_OOB_RAW is, and the comment in mtd.h
>>>      is not very verbose.
>>> 3. But in my opinion MTD_OOB_AUTO makes most sense and should be used
>>>      everywhere except for some tricky cases when you want to test things
>>>      by writing incorrect ECC, or you have an image with ECC and you want
>>>      to flash it as is.
>>> 4. In general, OOB should be considered as belonging to the driver, and
>>>      modern software should not rely on OOB at all.
>>> 5. So MTD_OOB_AUTO make free bytes in OOB look like a contiguous buffer
>>>      which the _user_ can freely and _independently_ use.
>>> 6. In your case only this assumption does not work and your ecclayout is
>>>      incorrect because the OOB areas you expose are not independent.
>>> 7. So in your case your ecclayout should be changed and you should
>>>      expose only independent ECC bytes.
>> The independent ECC bytes available only total to eight, which makes it
>> impossible to use YAFFS (which needs at least 16 bytes to stor e its
>> metadata in).
> Are you sure YAFFS can use the dependent bytes? I am not sure, but I
> thought YAFFS wants OOB to be independently writable, no?
YAFFS2 only writes a page once so it can use dependent bytes.  I have 
YAFFS2 working with the current ECC
layout where it *only* uses the dependent bytes, and units are already 
in the field.  YAFFS1 would delete a page by writing into the OOB area a 
2nd time.
>>   I can add the independent bytes at the end of the layout
>> (and tweak YAFFS to ignore them since it needs only 16 bytes if the
>> metadata is ECC'ed), but I still need to create a fix in JFFS2 (and
>> u-boot and utilities) to skip the first 16 bytes of oobfree area.
> As I said, I think you need to take a good look at MTD and think how you
> can teach it to distinguish with dependent and independent OOB bytes.
I assume you imply that the mtd-utils need to be changed in addition to 
MTD (to at least communicate to MTD not to write OOB data into dependent 
bytes).
>> That's why I think another ioctl call (GETOOBLAYOUT?) would be useful to
>> describe the oobfree list, as well as lists(or bitfields) that indicates
>> which bytes in oobfree are either ECC'ed as part of the data ECC, or
>> ECC'ed independently.
> Why new ioctl? Why not add another OOB access type (like MTD_OOB_AUTO)?
> Or may be one of the existing can be re-use? This should be carefully
> analyzed.
Grepping through a current 2.6 kernel I don't see any way to set the OOB 
method from usersapce.  MEMSETOOBSEL only exists in 
include/mtd/mtd-abi.h and nowhere in driver/mtd.  It looks like it was 
removed way back by Vitaly Wool back in 11/2005.  The current 
MEMWRITEOOB only uses MTD_OOB_PLACE in the kernel (see mtd_do_writeoob() 
in drivers/mtd/mtdchar.c).  Would adding a field (oobtype) in struct 
mtd_oob_buf be the way to go?
>> Another issue this exposes is that JFFS2 reads/compares the cleanmarker
>> w/o any ECC in the marker data to verify its validity - if a bitflip in
>> an unECC'd cleanmarker is read back, then I think JFFS2 will fail to use
>> that block.
> No, I think what JFFS2 should do is just assume the eraseblock needs
> erasure and just erase it. The whole purpose of clean markers is to
> erase less. If it is corrupted - we just do an extra erase - not big
> deal.
How's the best way to do this?  That would make this whole problem just 
go away, and make MLC devices much more happy with JFFS2.
>> Also, from what I can find, MTD does not provide a method of programming
>> OOB NAND data using MTD_OOB_AUTO as mtd_do_writeoob (called in mtdchar.c
>> from the MTDWRITEOOB ioctl) uses only MTD_OOB_PLACE.
> Probably MTD_OOB_AUTO is just a layer on top of MTD_OOB_PLACE? Anyway,
> this whole area of OOB is complex and needs some analysis, and even
> better documentation, and then you can choose the best way to solve your
> issue.
MTD_OOB_PLACE and MTD_OOB_AUTO follow the same path and use 
nand_fill_oob() and nand_transfer_oob() to write/extract the OOB buffer 
used in the actual write.


-- 
Peter Barada
peter.barada at gmail.com



From arnd at arndb.de  Thu Jun 30 18:22:26 2011
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 1 Jul 2011 00:22:26 +0200
Subject: [PATCH v5 1/3] ARM: mxs: add GPMI-NFC support for imx23/imx28
In-Reply-To: <19980.36638.134045.743619@ipc1.ka-ro>
References: <1309406028-2924-1-git-send-email-b32955@freescale.com>
	<201106301555.19440.arnd@arndb.de>
	<19980.36638.134045.743619@ipc1.ka-ro>
Message-ID: <201107010022.26597.arnd@arndb.de>

On Thursday 30 June 2011 16:58:38 Lothar Wa?mann wrote:
> > 
> > When adding new infrastructure, always keep in mind how you want it to look
> > after the device tree conversion. The partitions and min/max_* are easily covered
> > with that, but the init/exit function pointers are somewhat problematic.
> > 
> > Fortunately, you don't really require these functions for this driver. The _exit
> > function is completely unused, so just get rid of it.
> > 
> > The init function is used only to set up iomux, so the logical replacement is
> > a pointer to the iomux data, and calling mxs_iomux_setup_multiple_pads
> > directly from the driver.
> > 
> NO! I strongly object that. mxs_iomux_setup_multiple_pads() is a
> platform specific function and has no business inside a device driver
> that should be platform agnostic.
> Consider the same controller being part of a different SoC that
> requires you to call mxs_iomux_v2_setup_multiple_pads() instead. You
> would then have to check for the SoC type inside the driver to find
> the right function to call which is quite obscene.

Won't this problem just go away as soon as we get the mxs converted to the
generic pinmux subsystem that Linus Walleij is doing?

Obviously, you would not have to check the soc type really, you would have
to instead check for different versions of the gpmi, which you most likely
have to anyway because reusing the same hardware block in a new chip usually
comes with other changes as well. 

Note how the driver already does this with code like

+	if (GPMI_IS_MX23(this) || GPMI_IS_MX28(this))
+		nfc = &gpmi_nfc_hal_mxs;

If you really want to call out obsceneties, how about the fact that this
driver comes with an 805 line patch to add a HAL for a single chip!

Such abstractions should not be introduced as long as there is only
a single instance of the hardware.

> I would rather live with the iomux statically configured in the
> platform init code than having direct calls into platform specific
> code from device drivers.

That would certainly work until we have the pinmux subsystem to
take care of it.

	Arnd


From arnd at arndb.de  Thu Jun 30 18:29:51 2011
From: arnd at arndb.de (Arnd Bergmann)
Date: Fri, 1 Jul 2011 00:29:51 +0200
Subject: reply: [PATCH v5 1/3] ARM: mxs: add GPMI-NFC support for
	imx23/imx28
In-Reply-To: <14C4E31473AF7E4B98176CB73615181C19FBD3@039-SN1MPN1-006.039d.mgd.msft.net>
References: <14C4E31473AF7E4B98176CB73615181C19FBD3@039-SN1MPN1-006.039d.mgd.msft.net>
Message-ID: <201107010029.51965.arnd@arndb.de>

On Thursday 30 June 2011 18:12:27 Huang Shijie-B32955 wrote:
> 
> I think gpmi-nfc is much better then gpmi-nand or gpmi-flash.

Then how do you want to name the near field communication drivers?

> >I know that you didn't start this pattern, but I find these macros
> >extremely annoying. It obscures the use of the macros with the
> >string concatenation and the macro names are way too generic
> >for something platform specific. If people think it's a good idea
> >to have these, please submit a patch to add macros (without the
> >string concatenation) into include/linux/ioport.h.
> 
> >Until then, better spell out the resources.
> 
> ==============================================
> I ever tried several methods,  but  I can not find a better method to
> replace the current method.
> 
> It's annoying, but it really saves some lines.

It would save more lines if you introduce the macros globally and
convert all existing resource definitions ;-)

Making code shorter is usually a good idea, but not when it conflicts
with readability. Adding custom macros that do string concatenation
is such a case.

> >When adding new infrastructure, always keep in mind how you want it to look
> >after the device tree conversion. The partitions and min/max_* are easily covered
> >with that, but the init/exit function pointers are somewhat problematic.
> 
> >Fortunately, you don't really require these functions for this driver. The _exit
> >function is completely unused, so just get rid of it.
> ===================================================
> I am reluctant to remove it, I am not sure whether I will use the _exit() in future.
> But, yes, it can be removed now.

As a rule, you should never introduce infrastructure just because you might
need it in the future but don't know if you will really need it.

This is even more important for the actual driver, as I mentioned in my other
mail. You have a hardware abstraction layer, but only one variant of the hardware
posted along with the driver. Without seeing different hardware, how should
anyone be able to tell whether the abstraction is really needed or if it's the
correct abstraction?

	Arnd


From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.11.1309969785.20020.linux-mtd@lists.infradead.org>

this in Mainline versions. I think we have to do something.

Maybe we can handle this in a way that when no bad block table is
present we create one with the correct values? This way we could
eliminate the problem at least on boards with virgin flashes.

This whole topic totally sucks. Whatever we do now we end up with
corrupted flashes in one way or the other.

BTW the Bootrom code expects non swapped flash layout, so applying
a swap patch makes it impossible to update the bootloader in NAND.
Maybe that's the reason the FSL code has this disable_bi_swap sysfs
attribute in it.

Not calling this a bug makes me think you work for the Freescale
marketing department ;)

Sascha


-- 
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 zonque at gmail.com  Sat Jun 25 08:32:17 2011
From: zonque at gmail.com (Daniel Mack)
Date: Sat, 25 Jun 2011 14:32:17 +0200
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <1309000666-5242-1-git-send-email-leiwen@marvell.com>
References: <4E031900.50108@compulab.co.il>
	<1309000666-5242-1-git-send-email-leiwen@marvell.com>
Message-ID: <BANLkTimY2+qV_A7gSWOjAk0f54zKRC2wCg@mail.gmail.com>

On Sat, Jun 25, 2011 at 1:17 PM, Lei Wen <leiwen at marvell.com> wrote:
> Current pxa3xx_nand controller has two chip select which
> both be workable. This patch enable this feature.
>
> Update platform driver to support this feature.
>
> Another notice should be taken that:
> When you want to use this feature, you should not enable the
> keep configuration feature, for two chip select could be
> attached with different nand chip. The different page size
> and timing requirement make the keep configuration impossible.
>
> Signed-off-by: Lei Wen <leiwen at marvell.com>

I tested this on a PXA303 platform with one chipselect only, at at
least I can say that this patch doesn't seem to cause any regression
here. But I couldn't test the new feature it adds.

So, FWIW:

Tested-by: Daniel Mack <zonque at gmail.com>


Thanks!
Daniel


> ---
> ?arch/arm/mach-mmp/aspenite.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? ? ?| ? ?5 +-
> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? ? ?| ? ?5 +-
> ?arch/arm/mach-pxa/mxm8x10.c ? ? ? ? ? ? ? ? ?| ? ?9 +-
> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ? ? | ? ?5 +-
> ?arch/arm/plat-pxa/include/plat/pxa3xx_nand.h | ? 19 +-
> ?drivers/mtd/nand/pxa3xx_nand.c ? ? ? ? ? ? ? | ?512 +++++++++++++++-----------
> ?9 files changed, 346 insertions(+), 224 deletions(-)
>
> diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
> index 06b5fa8..c4996f3 100644
> --- a/arch/arm/mach-mmp/aspenite.c
> +++ b/arch/arm/mach-mmp/aspenite.c
> @@ -167,8 +167,9 @@ 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),
> + ? ? ? .num_cs = 1,
> + ? ? ? .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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
> index b2248e7..969d252 100644
> --- a/arch/arm/mach-pxa/cm-x300.c
> +++ b/arch/arm/mach-pxa/cm-x300.c
> @@ -423,8 +423,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 3f9be41..2b8ca0d 100644
> --- a/arch/arm/mach-pxa/colibri-pxa3xx.c
> +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
> @@ -139,8 +139,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 e5e326d..f6d1f9d 100644
> --- a/arch/arm/mach-pxa/littleton.c
> +++ b/arch/arm/mach-pxa/littleton.c
> @@ -325,8 +325,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 b5a8fd3..90928d6 100644
> --- a/arch/arm/mach-pxa/mxm8x10.c
> +++ b/arch/arm/mach-pxa/mxm8x10.c
> @@ -389,10 +389,11 @@ 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,
> + ? ? ? .num_cs ? ? ? ? = 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 d130f77..c7ec847 100644
> --- a/arch/arm/mach-pxa/raumfeld.c
> +++ b/arch/arm/mach-pxa/raumfeld.c
> @@ -349,8 +349,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 5821185..64fdac9 100644
> --- a/arch/arm/mach-pxa/zylonite.c
> +++ b/arch/arm/mach-pxa/zylonite.c
> @@ -366,8 +366,9 @@ 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),
> + ? ? ? .num_cs ? ? ? ? = 1,
> + ? ? ? .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 442301f..4e17309 100644
> --- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> +++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
> @@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
> ? ? ? ?struct pxa3xx_nand_timing *timing; ? ? ?/* NAND Flash timing */
> ?};
>
> +/*
> + * Current pxa3xx_nand controller has two chip select which
> + * both be workable.
> + *
> + * Notice should be taken that:
> + * When you want to use this feature, you should not enable the
> + * keep configuration feature, for two chip select could be
> + * attached with different nand chip. The different page size
> + * and timing requirement make the keep configuration impossible.
> + */
> +
> +/* The max num of chip select current support */
> +#define NUM_CHIP_SELECT ? ? ? ? ? ? ? ?(2)
> ?struct pxa3xx_nand_platform_data {
>
> ? ? ? ?/* the data flash bus is shared between the Static Memory
> @@ -52,8 +65,10 @@ 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;
> + ? ? ? /* indicate how many chip selects will be used */
> + ? ? ? int ? ? num_cs;
> + ? ? ? const struct mtd_partition ? ? ? ? ? ? ?*parts[NUM_CHIP_SELECT];
> + ? ? ? unsigned int ? ? ? ? ? ? ? ? ? ? ? ? ? ?nr_parts[NUM_CHIP_SELECT];
>
> ? ? ? ?const struct pxa3xx_nand_flash * ? ? ? ?flash;
> ? ? ? ?size_t ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?num_flash;
> diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
> index b7db1b2..0825b7d 100644
> --- a/drivers/mtd/nand/pxa3xx_nand.c
> +++ b/drivers/mtd/nand/pxa3xx_nand.c
> @@ -110,6 +110,7 @@ enum {
>
> ?enum {
> ? ? ? ?STATE_IDLE = 0,
> + ? ? ? STATE_PREPARED,
> ? ? ? ?STATE_CMD_HANDLE,
> ? ? ? ?STATE_DMA_READING,
> ? ? ? ?STATE_DMA_WRITING,
> @@ -120,21 +121,40 @@ enum {
> ? ? ? ?STATE_READY,
> ?};
>
> -struct pxa3xx_nand_info {
> - ? ? ? struct nand_chip ? ? ? ?nand_chip;
> +struct pxa3xx_nand_host {
> + ? ? ? struct nand_chip ? ? ? ?chip;
> + ? ? ? struct pxa3xx_nand_cmdset *cmdset;
> + ? ? ? struct mtd_info ? ? ? ? *mtd;
> + ? ? ? void ? ? ? ? ? ? ? ? ? ?*info_data;
>
> + ? ? ? /* page size of attached chip */
> + ? ? ? unsigned int ? ? ? ? ? ?page_size;
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? cs;
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? use_ecc;
> +
> + ? ? ? /* calculated from pxa3xx_nand_flash data */
> + ? ? ? unsigned int ? ? ? ? ? ?col_addr_cycles;
> + ? ? ? unsigned int ? ? ? ? ? ?row_addr_cycles;
> + ? ? ? size_t ? ? ? ? ? ? ? ? ?read_id_bytes;
> +
> + ? ? ? /* cached register value */
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr0cs0;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?ndtr1cs0;
> +};
> +
> +struct pxa3xx_nand_info {
> ? ? ? ?struct nand_hw_control ?controller;
> ? ? ? ?struct platform_device ? *pdev;
> - ? ? ? struct pxa3xx_nand_cmdset *cmdset;
>
> ? ? ? ?struct clk ? ? ? ? ? ? ?*clk;
> ? ? ? ?void __iomem ? ? ? ? ? ?*mmio_base;
> ? ? ? ?unsigned long ? ? ? ? ? mmio_phys;
> + ? ? ? struct completion ? ? ? cmd_complete;
>
> ? ? ? ?unsigned int ? ? ? ? ? ?buf_start;
> ? ? ? ?unsigned int ? ? ? ? ? ?buf_count;
>
> - ? ? ? struct mtd_info ? ? ? ? *mtd;
> ? ? ? ?/* DMA information */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_dat;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? drcmr_cmd;
> @@ -142,44 +162,27 @@ struct pxa3xx_nand_info {
> ? ? ? ?unsigned char ? ? ? ? ? *data_buff;
> ? ? ? ?unsigned char ? ? ? ? ? *oob_buff;
> ? ? ? ?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;
>
> - ? ? ? uint32_t ? ? ? ? ? ? ? ?reg_ndcr;
> -
> - ? ? ? /* saved column/page_addr during CMD_SEQIN */
> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_column;
> - ? ? ? int ? ? ? ? ? ? ? ? ? ? seqin_page_addr;
> -
> + ? ? ? struct pxa3xx_nand_host *host[NUM_CHIP_SELECT];
> ? ? ? ?/* relate to the command */
> ? ? ? ?unsigned int ? ? ? ? ? ?state;
>
> + ? ? ? int ? ? ? ? ? ? ? ? ? ? cs;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_ecc; ? ? ? ?/* use HW ECC ? */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? use_dma; ? ? ? ?/* use DMA ? */
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? is_ready;
>
> - ? ? ? unsigned int ? ? ? ? ? ?page_size; ? ? ?/* page size of attached chip */
> ? ? ? ?unsigned int ? ? ? ? ? ?data_size; ? ? ?/* data size in FIFO */
> + ? ? ? unsigned int ? ? ? ? ? ?oob_size;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? retcode;
> - ? ? ? struct completion ? ? ? cmd_complete;
>
> ? ? ? ?/* generated NDCBx register values */
> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?ndcb0;
> ? ? ? ?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;
> -
> - ? ? ? unsigned int ? ?col_addr_cycles;
> - ? ? ? unsigned int ? ?row_addr_cycles;
> ?};
>
> ?static int use_dma = 1;
> @@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
> ?/* Define a default flash type setting serve as flash detecting only */
> ?#define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
>
> -const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> +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)
> @@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
> ?/* convert nano-seconds to nand flash controller clock cycles */
> ?#define ns2cycle(ns, clk) ? ? ?(int)((ns) * (clk / 1000000) / 1000)
>
> -static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
> +static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? const struct pxa3xx_nand_timing *t)
> ?{
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?unsigned long nand_clk = clk_get_rate(info->clk);
> ? ? ? ?uint32_t ndtr0, ndtr1;
>
> @@ -258,23 +262,24 @@ 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;
> + ? ? ? host->ndtr0cs0 = ndtr0;
> + ? ? ? host->ndtr1cs0 = ndtr1;
> ? ? ? ?nand_writel(info, NDTR0CS0, ndtr0);
> ? ? ? ?nand_writel(info, NDTR1CS0, ndtr1);
> ?}
>
> ?static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> + ? ? ? int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
>
> - ? ? ? info->data_size = info->page_size;
> + ? ? ? info->data_size = host->page_size;
> ? ? ? ?if (!oob_enable) {
> ? ? ? ? ? ? ? ?info->oob_size = 0;
> ? ? ? ? ? ? ? ?return;
> ? ? ? ?}
>
> - ? ? ? switch (info->page_size) {
> + ? ? ? switch (host->page_size) {
> ? ? ? ?case 2048:
> ? ? ? ? ? ? ? ?info->oob_size = (info->use_ecc) ? 40 : 64;
> ? ? ? ? ? ? ? ?break;
> @@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
> ?*/
> ?static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
> ?{
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> ? ? ? ?uint32_t ndcr;
>
> - ? ? ? ndcr = info->reg_ndcr;
> + ? ? ? ndcr = host->reg_ndcr;
> ? ? ? ?ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
> ? ? ? ?ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
> ? ? ? ?ndcr |= NDCR_ND_RUN;
> @@ -359,8 +365,8 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?DIV_ROUND_UP(info->oob_size, 4));
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> - ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
> - ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? info->state);
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
> + ? ? ? ? ? ? ? ? ? ? ? info->state);
> ? ? ? ? ? ? ? ?BUG();
> ? ? ? ?}
> ?}
> @@ -385,7 +391,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
> ? ? ? ? ? ? ? ?desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?default:
> - ? ? ? ? ? ? ? printk(KERN_ERR "%s: invalid state %d\n", __func__,
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->state);
> ? ? ? ? ? ? ? ?BUG();
> ? ? ? ?}
> @@ -416,9 +422,17 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = devid;
> ? ? ? ?unsigned int status, is_completed = 0;
> + ? ? ? unsigned int ready, cmd_done;
> +
> + ? ? ? if (info->cs == 0) {
> + ? ? ? ? ? ? ? ready ? ? ? ? ? = NDSR_FLASH_RDY;
> + ? ? ? ? ? ? ? cmd_done ? ? ? ?= NDSR_CS0_CMDD;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? ready ? ? ? ? ? = NDSR_RDY;
> + ? ? ? ? ? ? ? cmd_done ? ? ? ?= NDSR_CS1_CMDD;
> + ? ? ? }
>
> ? ? ? ?status = nand_readl(info, NDSR);
> -
> ? ? ? ?if (status & NDSR_DBERR)
> ? ? ? ? ? ? ? ?info->retcode = ERR_DBERR;
> ? ? ? ?if (status & NDSR_SBERR)
> @@ -437,11 +451,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
> ? ? ? ? ? ? ? ? ? ? ? ?handle_data_pio(info);
> ? ? ? ? ? ? ? ?}
> ? ? ? ?}
> - ? ? ? if (status & NDSR_CS0_CMDD) {
> + ? ? ? if (status & cmd_done) {
> ? ? ? ? ? ? ? ?info->state = STATE_CMD_DONE;
> ? ? ? ? ? ? ? ?is_completed = 1;
> ? ? ? ?}
> - ? ? ? if (status & NDSR_FLASH_RDY) {
> + ? ? ? if (status & ready) {
> ? ? ? ? ? ? ? ?info->is_ready = 1;
> ? ? ? ? ? ? ? ?info->state = STATE_READY;
> ? ? ? ?}
> @@ -463,12 +477,6 @@ 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--)
> @@ -481,10 +489,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?uint16_t column, int page_addr)
> ?{
> ? ? ? ?uint16_t cmd;
> - ? ? ? int addr_cycle, exec_cmd, ndcb0;
> - ? ? ? struct mtd_info *mtd = info->mtd;
> + ? ? ? int addr_cycle, exec_cmd;
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> + ? ? ? struct mtd_info *mtd = host->mtd;
>
> - ? ? ? ndcb0 = 0;
> ? ? ? ?addr_cycle = 0;
> ? ? ? ?exec_cmd = 1;
>
> @@ -495,6 +503,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ?info->use_ecc ? ? ? ? ? = 0;
> ? ? ? ?info->is_ready ? ? ? ? ?= 0;
> ? ? ? ?info->retcode ? ? ? ? ? = ERR_NONE;
> + ? ? ? if (info->cs != 0)
> + ? ? ? ? ? ? ? info->ndcb0 = NDCB0_CSEL;
> + ? ? ? else
> + ? ? ? ? ? ? ? info->ndcb0 = 0;
>
> ? ? ? ?switch (command) {
> ? ? ? ?case NAND_CMD_READ0:
> @@ -512,20 +524,19 @@ 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);
> + ? ? ? addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + host->col_addr_cycles);
>
> ? ? ? ?switch (command) {
> ? ? ? ?case NAND_CMD_READOOB:
> ? ? ? ?case NAND_CMD_READ0:
> - ? ? ? ? ? ? ? cmd = info->cmdset->read1;
> + ? ? ? ? ? ? ? cmd = host->cmdset->read1;
> ? ? ? ? ? ? ? ?if (command == NAND_CMD_READOOB)
> ? ? ? ? ? ? ? ? ? ? ? ?info->buf_start = mtd->writesize + column;
> ? ? ? ? ? ? ? ?else
> ? ? ? ? ? ? ? ? ? ? ? ?info->buf_start = column;
>
> - ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
> + ? ? ? ? ? ? ? if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
> ? ? ? ? ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(0)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| addr_cycle
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (cmd & NDCB0_CMD1_MASK);
> @@ -537,7 +548,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ?case NAND_CMD_SEQIN:
> ? ? ? ? ? ? ? ?/* small page addr setting */
> - ? ? ? ? ? ? ? if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
> + ? ? ? ? ? ? ? if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
> ? ? ? ? ? ? ? ? ? ? ? ?info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| (column & 0xFF);
>
> @@ -564,7 +575,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ? ? ? ? ?break;
> ? ? ? ? ? ? ? ?}
>
> - ? ? ? ? ? ? ? cmd = info->cmdset->program;
> + ? ? ? ? ? ? ? cmd = host->cmdset->program;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ST_ROW_EN
> @@ -574,8 +585,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_READID:
> - ? ? ? ? ? ? ? cmd = info->cmdset->read_id;
> - ? ? ? ? ? ? ? info->buf_count = info->read_id_bytes;
> + ? ? ? ? ? ? ? cmd = host->cmdset->read_id;
> + ? ? ? ? ? ? ? info->buf_count = host->read_id_bytes;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(3)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
> @@ -583,7 +594,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?info->data_size = 8;
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_STATUS:
> - ? ? ? ? ? ? ? cmd = info->cmdset->read_status;
> + ? ? ? ? ? ? ? cmd = host->cmdset->read_status;
> ? ? ? ? ? ? ? ?info->buf_count = 1;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(4)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(1)
> @@ -593,7 +604,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ? ? ? ? ? ? ? ?break;
>
> ? ? ? ?case NAND_CMD_ERASE1:
> - ? ? ? ? ? ? ? cmd = info->cmdset->erase;
> + ? ? ? ? ? ? ? cmd = host->cmdset->erase;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(2)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_AUTO_RS
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| NDCB0_ADDR_CYC(3)
> @@ -604,7 +615,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?case NAND_CMD_RESET:
> - ? ? ? ? ? ? ? cmd = info->cmdset->reset;
> + ? ? ? ? ? ? ? cmd = host->cmdset->reset;
> ? ? ? ? ? ? ? ?info->ndcb0 |= NDCB0_CMD_TYPE(5)
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| cmd;
>
> @@ -616,7 +627,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
>
> ? ? ? ?default:
> ? ? ? ? ? ? ? ?exec_cmd = 0;
> - ? ? ? ? ? ? ? printk(KERN_ERR "pxa3xx-nand: non-supported"
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "pxa3xx-nand: non-supported"
> ? ? ? ? ? ? ? ? ? ? ? ?" command %x\n", command);
> ? ? ? ? ? ? ? ?break;
> ? ? ? ?}
> @@ -627,7 +638,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
> ?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_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?int ret, exec_cmd;
>
> ? ? ? ?/*
> @@ -635,9 +647,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> ? ? ? ? * "byte" address into a "word" address appropriate
> ? ? ? ? * for indexing a word-oriented device
> ? ? ? ? */
> - ? ? ? if (info->reg_ndcr & NDCR_DWIDTH_M)
> + ? ? ? if (host->reg_ndcr & NDCR_DWIDTH_M)
> ? ? ? ? ? ? ? ?column /= 2;
>
> + ? ? ? /*
> + ? ? ? ?* There may be different NAND chip hooked to
> + ? ? ? ?* different chip select, so check whether
> + ? ? ? ?* chip select has been changed, if yes, reset the timing
> + ? ? ? ?*/
> + ? ? ? if (info->cs != host->cs) {
> + ? ? ? ? ? ? ? info->cs = host->cs;
> + ? ? ? ? ? ? ? nand_writel(info, NDTR0CS0, host->ndtr0cs0);
> + ? ? ? ? ? ? ? nand_writel(info, NDTR1CS0, host->ndtr1cs0);
> + ? ? ? }
> +
> + ? ? ? info->state = STATE_PREPARED;
> ? ? ? ?exec_cmd = prepare_command_pool(info, command, column, page_addr);
> ? ? ? ?if (exec_cmd) {
> ? ? ? ? ? ? ? ?init_completion(&info->cmd_complete);
> @@ -646,12 +670,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
> ? ? ? ? ? ? ? ?ret = wait_for_completion_timeout(&info->cmd_complete,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?CHIP_DELAY_TIMEOUT);
> ? ? ? ? ? ? ? ?if (!ret) {
> - ? ? ? ? ? ? ? ? ? ? ? printk(KERN_ERR "Wait time out!!!\n");
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "Wait time out!!!\n");
> ? ? ? ? ? ? ? ? ? ? ? ?/* Stop State Machine for next command cycle */
> ? ? ? ? ? ? ? ? ? ? ? ?pxa3xx_nand_stop(info);
> ? ? ? ? ? ? ? ?}
> - ? ? ? ? ? ? ? info->state = STATE_IDLE;
> ? ? ? ?}
> + ? ? ? info->state = STATE_IDLE;
> ?}
>
> ?static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> @@ -664,7 +688,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
> ?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_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
>
> ? ? ? ?chip->read_buf(mtd, buf, mtd->writesize);
> ? ? ? ?chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
> @@ -695,7 +720,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
>
> ?static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?char retval = 0xFF;
>
> ? ? ? ?if (info->buf_start < info->buf_count)
> @@ -707,7 +733,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
>
> ?static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?u16 retval = 0xFFFF;
>
> ? ? ? ?if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
> @@ -719,7 +746,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
>
> ?static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>
> ? ? ? ?memcpy(buf, info->data_buff + info->buf_start, real_len);
> @@ -729,7 +757,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
> ?static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
> ? ? ? ? ? ? ? ?const uint8_t *buf, int len)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
>
> ? ? ? ?memcpy(info->data_buff + info->buf_start, buf, real_len);
> @@ -749,7 +778,8 @@ 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_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
>
> ? ? ? ?/* pxa3xx_nand_send_command has waited for command complete */
> ? ? ? ?if (this->state == FL_WRITING || this->state == FL_ERASING) {
> @@ -772,54 +802,69 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
> ?{
> ? ? ? ?struct platform_device *pdev = info->pdev;
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> + ? ? ? struct pxa3xx_nand_host *host = info->host[info->cs];
> ? ? ? ?uint32_t ndcr = 0x0; /* enable all interrupts */
>
> - ? ? ? if (f->page_size != 2048 && f->page_size != 512)
> + ? ? ? if (f->page_size != 2048 && f->page_size != 512) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
> ? ? ? ? ? ? ? ?return -EINVAL;
> + ? ? ? }
>
> - ? ? ? if (f->flash_width != 16 && f->flash_width != 8)
> + ? ? ? if (f->flash_width != 16 && f->flash_width != 8) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
> ? ? ? ? ? ? ? ?return -EINVAL;
> + ? ? ? }
>
> ? ? ? ?/* calculate flash information */
> - ? ? ? info->cmdset = &default_cmdset;
> - ? ? ? info->page_size = f->page_size;
> - ? ? ? info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
> + ? ? ? host->cmdset = &default_cmdset;
> + ? ? ? host->page_size = f->page_size;
> + ? ? ? host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
>
> ? ? ? ?/* calculate addressing information */
> - ? ? ? info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
> + ? ? ? host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
>
> ? ? ? ?if (f->num_blocks * f->page_per_block > 65536)
> - ? ? ? ? ? ? ? info->row_addr_cycles = 3;
> + ? ? ? ? ? ? ? host->row_addr_cycles = 3;
> ? ? ? ?else
> - ? ? ? ? ? ? ? info->row_addr_cycles = 2;
> + ? ? ? ? ? ? ? host->row_addr_cycles = 2;
>
> ? ? ? ?ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
> - ? ? ? ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
> + ? ? ? ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
> ? ? ? ?ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
> ? ? ? ?ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
> ? ? ? ?ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
> ? ? ? ?ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
>
> - ? ? ? ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
> + ? ? ? ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
> ? ? ? ?ndcr |= NDCR_SPARE_EN; /* enable spare by default */
>
> - ? ? ? info->reg_ndcr = ndcr;
> + ? ? ? host->reg_ndcr = ndcr;
>
> - ? ? ? pxa3xx_nand_set_timing(info, f->timing);
> + ? ? ? pxa3xx_nand_set_timing(host, f->timing);
> ? ? ? ?return 0;
> ?}
>
> ?static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ?{
> + ? ? ? /*
> + ? ? ? ?* We set 0 by hard coding here, for we don't support keep_config
> + ? ? ? ?* when there is more than one chip attached to the controller
> + ? ? ? ?*/
> + ? ? ? struct pxa3xx_nand_host *host = info->host[0];
> ? ? ? ?uint32_t ndcr = nand_readl(info, NDCR);
> - ? ? ? info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
> - ? ? ? /* set info fields needed to read id */
> - ? ? ? info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
> - ? ? ? info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
> - ? ? ? info->cmdset = &default_cmdset;
>
> - ? ? ? info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> - ? ? ? info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
> + ? ? ? if (ndcr & NDCR_PAGE_SZ) {
> + ? ? ? ? ? ? ? host->page_size = 2048;
> + ? ? ? ? ? ? ? host->read_id_bytes = 4;
> + ? ? ? } else {
> + ? ? ? ? ? ? ? host->page_size = 512;
> + ? ? ? ? ? ? ? host->read_id_bytes = 2;
> + ? ? ? }
> + ? ? ? host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
> + ? ? ? host->cmdset = &default_cmdset;
> +
> + ? ? ? host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
> + ? ? ? host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
>
> ? ? ? ?return 0;
> ?}
> @@ -829,59 +874,41 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
> ?* data buffer and the DMA descriptor
> ?*/
> ?#define MAX_BUFF_SIZE ?PAGE_SIZE
> -
> -static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
> +static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
> ?{
> - ? ? ? 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;
> + ? ? ? struct pxa3xx_nand_host *host;
> + ? ? ? struct mtd_info *mtd;
>
> - ? ? ? 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;
> - ? ? ? }
> + ? ? ? if (!info->host[cs])
> + ? ? ? ? ? ? ? return;
>
> - ? ? ? return 0;
> + ? ? ? host = info->host[cs];
> + ? ? ? mtd = host->mtd;
> + ? ? ? kfree(mtd);
> + ? ? ? info->host[cs] = NULL;
> ?}
>
> ?static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
> ?{
> - ? ? ? struct mtd_info *mtd = info->mtd;
> - ? ? ? struct nand_chip *chip = mtd->priv;
> + ? ? ? struct mtd_info *mtd = info->host[info->cs]->mtd;
> + ? ? ? int ret;
>
> ? ? ? ?/* 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);
> + ? ? ? ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
> + ? ? ? if (ret)
> + ? ? ? ? ? ? ? return ret;
> +
> + ? ? ? pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
> ? ? ? ?if (info->is_ready)
> - ? ? ? ? ? ? ? return 1;
> - ? ? ? else
> ? ? ? ? ? ? ? ?return 0;
> +
> + ? ? ? return -ENODEV;
> ?}
>
> ?static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ?{
> - ? ? ? struct pxa3xx_nand_info *info = mtd->priv;
> + ? ? ? struct pxa3xx_nand_host *host = mtd->priv;
> + ? ? ? struct pxa3xx_nand_info *info = host->info_data;
> ? ? ? ?struct platform_device *pdev = info->pdev;
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
> ? ? ? ?struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
> @@ -891,26 +918,26 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?uint64_t chipsize;
> ? ? ? ?int i, ret, num;
>
> + ? ? ? info->cs = host->cs;
> ? ? ? ?if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
> ? ? ? ? ? ? ? ?goto KEEP_CONFIG;
>
> ? ? ? ?ret = pxa3xx_nand_sensing(info);
> - ? ? ? if (!ret) {
> - ? ? ? ? ? ? ? kfree(mtd);
> - ? ? ? ? ? ? ? info->mtd = NULL;
> - ? ? ? ? ? ? ? printk(KERN_INFO "There is no nand chip on cs 0!\n");
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? free_cs_resource(info, info->cs);
> + ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n");
>
> - ? ? ? ? ? ? ? return -EINVAL;
> + ? ? ? ? ? ? ? return ret;
> ? ? ? ?}
>
> ? ? ? ?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);
> + ? ? ? ? ? ? ? dev_info(&info->pdev->dev, "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");
> + ? ? ? ? ? ? ? free_cs_resource(info, info->cs);
> + ? ? ? ? ? ? ? dev_warn(&info->pdev->dev, "Read out ID 0, "
> + ? ? ? ? ? ? ? ? ? ? ? ?"potential timing set wrong!!\n");
>
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
> @@ -928,14 +955,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
> ? ? ? ?}
>
> ? ? ? ?if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
> - ? ? ? ? ? ? ? kfree(mtd);
> - ? ? ? ? ? ? ? info->mtd = NULL;
> - ? ? ? ? ? ? ? printk(KERN_ERR "ERROR!! flash not defined!!!\n");
> + ? ? ? ? ? ? ? free_cs_resource(info, info->cs);
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
>
> ? ? ? ? ? ? ? ?return -EINVAL;
> ? ? ? ?}
>
> - ? ? ? pxa3xx_nand_config_flash(info, f);
> + ? ? ? ret = pxa3xx_nand_config_flash(info, f);
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
> + ? ? ? ? ? ? ? return ret;
> + ? ? ? }
> ? ? ? ?pxa3xx_flash_ids[0].name = f->name;
> ? ? ? ?pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
> ? ? ? ?pxa3xx_flash_ids[0].pagesize = f->page_size;
> @@ -950,66 +980,51 @@ KEEP_CONFIG:
> ? ? ? ?if (nand_scan_ident(mtd, 1, def))
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?/* calculate addressing information */
> - ? ? ? info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
> + ? ? ? if (mtd->writesize >= 2048)
> + ? ? ? ? ? ? ? host->col_addr_cycles = 2;
> + ? ? ? else
> + ? ? ? ? ? ? ? host->col_addr_cycles = 1;
> ? ? ? ?info->oob_buff = info->data_buff + mtd->writesize;
> ? ? ? ?if ((mtd->size >> chip->page_shift) > 65536)
> - ? ? ? ? ? ? ? info->row_addr_cycles = 3;
> + ? ? ? ? ? ? ? host->row_addr_cycles = 3;
> ? ? ? ?else
> - ? ? ? ? ? ? ? info->row_addr_cycles = 2;
> - ? ? ? mtd->name = mtd_names[0];
> + ? ? ? ? ? ? ? host->row_addr_cycles = 2;
> + ? ? ? mtd->name = mtd_names[info->cs];
> ? ? ? ?chip->ecc.mode = NAND_ECC_HW;
> - ? ? ? chip->ecc.size = info->page_size;
> + ? ? ? chip->ecc.size = host->page_size;
>
> - ? ? ? chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
> + ? ? ? chip->options = 0;
> + ? ? ? if (host->reg_ndcr & NDCR_DWIDTH_M)
> + ? ? ? ? ? ? ? chip->options = NAND_BUSWIDTH_16;
> ? ? ? ?chip->options |= NAND_NO_AUTOINCR;
> ? ? ? ?chip->options |= NAND_NO_READRDY;
>
> ? ? ? ?return nand_scan_tail(mtd);
> ?}
>
> -static
> -struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> +static int alloc_nand_resource(struct platform_device *pdev)
> ?{
> + ? ? ? struct pxa3xx_nand_platform_data *pdata;
> ? ? ? ?struct pxa3xx_nand_info *info;
> + ? ? ? struct pxa3xx_nand_host *host;
> ? ? ? ?struct nand_chip *chip;
> ? ? ? ?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) {
> + ? ? ? pdata = pdev->dev.platform_data;
> + ? ? ? info = kzalloc(sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
> + ? ? ? if (!info) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to allocate memory\n");
> - ? ? ? ? ? ? ? return NULL;
> + ? ? ? ? ? ? ? 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->controller ? ? ? ?= &info->controller;
> - ? ? ? 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;
> -
> - ? ? ? spin_lock_init(&chip->controller->lock);
> - ? ? ? init_waitqueue_head(&chip->controller->wq);
> ? ? ? ?info->clk = clk_get(&pdev->dev, NULL);
> ? ? ? ?if (IS_ERR(info->clk)) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to get nand clock\n");
> ? ? ? ? ? ? ? ?ret = PTR_ERR(info->clk);
> - ? ? ? ? ? ? ? goto fail_free_mtd;
> + ? ? ? ? ? ? ? goto fail_alloc;
> ? ? ? ?}
> ? ? ? ?clk_enable(info->clk);
>
> @@ -1058,10 +1073,6 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> ? ? ? ?}
> ? ? ? ?info->mmio_phys = r->start;
>
> - ? ? ? ret = pxa3xx_nand_init_buff(info);
> - ? ? ? if (ret)
> - ? ? ? ? ? ? ? goto fail_free_io;
> -
> ? ? ? ?/* initialize all interrupts to be disabled */
> ? ? ? ?disable_int(info, NDSR_MASK);
>
> @@ -1069,21 +1080,80 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
> ? ? ? ? ? ? ? ? ? ? ? ? ?pdev->name, info);
> ? ? ? ?if (ret < 0) {
> ? ? ? ? ? ? ? ?dev_err(&pdev->dev, "failed to request IRQ\n");
> - ? ? ? ? ? ? ? goto fail_free_buf;
> + ? ? ? ? ? ? ? ret = ENXIO;
> + ? ? ? ? ? ? ? goto fail_free_io;
> ? ? ? ?}
>
> ? ? ? ?platform_set_drvdata(pdev, info);
>
> - ? ? ? return info;
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++) {
> + ? ? ? ? ? ? ? mtd = kzalloc(sizeof(struct mtd_info)
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? + sizeof(struct pxa3xx_nand_host),
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? GFP_KERNEL);
> + ? ? ? ? ? ? ? if (!mtd) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to allocate memory\n");
> + ? ? ? ? ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? ? ? ? ? goto fail_free_irq;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? host = (struct pxa3xx_nand_host *)(&mtd[1]);
> + ? ? ? ? ? ? ? host->info_data = info;
> + ? ? ? ? ? ? ? host->cs = cs;
> + ? ? ? ? ? ? ? host->mtd = mtd;
> + ? ? ? ? ? ? ? mtd->priv = host;
> + ? ? ? ? ? ? ? mtd->owner = THIS_MODULE;
> + ? ? ? ? ? ? ? info->host[cs] = host;
> +
> + ? ? ? ? ? ? ? chip = (struct nand_chip *)(&mtd[1]);
> + ? ? ? ? ? ? ? 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;
> + ? ? ? }
> +
> + ? ? ? if (use_dma == 0) {
> + ? ? ? ? ? ? ? info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
> + ? ? ? ? ? ? ? if (info->data_buff == NULL) {
> + ? ? ? ? ? ? ? ? ? ? ? ret = -ENOMEM;
> + ? ? ? ? ? ? ? ? ? ? ? goto fail_free_buf;
> + ? ? ? ? ? ? ? }
> + ? ? ? ? ? ? ? goto success_exit;
> + ? ? ? }
> +
> + ? ? ? 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, info);
> + ? ? ? if (info->data_dma_ch < 0) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to request data dma\n");
> + ? ? ? ? ? ? ? ret = -ENXIO;
> + ? ? ? ? ? ? ? goto fail_free_dma_buf;
> + ? ? ? }
> +success_exit:
> + ? ? ? return 0;
>
> +fail_free_dma_buf:
> + ? ? ? dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
> + ? ? ? ? ? ? ? ? ? ? ? info->data_buff, info->data_buff_phys);
> ?fail_free_buf:
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++)
> + ? ? ? ? ? ? ? free_cs_resource(info, cs);
> +fail_free_irq:
> ? ? ? ?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);
> ?fail_free_res:
> @@ -1091,18 +1161,20 @@ fail_free_res:
> ?fail_put_clk:
> ? ? ? ?clk_disable(info->clk);
> ? ? ? ?clk_put(info->clk);
> -fail_free_mtd:
> - ? ? ? kfree(mtd);
> - ? ? ? return NULL;
> +fail_alloc:
> + ? ? ? kfree(info);
> + ? ? ? 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_platform_data *pdata;
> + ? ? ? struct pxa3xx_nand_host *host;
> ? ? ? ?struct resource *r;
> - ? ? ? int irq;
> + ? ? ? int irq, cs;
>
> + ? ? ? pdata = pdev->dev.platform_data;
> ? ? ? ?platform_set_drvdata(pdev, NULL);
>
> ? ? ? ?irq = platform_get_irq(pdev, 0);
> @@ -1110,7 +1182,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
> ? ? ? ? ? ? ? ?free_irq(irq, info);
> ? ? ? ?if (use_dma) {
> ? ? ? ? ? ? ? ?pxa_free_dma(info->data_dma_ch);
> - ? ? ? ? ? ? ? dma_free_writecombine(&pdev->dev, info->data_buff_size,
> + ? ? ? ? ? ? ? dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
> ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?info->data_buff, info->data_buff_phys);
> ? ? ? ?} else
> ? ? ? ? ? ? ? ?kfree(info->data_buff);
> @@ -1122,9 +1194,12 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
> ? ? ? ?clk_disable(info->clk);
> ? ? ? ?clk_put(info->clk);
>
> - ? ? ? if (mtd) {
> - ? ? ? ? ? ? ? nand_release(mtd);
> - ? ? ? ? ? ? ? kfree(mtd);
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++) {
> + ? ? ? ? ? ? ? host = info->host[cs];
> + ? ? ? ? ? ? ? if (!host)
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? nand_release(host->mtd);
> + ? ? ? ? ? ? ? free_cs_resource(info, cs);
> ? ? ? ?}
> ? ? ? ?return 0;
> ?}
> @@ -1133,6 +1208,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
> ?{
> ? ? ? ?struct pxa3xx_nand_platform_data *pdata;
> ? ? ? ?struct pxa3xx_nand_info *info;
> + ? ? ? int cs, ret, probe_success = 0;
>
> ? ? ? ?pdata = pdev->dev.platform_data;
> ? ? ? ?if (!pdata) {
> @@ -1140,18 +1216,38 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?}
>
> - ? ? ? info = alloc_nand_resource(pdev);
> - ? ? ? if (info == NULL)
> - ? ? ? ? ? ? ? return -ENOMEM;
> + ? ? ? if (pdata->keep_config && pdata->num_cs > 1) {
> + ? ? ? ? ? ? ? dev_warn(&pdev->dev, "keep_config is prohibited with multiple"
> + ? ? ? ? ? ? ? ? ? ? ? ?" chip selects feature!\n");
> + ? ? ? ? ? ? ? pdata->keep_config = 0;
> + ? ? ? }
> +
> + ? ? ? ret = alloc_nand_resource(pdev);
> + ? ? ? if (ret) {
> + ? ? ? ? ? ? ? dev_err(&pdev->dev, "alloc nand resource failed\n");
> + ? ? ? ? ? ? ? return ret;
> + ? ? ? }
> +
> + ? ? ? info = platform_get_drvdata(pdev);
> + ? ? ? for (cs = 0; cs < pdata->num_cs; cs++) {
> + ? ? ? ? ? ? ? ret = pxa3xx_nand_scan(info->host[cs]->mtd);
> + ? ? ? ? ? ? ? if (ret) {
> + ? ? ? ? ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
> + ? ? ? ? ? ? ? ? ? ? ? continue;
> + ? ? ? ? ? ? ? }
> +
> + ? ? ? ? ? ? ? ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
> + ? ? ? ? ? ? ? ? ? ? ? pdata->parts[cs], pdata->nr_parts[cs]);
> + ? ? ? ? ? ? ? if (!ret)
> + ? ? ? ? ? ? ? ? ? ? ? probe_success = 1;
> + ? ? ? }
>
> - ? ? ? if (pxa3xx_nand_scan(info->mtd)) {
> - ? ? ? ? ? ? ? dev_err(&pdev->dev, "failed to scan nand\n");
> + ? ? ? if (!probe_success) {
> ? ? ? ? ? ? ? ?pxa3xx_nand_remove(pdev);
> ? ? ? ? ? ? ? ?return -ENODEV;
> ? ? ? ?}
>
> - ? ? ? return mtd_device_parse_register(info->mtd, NULL, 0,
> - ? ? ? ? ? ? ? ? ? ? ? pdata->parts, pdata->nr_parts);
> + ? ? ? return 0;
> ?}
>
> ?#ifdef CONFIG_PM
> @@ -1171,8 +1267,12 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
> ?{
> ? ? ? ?struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
>
> - ? ? ? nand_writel(info, NDTR0CS0, info->ndtr0cs0);
> - ? ? ? nand_writel(info, NDTR1CS0, info->ndtr1cs0);
> + ? ? ? /*
> + ? ? ? ?* Directly set the chip select to a invalid value,
> + ? ? ? ?* then the driver would reset the timing according
> + ? ? ? ?* to current chip select at the beginning of cmdfunc
> + ? ? ? ?*/
> + ? ? ? info->cs = 0xff;
> ? ? ? ?clk_enable(info->clk);
>
> ? ? ? ?return 0;
> --
> 1.7.0.4
>
>

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From leiwen at marvell.com  Sat Jun 25 07:17:46 2011
From: leiwen at marvell.com (Lei Wen)
Date: Sat, 25 Jun 2011 04:17:46 -0700
Subject: [PATCH] MTD: pxa3xx_nand: enable multiple chip select support
In-Reply-To: <4E031900.50108@compulab.co.il>
References: <4E031900.50108@compulab.co.il>
Message-ID: <1309000666-5242-1-git-send-email-leiwen@marvell.com>

Current pxa3xx_nand controller has two chip select which
both be workable. This patch enable this feature.

Update platform driver to support this feature.

Another notice should be taken that:
When you want to use this feature, you should not enable the
keep configuration feature, for two chip select could be
attached with different nand chip. The different page size
and timing requirement make the keep configuration impossible.

Signed-off-by: Lei Wen <leiwen at marvell.com>
---
 arch/arm/mach-mmp/aspenite.c                 |    5 +-
 arch/arm/mach-pxa/cm-x300.c                  |    5 +-
 arch/arm/mach-pxa/colibri-pxa3xx.c           |    5 +-
 arch/arm/mach-pxa/littleton.c                |    5 +-
 arch/arm/mach-pxa/mxm8x10.c                  |    9 +-
 arch/arm/mach-pxa/raumfeld.c                 |    5 +-
 arch/arm/mach-pxa/zylonite.c                 |    5 +-
 arch/arm/plat-pxa/include/plat/pxa3xx_nand.h |   19 +-
 drivers/mtd/nand/pxa3xx_nand.c               |  512 +++++++++++++++-----------
 9 files changed, 346 insertions(+), 224 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 06b5fa8..c4996f3 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -167,8 +167,9 @@ 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),
+	.num_cs = 1,
+	.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-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index b2248e7..969d252 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -423,8 +423,9 @@ 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),
+	.num_cs		= 1,
+	.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 3f9be41..2b8ca0d 100644
--- a/arch/arm/mach-pxa/colibri-pxa3xx.c
+++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
@@ -139,8 +139,9 @@ 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),
+	.num_cs		= 1,
+	.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 e5e326d..f6d1f9d 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -325,8 +325,9 @@ 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),
+	.num_cs		= 1,
+	.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 b5a8fd3..90928d6 100644
--- a/arch/arm/mach-pxa/mxm8x10.c
+++ b/arch/arm/mach-pxa/mxm8x10.c
@@ -389,10 +389,11 @@ 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,
+	.num_cs		= 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 d130f77..c7ec847 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -349,8 +349,9 @@ 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),
+	.num_cs		= 1,
+	.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 5821185..64fdac9 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -366,8 +366,9 @@ 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),
+	.num_cs		= 1,
+	.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 442301f..4e17309 100644
--- a/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
+++ b/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
@@ -41,6 +41,19 @@ struct pxa3xx_nand_flash {
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
+/*
+ * Current pxa3xx_nand controller has two chip select which
+ * both be workable.
+ *
+ * Notice should be taken that:
+ * When you want to use this feature, you should not enable the
+ * keep configuration feature, for two chip select could be
+ * attached with different nand chip. The different page size
+ * and timing requirement make the keep configuration impossible.
+ */
+
+/* The max num of chip select current support */
+#define NUM_CHIP_SELECT		(2)
 struct pxa3xx_nand_platform_data {
 
 	/* the data flash bus is shared between the Static Memory
@@ -52,8 +65,10 @@ 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;
+	/* indicate how many chip selects will be used */
+	int	num_cs;
+	const struct mtd_partition		*parts[NUM_CHIP_SELECT];
+	unsigned int				nr_parts[NUM_CHIP_SELECT];
 
 	const struct pxa3xx_nand_flash * 	flash;
 	size_t					num_flash;
diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index b7db1b2..0825b7d 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -110,6 +110,7 @@ enum {
 
 enum {
 	STATE_IDLE = 0,
+	STATE_PREPARED,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
@@ -120,21 +121,40 @@ enum {
 	STATE_READY,
 };
 
-struct pxa3xx_nand_info {
-	struct nand_chip	nand_chip;
+struct pxa3xx_nand_host {
+	struct nand_chip	chip;
+	struct pxa3xx_nand_cmdset *cmdset;
+	struct mtd_info         *mtd;
+	void			*info_data;
 
+	/* page size of attached chip */
+	unsigned int		page_size;
+	int			cs;
+	int			use_ecc;
+
+	/* calculated from pxa3xx_nand_flash data */
+	unsigned int		col_addr_cycles;
+	unsigned int		row_addr_cycles;
+	size_t			read_id_bytes;
+
+	/* cached register value */
+	uint32_t		reg_ndcr;
+	uint32_t		ndtr0cs0;
+	uint32_t		ndtr1cs0;
+};
+
+struct pxa3xx_nand_info {
 	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
-	struct pxa3xx_nand_cmdset *cmdset;
 
 	struct clk		*clk;
 	void __iomem		*mmio_base;
 	unsigned long		mmio_phys;
+	struct completion	cmd_complete;
 
 	unsigned int 		buf_start;
 	unsigned int		buf_count;
 
-	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -142,44 +162,27 @@ struct pxa3xx_nand_info {
 	unsigned char		*data_buff;
 	unsigned char		*oob_buff;
 	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;
 
-	uint32_t		reg_ndcr;
-
-	/* saved column/page_addr during CMD_SEQIN */
-	int			seqin_column;
-	int			seqin_page_addr;
-
+	struct pxa3xx_nand_host	*host[NUM_CHIP_SELECT];
 	/* relate to the command */
 	unsigned int		state;
 
+	int			cs;
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
 	int			is_ready;
 
-	unsigned int		page_size;	/* page size of attached chip */
 	unsigned int		data_size;	/* data size in FIFO */
+	unsigned int		oob_size;
 	int 			retcode;
-	struct completion 	cmd_complete;
 
 	/* generated NDCBx register values */
 	uint32_t		ndcb0;
 	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;
-
-	unsigned int	col_addr_cycles;
-	unsigned int	row_addr_cycles;
 };
 
 static int use_dma = 1;
@@ -225,7 +228,7 @@ static struct pxa3xx_nand_flash builtin_flash_types[] = {
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
-const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+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)
@@ -241,9 +244,10 @@ const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
 /* convert nano-seconds to nand flash controller clock cycles */
 #define ns2cycle(ns, clk)	(int)((ns) * (clk / 1000000) / 1000)
 
-static void pxa3xx_nand_set_timing(struct pxa3xx_nand_info *info,
+static void pxa3xx_nand_set_timing(struct pxa3xx_nand_host *host,
 				   const struct pxa3xx_nand_timing *t)
 {
+	struct pxa3xx_nand_info *info = host->info_data;
 	unsigned long nand_clk = clk_get_rate(info->clk);
 	uint32_t ndtr0, ndtr1;
 
@@ -258,23 +262,24 @@ 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;
+	host->ndtr0cs0 = ndtr0;
+	host->ndtr1cs0 = ndtr1;
 	nand_writel(info, NDTR0CS0, ndtr0);
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
-	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	int oob_enable = host->reg_ndcr & NDCR_SPARE_EN;
 
-	info->data_size = info->page_size;
+	info->data_size = host->page_size;
 	if (!oob_enable) {
 		info->oob_size = 0;
 		return;
 	}
 
-	switch (info->page_size) {
+	switch (host->page_size) {
 	case 2048:
 		info->oob_size = (info->use_ecc) ? 40 : 64;
 		break;
@@ -292,9 +297,10 @@ static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
  */
 static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr;
 
-	ndcr = info->reg_ndcr;
+	ndcr = host->reg_ndcr;
 	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
 	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
 	ndcr |= NDCR_ND_RUN;
@@ -359,8 +365,8 @@ static void handle_data_pio(struct pxa3xx_nand_info *info)
 					DIV_ROUND_UP(info->oob_size, 4));
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
-				info->state);
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
+			info->state);
 		BUG();
 	}
 }
@@ -385,7 +391,7 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
 		break;
 	default:
-		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+		dev_err(&info->pdev->dev, "%s: invalid state %d\n", __func__,
 				info->state);
 		BUG();
 	}
@@ -416,9 +422,17 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
 	unsigned int status, is_completed = 0;
+	unsigned int ready, cmd_done;
+
+	if (info->cs == 0) {
+		ready           = NDSR_FLASH_RDY;
+		cmd_done        = NDSR_CS0_CMDD;
+	} else {
+		ready           = NDSR_RDY;
+		cmd_done        = NDSR_CS1_CMDD;
+	}
 
 	status = nand_readl(info, NDSR);
-
 	if (status & NDSR_DBERR)
 		info->retcode = ERR_DBERR;
 	if (status & NDSR_SBERR)
@@ -437,11 +451,11 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 			handle_data_pio(info);
 		}
 	}
-	if (status & NDSR_CS0_CMDD) {
+	if (status & cmd_done) {
 		info->state = STATE_CMD_DONE;
 		is_completed = 1;
 	}
-	if (status & NDSR_FLASH_RDY) {
+	if (status & ready) {
 		info->is_ready = 1;
 		info->state = STATE_READY;
 	}
@@ -463,12 +477,6 @@ 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--)
@@ -481,10 +489,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		uint16_t column, int page_addr)
 {
 	uint16_t cmd;
-	int addr_cycle, exec_cmd, ndcb0;
-	struct mtd_info *mtd = info->mtd;
+	int addr_cycle, exec_cmd;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
+	struct mtd_info *mtd = host->mtd;
 
-	ndcb0 = 0;
 	addr_cycle = 0;
 	exec_cmd = 1;
 
@@ -495,6 +503,10 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 	info->use_ecc		= 0;
 	info->is_ready		= 0;
 	info->retcode		= ERR_NONE;
+	if (info->cs != 0)
+		info->ndcb0 = NDCB0_CSEL;
+	else
+		info->ndcb0 = 0;
 
 	switch (command) {
 	case NAND_CMD_READ0:
@@ -512,20 +524,19 @@ 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);
+	addr_cycle = NDCB0_ADDR_CYC(host->row_addr_cycles
+				    + host->col_addr_cycles);
 
 	switch (command) {
 	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		cmd = info->cmdset->read1;
+		cmd = host->cmdset->read1;
 		if (command == NAND_CMD_READOOB)
 			info->buf_start = mtd->writesize + column;
 		else
 			info->buf_start = column;
 
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE))
 			info->ndcb0 |= NDCB0_CMD_TYPE(0)
 					| addr_cycle
 					| (cmd & NDCB0_CMD1_MASK);
@@ -537,7 +548,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	case NAND_CMD_SEQIN:
 		/* small page addr setting */
-		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+		if (unlikely(host->page_size < PAGE_CHUNK_SIZE)) {
 			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
 					| (column & 0xFF);
 
@@ -564,7 +575,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 			break;
 		}
 
-		cmd = info->cmdset->program;
+		cmd = host->cmdset->program;
 		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
 				| NDCB0_AUTO_RS
 				| NDCB0_ST_ROW_EN
@@ -574,8 +585,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		break;
 
 	case NAND_CMD_READID:
-		cmd = info->cmdset->read_id;
-		info->buf_count = info->read_id_bytes;
+		cmd = host->cmdset->read_id;
+		info->buf_count = host->read_id_bytes;
 		info->ndcb0 |= NDCB0_CMD_TYPE(3)
 				| NDCB0_ADDR_CYC(1)
 				| cmd;
@@ -583,7 +594,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		info->data_size = 8;
 		break;
 	case NAND_CMD_STATUS:
-		cmd = info->cmdset->read_status;
+		cmd = host->cmdset->read_status;
 		info->buf_count = 1;
 		info->ndcb0 |= NDCB0_CMD_TYPE(4)
 				| NDCB0_ADDR_CYC(1)
@@ -593,7 +604,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 		break;
 
 	case NAND_CMD_ERASE1:
-		cmd = info->cmdset->erase;
+		cmd = host->cmdset->erase;
 		info->ndcb0 |= NDCB0_CMD_TYPE(2)
 				| NDCB0_AUTO_RS
 				| NDCB0_ADDR_CYC(3)
@@ -604,7 +615,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 		break;
 	case NAND_CMD_RESET:
-		cmd = info->cmdset->reset;
+		cmd = host->cmdset->reset;
 		info->ndcb0 |= NDCB0_CMD_TYPE(5)
 				| cmd;
 
@@ -616,7 +627,7 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 
 	default:
 		exec_cmd = 0;
-		printk(KERN_ERR "pxa3xx-nand: non-supported"
+		dev_err(&info->pdev->dev, "pxa3xx-nand: non-supported"
 			" command %x\n", command);
 		break;
 	}
@@ -627,7 +638,8 @@ static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int ret, exec_cmd;
 
 	/*
@@ -635,9 +647,21 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 	 * "byte" address into a "word" address appropriate
 	 * for indexing a word-oriented device
 	 */
-	if (info->reg_ndcr & NDCR_DWIDTH_M)
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
 		column /= 2;
 
+	/*
+	 * There may be different NAND chip hooked to
+	 * different chip select, so check whether
+	 * chip select has been changed, if yes, reset the timing
+	 */
+	if (info->cs != host->cs) {
+		info->cs = host->cs;
+		nand_writel(info, NDTR0CS0, host->ndtr0cs0);
+		nand_writel(info, NDTR1CS0, host->ndtr1cs0);
+	}
+
+	info->state = STATE_PREPARED;
 	exec_cmd = prepare_command_pool(info, command, column, page_addr);
 	if (exec_cmd) {
 		init_completion(&info->cmd_complete);
@@ -646,12 +670,12 @@ static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
 		ret = wait_for_completion_timeout(&info->cmd_complete,
 				CHIP_DELAY_TIMEOUT);
 		if (!ret) {
-			printk(KERN_ERR "Wait time out!!!\n");
+			dev_err(&info->pdev->dev, "Wait time out!!!\n");
 			/* Stop State Machine for next command cycle */
 			pxa3xx_nand_stop(info);
 		}
-		info->state = STATE_IDLE;
 	}
+	info->state = STATE_IDLE;
 }
 
 static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
@@ -664,7 +688,8 @@ static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	chip->read_buf(mtd, buf, mtd->writesize);
 	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
@@ -695,7 +720,8 @@ static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	char retval = 0xFF;
 
 	if (info->buf_start < info->buf_count)
@@ -707,7 +733,8 @@ static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
 
 static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	u16 retval = 0xFFFF;
 
 	if (!(info->buf_start & 0x01) && info->buf_start < info->buf_count) {
@@ -719,7 +746,8 @@ static u16 pxa3xx_nand_read_word(struct mtd_info *mtd)
 
 static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(buf, info->data_buff + info->buf_start, real_len);
@@ -729,7 +757,8 @@ static void pxa3xx_nand_read_buf(struct mtd_info *mtd, uint8_t *buf, int len)
 static void pxa3xx_nand_write_buf(struct mtd_info *mtd,
 		const uint8_t *buf, int len)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	int real_len = min_t(size_t, len, info->buf_count - info->buf_start);
 
 	memcpy(info->data_buff + info->buf_start, buf, real_len);
@@ -749,7 +778,8 @@ 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_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 
 	/* pxa3xx_nand_send_command has waited for command complete */
 	if (this->state == FL_WRITING || this->state == FL_ERASING) {
@@ -772,54 +802,69 @@ static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct pxa3xx_nand_host *host = info->host[info->cs];
 	uint32_t ndcr = 0x0; /* enable all interrupts */
 
-	if (f->page_size != 2048 && f->page_size != 512)
+	if (f->page_size != 2048 && f->page_size != 512) {
+		dev_err(&pdev->dev, "Current only support 2048 and 512 size\n");
 		return -EINVAL;
+	}
 
-	if (f->flash_width != 16 && f->flash_width != 8)
+	if (f->flash_width != 16 && f->flash_width != 8) {
+		dev_err(&pdev->dev, "Only support 8bit and 16 bit!\n");
 		return -EINVAL;
+	}
 
 	/* calculate flash information */
-	info->cmdset = &default_cmdset;
-	info->page_size = f->page_size;
-	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
+	host->cmdset = &default_cmdset;
+	host->page_size = f->page_size;
+	host->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
 	/* calculate addressing information */
-	info->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
+	host->col_addr_cycles = (f->page_size == 2048) ? 2 : 1;
 
 	if (f->num_blocks * f->page_per_block > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
+		host->row_addr_cycles = 2;
 
 	ndcr |= (pdata->enable_arbiter) ? NDCR_ND_ARB_EN : 0;
-	ndcr |= (info->col_addr_cycles == 2) ? NDCR_RA_START : 0;
+	ndcr |= (host->col_addr_cycles == 2) ? NDCR_RA_START : 0;
 	ndcr |= (f->page_per_block == 64) ? NDCR_PG_PER_BLK : 0;
 	ndcr |= (f->page_size == 2048) ? NDCR_PAGE_SZ : 0;
 	ndcr |= (f->flash_width == 16) ? NDCR_DWIDTH_M : 0;
 	ndcr |= (f->dfc_width == 16) ? NDCR_DWIDTH_C : 0;
 
-	ndcr |= NDCR_RD_ID_CNT(info->read_id_bytes);
+	ndcr |= NDCR_RD_ID_CNT(host->read_id_bytes);
 	ndcr |= NDCR_SPARE_EN; /* enable spare by default */
 
-	info->reg_ndcr = ndcr;
+	host->reg_ndcr = ndcr;
 
-	pxa3xx_nand_set_timing(info, f->timing);
+	pxa3xx_nand_set_timing(host, f->timing);
 	return 0;
 }
 
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
+	/*
+	 * We set 0 by hard coding here, for we don't support keep_config
+	 * when there is more than one chip attached to the controller
+	 */
+	struct pxa3xx_nand_host *host = info->host[0];
 	uint32_t ndcr = nand_readl(info, NDCR);
-	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* set info fields needed to read id */
-	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
-	info->reg_ndcr = ndcr & ~NDCR_INT_MASK;
-	info->cmdset = &default_cmdset;
 
-	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
-	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
+	if (ndcr & NDCR_PAGE_SZ) {
+		host->page_size = 2048;
+		host->read_id_bytes = 4;
+	} else {
+		host->page_size = 512;
+		host->read_id_bytes = 2;
+	}
+	host->reg_ndcr = ndcr & ~NDCR_INT_MASK;
+	host->cmdset = &default_cmdset;
+
+	host->ndtr0cs0 = nand_readl(info, NDTR0CS0);
+	host->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
 	return 0;
 }
@@ -829,59 +874,41 @@ static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
  * data buffer and the DMA descriptor
  */
 #define MAX_BUFF_SIZE	PAGE_SIZE
-
-static int pxa3xx_nand_init_buff(struct pxa3xx_nand_info *info)
+static void free_cs_resource(struct pxa3xx_nand_info *info, int cs)
 {
-	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;
+	struct pxa3xx_nand_host *host;
+	struct mtd_info *mtd;
 
-	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;
-	}
+	if (!info->host[cs])
+		return;
 
-	return 0;
+	host = info->host[cs];
+	mtd = host->mtd;
+	kfree(mtd);
+	info->host[cs] = NULL;
 }
 
 static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
 {
-	struct mtd_info *mtd = info->mtd;
-	struct nand_chip *chip = mtd->priv;
+	struct mtd_info *mtd = info->host[info->cs]->mtd;
+	int ret;
 
 	/* 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);
+	ret = pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	if (ret)
+		return ret;
+
+	pxa3xx_nand_cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
 	if (info->is_ready)
-		return 1;
-	else
 		return 0;
+
+	return -ENODEV;
 }
 
 static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_host *host = mtd->priv;
+	struct pxa3xx_nand_info *info = host->info_data;
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
 	struct nand_flash_dev pxa3xx_flash_ids[2], *def = NULL;
@@ -891,26 +918,26 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	uint64_t chipsize;
 	int i, ret, num;
 
+	info->cs = host->cs;
 	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
 		goto KEEP_CONFIG;
 
 	ret = pxa3xx_nand_sensing(info);
-	if (!ret) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_INFO "There is no nand chip on cs 0!\n");
+	if (ret) {
+		free_cs_resource(info, info->cs);
+		dev_info(&info->pdev->dev, "There is no nand chip on cs 0!\n");
 
-		return -EINVAL;
+		return ret;
 	}
 
 	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);
+		dev_info(&info->pdev->dev, "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");
+		free_cs_resource(info, info->cs);
+		dev_warn(&info->pdev->dev, "Read out ID 0, "
+			 "potential timing set wrong!!\n");
 
 		return -EINVAL;
 	}
@@ -928,14 +955,17 @@ static int pxa3xx_nand_scan(struct mtd_info *mtd)
 	}
 
 	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
-		kfree(mtd);
-		info->mtd = NULL;
-		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+		free_cs_resource(info, info->cs);
+		dev_err(&info->pdev->dev, "ERROR!! flash not defined!!!\n");
 
 		return -EINVAL;
 	}
 
-	pxa3xx_nand_config_flash(info, f);
+	ret = pxa3xx_nand_config_flash(info, f);
+	if (ret) {
+		dev_err(&info->pdev->dev, "ERROR! Configure failed\n");
+		return ret;
+	}
 	pxa3xx_flash_ids[0].name = f->name;
 	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
 	pxa3xx_flash_ids[0].pagesize = f->page_size;
@@ -950,66 +980,51 @@ KEEP_CONFIG:
 	if (nand_scan_ident(mtd, 1, def))
 		return -ENODEV;
 	/* calculate addressing information */
-	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	if (mtd->writesize >= 2048)
+		host->col_addr_cycles = 2;
+	else
+		host->col_addr_cycles = 1;
 	info->oob_buff = info->data_buff + mtd->writesize;
 	if ((mtd->size >> chip->page_shift) > 65536)
-		info->row_addr_cycles = 3;
+		host->row_addr_cycles = 3;
 	else
-		info->row_addr_cycles = 2;
-	mtd->name = mtd_names[0];
+		host->row_addr_cycles = 2;
+	mtd->name = mtd_names[info->cs];
 	chip->ecc.mode = NAND_ECC_HW;
-	chip->ecc.size = info->page_size;
+	chip->ecc.size = host->page_size;
 
-	chip->options = (info->reg_ndcr & NDCR_DWIDTH_M) ? NAND_BUSWIDTH_16 : 0;
+	chip->options = 0;
+	if (host->reg_ndcr & NDCR_DWIDTH_M)
+		chip->options = NAND_BUSWIDTH_16;
 	chip->options |= NAND_NO_AUTOINCR;
 	chip->options |= NAND_NO_READRDY;
 
 	return nand_scan_tail(mtd);
 }
 
-static
-struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
+static int alloc_nand_resource(struct platform_device *pdev)
 {
+	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	struct pxa3xx_nand_host *host;
 	struct nand_chip *chip;
 	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) {
+	pdata = pdev->dev.platform_data;
+	info = kzalloc(sizeof(struct pxa3xx_nand_info), GFP_KERNEL);
+	if (!info) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return NULL;
+		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->controller        = &info->controller;
-	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;
-
-	spin_lock_init(&chip->controller->lock);
-	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
 		ret = PTR_ERR(info->clk);
-		goto fail_free_mtd;
+		goto fail_alloc;
 	}
 	clk_enable(info->clk);
 
@@ -1058,10 +1073,6 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 	}
 	info->mmio_phys = r->start;
 
-	ret = pxa3xx_nand_init_buff(info);
-	if (ret)
-		goto fail_free_io;
-
 	/* initialize all interrupts to be disabled */
 	disable_int(info, NDSR_MASK);
 
@@ -1069,21 +1080,80 @@ struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 			  pdev->name, info);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
-		goto fail_free_buf;
+		ret = ENXIO;
+		goto fail_free_io;
 	}
 
 	platform_set_drvdata(pdev, info);
 
-	return info;
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		mtd = kzalloc(sizeof(struct mtd_info)
+				+ sizeof(struct pxa3xx_nand_host),
+				GFP_KERNEL);
+		if (!mtd) {
+			dev_err(&pdev->dev, "failed to allocate memory\n");
+			ret = -ENOMEM;
+			goto fail_free_irq;
+		}
+
+		host = (struct pxa3xx_nand_host *)(&mtd[1]);
+		host->info_data = info;
+		host->cs = cs;
+		host->mtd = mtd;
+		mtd->priv = host;
+		mtd->owner = THIS_MODULE;
+		info->host[cs] = host;
+
+		chip = (struct nand_chip *)(&mtd[1]);
+		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;
+	}
+
+	if (use_dma == 0) {
+		info->data_buff = kmalloc(MAX_BUFF_SIZE, GFP_KERNEL);
+		if (info->data_buff == NULL) {
+			ret = -ENOMEM;
+			goto fail_free_buf;
+		}
+		goto success_exit;
+	}
+
+	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, info);
+	if (info->data_dma_ch < 0) {
+		dev_err(&pdev->dev, "failed to request data dma\n");
+		ret = -ENXIO;
+		goto fail_free_dma_buf;
+	}
+success_exit:
+	return 0;
 
+fail_free_dma_buf:
+	dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
+			info->data_buff, info->data_buff_phys);
 fail_free_buf:
+	for (cs = 0; cs < pdata->num_cs; cs++)
+		free_cs_resource(info, cs);
+fail_free_irq:
 	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);
 fail_free_res:
@@ -1091,18 +1161,20 @@ fail_free_res:
 fail_put_clk:
 	clk_disable(info->clk);
 	clk_put(info->clk);
-fail_free_mtd:
-	kfree(mtd);
-	return NULL;
+fail_alloc:
+	kfree(info);
+	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_platform_data *pdata;
+	struct pxa3xx_nand_host *host;
 	struct resource *r;
-	int irq;
+	int irq, cs;
 
+	pdata = pdev->dev.platform_data;
 	platform_set_drvdata(pdev, NULL);
 
 	irq = platform_get_irq(pdev, 0);
@@ -1110,7 +1182,7 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 		free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
-		dma_free_writecombine(&pdev->dev, info->data_buff_size,
+		dma_free_writecombine(&pdev->dev, MAX_BUFF_SIZE,
 				info->data_buff, info->data_buff_phys);
 	} else
 		kfree(info->data_buff);
@@ -1122,9 +1194,12 @@ static int pxa3xx_nand_remove(struct platform_device *pdev)
 	clk_disable(info->clk);
 	clk_put(info->clk);
 
-	if (mtd) {
-		nand_release(mtd);
-		kfree(mtd);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		host = info->host[cs];
+		if (!host)
+			continue;
+		nand_release(host->mtd);
+		free_cs_resource(info, cs);
 	}
 	return 0;
 }
@@ -1133,6 +1208,7 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
+	int cs, ret, probe_success = 0;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -1140,18 +1216,38 @@ static int pxa3xx_nand_probe(struct platform_device *pdev)
 		return -ENODEV;
 	}
 
-	info = alloc_nand_resource(pdev);
-	if (info == NULL)
-		return -ENOMEM;
+	if (pdata->keep_config && pdata->num_cs > 1) {
+		dev_warn(&pdev->dev, "keep_config is prohibited with multiple"
+			 " chip selects feature!\n");
+		pdata->keep_config = 0;
+	}
+
+	ret = alloc_nand_resource(pdev);
+	if (ret) {
+		dev_err(&pdev->dev, "alloc nand resource failed\n");
+		return ret;
+	}
+
+	info = platform_get_drvdata(pdev);
+	for (cs = 0; cs < pdata->num_cs; cs++) {
+		ret = pxa3xx_nand_scan(info->host[cs]->mtd);
+		if (ret) {
+			dev_err(&pdev->dev, "failed to scan nand\n");
+			continue;
+		}
+
+		ret = mtd_device_parse_register(info->host[cs]->mtd, NULL, 0,
+			pdata->parts[cs], pdata->nr_parts[cs]);
+		if (!ret)
+			probe_success = 1;
+	}
 
-	if (pxa3xx_nand_scan(info->mtd)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
+	if (!probe_success) {
 		pxa3xx_nand_remove(pdev);
 		return -ENODEV;
 	}
 
-	return mtd_device_parse_register(info->mtd, NULL, 0,
-			pdata->parts, pdata->nr_parts);
+	return 0;
 }
 
 #ifdef CONFIG_PM
@@ -1171,8 +1267,12 @@ static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
 	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
 
-	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
-	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
+	/*
+	 * Directly set the chip select to a invalid value,
+	 * then the driver would reset the timing according
+	 * to current chip select at the beginning of cmdfunc
+	 */
+	info->cs = 0xff;
 	clk_enable(info->clk);
 
 	return 0;
-- 
1.7.0.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel at lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel


From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.89.1313562957.20020.linux-mtd@lists.infradead.org>

size of NAND.

Please have a correction or any idea will be highly recommended.

Thanks,
Alex

On Wed, Apr 20, 2011 at 3:30 PM, Artem Bityutskiy <dedekind1 at gmail.com> wro=
te:
> Hi,
>
> On Wed, 2011-04-20 at 11:19 +0800, Nicholas wrote:
>> Dear Artem,
>>
>> Sorry for my late reply .
>
> Please, send proper Linux kernel patches. Hints:
>
> 1. Make a separate patch pere change, so that on modification is done by
> one patch. In your case, one buffer improvement pere patch.
> 2. Write good commit message.
> 3. Use git format-patch to create patches.
>
>>
>> #define MTD_SMALL_SIZE_PAGE_BLOCK_SIZE =C2=A0 =C2=A0 =C2=A0 =C2=A00x4000=
0 // block size for 2KB
>
> No, please just make buffer size to be ubi->max_write_size. Kill this
> constant.
>
>> orphan.c
>> In ubifs_mount_orphans()
>> c->orph_buf =3D vmalloc((c->leb_size)/4); // for temporary
>
> Similarly, just use ubi->max_write_size instead.
>
> --
> Best Regards,
> Artem Bityutskiy (=D0=90=D1=80=D1=82=D1=91=D0=BC =D0=91=D0=B8=D1=82=D1=8E=
=D1=86=D0=BA=D0=B8=D0=B9)
>
>


From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.115.1314916231.20020.linux-mtd@lists.infradead.org>

> A NOP instruction that appears in FIR ahead of the last instruction
> is executed with the timing of a regular command instruction, but
> neither LFCLE nor LFWE are asserted.  Thus a NOP instruction may be
> used to insert a pause matching the time taken for a regular command
> write.

So the NOP does generate a delay.  Would be nice to know exactly why
it's required.

Have you tried doing this under load with parallel NOR activity?  With
CE-don't-care operation, during the times when CE is not asserted, does
it matter what happens with CLE/ALE/RE?  These signals could be driven
for another chipselect during that time.

-Scott



From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.118.1315131608.20020.linux-mtd@lists.infradead.org>

writepage size restriction is because
the flash device is memory mapped for caching purposes.
Initially, I wouldnt want to have the caching feature. Is there some
code in the ancient logfs tree
(http://git.kernel.org/?p=3Dlinux/kernel/git/joern/ancient_logfs.git;a=3Dsu=
mmary)
without the device mapping, that i can make use of?

Thanks,
mugunthan


From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.134.1316024537.20020.linux-mtd@lists.infradead.org>

So I'd actually recommend that Artem push this patch (patch 03) out of
'master' and into the 'brian' branch, then we can review the final
product there. In the end, I intended nandwrite to only have a single
buffer for OOB, instead of having a read buffer and an oob buffer. We
would simply pass our unmodified OOB data to mtd_write() and then to
the new MEMWRITE ioctl, where the kernel would do AUTO or PLACE
layouts for us depending on the mode we chose.

Of course, this is just the ideal approach; many kernels will not
support MEMWRITE yet, so they would fall back to the old code. That's
what patch 07 did; it cut out one buffer and moved the old layout code
into its own libmtd function, legacy_auto_oob_layout().
legacy_auto_oob_layout allocates its own buffer when needed; this part
is very inefficient (and actually has a memory leak now that I look at
it...) Perhaps the "legacy" handling should be reviewed a little more
to prevent too many trivial buffers and memcpy's.

If nothing else, I will at least need to send a v2 for patch 07 so we
free `tmp_buf' in `legacy_auto_oob_layout()'. But it'd be better just
to completely rework that function's buffers...

Brian


From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.143.1316533485.20020.linux-mtd@lists.infradead.org>

memory bus writes ensure the necessary time, as the NOP write takes as much time
as the DOCG3 decides it to last.

Unless you have a timing to provide (or even better, a specification), I'll
leave the NOP writes.

>> +static int doc_wait_ready(struct docg3 *docg3)
>> +{
>> +	int maxWaitCycles = 100;
>> +
>> +	do {
>> +		doc_delay(docg3, 4);
>> +	} while (!doc_is_ready(docg3) && maxWaitCycles--);
>> +	doc_delay(docg3, 2);
>> +	if (maxWaitCycles > 0)
>> +		return 0;
>> +	else
>> +		return -EIO;
>> +}
>
> There are things like cpu_relax() which are used in busy-loops - did you
> look at those?
No, but I'll amend that loop with cpu_relax, that makes perfect sense.

>
>> +/*
>> + * Debug sysfs entries
>> + */
>> +#ifdef CONFIG_DEBUG_FS
>
> You do not need to use CONFIG_DEBUG_FS - debugfs makes all calls to be
> noop if it is not present.
>
> Either remove all macros or use DEBUG
OK, will remove the ifdef.

>> +#define DEBUGFS_RO_ATTR(name, show_fct) \
>> +	static int name##_open(struct inode *inode, struct file *file) \
>> +	{ return single_open(file, show_fct, inode->i_private); }      \
>> +	static const struct file_operations name##_fops = { \
>> +		.owner = THIS_MODULE, \
>> +		.open = name##_open, \
>> +		.llseek = seq_lseek, \
>> +		.read = seq_read, \
>> +		.release = single_release \
>> +	};
>
> Hmm, looks like something which should be generic, not DoC-specific.
True, but it's not available yet.
And as it's not available, and I don't think debugfs will accept such a patch, I
think I'll leave it here. And if you wish, I'll fill in a separate patch to
debugfs, and *if* it's merged, I'll remove that part then.

Cheers.

-- 
Robert


From bogus@does.not.exist.com  Mon Jun 27 16:47:34 2011
From: bogus@does.not.exist.com ()
Date: Mon, 27 Jun 2011 20:47:34 -0000
Subject: No subject
Message-ID: <mailman.197.1319797859.20020.linux-mtd@lists.infradead.org>

Pages can contain errors caused by memory alteration. To correct these errors,
the ROM code uses ECC,
based on Hamming codes for SLC NAND and BCH (Bose, Ray-Chaudhuri, Hocquenghem)
code for
multilevel cell (MLC) devices. The computed ECC is compared to ECC stored in the
spare area of the
corresponding page. If there are uncorrectable errors, the ROM code returns with
FAIL.


