bk://linux-mtd.bkbits.net/mtd-2.6 dwmw2@shinybook.infradead.org|ChangeSet|20041117104515|42063 dwmw2 # This is a BitKeeper generated diff -Nru style patch. # # ChangeSet # 2004/11/17 10:45:15+00:00 dwmw2@shinybook.infradead.org # MTD: Fix chip ident definition for AMD 29F002T devices. # # They were missing unlock address and command set fields. # # From: David Vrabel # Signed-off-by: David Woodhouse # # drivers/mtd/chips/jedec_probe.c # 2004/11/17 10:44:46+00:00 dwmw2@shinybook.infradead.org +43 -28 # revision 1.59 # date: 2004/11/17 09:46:24; author: dvrabel; state: Exp; lines: +43 -28 # Add missing uddr and CmdSet fields to the entries for the 29F002T devices. # # ChangeSet # 2004/11/17 09:36:39+00:00 dwmw2@shinybook.infradead.org # JFFS2: Remove definition of obsolete struct jffs2_scan_info # # We no longer use this, since we rewrote the mount code to behave # entirely differently and not build up all the trees on mount. # # Signed-off-by: Artem Bityuckiy # Signed-off-by: David Woodhouse # # fs/jffs2/nodelist.h # 2004/11/17 09:36:16+00:00 dwmw2@shinybook.infradead.org +1 -8 # revision 1.124 # date: 2004/11/17 09:30:02; author: dedekind; state: Exp; lines: +1 -8 # Remove unused depricated struct jffs2_scan_info definition, # # ChangeSet # 2004/11/17 00:10:01-08:00 akpm@bix.(none) # Merge bk://linux-mtd.bkbits.net/mtd-2.6 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/11/17 00:09:56-08:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/11/17 00:09:56-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/11/16 20:53:10+00:00 dwmw2@shinybook.infradead.org # Email address update. # # The work address is increasingly unreliable and incompetently run. # Time to remove all visible instances of it and rely only on one # which isn't run by crack-monkeys. # # Signed-off-by: David Woodhouse # # kernel/workqueue.c # 2004/11/16 20:52:49+00:00 dwmw2@shinybook.infradead.org +1 -1 # Update email address to one at a competently-run domain. # # include/linux/jffs2.h # 2004/11/16 20:52:49+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/writev.c # 2004/11/16 20:52:49+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/write.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/wbuf.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/symlink.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/super.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/scan.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/readinode.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/read.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/pushpull.h # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/os-linux.h # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/nodemgmt.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/nodelist.h # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/nodelist.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/malloc.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/ioctl.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/gc.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/fs.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/file.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/erase.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/dir.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/compr_zlib.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/build.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # fs/jffs2/background.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +2 -2 # Update email address to one at a competently-run domain. # # drivers/char/applicom.c # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +1 -1 # Update email address to one at a competently-run domain. # # MAINTAINERS # 2004/11/16 20:52:48+00:00 dwmw2@shinybook.infradead.org +1 -1 # Update email address to one at a competently-run domain. # # CREDITS # 2004/11/16 20:52:47+00:00 dwmw2@shinybook.infradead.org +0 -1 # Update email address to one at a competently-run domain. # # ChangeSet # 2004/11/16 20:12:00+00:00 dwmw2@shinybook.infradead.org # JFFS2: Add notes on inocache_lock spinlock to README.Locking # # Signed-off-by: Artem Bityuckiy # Signed-off-by: David Woodhouse # # fs/jffs2/README.Locking # 2004/11/16 20:11:36+00:00 dwmw2@shinybook.infradead.org +26 -7 # revision 1.8 # date: 2004/11/14 11:43:41; author: dedekind; state: Exp; lines: +3 -3 # Fix typos in the newly added text. # ---------------------------- # revision 1.7 # date: 2004/11/14 11:38:54; author: dedekind; state: Exp; lines: +20 -1 # Add some information about the inocache_lock spinlock. # # ChangeSet # 2004/11/16 19:04:30+00:00 dwmw2@shinybook.infradead.org # JFFS2: Move very noisy debugging messages from level 1 to level 2. # # Signed-off-by: Artem Bityuckiy # Signed-off-by: David Woodhouse # # fs/jffs2/readinode.c # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +4 -2 # Nove very noisy debugging messages from level 1 to level 2. # # fs/jffs2/read.c # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +2 -2 # Nove very noisy debugging messages from level 1 to level 2. # # fs/jffs2/nodemgmt.c # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +2 -2 # Nove very noisy debugging messages from level 1 to level 2. # # fs/jffs2/nodelist.h # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +2 -2 # Nove very noisy debugging messages from level 1 to level 2. # # fs/jffs2/gc.c # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +3 -3 # Nove very noisy debugging messages from level 1 to level 2. # # fs/jffs2/fs.c # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +2 -2 # Nove very noisy debugging messages from level 1 to level 2. # # fs/jffs2/build.c # 2004/11/16 19:04:09+00:00 dwmw2@shinybook.infradead.org +3 -3 # Nove very noisy debugging messages from level 1 to level 2. # # ChangeSet # 2004/11/16 19:02:03+00:00 dwmw2@shinybook.infradead.org # MTD: NAND driver updates # # - Support 2048-byte HW ECC (from Juha Yrjölä ) # - Allow board drivers to provide pattern for bad block scanning # # Signed-off-by: Thomas Gleixner # Signed-off-by: David Woodhouse # # include/linux/mtd/nand.h # 2004/11/16 19:01:44+00:00 dwmw2@shinybook.infradead.org +7 -1 # revision 1.68 # date: 2004/11/12 10:40:37; author: gleixner; state: Exp; lines: +3 -1 # Allow board drivers to provide their own scan pattern for bad block scanning # ---------------------------- # revision 1.67 # date: 2004/11/01 20:03:59; author: gleixner; state: Exp; lines: +5 -1 # Cleanup HW-ECC. Calc ecc bytes during setup. Add HW12_2048 ECC mode (Initial Patch provided by Juha Yrjola ) # # drivers/mtd/nand/nand_bbt.c # 2004/11/16 19:01:44+00:00 dwmw2@shinybook.infradead.org +12 -10 # revision 1.28 # date: 2004/11/13 10:19:09; author: gleixner; state: Exp; lines: +9 -5 # Do not enforce flahsbased bad block tables. Stupid me # ---------------------------- # revision 1.27 # date: 2004/11/12 10:40:36; author: gleixner; state: Exp; lines: +8 -10 # Allow board drivers to provide their own scan pattern for bad block scanning # # drivers/mtd/nand/nand_base.c # 2004/11/16 19:01:44+00:00 dwmw2@shinybook.infradead.org +48 -51 # revision 1.123 # date: 2004/11/02 22:36:59; author: gleixner; state: Exp; lines: +2 -2 # Fix typo. Hmm, I start to adopt dwmw2's bad habits. Pointed out by Ed Berube # ---------------------------- # revision 1.122 # date: 2004/11/01 20:03:57; author: gleixner; state: Exp; lines: +48 -51 # Cleanup HW-ECC. Calc ecc bytes during setup. Add HW12_2048 ECC mode (Initial Patch provided by Juha Yrjola ) # # ChangeSet # 2004/11/16 18:58:15+00:00 dwmw2@shinybook.infradead.org # MTD: Provide XIP support for Intel flash chips. # # This allows for MTD support to be used on flash memory which is also used # for XIP purposes, either XIP kernel or XIP userspace. The whole idea is # to relocate functions actually modifying the flash state away from array mode # to ram and run them with interrupt disabled. When the flash needs some time # to complete a certain operation, we poll the processor for pending (but still # masked) interrupts, and when they occur we suspend the flash operation in order # to unmask interrupts and let the system run again. # # Signed-off-by: Nicolas Pitre # Signed-off-by: David Woodhouse # # include/linux/mtd/xip.h # 2004/11/16 18:57:52+00:00 dwmw2@shinybook.infradead.org +99 -0 # # include/linux/mtd/xip.h # 2004/11/16 18:57:52+00:00 dwmw2@shinybook.infradead.org +0 -0 # BitKeeper file /home/dwmw2/bk/mtd-2.6/include/linux/mtd/xip.h # # include/linux/mtd/flashchip.h # 2004/11/16 18:57:52+00:00 dwmw2@shinybook.infradead.org +3 -1 # revision 1.15 # date: 2004/11/05 22:41:06; author: nico; state: Exp; lines: +3 -1 # This allows for MTD support to be used on flash memory which is also used # for XIP purposes, either XIP kernel or XIP userspace. The whole idea is # to relocate functions actually modifying the flash state away from array mode # to ram and run them with interrupt disabled. When the flash needs some time # to complete a certain operation, we poll the processor for pending (but still # masked) interrupts, and when they occur we suspend the flash operation in order # to unmask interrupts and let the system run again. # # drivers/mtd/chips/cfi_util.c # 2004/11/16 18:57:51+00:00 dwmw2@shinybook.infradead.org +22 -13 # revision 1.7 # date: 2004/11/05 22:41:05; author: nico; state: Exp; lines: +13 -2 # This allows for MTD support to be used on flash memory which is also used # for XIP purposes, either XIP kernel or XIP userspace. The whole idea is # to relocate functions actually modifying the flash state away from array mode # to ram and run them with interrupt disabled. When the flash needs some time # to complete a certain operation, we poll the processor for pending (but still # masked) interrupts, and when they occur we suspend the flash operation in order # to unmask interrupts and let the system run again. # ---------------------------- # revision 1.6 # date: 2004/11/01 06:02:24; author: nico; state: Exp; lines: +10 -12 # Prerequisite cleanup for the upcoming patch. # This should not have changed the code logic at all. Sue me if it did. # # drivers/mtd/chips/cfi_probe.c # 2004/11/16 18:57:51+00:00 dwmw2@shinybook.infradead.org +77 -31 # revision 1.83 # date: 2004/11/16 18:19:02; author: nico; state: Exp; lines: +2 -2 # fix bogus comment # ---------------------------- # revision 1.81 # date: 2004/11/05 22:41:05; author: nico; state: Exp; lines: +54 -7 # This allows for MTD support to be used on flash memory which is also used # for XIP purposes, either XIP kernel or XIP userspace. The whole idea is # to relocate functions actually modifying the flash state away from array mode # to ram and run them with interrupt disabled. When the flash needs some time # to complete a certain operation, we poll the processor for pending (but still # masked) interrupts, and when they occur we suspend the flash operation in order # to unmask interrupts and let the system run again. # ---------------------------- # revision 1.80 # date: 2004/11/01 06:02:24; author: nico; state: Exp; lines: +23 -24 # Prerequisite cleanup for the upcoming patch. # This should not have changed the code logic at all. Sue me if it did. # # drivers/mtd/chips/cfi_cmdset_0001.c # 2004/11/16 18:57:51+00:00 dwmw2@shinybook.infradead.org +291 -30 # revision 1.163 # date: 2004/11/15 20:56:31; author: nico; state: Exp; lines: +106 -26 # Determine number of hw partitions from extended query data instead of # hardcoding it. # ---------------------------- # revision 1.162 # date: 2004/11/11 11:13:19; author: dwmw2; state: Exp; lines: +12 -2 # Restore oldstate to FL_READY on resume (or suspend failure). # ---------------------------- # revision 1.161 # date: 2004/11/05 22:41:04; author: nico; state: Exp; lines: +289 -27 # This allows for MTD support to be used on flash memory which is also used # for XIP purposes, either XIP kernel or XIP userspace. The whole idea is # to relocate functions actually modifying the flash state away from array mode # to ram and run them with interrupt disabled. When the flash needs some time # to complete a certain operation, we poll the processor for pending (but still # masked) interrupts, and when they occur we suspend the flash operation in order # to unmask interrupts and let the system run again. # # drivers/mtd/chips/Kconfig # 2004/11/16 18:57:51+00:00 dwmw2@shinybook.infradead.org +10 -1 # revision 1.10 # date: 2004/11/05 22:41:04; author: nico; state: Exp; lines: +10 -1 # This allows for MTD support to be used on flash memory which is also used # for XIP purposes, either XIP kernel or XIP userspace. The whole idea is # to relocate functions actually modifying the flash state away from array mode # to ram and run them with interrupt disabled. When the flash needs some time # to complete a certain operation, we poll the processor for pending (but still # masked) interrupts, and when they occur we suspend the flash operation in order # to unmask interrupts and let the system run again. # # ChangeSet # 2004/11/16 18:54:16+00:00 dwmw2@shinybook.infradead.org # JFFS2: Add support for bizarre NOR flash with ECC. # # Signed-off-by: Josh Boyer # Signed-off-by: David Woodhouse # # include/linux/jffs2_fs_sb.h # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +2 -2 # revision 1.46 # date: 2004/11/03 12:57:39; author: jwboyer; state: Exp; lines: +2 -2 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # fs/jffs2/wbuf.c # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +59 -9 # revision 1.76 # date: 2004/11/05 12:41:10; author: jwboyer; state: Exp; lines: +3 -1 # Fixed compilation with NAND=y but NOR_ECC=n. Ferenc was right in the first # place. Perhaps my stupidity is a reason to remove these config options finally # ---------------------------- # revision 1.75 # date: 2004/11/04 22:10:28; author: jwboyer; state: Exp; lines: +1 -5 # Fixup the fix from Ferenc. Stupid me # ---------------------------- # revision 1.74 # date: 2004/11/04 21:42:14; author: havasi; state: Exp; lines: +5 -1 # Make it compilable without JFFS2_FS_NOR_ECC, too # ---------------------------- # revision 1.73 # date: 2004/11/03 12:57:39; author: jwboyer; state: Exp; lines: +57 -9 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # fs/jffs2/scan.c # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +3 -3 # revision 1.113 # date: 2004/11/03 12:57:39; author: jwboyer; state: Exp; lines: +3 -3 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # ---------------------------- # # fs/jffs2/os-linux.h # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +18 -4 # revision 1.50 # date: 2004/11/04 22:10:28; author: jwboyer; state: Exp; lines: +5 -2 # Fixup the fix from Ferenc. Stupid me # ---------------------------- # revision 1.49 # date: 2004/11/04 21:42:14; author: havasi; state: Exp; lines: +3 -3 # Make it compilable without JFFS2_FS_NOR_ECC, too # ---------------------------- # revision 1.48 # date: 2004/11/03 12:57:39; author: jwboyer; state: Exp; lines: +15 -4 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # fs/jffs2/fs.c # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +9 -1 # revision 1.47 # date: 2004/11/03 12:57:39; author: jwboyer; state: Exp; lines: +9 -1 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # fs/jffs2/erase.c # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +7 -3 # revision 1.65 # date: 2004/11/13 10:51:47; author: dedekind; state: Exp; lines: +2 -2 # Use kvec instead of iovec structure to pass to the # jffs2_flash_direct_writev() function. # ---------------------------- # revision 1.64 # date: 2004/11/12 15:25:14; author: jwboyer; state: Exp; lines: +5 -10 # Make cleanmarkers on NOR always write directly. This fixes some ECOS problems # as well. # ---------------------------- # revision 1.63 # date: 2004/11/11 12:38:28; author: dwmw2; state: Exp; lines: +2 -1 # Set bad_offset when erase fails under eCos # ---------------------------- # revision 1.62 # date: 2004/11/03 12:57:39; author: jwboyer; state: Exp; lines: +10 -2 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # fs/jffs2/Makefile # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +2 -1 # revision 1.7 # date: 2004/11/03 12:57:38; author: jwboyer; state: Exp; lines: +2 -1 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # fs/Kconfig # 2004/11/16 18:53:54+00:00 dwmw2@shinybook.infradead.org +9 -0 # revision 1.8 # date: 2004/11/03 12:57:37; author: jwboyer; state: Exp; lines: +9 -0 # Adding ECC'd NOR support to JFFS2. Works with cfi_cmdset_0020.c # # Signed-off-by: Josh Boyer # # ChangeSet # 2004/11/11 14:52:18-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/11/11 14:52:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/11/11 14:52:14-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/11/07 21:11:44-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/11/07 21:11:40-08:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/11/07 21:11:40-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/11/04 18:20:27-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/11/04 18:20:21-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/11/03 12:35:31-08:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/11/03 12:35:27-08:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/30 22:49:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/10/30 22:49:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/29 15:36:21-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/10/29 15:36:16-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/10/29 15:36:16-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/28 11:59:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/10/28 11:59:54-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/25 19:06:15-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/10/25 19:06:11-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/22 20:52:26-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/10/22 20:52:21-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/19 16:52:39-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/10/19 16:52:35-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/10/19 16:52:35-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/05 22:13:15-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/10/05 22:13:11-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/10/04 22:16:15-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/10/04 22:16:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/22 23:36:08-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/09/22 23:36:03-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/16 16:09:04-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/09/16 16:08:58-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/07 20:52:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/09/07 20:52:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/09/03 14:06:33-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/09/03 14:06:28-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/09/03 14:06:28-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/31 13:47:05-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/31 13:47:01-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/28 16:14:36-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/28 16:14:32-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/27 23:43:56-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/27 23:43:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/27 13:52:59-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/27 13:52:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/27 13:52:55-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/25 19:23:49-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/25 19:23:45-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/24 17:30:14-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/24 17:30:09-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 21:25:06-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # ChangeSet # 2004/08/23 16:39:08-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/23 21:25:02-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/23 16:39:03-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/23 14:23:56-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/23 14:23:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/23 14:23:52-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/22 21:30:25-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/22 21:30:21-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/09 18:43:41-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/09 18:43:38-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/05 12:56:24-07:00 akpm@bix.(none) # Merge bk://linux-mtd.bkbits.net/mtd-2.6 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/05 12:56:20-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/05 12:56:20-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/04 02:53:11-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/04 02:53:07-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/02 13:25:52-07:00 akpm@bix.(none) # Merge bix.(none):/usr/src/bk25 into bix.(none):/usr/src/bk-mtd # # MAINTAINERS # 2004/08/02 13:25:49-07:00 akpm@bix.(none) +0 -0 # Auto merged # # ChangeSet # 2004/08/02 01:16:16-07:00 akpm@bix.(none) # Merge bk://linux-mtd.bkbits.net/mtd-2.6 into bix.(none):/usr/src/bk-mtd # # fs/Kconfig # 2004/08/02 01:16:13-07:00 akpm@bix.(none) +0 -0 # Auto merged # # MAINTAINERS # 2004/08/02 01:16:12-07:00 akpm@bix.(none) +0 -0 # Auto merged # diff -Nru a/CREDITS b/CREDITS --- a/CREDITS 2004-11-17 19:39:36 -08:00 +++ b/CREDITS 2004-11-17 19:39:36 -08:00 @@ -3569,7 +3569,6 @@ N: David Woodhouse E: dwmw2@infradead.org -E: dwmw2@redhat.com D: ARCnet stuff, Applicom board driver, SO_BINDTODEVICE, D: some Alpha platform porting from 2.0, Memory Technology Devices, D: Acquire watchdog timer, PC speaker driver maintenance, diff -Nru a/MAINTAINERS b/MAINTAINERS --- a/MAINTAINERS 2004-11-17 19:39:36 -08:00 +++ b/MAINTAINERS 2004-11-17 19:39:36 -08:00 @@ -1433,7 +1433,7 @@ MEMORY TECHNOLOGY DEVICES P: David Woodhouse -M: dwmw2@redhat.com +M: dwmw2@infradead.org W: http://www.linux-mtd.infradead.org/ L: linux-mtd@lists.infradead.org S: Maintained diff -Nru a/drivers/char/applicom.c b/drivers/char/applicom.c --- a/drivers/char/applicom.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/char/applicom.c 2004-11-17 19:39:36 -08:00 @@ -1,6 +1,6 @@ /* Derived from Applicom driver ac.c for SCO Unix */ /* Ported by David Woodhouse, Axiom (Cambridge) Ltd. */ -/* dwmw2@redhat.com 30/8/98 */ +/* dwmw2@infradead.org 30/8/98 */ /* $Id: ac.c,v 1.30 2000/03/22 16:03:57 dwmw2 Exp $ */ /* This module is for Linux 2.1 and 2.2 series kernels. */ /*****************************************************************************/ diff -Nru a/drivers/mtd/chips/Kconfig b/drivers/mtd/chips/Kconfig --- a/drivers/mtd/chips/Kconfig 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/chips/Kconfig 2004-11-17 19:39:36 -08:00 @@ -1,5 +1,5 @@ # drivers/mtd/chips/Kconfig -# $Id: Kconfig,v 1.9 2004/07/16 15:32:14 dwmw2 Exp $ +# $Id: Kconfig,v 1.10 2004/11/05 22:41:04 nico Exp $ menu "RAM/ROM/Flash chip drivers" depends on MTD!=n @@ -271,6 +271,15 @@ only called JEDEC because the JEDEC association distributes the identification codes for the chips. + +config MTD_XIP + bool "XIP aware MTD support" + depends on !SMP && MTD_CFI_INTELEXT && EXPERIMENTAL + default y if XIP_KERNEL + help + This allows MTD support to work with flash memory which is also + used for XIP purposes. If you're not sure what this is all about + then say N. endmenu diff -Nru a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c --- a/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-17 19:39:36 -08:00 @@ -4,9 +4,8 @@ * * (C) 2000 Red Hat. GPL'd * - * $Id: cfi_cmdset_0001.c,v 1.160 2004/11/01 06:02:24 nico Exp $ - * (+ suspend fix from v1.162) - * (+ partition detection fix from v1.163) + * $Id: cfi_cmdset_0001.c,v 1.164 2004/11/16 18:29:00 dwmw2 Exp $ + * * * 10/10/2000 Nicolas Pitre * - completely revamped method functions so they are aware and @@ -30,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +37,10 @@ /* #define CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE */ +#ifdef CONFIG_MTD_XIP +#define CMDSET0001_DISABLE_WRITE_SUSPEND +#endif + // debugging, turns off buffer write mode if set to 1 #define FORCE_WORD_WRITE 0 @@ -147,6 +151,21 @@ } #endif +#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND +/* The XIP config appears to have problems using write suspend at the moment */ +static void fixup_no_write_suspend(struct mtd_info *mtd, void* param) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + struct cfi_pri_intelext *cfip = cfi->cmdset_priv; + + if (cfip && (cfip->FeatureSupport&4)) { + cfip->FeatureSupport &= ~4; + printk(KERN_WARNING "cfi_cmdset_0001: write suspend disabled\n"); + } +} +#endif + static void fixup_st_m28w320ct(struct mtd_info *mtd, void* param) { struct map_info *map = mtd->priv; @@ -189,6 +208,9 @@ #ifdef CMDSET0001_DISABLE_ERASE_SUSPEND_ON_WRITE { CFI_MFR_ANY, CFI_ID_ANY, fixup_intel_strataflash, NULL }, #endif +#ifdef CMDSET0001_DISABLE_WRITE_SUSPEND + { CFI_MFR_ANY, CFI_ID_ANY, fixup_no_write_suspend, NULL }, +#endif #if !FORCE_WORD_WRITE { CFI_MFR_ANY, CFI_ID_ANY, fixup_use_write_buffers, NULL }, #endif @@ -679,6 +701,14 @@ chip->state = FL_STATUS; return 0; + case FL_XIP_WHILE_ERASING: + if (mode != FL_READY && mode != FL_POINT && + (mode != FL_WRITING || !cfip || !(cfip->SuspendCmdSupport&1))) + goto sleep; + chip->oldstate = chip->state; + chip->state = FL_READY; + return 0; + case FL_POINT: /* Only if there's no operation suspended... */ if (mode == FL_READY && chip->oldstate == FL_READY) @@ -746,6 +776,11 @@ chip->state = FL_ERASING; break; + case FL_XIP_WHILE_ERASING: + chip->state = chip->oldstate; + chip->oldstate = FL_READY; + break; + case FL_READY: case FL_STATUS: case FL_JEDEC_QUERY: @@ -758,6 +793,201 @@ wake_up(&chip->wq); } +#ifdef CONFIG_MTD_XIP + +/* + * No interrupt what so ever can be serviced while the flash isn't in array + * mode. This is ensured by the xip_disable() and xip_enable() functions + * enclosing any code path where the flash is known not to be in array mode. + * And within a XIP disabled code path, only functions marked with __xipram + * may be called and nothing else (it's a good thing to inspect generated + * assembly to make sure inline functions were actually inlined and that gcc + * didn't emit calls to its own support functions). Also configuring MTD CFI + * support to a single buswidth and a single interleave is also recommended. + * Note that not only IRQs are disabled but the preemption count is also + * increased to prevent other locking primitives (namely spin_unlock) from + * decrementing the preempt count to zero and scheduling the CPU away while + * not in array mode. + */ + +static void xip_disable(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + /* TODO: chips with no XIP use should ignore and return */ + (void) map_read(map, adr); /* ensure mmu mapping is up to date */ + preempt_disable(); + local_irq_disable(); +} + +static void __xipram xip_enable(struct map_info *map, struct flchip *chip, + unsigned long adr) +{ + struct cfi_private *cfi = map->fldrv_priv; + if (chip->state != FL_POINT && chip->state != FL_READY) { + map_write(map, CMD(0xff), adr); + chip->state = FL_READY; + } + (void) map_read(map, adr); + asm volatile (".rep 8; nop; .endr"); /* fill instruction prefetch */ + local_irq_enable(); + preempt_enable(); +} + +/* + * When a delay is required for the flash operation to complete, the + * xip_udelay() function is polling for both the given timeout and pending + * (but still masked) hardware interrupts. Whenever there is an interrupt + * pending then the flash erase or write operation is suspended, array mode + * restored and interrupts unmasked. Task scheduling might also happen at that + * point. The CPU eventually returns from the interrupt or the call to + * schedule() and the suspended flash operation is resumed for the remaining + * of the delay period. + * + * Warning: this function _will_ fool interrupt latency tracing tools. + */ + +static void __xipram xip_udelay(struct map_info *map, struct flchip *chip, + unsigned long adr, int usec) +{ + struct cfi_private *cfi = map->fldrv_priv; + struct cfi_pri_intelext *cfip = cfi->cmdset_priv; + map_word status, OK = CMD(0x80); + unsigned long suspended, start = xip_currtime(); + flstate_t oldstate, newstate; + + do { + cpu_relax(); + if (xip_irqpending() && cfip && + ((chip->state == FL_ERASING && (cfip->FeatureSupport&2)) || + (chip->state == FL_WRITING && (cfip->FeatureSupport&4))) && + (cfi_interleave_is_1(cfi) || chip->oldstate == FL_READY)) { + /* + * Let's suspend the erase or write operation when + * supported. Note that we currently don't try to + * suspend interleaved chips if there is already + * another operation suspended (imagine what happens + * when one chip was already done with the current + * operation while another chip suspended it, then + * we resume the whole thing at once). Yes, it + * can happen! + */ + map_write(map, CMD(0xb0), adr); + map_write(map, CMD(0x70), adr); + usec -= xip_elapsed_since(start); + suspended = xip_currtime(); + do { + if (xip_elapsed_since(suspended) > 100000) { + /* + * The chip doesn't want to suspend + * after waiting for 100 msecs. + * This is a critical error but there + * is not much we can do here. + */ + return; + } + status = map_read(map, adr); + } while (!map_word_andequal(map, status, OK, OK)); + + /* Suspend succeeded */ + oldstate = chip->state; + if (oldstate == FL_ERASING) { + if (!map_word_bitsset(map, status, CMD(0x40))) + break; + newstate = FL_XIP_WHILE_ERASING; + chip->erase_suspended = 1; + } else { + if (!map_word_bitsset(map, status, CMD(0x04))) + break; + newstate = FL_XIP_WHILE_WRITING; + chip->write_suspended = 1; + } + chip->state = newstate; + map_write(map, CMD(0xff), adr); + (void) map_read(map, adr); + asm volatile (".rep 8; nop; .endr"); + local_irq_enable(); + preempt_enable(); + asm volatile (".rep 8; nop; .endr"); + cond_resched(); + + /* + * We're back. However someone else might have + * decided to go write to the chip if we are in + * a suspended erase state. If so let's wait + * until it's done. + */ + preempt_disable(); + while (chip->state != newstate) { + DECLARE_WAITQUEUE(wait, current); + set_current_state(TASK_UNINTERRUPTIBLE); + add_wait_queue(&chip->wq, &wait); + preempt_enable(); + schedule(); + remove_wait_queue(&chip->wq, &wait); + preempt_disable(); + } + /* Disallow XIP again */ + local_irq_disable(); + + /* Resume the write or erase operation */ + map_write(map, CMD(0xd0), adr); + map_write(map, CMD(0x70), adr); + chip->state = oldstate; + start = xip_currtime(); + } else if (usec >= 1000000/HZ) { + /* + * Try to save on CPU power when waiting delay + * is at least a system timer tick period. + * No need to be extremely accurate here. + */ + xip_cpu_idle(); + } + status = map_read(map, adr); + } while (!map_word_andequal(map, status, OK, OK) + && xip_elapsed_since(start) < usec); +} + +#define UDELAY(map, chip, adr, usec) xip_udelay(map, chip, adr, usec) + +/* + * The INVALIDATE_CACHED_RANGE() macro is normally used in parallel while + * the flash is actively programming or erasing since we have to poll for + * the operation to complete anyway. We can't do that in a generic way with + * a XIP setup so do it before the actual flash operation in this case. + */ +#undef INVALIDATE_CACHED_RANGE +#define INVALIDATE_CACHED_RANGE(x...) +#define XIP_INVAL_CACHED_RANGE(map, from, size) \ + do { if(map->inval_cache) map->inval_cache(map, from, size); } while(0) + +/* + * Extra notes: + * + * Activating this XIP support changes the way the code works a bit. For + * example the code to suspend the current process when concurrent access + * happens is never executed because xip_udelay() will always return with the + * same chip state as it was entered with. This is why there is no care for + * the presence of add_wait_queue() or schedule() calls from within a couple + * xip_disable()'d areas of code, like in do_erase_oneblock for example. + * The queueing and scheduling are always happening within xip_udelay(). + * + * Similarly, get_chip() and put_chip() just happen to always be executed + * with chip->state set to FL_READY (or FL_XIP_WHILE_*) where flash state + * is in array mode, therefore never executing many cases therein and not + * causing any problem with XIP. + */ + +#else + +#define xip_disable(map, chip, adr) +#define xip_enable(map, chip, adr) + +#define UDELAY(map, chip, adr, usec) cfi_udelay(usec) + +#define XIP_INVAL_CACHED_RANGE(x...) + +#endif + static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len) { unsigned long cmd_addr; @@ -944,7 +1174,11 @@ } #if 0 -static int cfi_intelext_read_prot_reg (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf, int base_offst, int reg_sz) +static int __xipram cfi_intelext_read_prot_reg (struct mtd_info *mtd, + loff_t from, size_t len, + size_t *retlen, + u_char *buf, + int base_offst, int reg_sz) { struct map_info *map = mtd->priv; struct cfi_private *cfi = map->fldrv_priv; @@ -973,6 +1207,8 @@ return (len-count)?:ret; } + xip_disable(map, chip, chip->start); + if (chip->state != FL_JEDEC_QUERY) { map_write(map, CMD(0x90), chip->start); chip->state = FL_JEDEC_QUERY; @@ -985,6 +1221,7 @@ count--; } + xip_enable(map, chip, chip->start); put_chip(map, chip, chip->start); spin_unlock(chip->mutex); @@ -1036,7 +1273,8 @@ } #endif -static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, map_word datum) +static int __xipram do_write_oneword(struct map_info *map, struct flchip *chip, + unsigned long adr, map_word datum) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; @@ -1055,14 +1293,16 @@ return ret; } + XIP_INVAL_CACHED_RANGE(map, adr, map_bankwidth(map)); ENABLE_VPP(map); + xip_disable(map, chip, adr); map_write(map, CMD(0x40), adr); map_write(map, datum, adr); chip->state = FL_WRITING; spin_unlock(chip->mutex); INVALIDATE_CACHED_RANGE(map, adr, map_bankwidth(map)); - cfi_udelay(chip->word_write_time); + UDELAY(map, chip, adr, chip->word_write_time); spin_lock(chip->mutex); timeo = jiffies + (HZ/2); @@ -1089,6 +1329,7 @@ /* OK Still waiting */ if (time_after(jiffies, timeo)) { chip->state = FL_STATUS; + xip_enable(map, chip, adr); printk(KERN_ERR "waiting for chip to be ready timed out in word write\n"); ret = -EIO; goto out; @@ -1097,7 +1338,7 @@ /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock(chip->mutex); z++; - cfi_udelay(1); + UDELAY(map, chip, adr, 1); spin_lock(chip->mutex); } if (!z) { @@ -1119,8 +1360,9 @@ map_write(map, CMD(0x70), adr); ret = -EROFS; } - out: - put_chip(map, chip, adr); + + xip_enable(map, chip, adr); + out: put_chip(map, chip, adr); spin_unlock(chip->mutex); return ret; @@ -1210,8 +1452,8 @@ } -static inline int do_write_buffer(struct map_info *map, struct flchip *chip, - unsigned long adr, const u_char *buf, int len) +static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, + unsigned long adr, const u_char *buf, int len) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; @@ -1232,6 +1474,10 @@ return ret; } + XIP_INVAL_CACHED_RANGE(map, adr, len); + ENABLE_VPP(map); + xip_disable(map, chip, cmd_adr); + /* §4.8 of the 28FxxxJ3A datasheet says "Any time SR.4 and/or SR.5 is set [...], the device will not accept any more Write to Buffer commands". So we must check here and reset those bits if they're set. Otherwise @@ -1240,12 +1486,13 @@ map_write(map, CMD(0x70), cmd_adr); status = map_read(map, cmd_adr); if (map_word_bitsset(map, status, CMD(0x30))) { + xip_enable(map, chip, cmd_adr); printk(KERN_WARNING "SR.4 or SR.5 bits set in buffer write (status %lx). Clearing.\n", status.x[0]); + xip_disable(map, chip, cmd_adr); map_write(map, CMD(0x50), cmd_adr); map_write(map, CMD(0x70), cmd_adr); } - ENABLE_VPP(map); chip->state = FL_WRITING_TO_BUFFER; z = 0; @@ -1257,7 +1504,7 @@ break; spin_unlock(chip->mutex); - cfi_udelay(1); + UDELAY(map, chip, cmd_adr, 1); spin_lock(chip->mutex); if (++z > 20) { @@ -1269,6 +1516,7 @@ /* Odd. Clear status bits */ map_write(map, CMD(0x50), cmd_adr); map_write(map, CMD(0x70), cmd_adr); + xip_enable(map, chip, cmd_adr); printk(KERN_ERR "Chip not ready for buffer write. status = %lx, Xstatus = %lx\n", status.x[0], Xstatus.x[0]); ret = -EIO; @@ -1305,7 +1553,7 @@ spin_unlock(chip->mutex); INVALIDATE_CACHED_RANGE(map, adr, len); - cfi_udelay(chip->buffer_write_time); + UDELAY(map, chip, cmd_adr, chip->buffer_write_time); spin_lock(chip->mutex); timeo = jiffies + (HZ/2); @@ -1331,6 +1579,7 @@ /* OK Still waiting */ if (time_after(jiffies, timeo)) { chip->state = FL_STATUS; + xip_enable(map, chip, cmd_adr); printk(KERN_ERR "waiting for chip to be ready timed out in bufwrite\n"); ret = -EIO; goto out; @@ -1338,7 +1587,7 @@ /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock(chip->mutex); - cfi_udelay(1); + UDELAY(map, chip, cmd_adr, 1); z++; spin_lock(chip->mutex); } @@ -1362,8 +1611,8 @@ ret = -EROFS; } - out: - put_chip(map, chip, cmd_adr); + xip_enable(map, chip, cmd_adr); + out: put_chip(map, chip, cmd_adr); spin_unlock(chip->mutex); return ret; } @@ -1432,8 +1681,8 @@ return 0; } -static int do_erase_oneblock(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk) +static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; @@ -1455,7 +1704,10 @@ return ret; } + XIP_INVAL_CACHED_RANGE(map, adr, len); ENABLE_VPP(map); + xip_disable(map, chip, adr); + /* Clear the status register first */ map_write(map, CMD(0x50), adr); @@ -1467,7 +1719,7 @@ spin_unlock(chip->mutex); INVALIDATE_CACHED_RANGE(map, adr, len); - msleep(chip->erase_time / 2); + UDELAY(map, chip, adr, chip->erase_time*1000/2); spin_lock(chip->mutex); /* FIXME. Use a timer to check this, and return immediately. */ @@ -1505,6 +1757,7 @@ /* Clear status bits */ map_write(map, CMD(0x50), adr); map_write(map, CMD(0x70), adr); + xip_enable(map, chip, adr); printk(KERN_ERR "waiting for erase at %08lx to complete timed out. status = %lx, Xstatus = %lx.\n", adr, status.x[0], Xstatus.x[0]); ret = -EIO; @@ -1513,8 +1766,7 @@ /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock(chip->mutex); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(1); + UDELAY(map, chip, adr, 1000000/HZ); spin_lock(chip->mutex); } @@ -1530,6 +1782,7 @@ /* Reset the error bits */ map_write(map, CMD(0x50), adr); map_write(map, CMD(0x70), adr); + xip_enable(map, chip, adr); chipstatus = status.x[0]; if (!map_word_equal(map, status, CMD(chipstatus))) { @@ -1565,6 +1818,7 @@ ret = -EIO; } } else { + xip_enable(map, chip, adr); ret = 0; } @@ -1632,15 +1886,19 @@ } #ifdef DEBUG_LOCK_BITS -static int do_printlockstatus_oneblock(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk) +static int __xipram do_printlockstatus_oneblock(struct map_info *map, + struct flchip *chip, + unsigned long adr, + int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; int status, ofs_factor = cfi->interleave * cfi->device_type; + xip_disable(map, chip, adr+(2*ofs_factor)); cfi_send_gen_cmd(0x90, 0x55, 0, map, cfi, cfi->device_type, NULL); chip->state = FL_JEDEC_QUERY; status = cfi_read_query(map, adr+(2*ofs_factor)); + xip_enable(map, chip, 0); printk(KERN_DEBUG "block status register for 0x%08lx is %x\n", adr, status); return 0; @@ -1650,8 +1908,8 @@ #define DO_XXLOCK_ONEBLOCK_LOCK ((void *) 1) #define DO_XXLOCK_ONEBLOCK_UNLOCK ((void *) 2) -static int do_xxlock_oneblock(struct map_info *map, struct flchip *chip, - unsigned long adr, int len, void *thunk) +static int __xipram do_xxlock_oneblock(struct map_info *map, struct flchip *chip, + unsigned long adr, int len, void *thunk) { struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK; @@ -1671,8 +1929,9 @@ } ENABLE_VPP(map); + xip_disable(map, chip, adr); + map_write(map, CMD(0x60), adr); - if (thunk == DO_XXLOCK_ONEBLOCK_LOCK) { map_write(map, CMD(0x01), adr); chip->state = FL_LOCKING; @@ -1683,7 +1942,7 @@ BUG(); spin_unlock(chip->mutex); - schedule_timeout(HZ); + UDELAY(map, chip, adr, 1000000/HZ); spin_lock(chip->mutex); /* FIXME. Use a timer to check this, and return immediately. */ @@ -1702,6 +1961,7 @@ map_write(map, CMD(0x70), adr); chip->state = FL_STATUS; Xstatus = map_read(map, adr); + xip_enable(map, chip, adr); printk(KERN_ERR "waiting for unlock to complete timed out. status = %lx, Xstatus = %lx.\n", status.x[0], Xstatus.x[0]); put_chip(map, chip, adr); @@ -1711,12 +1971,13 @@ /* Latency issues. Drop the lock, wait a while and retry */ spin_unlock(chip->mutex); - cfi_udelay(1); + UDELAY(map, chip, adr, 1); spin_lock(chip->mutex); } /* Done and happy. */ chip->state = FL_STATUS; + xip_enable(map, chip, adr); put_chip(map, chip, adr); spin_unlock(chip->mutex); return 0; @@ -1875,7 +2136,7 @@ static char im_name_1[]="cfi_cmdset_0001"; static char im_name_3[]="cfi_cmdset_0003"; -int __init cfi_intelext_init(void) +static int __init cfi_intelext_init(void) { inter_module_register(im_name_1, THIS_MODULE, &cfi_cmdset_0001); inter_module_register(im_name_3, THIS_MODULE, &cfi_cmdset_0001); diff -Nru a/drivers/mtd/chips/cfi_probe.c b/drivers/mtd/chips/cfi_probe.c --- a/drivers/mtd/chips/cfi_probe.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/chips/cfi_probe.c 2004-11-17 19:39:36 -08:00 @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: cfi_probe.c,v 1.79 2004/10/20 23:04:01 dwmw2 Exp $ + $Id: cfi_probe.c,v 1.83 2004/11/16 18:19:02 nico Exp $ */ #include @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -31,11 +32,47 @@ struct mtd_info *cfi_probe(struct map_info *map); +#ifdef CONFIG_MTD_XIP + +/* only needed for short periods, so this is rather simple */ +#define xip_disable() local_irq_disable() + +#define xip_allowed(base, map) \ +do { \ + (void) map_read(map, base); \ + asm volatile (".rep 8; nop; .endr"); \ + local_irq_enable(); \ +} while (0) + +#define xip_enable(base, map, cfi) \ +do { \ + 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); \ + xip_allowed(base, map); \ +} while (0) + +#define xip_disable_qry(base, map, cfi) \ +do { \ + xip_disable(); \ + 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); \ +} while (0) + +#else + +#define xip_disable() do { } while (0) +#define xip_allowed(base, map) do { } while (0) +#define xip_enable(base, map, cfi) do { } while (0) +#define xip_disable_qry(base, map, cfi) do { } while (0) + +#endif + /* check for QRY. in: interleave,type,mode ret: table index, <0 for error */ -static int qry_present(struct map_info *map, __u32 base, +static int __xipram qry_present(struct map_info *map, __u32 base, struct cfi_private *cfi) { int osf = cfi->interleave * cfi->device_type; // scale factor @@ -59,11 +96,11 @@ if (!map_word_equal(map, qry[2], val[2])) return 0; - return 1; // nothing found + return 1; // "QRY" found } -static int cfi_probe_chip(struct map_info *map, __u32 base, - unsigned long *chip_map, struct cfi_private *cfi) +static int __xipram cfi_probe_chip(struct map_info *map, __u32 base, + unsigned long *chip_map, struct cfi_private *cfi) { int i; @@ -79,12 +116,16 @@ (unsigned long)base + 0x55, map->size -1); return 0; } + + xip_disable(); 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 (!qry_present(map,base,cfi)) + if (!qry_present(map,base,cfi)) { + xip_enable(base, map, cfi); return 0; + } if (!cfi->numchips) { /* This is the first time we're called. Set up the CFI @@ -110,6 +151,7 @@ /* If the QRY marker goes away, it's an alias */ if (!qry_present(map, start, cfi)) { + xip_allowed(base, map); printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", map->name, base, start); return 0; @@ -122,6 +164,7 @@ cfi_send_gen_cmd(0xFF, 0, start, map, cfi, cfi->device_type, NULL); if (qry_present(map, base, cfi)) { + xip_allowed(base, map); printk(KERN_DEBUG "%s: Found an alias at 0x%x for the chip at 0x%lx\n", map->name, base, start); return 0; @@ -137,6 +180,7 @@ /* Put it back into Read Mode */ 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); + xip_allowed(base, map); printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", map->name, cfi->interleave, cfi->device_type*8, base, @@ -145,14 +189,15 @@ return 1; } -static int cfi_chip_setup(struct map_info *map, - struct cfi_private *cfi) +static int __xipram cfi_chip_setup(struct map_info *map, + struct cfi_private *cfi) { int ofs_factor = cfi->interleave*cfi->device_type; __u32 base = 0; int num_erase_regions = cfi_read_query(map, base + (0x10 + 28)*ofs_factor); int i; + xip_enable(base, map, cfi); #ifdef DEBUG_CFI printk("Number of erase regions: %d\n", num_erase_regions); #endif @@ -170,13 +215,33 @@ cfi->cfi_mode = CFI_MODE_CFI; /* Read the CFI info structure */ - for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) { + xip_disable_qry(base, map, cfi); + for (i=0; i<(sizeof(struct cfi_ident) + num_erase_regions * 4); i++) ((unsigned char *)cfi->cfiq)[i] = cfi_read_query(map,base + (0x10 + i)*ofs_factor); - } - + + /* Note we put the device back into Read Mode BEFORE going into Auto + * Select Mode, as some devices support nesting of modes, others + * don't. This way should always work. + * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and + * so should be treated as nops or illegal (and so put the device + * back into Read Mode, which is a nop in this case). + */ + 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(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); + cfi->mfr = cfi_read_query(map, base); + cfi->id = cfi_read_query(map, base + ofs_factor); + + /* Put it back into Read Mode */ + cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); + /* ... even if it's an Intel chip */ + cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); + xip_allowed(base, map); + /* Do any necessary byteswapping */ cfi->cfiq->P_ID = le16_to_cpu(cfi->cfiq->P_ID); - + cfi->cfiq->P_ADR = le16_to_cpu(cfi->cfiq->P_ADR); cfi->cfiq->A_ID = le16_to_cpu(cfi->cfiq->A_ID); cfi->cfiq->A_ADR = le16_to_cpu(cfi->cfiq->A_ADR); @@ -197,25 +262,6 @@ (cfi->cfiq->EraseRegionInfo[i] & 0xffff) + 1); #endif } - - /* Note we put the device back into Read Mode BEFORE going into Auto - * Select Mode, as some devices support nesting of modes, others - * don't. This way should always work. - * On cmdset 0001 the writes of 0xaa and 0x55 are not needed, and - * so should be treated as nops or illegal (and so put the device - * back into Read Mode, which is a nop in this case). - */ - 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(0x90, 0x555, base, map, cfi, cfi->device_type, NULL); - cfi->mfr = cfi_read_query(map, base); - cfi->id = cfi_read_query(map, base + ofs_factor); - - /* Put it back into Read Mode */ - cfi_send_gen_cmd(0xF0, 0, base, map, cfi, cfi->device_type, NULL); - /* ... even if it's an Intel chip */ - cfi_send_gen_cmd(0xFF, 0, base, map, cfi, cfi->device_type, NULL); printk(KERN_INFO "%s: Found %d x%d devices at 0x%x in %d-bit bank\n", map->name, cfi->interleave, cfi->device_type*8, base, diff -Nru a/drivers/mtd/chips/cfi_util.c b/drivers/mtd/chips/cfi_util.c --- a/drivers/mtd/chips/cfi_util.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/chips/cfi_util.c 2004-11-17 19:39:36 -08:00 @@ -7,7 +7,7 @@ * * This code is covered by the GPL. * - * $Id: cfi_util.c,v 1.5 2004/08/12 06:40:23 eric Exp $ + * $Id: cfi_util.c,v 1.7 2004/11/05 22:41:05 nico Exp $ * */ @@ -22,13 +22,14 @@ #include #include #include +#include #include #include #include #include struct cfi_extquery * -cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) +__xipram cfi_read_pri(struct map_info *map, __u16 adr, __u16 size, const char* name) { struct cfi_private *cfi = map->fldrv_priv; __u32 base = 0; // cfi->chips[0].start; @@ -40,21 +41,35 @@ if (!adr) goto out; - /* Switch it into Query Mode */ - cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); - extp = kmalloc(size, GFP_KERNEL); if (!extp) { printk(KERN_ERR "Failed to allocate memory\n"); goto out; } - + +#ifdef CONFIG_MTD_XIP + local_irq_disable(); +#endif + + /* Switch it into Query Mode */ + cfi_send_gen_cmd(0x98, 0x55, base, map, cfi, cfi->device_type, NULL); + /* Read in the Extended Query Table */ for (i=0; idevice_type, NULL); + cfi_send_gen_cmd(0xff, 0, base, map, cfi, cfi->device_type, NULL); + +#ifdef CONFIG_MTD_XIP + (void) map_read(map, base); + asm volatile (".rep 8; nop; .endr"); + local_irq_enable(); +#endif + if (extp->MajorVersion != '1' || (extp->MinorVersion < '0' || extp->MinorVersion > '3')) { printk(KERN_WARNING " Unknown %s Extended Query " @@ -62,15 +77,9 @@ extp->MinorVersion); kfree(extp); extp = NULL; - goto out; } -out: - /* Make sure it's in read mode */ - 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); - - return extp; + out: return extp; } EXPORT_SYMBOL(cfi_read_pri); diff -Nru a/drivers/mtd/chips/jedec_probe.c b/drivers/mtd/chips/jedec_probe.c --- a/drivers/mtd/chips/jedec_probe.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/chips/jedec_probe.c 2004-11-17 19:39:36 -08:00 @@ -1,7 +1,7 @@ /* Common Flash Interface probe code. (C) 2000 Red Hat. GPL'd. - $Id: jedec_probe.c,v 1.58 2004/11/16 18:29:00 dwmw2 Exp $ + $Id: jedec_probe.c,v 1.59 2004/11/17 09:46:24 dvrabel Exp $ See JEDEC (http://www.jedec.org/) standard JESD21C (section 3.5) for the standard this probe goes back to. @@ -514,15 +514,20 @@ ERASEINFO(0x10000,8), } }, { - mfr_id: MANUFACTURER_AMD, - dev_id: AM29F002T, - name: "AMD AM29F002T", - DevSize: SIZE_256KiB, - NumEraseRegions: 4, - regions: {ERASEINFO(0x10000,3), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) + .mfr_id = MANUFACTURER_AMD, + .dev_id = AM29F002T, + .name = "AMD AM29F002T", + .uaddr = { + [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ + }, + .DevSize = SIZE_256KiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 4, + .regions = { + ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1), } }, { .mfr_id = MANUFACTURER_ATMEL, @@ -770,15 +775,20 @@ ERASEINFO(0x04000,1) } }, { - mfr_id: MANUFACTURER_HYUNDAI, - dev_id: HY29F002T, - name: "Hyundai HY29F002T", - DevSize: SIZE_256KiB, - NumEraseRegions: 4, - regions: {ERASEINFO(0x10000,3), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) + .mfr_id = MANUFACTURER_HYUNDAI, + .dev_id = HY29F002T, + .name = "Hyundai HY29F002T", + .uaddr = { + [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ + }, + .DevSize = SIZE_256KiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 4, + .regions = { + ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1), } }, { .mfr_id = MANUFACTURER_INTEL, @@ -1177,15 +1187,20 @@ ERASEINFO(0x10000,7), } }, { - mfr_id: MANUFACTURER_MACRONIX, - dev_id: MX29F002T, - name: "Macronix MX29F002T", - DevSize: SIZE_256KiB, - NumEraseRegions: 4, - regions: {ERASEINFO(0x10000,3), - ERASEINFO(0x08000,1), - ERASEINFO(0x02000,2), - ERASEINFO(0x04000,1) + .mfr_id = MANUFACTURER_MACRONIX, + .dev_id = MX29F002T, + .name = "Macronix MX29F002T", + .uaddr = { + [0] = MTD_UADDR_0x0555_0x02AA /* x8 */ + }, + .DevSize = SIZE_256KiB, + .CmdSet = P_ID_AMD_STD, + .NumEraseRegions= 4, + .regions = { + ERASEINFO(0x10000,3), + ERASEINFO(0x08000,1), + ERASEINFO(0x02000,2), + ERASEINFO(0x04000,1), } }, { .mfr_id = MANUFACTURER_PMC, diff -Nru a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c --- a/drivers/mtd/nand/nand_base.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/nand/nand_base.c 2004-11-17 19:39:36 -08:00 @@ -41,7 +41,7 @@ * The AG-AND chips have nice features for speed improvement, * which are not supported yet. Read / program 4 pages in one go. * - * $Id: nand_base.c,v 1.121 2004/10/06 19:53:11 gleixner Exp $ + * $Id: nand_base.c,v 1.123 2004/11/02 22:36:59 gleixner Exp $ * * 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 @@ -840,18 +840,8 @@ } this->write_buf(mtd, this->data_poi, mtd->oobblock); break; - - /* Hardware ecc 8 byte / 512 byte data */ - case NAND_ECC_HW8_512: - eccbytes += 2; - /* Hardware ecc 6 byte / 512 byte data */ - case NAND_ECC_HW6_512: - eccbytes += 3; - /* Hardware ecc 3 byte / 256 data */ - /* Hardware ecc 3 byte / 512 byte data */ - case NAND_ECC_HW3_256: - case NAND_ECC_HW3_512: - eccbytes += 3; + default: + eccbytes = this->eccbytes; for (; eccsteps; eccsteps--) { /* enable hardware ecc logic for write */ this->enable_hwecc(mtd, NAND_ECC_WRITE); @@ -864,14 +854,9 @@ * the data bytes (words) */ if (this->options & NAND_HWECC_SYNDROME) this->write_buf(mtd, ecc_code, eccbytes); - datidx += this->eccsize; } break; - - default: - printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); - BUG(); } /* Write out OOB data */ @@ -1051,7 +1036,7 @@ int eccmode, eccsteps; int *oob_config, datidx; int blockcheck = (1 << (this->phys_erase_shift - this->page_shift)) - 1; - int eccbytes = 3; + int eccbytes; int compareecc = 1; int oobreadlen; @@ -1092,19 +1077,9 @@ end = mtd->oobblock; ecc = this->eccsize; - switch (eccmode) { - case NAND_ECC_HW6_512: /* Hardware ECC 6 byte / 512 byte data */ - eccbytes = 6; - break; - case NAND_ECC_HW8_512: /* Hardware ECC 8 byte / 512 byte data */ - eccbytes = 8; - break; - case NAND_ECC_NONE: - compareecc = 0; - break; - } - - if (this->options & NAND_HWECC_SYNDROME) + eccbytes = this->eccbytes; + + if ((eccmode == NAND_ECC_NONE) || (this->options & NAND_HWECC_SYNDROME)) compareecc = 0; oobreadlen = mtd->oobsize; @@ -1164,13 +1139,10 @@ for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=3, datidx += ecc) this->calculate_ecc(mtd, &data_poi[datidx], &ecc_calc[i]); break; - - case NAND_ECC_HW3_256: /* Hardware ECC 3 byte /256 byte data */ - case NAND_ECC_HW3_512: /* Hardware ECC 3 byte /512 byte data */ - case NAND_ECC_HW6_512: /* Hardware ECC 6 byte / 512 byte data */ - case NAND_ECC_HW8_512: /* Hardware ECC 8 byte / 512 byte data */ + + default: for (i = 0, datidx = 0; eccsteps; eccsteps--, i+=eccbytes, datidx += ecc) { - this->enable_hwecc(mtd, NAND_ECC_READ); + this->enable_hwecc(mtd, NAND_ECC_READ); this->read_buf(mtd, &data_poi[datidx], ecc); /* HW ecc with syndrome calculation must read the @@ -1193,10 +1165,6 @@ } } break; - - default: - printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); - BUG(); } /* read oobdata */ @@ -2433,8 +2401,19 @@ * fallback to software ECC */ this->eccsize = 256; /* set default eccsize */ + this->eccbytes = 3; switch (this->eccmode) { + case NAND_ECC_HW12_2048: + if (mtd->oobblock < 2048) { + printk(KERN_WARNING "2048 byte HW ECC not possible on %d byte page size, fallback to SW ECC\n", + mtd->oobblock); + this->eccmode = NAND_ECC_SOFT; + this->calculate_ecc = nand_calculate_ecc; + this->correct_data = nand_correct_data; + } else + this->eccsize = 2048; + break; case NAND_ECC_HW3_512: case NAND_ECC_HW6_512: @@ -2444,16 +2423,13 @@ this->eccmode = NAND_ECC_SOFT; this->calculate_ecc = nand_calculate_ecc; this->correct_data = nand_correct_data; - break; } else - this->eccsize = 512; /* set eccsize to 512 and fall through for function check */ - + this->eccsize = 512; /* set eccsize to 512 */ + break; + case NAND_ECC_HW3_256: - if (this->calculate_ecc && this->correct_data && this->enable_hwecc) - break; - printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); - BUG(); - + break; + case NAND_ECC_NONE: printk (KERN_WARNING "NAND_ECC_NONE selected by board driver. This is not recommended !!\n"); this->eccmode = NAND_ECC_NONE; @@ -2468,11 +2444,32 @@ printk (KERN_WARNING "Invalid NAND_ECC_MODE %d\n", this->eccmode); BUG(); } - + + /* Check hardware ecc function availability and adjust number of ecc bytes per + * calculation step + */ + switch (this->eccmode) { + case NAND_ECC_HW12_2048: + this->eccbytes += 4; + case NAND_ECC_HW8_512: + this->eccbytes += 2; + case NAND_ECC_HW6_512: + this->eccbytes += 3; + case NAND_ECC_HW3_512: + case NAND_ECC_HW3_256: + if (this->calculate_ecc && this->correct_data && this->enable_hwecc) + break; + printk (KERN_WARNING "No ECC functions supplied, Hardware ECC not possible\n"); + BUG(); + } + mtd->eccsize = this->eccsize; /* Set the number of read / write steps for one page to ensure ECC generation */ switch (this->eccmode) { + case NAND_ECC_HW12_2048: + this->eccsteps = mtd->oobblock / 2048; + break; case NAND_ECC_HW3_512: case NAND_ECC_HW6_512: case NAND_ECC_HW8_512: diff -Nru a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c --- a/drivers/mtd/nand/nand_bbt.c 2004-11-17 19:39:36 -08:00 +++ b/drivers/mtd/nand/nand_bbt.c 2004-11-17 19:39:36 -08:00 @@ -6,7 +6,7 @@ * * Copyright (C) 2004 Thomas Gleixner (tglx@linutronix.de) * - * $Id: nand_bbt.c,v 1.26 2004/10/05 13:50:20 gleixner Exp $ + * $Id: nand_bbt.c,v 1.28 2004/11/13 10:19:09 gleixner Exp $ * * 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 @@ -1001,25 +1001,27 @@ return nand_scan_bbt (mtd, &agand_flashbased); } + /* Is a flash based bad block table requested ? */ if (this->options & NAND_USE_FLASH_BBT) { /* Use the default pattern descriptors */ if (!this->bbt_td) { this->bbt_td = &bbt_main_descr; this->bbt_md = &bbt_mirror_descr; - } - if (mtd->oobblock > 512) - return nand_scan_bbt (mtd, &largepage_flashbased); - else - return nand_scan_bbt (mtd, &smallpage_flashbased); + } + if (!this->badblock_pattern) { + this->badblock_pattern = (mtd->oobblock > 512) ? + &largepage_flashbased : &smallpage_flashbased; + } } else { this->bbt_td = NULL; this->bbt_md = NULL; - if (mtd->oobblock > 512) - return nand_scan_bbt (mtd, &largepage_memorybased); - else - return nand_scan_bbt (mtd, &smallpage_memorybased); + if (!this->badblock_pattern) { + this->badblock_pattern = (mtd->oobblock > 512) ? + &largepage_memorybased : &smallpage_memorybased; + } } + return nand_scan_bbt (mtd, this->badblock_pattern); } /** diff -Nru a/fs/Kconfig b/fs/Kconfig --- a/fs/Kconfig 2004-11-17 19:39:36 -08:00 +++ b/fs/Kconfig 2004-11-17 19:39:36 -08:00 @@ -1179,6 +1179,15 @@ Say 'N' unless you have NAND flash. +config JFFS2_FS_NOR_ECC + bool "JFFS2 support for ECC'd NOR flash (EXPERIMENTAL)" + depends on JFFS2_FS && EXPERIMENTAL + default n + help + This enables the experimental support for NOR flash with transparent + ECC for JFFS2. This type of flash chip is not common, however it is + available from ST Microelectronics. + config JFFS2_COMPRESSION_OPTIONS bool "Advanced compression options for JFFS2" depends on JFFS2_FS diff -Nru a/fs/jffs2/Makefile b/fs/jffs2/Makefile --- a/fs/jffs2/Makefile 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/Makefile 2004-11-17 19:39:36 -08:00 @@ -1,7 +1,7 @@ # # Makefile for the Linux Journalling Flash File System v2 (JFFS2) # -# $Id: Makefile.common,v 1.6 2004/07/16 15:17:57 dwmw2 Exp $ +# $Id: Makefile.common,v 1.7 2004/11/03 12:57:38 jwboyer Exp $ # obj-$(CONFIG_JFFS2_FS) += jffs2.o @@ -12,6 +12,7 @@ jffs2-y += super.o jffs2-$(CONFIG_JFFS2_FS_NAND) += wbuf.o +jffs2-$(CONFIG_JFFS2_FS_NOR_ECC) += wbuf.o jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o diff -Nru a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking --- a/fs/jffs2/README.Locking 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/README.Locking 2004-11-17 19:39:36 -08:00 @@ -1,4 +1,4 @@ - $Id: README.Locking,v 1.4 2002/03/08 16:20:06 dwmw2 Exp $ + $Id: README.Locking,v 1.8 2004/11/14 11:43:41 dedekind Exp $ JFFS2 LOCKING DOCUMENTATION --------------------------- @@ -80,10 +80,10 @@ (NB) the per-inode list of physical nodes. The latter is a special case - see below. -As the MTD API permits erase-completion callback functions to be -called from bottom-half (timer) context, and these functions access -the data structures protected by this lock, it must be locked with -spin_lock_bh(). +As the MTD API no longer permits erase-completion callback functions +to be called from bottom-half (timer) context (on the basis that nobody +ever actually implemented such a thing), it's now sufficient to use +a simple spin_lock() rather than spin_lock_bh(). Note that the per-inode list of physical nodes (f->nodes) is a special case. Any changes to _valid_ nodes (i.e. ->flash_offset & 1 == 0) in @@ -99,8 +99,27 @@ GC thread locks it, sends the signal, then unlocks it - while the GC thread itself locks it, zeroes c->gc_task, then unlocks on the exit path. - node_free_sem - ------------- + + inocache_lock spinlock + ---------------------- + +This spinlock protects the hashed list (c->inocache_list) of the +in-core jffs2_inode_cache objects (each inode in JFFS2 has the +correspondent jffs2_inode_cache object). So, the inocache_lock +has to be locked while walking the c->inocache_list hash buckets. + +Note, the f->sem guarantees that the correspondent jffs2_inode_cache +will not be removed. So, it is allowed to access it without locking +the inocache_lock spinlock. + +Ordering constraints: + + If both erase_completion_lock and inocache_lock are needed, the + c->erase_completion has to be acquired first. + + + erase_free_sem + -------------- This semaphore is only used by the erase code which frees obsolete node references and the jffs2_garbage_collect_deletion_dirent() diff -Nru a/fs/jffs2/background.c b/fs/jffs2/background.c --- a/fs/jffs2/background.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/background.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: background.c,v 1.49 2004/07/13 08:56:40 dwmw2 Exp $ + * $Id: background.c,v 1.50 2004/11/16 20:36:10 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/build.c b/fs/jffs2/build.c --- a/fs/jffs2/build.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/build.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: build.c,v 1.55 2003/10/28 17:02:44 dwmw2 Exp $ + * $Id: build.c,v 1.57 2004/11/16 20:36:11 dwmw2 Exp $ * */ @@ -101,7 +101,7 @@ return ret; D1(printk(KERN_DEBUG "Scanned flash completely\n")); - D1(jffs2_dump_block_lists(c)); + D2(jffs2_dump_block_lists(c)); /* Now scan the directory tree, increasing nlink according to every dirent found. */ for_each_inode(i, c, ic) { @@ -164,7 +164,7 @@ cond_resched(); } D1(printk(KERN_DEBUG "Pass 3 complete\n")); - D1(jffs2_dump_block_lists(c)); + D2(jffs2_dump_block_lists(c)); /* Rotate the lists by some number to ensure wear levelling */ jffs2_rotate_lists(c); diff -Nru a/fs/jffs2/compr_zlib.c b/fs/jffs2/compr_zlib.c --- a/fs/jffs2/compr_zlib.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/compr_zlib.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: compr_zlib.c,v 1.28 2004/06/23 16:34:40 havasi Exp $ + * $Id: compr_zlib.c,v 1.29 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/dir.c b/fs/jffs2/dir.c --- a/fs/jffs2/dir.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/dir.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: dir.c,v 1.83 2004/10/19 07:48:44 havasi Exp $ + * $Id: dir.c,v 1.84 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/erase.c b/fs/jffs2/erase.c --- a/fs/jffs2/erase.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/erase.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: erase.c,v 1.61 2004/10/20 23:59:49 dwmw2 Exp $ + * $Id: erase.c,v 1.66 2004/11/16 20:36:11 dwmw2 Exp $ * */ @@ -43,6 +43,7 @@ jffs2_erase_succeeded(c, jeb); return; } + bad_offset = jeb->offset; #else /* Linux */ struct erase_info *instr; @@ -386,6 +387,7 @@ jeb->dirty_size = 0; jeb->wasted_size = 0; } else { + struct kvec vecs[1]; struct jffs2_unknown_node marker = { .magic = cpu_to_je16(JFFS2_MAGIC_BITMASK), .nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER), @@ -394,8 +396,10 @@ marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); - /* We only write the header; the rest was noise or padding anyway */ - ret = jffs2_flash_write(c, jeb->offset, sizeof(marker), &retlen, (char *)&marker); + vecs[0].iov_base = (unsigned char *) ▮ + vecs[0].iov_len = sizeof(marker); + ret = jffs2_flash_direct_writev(c, vecs, 1, jeb->offset, &retlen); + if (ret) { printk(KERN_WARNING "Write clean marker to block at 0x%08x failed: %d\n", jeb->offset, ret); diff -Nru a/fs/jffs2/file.c b/fs/jffs2/file.c --- a/fs/jffs2/file.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/file.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: file.c,v 1.98 2004/03/19 16:41:09 dwmw2 Exp $ + * $Id: file.c,v 1.99 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/fs.c b/fs/jffs2/fs.c --- a/fs/jffs2/fs.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/fs.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: fs.c,v 1.46 2004/07/13 08:56:54 dwmw2 Exp $ + * $Id: fs.c,v 1.49 2004/11/16 20:36:11 dwmw2 Exp $ * */ @@ -202,7 +202,7 @@ buf->f_bavail = buf->f_bfree = avail >> PAGE_SHIFT; - D1(jffs2_dump_block_lists(c)); + D2(jffs2_dump_block_lists(c)); spin_unlock(&c->erase_completion_lock); @@ -649,6 +649,11 @@ } /* add setups for other bizarre flashes here... */ + if (jffs2_nor_ecc(c)) { + ret = jffs2_nor_ecc_flash_setup(c); + if (ret) + return ret; + } return ret; } @@ -659,4 +664,7 @@ } /* add cleanups for other bizarre flashes here... */ + if (jffs2_nor_ecc(c)) { + jffs2_nor_ecc_flash_cleanup(c); + } } diff -Nru a/fs/jffs2/gc.c b/fs/jffs2/gc.c --- a/fs/jffs2/gc.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/gc.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: gc.c,v 1.140 2004/11/13 10:59:22 dedekind Exp $ + * $Id: gc.c,v 1.143 2004/11/16 20:36:11 dwmw2 Exp $ * */ @@ -103,7 +103,7 @@ ret->wasted_size = 0; } - D1(jffs2_dump_block_lists(c)); + D2(jffs2_dump_block_lists(c)); return ret; } @@ -134,7 +134,7 @@ if (c->checked_ino > c->highest_ino) { printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", c->unchecked_size); - D1(jffs2_dump_block_lists(c)); + D2(jffs2_dump_block_lists(c)); spin_unlock(&c->erase_completion_lock); BUG(); } diff -Nru a/fs/jffs2/ioctl.c b/fs/jffs2/ioctl.c --- a/fs/jffs2/ioctl.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/ioctl.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: ioctl.c,v 1.8 2003/10/28 16:16:28 dwmw2 Exp $ + * $Id: ioctl.c,v 1.9 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c --- a/fs/jffs2/malloc.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/malloc.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: malloc.c,v 1.27 2003/10/28 17:14:58 dwmw2 Exp $ + * $Id: malloc.c,v 1.28 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c --- a/fs/jffs2/nodelist.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/nodelist.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.c,v 1.87 2004/11/14 17:07:07 dedekind Exp $ + * $Id: nodelist.c,v 1.88 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h --- a/fs/jffs2/nodelist.h 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/nodelist.h 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodelist.h,v 1.121 2004/11/14 17:07:07 dedekind Exp $ + * $Id: nodelist.h,v 1.124 2004/11/17 09:30:02 dedekind Exp $ * */ @@ -148,13 +148,6 @@ #define INOCACHE_HASHSIZE 128 -struct jffs2_scan_info { - struct jffs2_full_dirent *dents; - struct jffs2_tmp_dnode_info *tmpnodes; - /* Latest i_size info */ - uint32_t version; - uint32_t isize; -}; /* Larger representation of a raw node, kept in-core only when the struct inode for this particular ino is instantiated. @@ -396,7 +389,7 @@ #define frag_erase(frag, list) rb_erase(&frag->rb, list); /* nodelist.c */ -D1(void jffs2_print_frag_list(struct jffs2_inode_info *f)); +D2(void jffs2_print_frag_list(struct jffs2_inode_info *f)); void jffs2_add_fd_to_list(struct jffs2_sb_info *c, struct jffs2_full_dirent *new, struct jffs2_full_dirent **list); int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info **tnp, struct jffs2_full_dirent **fdp, diff -Nru a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c --- a/fs/jffs2/nodemgmt.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/nodemgmt.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: nodemgmt.c,v 1.109 2004/10/07 15:08:47 havasi Exp $ + * $Id: nodemgmt.c,v 1.111 2004/11/16 20:36:11 dwmw2 Exp $ * */ @@ -604,7 +604,7 @@ } } -#if CONFIG_JFFS2_FS_DEBUG > 0 +#if CONFIG_JFFS2_FS_DEBUG >= 2 void jffs2_dump_block_lists(struct jffs2_sb_info *c) { diff -Nru a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h --- a/fs/jffs2/os-linux.h 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/os-linux.h 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2002-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: os-linux.h,v 1.47 2004/07/14 13:20:23 dwmw2 Exp $ + * $Id: os-linux.h,v 1.51 2004/11/16 20:36:11 dwmw2 Exp $ * */ @@ -99,7 +99,7 @@ #define jffs2_is_readonly(c) (OFNI_BS_2SFFJ(c)->s_flags & MS_RDONLY) -#ifndef CONFIG_JFFS2_FS_NAND +#if (!defined CONFIG_JFFS2_FS_NAND && !defined CONFIG_JFFS2_FS_NOR_ECC) #define jffs2_can_mark_obsolete(c) (1) #define jffs2_cleanmarker_oob(c) (0) #define jffs2_write_nand_cleanmarker(c,jeb) (-EIO) @@ -115,10 +115,13 @@ #define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) #define jffs2_wbuf_timeout NULL #define jffs2_wbuf_process NULL +#define jffs2_nor_ecc(c) (0) +#define jffs2_nor_ecc_flash_setup(c) (0) +#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) -#else /* NAND support present */ +#else /* NAND and/or ECC'd NOR support present */ -#define jffs2_can_mark_obsolete(c) (c->mtd->type == MTD_NORFLASH || c->mtd->type == MTD_RAM) +#define jffs2_can_mark_obsolete(c) ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & MTD_ECC)) || c->mtd->type == MTD_RAM) #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) #define jffs2_flash_write_oob(c, ofs, len, retlen, buf) ((c)->mtd->write_oob((c)->mtd, ofs, len, retlen, buf)) @@ -135,8 +138,19 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); void jffs2_wbuf_timeout(unsigned long data); void jffs2_wbuf_process(void *data); +int jffs2_flush_wbuf_gc(struct jffs2_sb_info *c, uint32_t ino); +int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c); int jffs2_nand_flash_setup(struct jffs2_sb_info *c); void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c); +#ifdef CONFIG_JFFS2_FS_NOR_ECC +#define jffs2_nor_ecc(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_ECC)) +int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c); +void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c); +#else +#define jffs2_nor_ecc(c) (0) +#define jffs2_nor_ecc_flash_setup(c) (0) +#define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) +#endif /* NOR ECC */ #endif /* NAND */ /* erase.c */ diff -Nru a/fs/jffs2/pushpull.h b/fs/jffs2/pushpull.h --- a/fs/jffs2/pushpull.h 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/pushpull.h 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001, 2002 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: pushpull.h,v 1.9 2003/10/04 08:33:06 dwmw2 Exp $ + * $Id: pushpull.h,v 1.10 2004/11/16 20:36:11 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/read.c b/fs/jffs2/read.c --- a/fs/jffs2/read.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/read.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: read.c,v 1.36 2004/05/25 11:12:32 havasi Exp $ + * $Id: read.c,v 1.38 2004/11/16 20:36:12 dwmw2 Exp $ * */ @@ -174,7 +174,7 @@ if (frag) { D1(printk(KERN_NOTICE "Eep. Hole in ino #%u fraglist. frag->ofs = 0x%08x, offset = 0x%08x\n", f->inocache->ino, frag->ofs, offset)); holesize = min(holesize, frag->ofs - offset); - D1(jffs2_print_frag_list(f)); + D2(jffs2_print_frag_list(f)); } D1(printk(KERN_DEBUG "Filling non-frag hole from %d-%d\n", offset, offset+holesize)); memset(buf, 0, holesize); diff -Nru a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c --- a/fs/jffs2/readinode.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/readinode.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: readinode.c,v 1.114 2004/11/14 17:07:07 dedekind Exp $ + * $Id: readinode.c,v 1.116 2004/11/16 20:36:12 dwmw2 Exp $ * */ @@ -22,7 +22,7 @@ static int jffs2_add_frag_to_fragtree(struct jffs2_sb_info *c, struct rb_root *list, struct jffs2_node_frag *newfrag); -#if CONFIG_JFFS2_FS_DEBUG >= 1 +#if CONFIG_JFFS2_FS_DEBUG >= 2 static void jffs2_print_fragtree(struct rb_root *list, int permitbug) { struct jffs2_node_frag *this = frag_first(list); @@ -56,7 +56,9 @@ printk(KERN_DEBUG "metadata at 0x%08x\n", ref_offset(f->metadata->raw)); } } +#endif +#if CONFIG_JFFS2_FS_DEBUG >= 1 static int jffs2_sanitycheck_fragtree(struct jffs2_inode_info *f) { struct jffs2_node_frag *frag; diff -Nru a/fs/jffs2/scan.c b/fs/jffs2/scan.c --- a/fs/jffs2/scan.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/scan.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: scan.c,v 1.112 2004/09/12 09:56:13 gleixner Exp $ + * $Id: scan.c,v 1.114 2004/11/16 20:36:12 dwmw2 Exp $ * */ #include @@ -68,7 +68,7 @@ static inline int min_free(struct jffs2_sb_info *c) { uint32_t min = 2 * sizeof(struct jffs2_raw_inode); -#ifdef CONFIG_JFFS2_FS_NAND +#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC if (!jffs2_can_mark_obsolete(c) && min < c->wbuf_pagesize) return c->wbuf_pagesize; #endif @@ -223,7 +223,7 @@ c->dirty_size -= c->nextblock->dirty_size; c->nextblock->dirty_size = 0; } -#ifdef CONFIG_JFFS2_FS_NAND +#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC if (!jffs2_can_mark_obsolete(c) && c->nextblock && (c->nextblock->free_size & (c->wbuf_pagesize-1))) { /* If we're going to start writing into a block which already contains data, and the end of the data isn't page-aligned, diff -Nru a/fs/jffs2/super.c b/fs/jffs2/super.c --- a/fs/jffs2/super.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/super.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: super.c,v 1.102 2004/11/12 02:42:17 tpoynor Exp $ + * $Id: super.c,v 1.103 2004/11/16 20:36:12 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c --- a/fs/jffs2/symlink.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/symlink.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001, 2002 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: symlink.c,v 1.13 2004/07/13 08:59:04 dwmw2 Exp $ + * $Id: symlink.c,v 1.14 2004/11/16 20:36:12 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c --- a/fs/jffs2/wbuf.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/wbuf.c 2004-11-17 19:39:36 -08:00 @@ -4,12 +4,12 @@ * Copyright (C) 2001-2003 Red Hat, Inc. * Copyright (C) 2004 Thomas Gleixner * - * Created by David Woodhouse + * Created by David Woodhouse * Modified debugged and enhanced by Thomas Gleixner * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: wbuf.c,v 1.72 2004/09/11 19:22:43 gleixner Exp $ + * $Id: wbuf.c,v 1.77 2004/11/16 20:36:12 dwmw2 Exp $ * */ @@ -224,7 +224,11 @@ } /* Do the read... */ - ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); + if (jffs2_cleanmarker_oob(c)) + ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); + else + ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); + if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { /* ECC recovered */ ret = 0; @@ -281,8 +285,11 @@ ret = -EIO; } else #endif + if (jffs2_cleanmarker_oob(c)) ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, buf, NULL, c->oobinfo); + else + ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, buf); if (ret || retlen != towrite) { /* Argh. We tried. Really we did. */ @@ -419,6 +426,10 @@ */ if (pad) { c->wbuf_len = PAD(c->wbuf_len); + + /* Pad with JFFS2_DIRTY_BITMASK initially. this helps out ECC'd NOR + with 8 byte page size */ + memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); if ( c->wbuf_len + sizeof(struct jffs2_unknown_node) < c->wbuf_pagesize) { struct jffs2_unknown_node *padnode = (void *)(c->wbuf + c->wbuf_len); @@ -426,9 +437,6 @@ padnode->nodetype = cpu_to_je16(JFFS2_NODETYPE_PADDING); padnode->totlen = cpu_to_je32(c->wbuf_pagesize - c->wbuf_len); padnode->hdr_crc = cpu_to_je32(crc32(0, padnode, sizeof(*padnode)-4)); - } else { - /* Pad with JFFS2_DIRTY_BITMASK */ - memset(c->wbuf + c->wbuf_len, 0, c->wbuf_pagesize - c->wbuf_len); } } /* else jffs2_flash_writev has actually filled in the rest of the @@ -444,8 +452,11 @@ ret = -EIO; } else #endif - ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); - + + if (jffs2_cleanmarker_oob(c)) + ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); + else + ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf); if (ret || retlen != c->wbuf_pagesize) { if (ret) @@ -582,6 +593,17 @@ memset(c->wbuf,0xff,c->wbuf_pagesize); } + /* Fixup the wbuf if we are moving to a new eraseblock. The checks below + fail for ECC'd NOR because cleanmarker == 16, so a block starts at + xxx0010. */ + if (jffs2_nor_ecc(c)) { + if (((c->wbuf_ofs % c->sector_size) == 0) && !c->wbuf_len) { + c->wbuf_ofs = PAGE_DIV(to); + c->wbuf_len = PAGE_MOD(to); + memset(c->wbuf,0xff,c->wbuf_pagesize); + } + } + /* Sanity checks on target address. It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), and it's permitted to write at the beginning of a new @@ -715,7 +737,11 @@ outvecs[splitvec].iov_len = split_ofs; /* We did cross a page boundary, so we write some now */ - ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); + if (jffs2_cleanmarker_oob(c)) + ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); + else + ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); + if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { /* At this point we have no problem, c->wbuf is empty. @@ -789,7 +815,10 @@ /* Read flash */ if (!jffs2_can_mark_obsolete(c)) { - ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); + if (jffs2_cleanmarker_oob(c)) + ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); + else + ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); if ( (ret == -EBADMSG) && (*retlen == len) ) { printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", @@ -1105,3 +1134,24 @@ { kfree(c->wbuf); } + +#ifdef CONFIG_JFFS2_FS_NOR_ECC +int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { + /* Cleanmarker is actually larger on the flashes */ + c->cleanmarker_size = 16; + + /* Initialize write buffer */ + c->wbuf_pagesize = c->mtd->eccsize; + c->wbuf_ofs = 0xFFFFFFFF; + + c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); + if (!c->wbuf) + return -ENOMEM; + + return 0; +} + +void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { + kfree(c->wbuf); +} +#endif diff -Nru a/fs/jffs2/write.c b/fs/jffs2/write.c --- a/fs/jffs2/write.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/write.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: write.c,v 1.86 2004/11/13 10:44:26 dedekind Exp $ + * $Id: write.c,v 1.87 2004/11/16 20:36:12 dwmw2 Exp $ * */ diff -Nru a/fs/jffs2/writev.c b/fs/jffs2/writev.c --- a/fs/jffs2/writev.c 2004-11-17 19:39:36 -08:00 +++ b/fs/jffs2/writev.c 2004-11-17 19:39:36 -08:00 @@ -3,11 +3,11 @@ * * Copyright (C) 2001, 2002 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in this directory. * - * $Id: writev.c,v 1.5 2004/07/13 08:58:25 dwmw2 Exp $ + * $Id: writev.c,v 1.6 2004/11/16 20:36:12 dwmw2 Exp $ * */ diff -Nru a/include/linux/jffs2.h b/include/linux/jffs2.h --- a/include/linux/jffs2.h 2004-11-17 19:39:36 -08:00 +++ b/include/linux/jffs2.h 2004-11-17 19:39:36 -08:00 @@ -3,12 +3,12 @@ * * Copyright (C) 2001-2003 Red Hat, Inc. * - * Created by David Woodhouse + * Created by David Woodhouse * * For licensing information, see the file 'LICENCE' in the * jffs2 directory. * - * $Id: jffs2.h,v 1.33 2004/05/25 11:31:55 havasi Exp $ + * $Id: jffs2.h,v 1.34 2004/11/16 20:36:14 dwmw2 Exp $ * */ diff -Nru a/include/linux/jffs2_fs_sb.h b/include/linux/jffs2_fs_sb.h --- a/include/linux/jffs2_fs_sb.h 2004-11-17 19:39:36 -08:00 +++ b/include/linux/jffs2_fs_sb.h 2004-11-17 19:39:36 -08:00 @@ -1,4 +1,4 @@ -/* $Id: jffs2_fs_sb.h,v 1.45 2003/10/08 11:46:27 dwmw2 Exp $ */ +/* $Id: jffs2_fs_sb.h,v 1.46 2004/11/03 12:57:39 jwboyer Exp $ */ #ifndef _JFFS2_FS_SB #define _JFFS2_FS_SB @@ -95,7 +95,7 @@ to an obsoleted node. I don't like this. Alternatives welcomed. */ struct semaphore erase_free_sem; -#ifdef CONFIG_JFFS2_FS_NAND +#if defined CONFIG_JFFS2_FS_NAND || defined CONFIG_JFFS2_FS_NOR_ECC /* Write-behind buffer for NAND flash */ unsigned char *wbuf; uint32_t wbuf_ofs; diff -Nru a/include/linux/mtd/flashchip.h b/include/linux/mtd/flashchip.h --- a/include/linux/mtd/flashchip.h 2004-11-17 19:39:36 -08:00 +++ b/include/linux/mtd/flashchip.h 2004-11-17 19:39:36 -08:00 @@ -6,7 +6,7 @@ * * (C) 2000 Red Hat. GPLd. * - * $Id: flashchip.h,v 1.14 2004/06/15 16:44:59 nico Exp $ + * $Id: flashchip.h,v 1.15 2004/11/05 22:41:06 nico Exp $ * */ @@ -37,6 +37,8 @@ FL_LOCKING, FL_UNLOCKING, FL_POINT, + FL_XIP_WHILE_ERASING, + FL_XIP_WHILE_WRITING, FL_UNKNOWN } flstate_t; diff -Nru a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h --- a/include/linux/mtd/nand.h 2004-11-17 19:39:36 -08:00 +++ b/include/linux/mtd/nand.h 2004-11-17 19:39:36 -08:00 @@ -5,7 +5,7 @@ * Steven J. Hill * Thomas Gleixner * - * $Id: nand.h,v 1.66 2004/10/02 10:07:08 gleixner Exp $ + * $Id: nand.h,v 1.68 2004/11/12 10:40:37 gleixner Exp $ * * 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 @@ -138,6 +138,8 @@ #define NAND_ECC_HW6_512 4 /* Hardware ECC 8 byte ECC per 512 Byte data */ #define NAND_ECC_HW8_512 6 +/* Hardware ECC 12 byte ECC per 2048 Byte data */ +#define NAND_ECC_HW12_2048 7 /* * Constants for Hardware ECC @@ -253,6 +255,7 @@ * @scan_bbt: [REPLACEABLE] function to scan bad block table * @eccmode: [BOARDSPECIFIC] mode of ecc, see defines * @eccsize: [INTERN] databytes used per ecc-calculation + * @eccbytes: [INTERN] number of ecc bytes per ecc-calculation step * @eccsteps: [INTERN] number of ecc calculation steps per page * @chip_delay: [BOARDSPECIFIC] chip dependent delay for transfering data from array to read regs (tR) * @chip_lock: [INTERN] spinlock used to protect access to this structure and the chip @@ -277,6 +280,7 @@ * @bbt: [INTERN] bad block table pointer * @bbt_td: [REPLACEABLE] bad block table descriptor for flash lookup * @bbt_md: [REPLACEABLE] bad block table mirror descriptor + * @badblock_pattern: [REPLACEABLE] bad block scan pattern used for initial bad block scan * @controller: [OPTIONAL] a pointer to a hardware controller structure which is shared among multiple independend devices * @priv: [OPTIONAL] pointer to private chip date */ @@ -307,6 +311,7 @@ int (*scan_bbt)(struct mtd_info *mtd); int eccmode; int eccsize; + int eccbytes; int eccsteps; int chip_delay; spinlock_t chip_lock; @@ -330,6 +335,7 @@ uint8_t *bbt; struct nand_bbt_descr *bbt_td; struct nand_bbt_descr *bbt_md; + struct nand_bbt_descr *badblock_pattern; struct nand_hw_control *controller; void *priv; }; diff -Nru a/include/linux/mtd/xip.h b/include/linux/mtd/xip.h --- /dev/null Wed Dec 31 16:00:00 196900 +++ b/include/linux/mtd/xip.h 2004-11-17 19:39:36 -08:00 @@ -0,0 +1,99 @@ +/* + * MTD primitives for XIP support + * + * Author: Nicolas Pitre + * Created: Nov 2, 2004 + * Copyright: (C) 2004 MontaVista Software, Inc. + * + * This XIP support for MTD has been loosely inspired + * by an earlier patch authored by David Woodhouse. + * + * 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. + * + * $Id: xip.h,v 1.1 2004/11/05 22:41:06 nico Exp $ + */ + +#ifndef __LINUX_MTD_XIP_H__ +#define __LINUX_MTD_XIP_H__ + +#include + +#ifdef CONFIG_MTD_XIP + +/* + * Function that are modifying the flash state away from array mode must + * obviously not be running from flash. The __xipram is therefore marking + * those functions so they get relocated to ram. + */ +#define __xipram __attribute__ ((__section__ (".data"))) + +/* + * We really don't want gcc to guess anything. + * We absolutely _need_ proper inlining. + */ +#include + +/* + * Each architecture has to provide the following macros. They must access + * the hardware directly and not rely on any other (XIP) functions since they + * won't be available when used (flash not in array mode). + * + * xip_irqpending() + * + * return non zero when any hardware interrupt is pending. + * + * xip_currtime() + * + * return a platform specific time reference to be used with + * xip_elapsed_since(). + * + * xip_elapsed_since(x) + * + * return in usecs the elapsed timebetween now and the reference x as + * returned by xip_currtime(). + * + * note 1: convertion to usec can be approximated, as long as the + * returned value is <= the real elapsed time. + * note 2: this should be able to cope with a few seconds without + * overflowing. + */ + +#if defined(CONFIG_ARCH_SA1100) || defined(CONFIG_ARCH_PXA) + +#include +#ifdef CONFIG_ARCH_PXA +#include +#endif + +#define xip_irqpending() (ICIP & ICMR) + +/* we sample OSCR and convert desired delta to usec (1/4 ~= 1000000/3686400) */ +#define xip_currtime() (OSCR) +#define xip_elapsed_since(x) (signed)((OSCR - (x)) / 4) + +#else +#error "missing IRQ and timer primitives for XIP MTD support" +#endif + +/* + * xip_cpu_idle() is used when waiting for a delay equal or larger than + * the system timer tick period. This should put the CPU into idle mode + * to save power and to be woken up only when some interrupts are pending. + * As above, this should not rely upon standard kernel code. + */ + +#if defined(CONFIG_CPU_XSCALE) +#define xip_cpu_idle() asm volatile ("mcr p14, 0, %0, c7, c0, 0" :: "r" (1)) +#else +#define xip_cpu_idle() do { } while (0) +#endif + +#else + +#define __xipram + +#endif /* CONFIG_MTD_XIP */ + +#endif /* __LINUX_MTD_XIP_H__ */ diff -Nru a/kernel/workqueue.c b/kernel/workqueue.c --- a/kernel/workqueue.c 2004-11-17 19:39:36 -08:00 +++ b/kernel/workqueue.c 2004-11-17 19:39:36 -08:00 @@ -8,7 +8,7 @@ * * Derived from the taskqueue/keventd code by: * - * David Woodhouse + * David Woodhouse * Andrew Morton * Kai Petzke * Theodore Ts'o